diff --git a/DEPS b/DEPS
index 00269c7..9553c1d 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': '43f49b4d52a42dd6d4ecdeca676f5589a43a849f',
+  'skia_revision': 'c1c3c6d70d326a27b7b9fa82203ff2db28043be7',
   # 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': 'dca4660474efaf37c89377b0cf6ad8b8af5652a8',
+  'v8_revision': '26d2954fbe8d1d68f3daf3fc59f1826dd91d6383',
   # 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': '2e5647c8eede78ea1cf6def49bb624f837590176',
+  'angle_revision': '9ae6d7f2ee9e12b707483dc9cadd7c3529595016',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -215,7 +215,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '46d39660e0e6c8f54d2677a0054530fcbba25c07',
+  'pdfium_revision': '5f4456e3c52fbe17db79da16b1122f21dbcd3582',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -258,7 +258,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '69d93258d753ea8b5fdd46abce7c5dd9f04e2d83',
+  'catapult_revision': '5abddab6695ed03674a936d0fe48ce68bd1efd3e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # 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': '02b64b9591b9421f10f949d8a8f2ecd13d7476c1',
+  'devtools_frontend_revision': 'c0263ae980bf6d062fac2e520e6046beece610f5',
   # 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.
@@ -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': '24b5971b84c0b27aebae4a644a93d0765590661c',
+  'dawn_revision': '5e9b29fab92d6d79125555ea0d84afde9ace908b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -946,7 +946,7 @@
     Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'e46493b9148e0d1e63f55b5890bff503822616e5',
 
   'src/third_party/glslang/src':
-    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'd253278f986574cb8e80ec9a4e84094ec1b25349',
+    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '758b30727efce459aea368ac21b73ad10ebe9565',
 
   'src/third_party/google_toolbox_for_mac/src': {
       'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'),
@@ -1508,7 +1508,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/linux-amd64',
-          'version': 'ZiDTT5CqX1lXQ1R-CzXmgpkUD75XGpPt-xscFwwYAQAC',
+          'version': 'cEqPPVvSDVKN1I5f3TPm2MSFzCHppLOnHzJR9_0f8EsC',
         },
       ],
       'dep_type': 'cipd',
@@ -1518,7 +1518,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/windows-amd64',
-          'version': 'AJ3gzpNiFIZohkcHKfxOAXUjhROtipQtPmnH7iw0bRsC',
+          'version': 'FGY81gj5rN-lYgus1n59hFCTvkzS0qX1MBoh45KlK9kC',
         },
       ],
       'dep_type': 'cipd',
@@ -1528,7 +1528,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-amd64',
-          'version': 'RsM_sOD83w123V_S6QXh4i2X94fBRpvEIDO3F7WpCQ8C',
+          'version': 'eO-DAUMR6rTRR-7RdL-20Yp8jOXi8udNCchBUV1Oq7IC',
         },
       ],
       'dep_type': 'cipd',
@@ -1542,7 +1542,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a2a426bd66bc318b822d153f54e6de5987a3e112',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f1b37b7a9dad80220a166305ef17a5da9f1fbfe1',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index e5ce243c..fd25a45 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -220,7 +220,8 @@
 
     features.DisableIfNotSet(::features::kBackgroundFetch);
 
-    features.EnableIfNotSet(::features::kDisableSurfaceControlForWebview);
+    // SurfaceControl is not supported on webview.
+    features.DisableIfNotSet(::features::kAndroidSurfaceControl);
 
     // TODO(https://crbug.com/963653): SmsReceiver is not yet supported on
     // WebView.
diff --git a/base/util/ranges/algorithm.h b/base/util/ranges/algorithm.h
index 68c4ee3..53d6a06 100644
--- a/base/util/ranges/algorithm.h
+++ b/base/util/ranges/algorithm.h
@@ -4142,27 +4142,296 @@
 // [push.heap] push_heap
 // Reference: https://wg21.link/push.heap
 
-// TODO(crbug.com/1071094): Implement.
+// Preconditions: The range `[first, last - 1)` is a valid heap with respect to
+// `comp` and `proj`.
+//
+// Effects: Places the value in the location `last - 1` into the resulting heap
+// `[first, last)`.
+//
+// Returns: `last`.
+//
+// Complexity: At most `log(last - first)` comparisons and twice as many
+// projections.
+//
+// Reference: https://wg21.link/push.heap#:~:text=ranges::push_heap(I
+template <typename RandomAccessIterator,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::iterator_category_t<RandomAccessIterator>,
+          typename = indirect_result_t<Comp&,
+                                       projected<RandomAccessIterator, Proj>,
+                                       projected<RandomAccessIterator, Proj>>>
+constexpr auto push_heap(RandomAccessIterator first,
+                         RandomAccessIterator last,
+                         Comp comp = {},
+                         Proj proj = {}) {
+  std::push_heap(first, last,
+                 internal::ProjectedBinaryPredicate(comp, proj, proj));
+  return last;
+}
+
+// Preconditions: The range `[begin(range), end(range) - 1)` is a valid heap
+// with respect to `comp` and `proj`.
+//
+// Effects: Places the value in the location `end(range) - 1` into the resulting
+// heap `range`.
+//
+// Returns: `end(range)`.
+//
+// Complexity: At most `log(size(range))` comparisons and twice as many
+// projections.
+//
+// Reference: https://wg21.link/push.heap#:~:text=ranges::push_heap(R
+template <typename Range,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::range_category_t<Range>,
+          typename = indirect_result_t<Comp&,
+                                       projected<iterator_t<Range>, Proj>,
+                                       projected<iterator_t<Range>, Proj>>>
+constexpr auto push_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
+  return ranges::push_heap(ranges::begin(range), ranges::end(range),
+                           std::move(comp), std::move(proj));
+}
 
 // [pop.heap] pop_heap
 // Reference: https://wg21.link/pop.heap
 
-// TODO(crbug.com/1071094): Implement.
+// Preconditions: The range `[first, last)` is a valid non-empty heap with
+// respect to `comp` and `proj`.
+//
+// Effects: Swaps the value in the location `first` with the value in the
+// location `last - 1` and makes `[first, last - 1)` into a heap with respect to
+// `comp` and `proj`.
+//
+// Returns: `last`.
+//
+// Complexity: At most `2 log(last - first)` comparisons and twice as many
+// projections.
+//
+// Reference: https://wg21.link/pop.heap#:~:text=ranges::pop_heap(I
+template <typename RandomAccessIterator,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::iterator_category_t<RandomAccessIterator>,
+          typename = indirect_result_t<Comp&,
+                                       projected<RandomAccessIterator, Proj>,
+                                       projected<RandomAccessIterator, Proj>>>
+constexpr auto pop_heap(RandomAccessIterator first,
+                        RandomAccessIterator last,
+                        Comp comp = {},
+                        Proj proj = {}) {
+  std::pop_heap(first, last,
+                internal::ProjectedBinaryPredicate(comp, proj, proj));
+  return last;
+}
+
+// Preconditions: `range` is a valid non-empty heap with respect to `comp` and
+// `proj`.
+//
+// Effects: Swaps the value in the location `begin(range)` with the value in the
+// location `end(range) - 1` and makes `[begin(range), end(range) - 1)` into a
+// heap with respect to `comp` and `proj`.
+//
+// Returns: `end(range)`.
+//
+// Complexity: At most `2 log(size(range))` comparisons and twice as many
+// projections.
+//
+// Reference: https://wg21.link/pop.heap#:~:text=ranges::pop_heap(R
+template <typename Range,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::range_category_t<Range>,
+          typename = indirect_result_t<Comp&,
+                                       projected<iterator_t<Range>, Proj>,
+                                       projected<iterator_t<Range>, Proj>>>
+constexpr auto pop_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
+  return ranges::pop_heap(ranges::begin(range), ranges::end(range),
+                          std::move(comp), std::move(proj));
+}
 
 // [make.heap] make_heap
 // Reference: https://wg21.link/make.heap
 
-// TODO(crbug.com/1071094): Implement.
+// Effects: Constructs a heap with respect to `comp` and `proj` out of the range
+// `[first, last)`.
+//
+// Returns: `last`.
+//
+// Complexity: At most `3 log(last - first)` comparisons and twice as many
+// projections.
+//
+// Reference: https://wg21.link/make.heap#:~:text=ranges::make_heap(I
+template <typename RandomAccessIterator,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::iterator_category_t<RandomAccessIterator>,
+          typename = indirect_result_t<Comp&,
+                                       projected<RandomAccessIterator, Proj>,
+                                       projected<RandomAccessIterator, Proj>>>
+constexpr auto make_heap(RandomAccessIterator first,
+                         RandomAccessIterator last,
+                         Comp comp = {},
+                         Proj proj = {}) {
+  std::make_heap(first, last,
+                 internal::ProjectedBinaryPredicate(comp, proj, proj));
+  return last;
+}
+
+// Effects: Constructs a heap with respect to `comp` and `proj` out of `range`.
+//
+// Returns: `end(range)`.
+//
+// Complexity: At most `3 log(size(range))` comparisons and twice as many
+// projections.
+//
+// Reference: https://wg21.link/make.heap#:~:text=ranges::make_heap(R
+template <typename Range,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::range_category_t<Range>,
+          typename = indirect_result_t<Comp&,
+                                       projected<iterator_t<Range>, Proj>,
+                                       projected<iterator_t<Range>, Proj>>>
+constexpr auto make_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
+  return ranges::make_heap(ranges::begin(range), ranges::end(range),
+                           std::move(comp), std::move(proj));
+}
 
 // [sort.heap] sort_heap
 // Reference: https://wg21.link/sort.heap
 
-// TODO(crbug.com/1071094): Implement.
+// Preconditions: The range `[first, last)` is a valid heap with respect to
+// `comp` and `proj`.
+//
+// Effects: Sorts elements in the heap `[first, last)` with respect to `comp`
+// and `proj`.
+//
+// Returns: `last`.
+//
+// Complexity: At most `2 N log N` comparisons, where `N = last - first`, and
+// twice as many projections.
+//
+// Reference: https://wg21.link/sort.heap#:~:text=ranges::sort_heap(I
+template <typename RandomAccessIterator,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::iterator_category_t<RandomAccessIterator>,
+          typename = indirect_result_t<Comp&,
+                                       projected<RandomAccessIterator, Proj>,
+                                       projected<RandomAccessIterator, Proj>>>
+constexpr auto sort_heap(RandomAccessIterator first,
+                         RandomAccessIterator last,
+                         Comp comp = {},
+                         Proj proj = {}) {
+  std::sort_heap(first, last,
+                 internal::ProjectedBinaryPredicate(comp, proj, proj));
+  return last;
+}
+
+// Preconditions: `range` is a valid heap with respect to `comp` and `proj`.
+//
+// Effects: Sorts elements in the heap `range` with respect to `comp` and
+// `proj`.
+//
+// Returns: `end(range)`.
+//
+// Complexity: At most `2 N log N` comparisons, where `N = size(range)`, and
+// twice as many projections.
+//
+// Reference: https://wg21.link/sort.heap#:~:text=ranges::sort_heap(R
+template <typename Range,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::range_category_t<Range>,
+          typename = indirect_result_t<Comp&,
+                                       projected<iterator_t<Range>, Proj>,
+                                       projected<iterator_t<Range>, Proj>>>
+constexpr auto sort_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
+  return ranges::sort_heap(ranges::begin(range), ranges::end(range),
+                           std::move(comp), std::move(proj));
+}
 
 // [is.heap] is_heap
 // Reference: https://wg21.link/is.heap
 
-// TODO(crbug.com/1071094): Implement.
+// Returns: Whether the range `[first, last)` is a heap with respect to `comp`
+// and `proj`.
+//
+// Complexity: Linear.
+//
+// Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap(I
+template <typename RandomAccessIterator,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::iterator_category_t<RandomAccessIterator>,
+          typename = indirect_result_t<Comp&,
+                                       projected<RandomAccessIterator, Proj>,
+                                       projected<RandomAccessIterator, Proj>>>
+constexpr auto is_heap(RandomAccessIterator first,
+                       RandomAccessIterator last,
+                       Comp comp = {},
+                       Proj proj = {}) {
+  return std::is_heap(first, last,
+                      internal::ProjectedBinaryPredicate(comp, proj, proj));
+}
+
+// Returns: Whether `range` is a heap with respect to `comp` and `proj`.
+//
+// Complexity: Linear.
+//
+// Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap(R
+template <typename Range,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::range_category_t<Range>,
+          typename = indirect_result_t<Comp&,
+                                       projected<iterator_t<Range>, Proj>,
+                                       projected<iterator_t<Range>, Proj>>>
+constexpr auto is_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
+  return ranges::is_heap(ranges::begin(range), ranges::end(range),
+                         std::move(comp), std::move(proj));
+}
+
+// Returns: The last iterator `i` in `[first, last]` for which the range
+// `[first, i)` is a heap with respect to `comp` and `proj`.
+//
+// Complexity: Linear.
+//
+// Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap_until(I
+template <typename RandomAccessIterator,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::iterator_category_t<RandomAccessIterator>,
+          typename = indirect_result_t<Comp&,
+                                       projected<RandomAccessIterator, Proj>,
+                                       projected<RandomAccessIterator, Proj>>>
+constexpr auto is_heap_until(RandomAccessIterator first,
+                             RandomAccessIterator last,
+                             Comp comp = {},
+                             Proj proj = {}) {
+  return std::is_heap_until(
+      first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
+}
+
+// Returns: The last iterator `i` in `[begin(range), end(range)]` for which the
+// range `[begin(range), i)` is a heap with respect to `comp` and `proj`.
+//
+// Complexity: Linear.
+//
+// Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap_until(R
+template <typename Range,
+          typename Comp = ranges::less,
+          typename Proj = identity,
+          typename = internal::range_category_t<Range>,
+          typename = indirect_result_t<Comp&,
+                                       projected<iterator_t<Range>, Proj>,
+                                       projected<iterator_t<Range>, Proj>>>
+constexpr auto is_heap_until(Range&& range, Comp comp = {}, Proj proj = {}) {
+  return ranges::is_heap_until(ranges::begin(range), ranges::end(range),
+                               std::move(comp), std::move(proj));
+}
 
 // [alg.min.max] Minimum and maximum
 // Reference: https://wg21.link/alg.min.max
diff --git a/base/util/ranges/algorithm_unittest.cc b/base/util/ranges/algorithm_unittest.cc
index 0a9338c..59fbcc2 100644
--- a/base/util/ranges/algorithm_unittest.cc
+++ b/base/util/ranges/algorithm_unittest.cc
@@ -16,7 +16,9 @@
 
 using ::testing::ElementsAre;
 using ::testing::Field;
+using ::testing::Ge;
 using ::testing::Gt;
+using ::testing::Le;
 using ::testing::Lt;
 using ::testing::Pair;
 
@@ -43,6 +45,14 @@
   return lhs.value > rhs.value;
 }
 
+bool operator<=(Int lhs, Int rhs) {
+  return lhs.value <= rhs.value;
+}
+
+bool operator>=(Int lhs, Int rhs) {
+  return lhs.value >= rhs.value;
+}
+
 // Move-only int that clears `value` when moving out.
 struct MoveOnlyInt {
   MoveOnlyInt(int value) : value(value) {}
@@ -1293,4 +1303,72 @@
               ElementsAre(0, 1, 3, 4, 5, 7, 8, 9));
 }
 
+TEST(RangesTest, PushHeap) {
+  int heap[] = {6, 4, 3, 2, 1, 0, 5};
+  EXPECT_EQ(heap + 7, ranges::push_heap(heap, heap + 7));
+  EXPECT_THAT(heap, ElementsAre(6, Ge(4), Ge(4), Le(3), Le(3), Le(3), Le(3)));
+
+  Int heap_int[] = {1, 2, 3, 4, 5, 6, 0};
+  EXPECT_EQ(heap_int + 7,
+            ranges::push_heap(heap_int, ranges::greater(), &Int::value));
+  EXPECT_THAT(heap_int, ElementsAre(0, 2, 1, 4, 5, 6, 3));
+  EXPECT_THAT(heap_int,
+              ElementsAre(0, Le(2), Le(2), Ge(3), Ge(3), Ge(3), Ge(3)));
+}
+
+TEST(RangesTest, PopHeap) {
+  int heap[] = {6, 5, 4, 3, 2, 1, 0};
+  EXPECT_EQ(heap + 7, ranges::pop_heap(heap, heap + 7));
+  EXPECT_THAT(heap, ElementsAre(5, Ge(3), Ge(3), Le(2), Le(2), Le(2), 6));
+
+  Int heap_int[] = {0, 1, 2, 3, 4, 5, 6};
+  EXPECT_EQ(heap_int + 7,
+            ranges::pop_heap(heap_int, ranges::greater(), &Int::value));
+  EXPECT_THAT(heap_int, ElementsAre(1, Le(3), Le(3), Ge(4), Ge(4), Ge(4), 0));
+}
+
+TEST(RangesTest, MakeHeap) {
+  int heap[] = {0, 1, 2, 3, 4, 5, 6};
+  EXPECT_EQ(heap + 7, ranges::make_heap(heap, heap + 7));
+  EXPECT_THAT(heap, ElementsAre(6, Ge(4), Ge(4), Le(3), Le(3), Le(3), Le(3)));
+
+  Int heap_int[] = {6, 5, 4, 3, 2, 1, 0};
+  EXPECT_EQ(heap_int + 7,
+            ranges::make_heap(heap_int, ranges::greater(), &Int::value));
+  EXPECT_THAT(heap_int,
+              ElementsAre(0, Le(2), Le(2), Ge(3), Ge(3), Ge(3), Ge(3)));
+}
+
+TEST(RangesTest, SortHeap) {
+  int heap[] = {6, 4, 5, 0, 1, 2, 3};
+  EXPECT_EQ(heap + 7, ranges::sort_heap(heap, heap + 7));
+  EXPECT_THAT(heap, ElementsAre(0, 1, 2, 3, 4, 5, 6));
+
+  Int heap_int[] = {0, 2, 1, 4, 3, 6, 5};
+  EXPECT_EQ(heap_int + 7,
+            ranges::sort_heap(heap_int, ranges::greater(), &Int::value));
+  EXPECT_THAT(heap_int, ElementsAre(6, 5, 4, 3, 2, 1, 0));
+}
+
+TEST(RangesTest, IsHeap) {
+  int heap[] = {6, 4, 5, 0, 1, 2, 3};
+  EXPECT_TRUE(ranges::is_heap(heap, heap + 7));
+  EXPECT_FALSE(ranges::is_heap(heap, heap + 7, ranges::greater()));
+
+  Int heap_int[] = {0, 2, 1, 4, 3, 6, 5};
+  EXPECT_TRUE(ranges::is_heap(heap_int, ranges::greater(), &Int::value));
+  EXPECT_FALSE(ranges::is_heap(heap_int, {}, &Int::value));
+}
+
+TEST(RangesTest, IsHeapUntil) {
+  int heap[] = {6, 4, 5, 0, 1, 2, 3};
+  EXPECT_EQ(heap + 7, ranges::is_heap_until(heap, heap + 7));
+  EXPECT_EQ(heap + 1, ranges::is_heap_until(heap, heap + 7, ranges::greater()));
+
+  Int heap_int[] = {0, 2, 1, 4, 3, 6, 5};
+  EXPECT_EQ(heap_int + 7,
+            ranges::is_heap_until(heap_int, ranges::greater(), &Int::value));
+  EXPECT_EQ(heap_int + 1, ranges::is_heap_until(heap_int, {}, &Int::value));
+}
+
 }  // namespace util
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index f5860f3..9e15f93 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20200814.3.1
+0.20200815.3.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index f5860f3..66548964 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20200814.3.1
+0.20200815.2.1
diff --git a/chrome/VERSION b/chrome/VERSION
index 0431b39..40d6444 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=86
 MINOR=0
-BUILD=4234
+BUILD=4236
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppServiceBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppServiceBridge.java
index 05f425c6..c44e6b2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppServiceBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppServiceBridge.java
@@ -43,7 +43,8 @@
 
         PaymentAppServiceBridgeJni.get().create(delegate.getParams().getRenderFrameHost(),
                 delegate.getParams().getTopLevelOrigin(), delegate.getParams().getSpec(),
-                delegate.getParams().getMayCrawl(), callback);
+                delegate.getParams().getTwaPackageName(), delegate.getParams().getMayCrawl(),
+                callback);
     }
 
     /** Handles callbacks from native PaymentAppService. */
@@ -89,8 +90,21 @@
 
     @NativeMethods
     /* package */ interface Natives {
+        /**
+         * Creates a native payment app service.
+         * @param initiatorRenderFrameHost The host of the render frame where PaymentRequest API was
+         * invoked.
+         * @param topOrigin The (scheme, host, port) tuple of top level context where
+         * PaymentRequest API was invoked.
+         * @param spec The parameters passed into the PaymentRequest API.
+         * @param twaPackageName The Android package name of the Trusted Web Activity that invoked
+         * Chrome. If not running in TWA mode, then this string is null or empty.
+         * @param mayCrawlForInstallablePaymentApps Whether crawling for just-in-time installable
+         * payment apps is allowed.
+         * @param callback The callback that receives the discovered payment apps.
+         */
         void create(RenderFrameHost initiatorRenderFrameHost, String topOrigin,
-                PaymentRequestSpec spec, boolean mayCrawlForInstallablePaymentApps,
-                PaymentAppServiceCallback callback);
+                PaymentRequestSpec spec, String twaPackageName,
+                boolean mayCrawlForInstallablePaymentApps, PaymentAppServiceCallback callback);
     }
 }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 92368e6a..df908b1 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -6298,6 +6298,10 @@
      flag_descriptions::kCpuAffinityRestrictToLittleCoresDescription,
      kOsAndroid,
      FEATURE_VALUE_TYPE(features::kCpuAffinityRestrictToLittleCores)},
+
+    {"enable-surface-control", flag_descriptions::kAndroidSurfaceControlName,
+     flag_descriptions::kAndroidSurfaceControlDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(features::kAndroidSurfaceControl)},
 #endif  // OS_ANDROID
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index f136281..55d07ac 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -3481,6 +3481,8 @@
     "release_notes/release_notes_notification_unittest.cc",
     "release_notes/release_notes_storage_unittest.cc",
     "remote_apps/remote_apps_model_unittest.cc",
+    "scanning/fake_lorgnette_scanner_manager.cc",
+    "scanning/fake_lorgnette_scanner_manager.h",
     "scanning/lorgnette_scanner_manager_unittest.cc",
     "scanning/lorgnette_scanner_manager_util_unittest.cc",
     "scanning/zeroconf_scanner_detector_unittest.cc",
diff --git a/chrome/browser/chromeos/extensions/document_scan/document_scan_api.cc b/chrome/browser/chromeos/extensions/document_scan/document_scan_api.cc
index 6a6e633..3a21eee8 100644
--- a/chrome/browser/chromeos/extensions/document_scan/document_scan_api.cc
+++ b/chrome/browser/chromeos/extensions/document_scan/document_scan_api.cc
@@ -9,10 +9,9 @@
 
 #include "base/base64.h"
 #include "base/bind.h"
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/lorgnette_manager_client.h"
+#include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager.h"
+#include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager_factory.h"
+#include "content/public/browser/browser_context.h"
 #include "third_party/cros_system_api/dbus/lorgnette/dbus-constants.h"
 
 namespace extensions {
@@ -24,7 +23,6 @@
 // Error messages that can be included in a response when scanning fails.
 constexpr char kUserGestureRequiredError[] =
     "User gesture required to perform scan";
-constexpr char kListScannersError[] = "Failed to obtain list of scanners";
 constexpr char kNoScannersAvailableError[] = "No scanners available";
 constexpr char kUnsupportedMimeTypesError[] = "Unsupported MIME types";
 constexpr char kScanImageError[] = "Failed to scan image";
@@ -35,11 +33,6 @@
 // The PNG image data URL prefix of a scanned image.
 constexpr char kPngImageDataUrlPrefix[] = "data:image/png;base64,";
 
-chromeos::LorgnetteManagerClient* GetLorgnetteManagerClient() {
-  DCHECK(chromeos::DBusThreadManager::IsInitialized());
-  return chromeos::DBusThreadManager::Get()->GetLorgnetteManagerClient();
-}
-
 }  // namespace
 
 DocumentScanScanFunction::DocumentScanScanFunction() = default;
@@ -53,19 +46,16 @@
   if (!user_gesture())
     return RespondNow(Error(kUserGestureRequiredError));
 
-  GetLorgnetteManagerClient()->ListScanners(
-      base::BindOnce(&DocumentScanScanFunction::OnScannerListReceived, this));
+  chromeos::LorgnetteScannerManagerFactory::GetForBrowserContext(
+      browser_context())
+      ->GetScannerNames(
+          base::BindOnce(&DocumentScanScanFunction::OnNamesReceived, this));
   return did_respond() ? AlreadyResponded() : RespondLater();
 }
 
-void DocumentScanScanFunction::OnScannerListReceived(
-    base::Optional<lorgnette::ListScannersResponse> response) {
-  if (!response) {
-    Respond(Error(kListScannersError));
-    return;
-  }
-
-  if (response->scanners_size() == 0) {
+void DocumentScanScanFunction::OnNamesReceived(
+    std::vector<std::string> scanner_names) {
+  if (scanner_names.empty()) {
     Respond(Error(kNoScannersAvailableError));
     return;
   }
@@ -83,13 +73,14 @@
   // The first scanner supporting one of the requested MIME types used to be
   // selected. Since all of the scanners only support PNG, this results in
   // selecting the first scanner in the list.
-  const auto& scanner = response->scanners()[0];
+  const std::string& scanner_name = scanner_names[0];
   chromeos::LorgnetteManagerClient::ScanProperties properties;
   properties.mode = lorgnette::kScanPropertyModeColor;
-  GetLorgnetteManagerClient()->StartScan(
-      scanner.name(), properties,
-      base::BindOnce(&DocumentScanScanFunction::OnResultsReceived, this),
-      base::nullopt);
+  chromeos::LorgnetteScannerManagerFactory::GetForBrowserContext(
+      browser_context())
+      ->Scan(
+          scanner_name, properties,
+          base::BindOnce(&DocumentScanScanFunction::OnResultsReceived, this));
 }
 
 void DocumentScanScanFunction::OnResultsReceived(
diff --git a/chrome/browser/chromeos/extensions/document_scan/document_scan_api.h b/chrome/browser/chromeos/extensions/document_scan/document_scan_api.h
index b36a305..c96778d7 100644
--- a/chrome/browser/chromeos/extensions/document_scan/document_scan_api.h
+++ b/chrome/browser/chromeos/extensions/document_scan/document_scan_api.h
@@ -7,10 +7,10 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/optional.h"
 #include "chrome/common/extensions/api/document_scan.h"
-#include "chromeos/dbus/lorgnette/lorgnette_service.pb.h"
 #include "extensions/browser/extension_function.h"
 
 namespace extensions {
@@ -33,8 +33,7 @@
  private:
   friend class DocumentScanScanFunctionTest;
 
-  void OnScannerListReceived(
-      base::Optional<lorgnette::ListScannersResponse> response);
+  void OnNamesReceived(std::vector<std::string> scanner_names);
   void OnResultsReceived(base::Optional<std::string> scanned_image);
 
   std::unique_ptr<document_scan::Scan::Params> params_;
diff --git a/chrome/browser/chromeos/extensions/document_scan/document_scan_api_unittest.cc b/chrome/browser/chromeos/extensions/document_scan/document_scan_api_unittest.cc
index 62ce8352..3312f2a9 100644
--- a/chrome/browser/chromeos/extensions/document_scan/document_scan_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/document_scan/document_scan_api_unittest.cc
@@ -2,18 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <memory>
 #include <string>
 #include <utility>
 
+#include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/extensions/document_scan/document_scan_api.h"
+#include "chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.h"
+#include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager_factory.h"
 #include "chrome/browser/extensions/extension_api_unittest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_lorgnette_manager_client.h"
-#include "chromeos/dbus/lorgnette/lorgnette_service.pb.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "content/public/browser/browser_context.h"
 #include "extensions/browser/api_test_utils.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -25,15 +28,13 @@
 
 namespace {
 
-lorgnette::ListScannersResponse CreateListScannersResponse() {
-  lorgnette::ScannerInfo scanner;
-  scanner.set_name("Dank Scanner");
-  scanner.set_manufacturer("Scanners, Inc.");
-  scanner.set_model("TX1000");
-  scanner.set_type("Flatbed");
-  lorgnette::ListScannersResponse response;
-  *response.add_scanners() = std::move(scanner);
-  return response;
+// Scanner name used for tests.
+constexpr char kTestScannerName[] = "Test Scanner";
+
+// Creates a new FakeLorgnetteScannerManager for the given |context|.
+std::unique_ptr<KeyedService> BuildLorgnetteScannerManager(
+    content::BrowserContext* context) {
+  return std::make_unique<chromeos::FakeLorgnetteScannerManager>();
 }
 
 }  // namespace
@@ -46,18 +47,16 @@
 
   void SetUp() override {
     ExtensionApiUnittest::SetUp();
-    chromeos::DBusThreadManager::Initialize();
     function_->set_user_gesture(true);
+    chromeos::LorgnetteScannerManagerFactory::GetInstance()->SetTestingFactory(
+        browser()->profile(),
+        base::BindRepeating(&BuildLorgnetteScannerManager));
   }
 
-  void TearDown() override {
-    chromeos::DBusThreadManager::Shutdown();
-    ExtensionApiUnittest::TearDown();
-  }
-
-  chromeos::FakeLorgnetteManagerClient* GetLorgnetteManagerClient() {
-    return static_cast<chromeos::FakeLorgnetteManagerClient*>(
-        chromeos::DBusThreadManager::Get()->GetLorgnetteManagerClient());
+  chromeos::FakeLorgnetteScannerManager* GetLorgnetteScannerManager() {
+    return static_cast<chromeos::FakeLorgnetteScannerManager*>(
+        chromeos::LorgnetteScannerManagerFactory::GetForBrowserContext(
+            browser()->profile()));
   }
 
  protected:
@@ -78,37 +77,27 @@
             RunFunctionAndReturnError("[{}]"));
 }
 
-TEST_F(DocumentScanScanFunctionTest, ListScannersError) {
-  GetLorgnetteManagerClient()->SetListScannersResponse(base::nullopt);
-  EXPECT_EQ("Failed to obtain list of scanners",
-            RunFunctionAndReturnError("[{}]"));
-}
-
 TEST_F(DocumentScanScanFunctionTest, NoScannersAvailableError) {
-  lorgnette::ListScannersResponse response;
-  GetLorgnetteManagerClient()->SetListScannersResponse(response);
+  GetLorgnetteScannerManager()->SetGetScannerNamesResponse({});
   EXPECT_EQ("No scanners available", RunFunctionAndReturnError("[{}]"));
 }
 
 TEST_F(DocumentScanScanFunctionTest, UnsupportedMimeTypesError) {
-  GetLorgnetteManagerClient()->SetListScannersResponse(
-      CreateListScannersResponse());
+  GetLorgnetteScannerManager()->SetGetScannerNamesResponse({kTestScannerName});
   EXPECT_EQ("Unsupported MIME types",
             RunFunctionAndReturnError("[{\"mimeTypes\": [\"image/tiff\"]}]"));
 }
 
 TEST_F(DocumentScanScanFunctionTest, ScanImageError) {
-  GetLorgnetteManagerClient()->SetListScannersResponse(
-      CreateListScannersResponse());
-  GetLorgnetteManagerClient()->SetScanResponse(base::nullopt);
+  GetLorgnetteScannerManager()->SetGetScannerNamesResponse({kTestScannerName});
+  GetLorgnetteScannerManager()->SetScanResponse(base::nullopt);
   EXPECT_EQ("Failed to scan image",
             RunFunctionAndReturnError("[{\"mimeTypes\": [\"image/png\"]}]"));
 }
 
 TEST_F(DocumentScanScanFunctionTest, Success) {
-  GetLorgnetteManagerClient()->SetListScannersResponse(
-      CreateListScannersResponse());
-  GetLorgnetteManagerClient()->SetScanResponse("PrettyPicture");
+  GetLorgnetteScannerManager()->SetGetScannerNamesResponse({kTestScannerName});
+  GetLorgnetteScannerManager()->SetScanResponse("PrettyPicture");
   std::unique_ptr<base::DictionaryValue> result(RunFunctionAndReturnDictionary(
       function_.get(), "[{\"mimeTypes\": [\"image/png\"]}]"));
   ASSERT_NE(nullptr, result.get());
diff --git a/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc b/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc
new file mode 100644
index 0000000..ecf0e2d
--- /dev/null
+++ b/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+
+namespace chromeos {
+
+FakeLorgnetteScannerManager::FakeLorgnetteScannerManager() = default;
+
+FakeLorgnetteScannerManager::~FakeLorgnetteScannerManager() = default;
+
+void FakeLorgnetteScannerManager::GetScannerNames(
+    GetScannerNamesCallback callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), scanner_names_));
+}
+
+void FakeLorgnetteScannerManager::Scan(
+    const std::string& scanner_name,
+    const LorgnetteManagerClient::ScanProperties& scan_properties,
+    ScanCallback callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), std::move(scan_data_)));
+}
+
+void FakeLorgnetteScannerManager::SetGetScannerNamesResponse(
+    const std::vector<std::string>& scanner_names) {
+  scanner_names_ = scanner_names;
+}
+
+void FakeLorgnetteScannerManager::SetScanResponse(
+    const base::Optional<std::string>& scan_data) {
+  scan_data_ = scan_data;
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.h b/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.h
new file mode 100644
index 0000000..9c7110a
--- /dev/null
+++ b/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.h
@@ -0,0 +1,46 @@
+// 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_SCANNING_FAKE_LORGNETTE_SCANNER_MANAGER_H_
+#define CHROME_BROWSER_CHROMEOS_SCANNING_FAKE_LORGNETTE_SCANNER_MANAGER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/optional.h"
+#include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager.h"
+#include "chromeos/dbus/lorgnette_manager_client.h"
+
+namespace chromeos {
+
+// Fake implementation of LorgnetteScannerManager for tests.
+class FakeLorgnetteScannerManager final : public LorgnetteScannerManager {
+ public:
+  FakeLorgnetteScannerManager();
+  FakeLorgnetteScannerManager(const FakeLorgnetteScannerManager&) = delete;
+  FakeLorgnetteScannerManager& operator=(const FakeLorgnetteScannerManager&) =
+      delete;
+  ~FakeLorgnetteScannerManager() override;
+
+  // LorgnetteScannerManager:
+  void GetScannerNames(GetScannerNamesCallback callback) override;
+  void Scan(const std::string& scanner_name,
+            const LorgnetteManagerClient::ScanProperties& scan_properties,
+            ScanCallback callback) override;
+
+  // Sets the response returned by GetScannerNames().
+  void SetGetScannerNamesResponse(
+      const std::vector<std::string>& scanner_names);
+
+  // Sets the response returned by Scan().
+  void SetScanResponse(const base::Optional<std::string>& scan_data);
+
+ private:
+  std::vector<std::string> scanner_names_;
+  base::Optional<std::string> scan_data_;
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_SCANNING_FAKE_LORGNETTE_SCANNER_MANAGER_H_
diff --git a/chrome/browser/chromeos/web_applications/scanning_app_integration_browsertest.cc b/chrome/browser/chromeos/web_applications/scanning_app_integration_browsertest.cc
index 5a15da6..2f9aaff 100644
--- a/chrome/browser/chromeos/web_applications/scanning_app_integration_browsertest.cc
+++ b/chrome/browser/chromeos/web_applications/scanning_app_integration_browsertest.cc
@@ -30,8 +30,11 @@
       ExpectSystemWebAppValid(web_app::SystemAppType::SCANNING, url, "Scan"));
 }
 
-INSTANTIATE_TEST_SUITE_P(All,
-                         ScanningAppIntegrationTest,
-                         ::testing::Values(web_app::ProviderType::kBookmarkApps,
-                                           web_app::ProviderType::kWebApps),
-                         web_app::ProviderTypeParamToString);
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    ScanningAppIntegrationTest,
+    ::testing::Combine(
+        ::testing::Values(web_app::ProviderType::kBookmarkApps,
+                          web_app::ProviderType::kWebApps),
+        ::testing::Values(web_app::InstallationType::kWebAppInfoInstall)),
+    web_app::ProviderAndInstallationTypeToString);
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 0dfe322..8a6f818 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -2094,6 +2094,11 @@
     "expiry_milestone": 87
   },
   {
+    "name": "enable-surface-control",
+    "owners": [ "vikassoni", "khushalsagar" ],
+    "expiry_milestone": 90
+  },
+  {
     "name": "enable-sxg-prefetch-cache-for-navigations",
     "owners": [ "horo", "//content/browser/web_package/OWNERS" ],
     "expiry_milestone": 87
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index fd9336e4..2d52ccb 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2566,6 +2566,11 @@
 const char kAndroidMultipleDisplayDescription[] =
     "When enabled, tabs can be moved to the secondary display.";
 
+const char kAndroidSurfaceControlName[] = "Android SurfaceControl";
+const char kAndroidSurfaceControlDescription[] =
+    " Enables SurfaceControl to "
+    " manage the buffer queue for the DisplayCompositor on Android.";
+
 const char kAppNotificationStatusMessagingName[] =
     "App notification status messaging";
 const char kAppNotificationStatusMessagingDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 3c86125..d17ce02 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1486,6 +1486,9 @@
 extern const char kAndroidPartnerCustomizationPhenotypeName[];
 extern const char kAndroidPartnerCustomizationPhenotypeDescription[];
 
+extern const char kAndroidSurfaceControlName[];
+extern const char kAndroidSurfaceControlDescription[];
+
 extern const char kAppNotificationStatusMessagingName[];
 extern const char kAppNotificationStatusMessagingDescription[];
 
diff --git a/chrome/browser/media/autoplay_metrics_browsertest.cc b/chrome/browser/media/autoplay_metrics_browsertest.cc
index 992fc5e..54031a9 100644
--- a/chrome/browser/media/autoplay_metrics_browsertest.cc
+++ b/chrome/browser/media/autoplay_metrics_browsertest.cc
@@ -64,8 +64,8 @@
   }
 };
 
-// Flaky on Windows. https://crbug.com/1101841
-#if defined(OS_WIN)
+// Flaky on various platforms. https://crbug.com/1101841
+#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS)
 #define MAYBE_RecordAutoplayAttemptUkm DISABLED_RecordAutoplayAttemptUkm
 #else
 #define MAYBE_RecordAutoplayAttemptUkm RecordAutoplayAttemptUkm
diff --git a/chrome/browser/native_file_system/chrome_native_file_system_permission_context_unittest.cc b/chrome/browser/native_file_system/chrome_native_file_system_permission_context_unittest.cc
index 0bbbe19..8cfd3b35 100644
--- a/chrome/browser/native_file_system/chrome_native_file_system_permission_context_unittest.cc
+++ b/chrome/browser/native_file_system/chrome_native_file_system_permission_context_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/base_paths.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/json/json_reader.h"
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_path_override.h"
@@ -19,6 +20,8 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/common/pref_names.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_renderer_host.h"
@@ -128,6 +131,7 @@
     return permission_context_.get();
   }
   BrowserContext* browser_context() { return &profile_; }
+  TestingProfile* profile() { return &profile_; }
 
  protected:
   const url::Origin kTestOrigin =
@@ -339,4 +343,67 @@
   EXPECT_TRUE(permission_context()->CanObtainWritePermission(kChromeOrigin));
 }
 
+TEST_F(ChromeNativeFileSystemPermissionContextTest, PolicyReadGuardPermission) {
+  auto* prefs = profile()->GetTestingPrefService();
+  prefs->SetManagedPref(prefs::kManagedDefaultFileSystemReadGuardSetting,
+                        std::make_unique<base::Value>(CONTENT_SETTING_BLOCK));
+
+  EXPECT_FALSE(permission_context()->CanObtainReadPermission(kTestOrigin));
+}
+
+TEST_F(ChromeNativeFileSystemPermissionContextTest,
+       PolicyWriteGuardPermission) {
+  auto* prefs = profile()->GetTestingPrefService();
+  prefs->SetManagedPref(prefs::kManagedDefaultFileSystemWriteGuardSetting,
+                        std::make_unique<base::Value>(CONTENT_SETTING_BLOCK));
+
+  EXPECT_FALSE(permission_context()->CanObtainWritePermission(kTestOrigin));
+}
+
+TEST_F(ChromeNativeFileSystemPermissionContextTest, PolicyReadAskForUrls) {
+  // Set the default to "block" so that the policy being tested overrides it.
+  auto* prefs = profile()->GetTestingPrefService();
+  prefs->SetManagedPref(prefs::kManagedDefaultFileSystemReadGuardSetting,
+                        std::make_unique<base::Value>(CONTENT_SETTING_BLOCK));
+  prefs->SetManagedPref(prefs::kManagedFileSystemReadAskForUrls,
+                        base::JSONReader::ReadDeprecated(
+                            "[\"" + kTestOrigin.Serialize() + "\"]"));
+
+  EXPECT_TRUE(permission_context()->CanObtainReadPermission(kTestOrigin));
+  EXPECT_FALSE(permission_context()->CanObtainReadPermission(kTestOrigin2));
+}
+
+TEST_F(ChromeNativeFileSystemPermissionContextTest, PolicyReadBlockedForUrls) {
+  auto* prefs = profile()->GetTestingPrefService();
+  prefs->SetManagedPref(prefs::kManagedFileSystemReadBlockedForUrls,
+                        base::JSONReader::ReadDeprecated(
+                            "[\"" + kTestOrigin.Serialize() + "\"]"));
+
+  EXPECT_FALSE(permission_context()->CanObtainReadPermission(kTestOrigin));
+  EXPECT_TRUE(permission_context()->CanObtainReadPermission(kTestOrigin2));
+}
+
+TEST_F(ChromeNativeFileSystemPermissionContextTest, PolicyWriteAskForUrls) {
+  // Set the default to "block" so that the policy being tested overrides it.
+  auto* prefs = profile()->GetTestingPrefService();
+  prefs->SetManagedPref(prefs::kManagedDefaultFileSystemWriteGuardSetting,
+                        std::make_unique<base::Value>(CONTENT_SETTING_BLOCK));
+  prefs->SetManagedPref(prefs::kManagedFileSystemWriteAskForUrls,
+                        base::JSONReader::ReadDeprecated(
+                            "[\"" + kTestOrigin.Serialize() + "\"]"));
+
+  EXPECT_TRUE(permission_context()->CanObtainWritePermission(kTestOrigin));
+  EXPECT_FALSE(permission_context()->CanObtainWritePermission(kTestOrigin2));
+}
+
+TEST_F(ChromeNativeFileSystemPermissionContextTest, PolicyWriteBlockedForUrls) {
+  auto* prefs = profile()->GetTestingPrefService();
+  prefs->SetManagedPref(prefs::kManagedFileSystemWriteBlockedForUrls,
+                        base::JSONReader::ReadDeprecated(
+                            "[\"" + kTestOrigin.Serialize() + "\"]"));
+
+  EXPECT_FALSE(permission_context()->CanObtainWritePermission(kTestOrigin));
+  EXPECT_TRUE(permission_context()->CanObtainWritePermission(kTestOrigin2));
+}
+
 #endif  // !defined(OS_ANDROID)
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
index 791f496d..a03bea7 100644
--- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
@@ -319,6 +319,7 @@
     RecordInputTimingMetrics();
   }
   ReportLayoutStability();
+  ReportPerfectHeuristicsMetrics();
   ReportAbortMetrics(timing, current_time);
 }
 
@@ -877,6 +878,15 @@
   }
 }
 
+void UkmPageLoadMetricsObserver::ReportPerfectHeuristicsMetrics() {
+  ukm::builders::PerfectHeuristics builder(GetDelegate().GetPageUkmSourceId());
+  if (!delay_async_script_execution_before_finished_parsing_seen_)
+    return;
+
+  builder.Setdelay_async_script_execution_before_finished_parsing(1).Record(
+      ukm::UkmRecorder::Get());
+}
+
 void UkmPageLoadMetricsObserver::ReportAbortMetrics(
     const page_load_metrics::mojom::PageLoadTiming& timing,
     base::TimeTicks page_end_time) {
@@ -1144,4 +1154,10 @@
                           kLoadingBehaviorFontPreloadStartedBeforeRendering) {
     font_preload_started_before_rendering_observed_ = true;
   }
+
+  if (behavior_flag &
+      blink::LoadingBehaviorFlag::
+          kLoadingBehaviorAsyncScriptReadyBeforeDocumentFinishedParsing) {
+    delay_async_script_execution_before_finished_parsing_seen_ = true;
+  }
 }
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h
index 46506633..3ceb54a8 100644
--- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h
@@ -142,6 +142,8 @@
 
   void ReportLayoutStability();
 
+  void ReportPerfectHeuristicsMetrics();
+
   void ReportAbortMetrics(
       const page_load_metrics::mojom::PageLoadTiming& timing,
       base::TimeTicks page_end_time);
@@ -248,7 +250,9 @@
   // Unique across the lifetime of the browser process.
   int main_document_sequence_number_ = -1;
 
+  // These are to capture observed LoadingBehaviorFlags.
   bool font_preload_started_before_rendering_observed_ = false;
+  bool delay_async_script_execution_before_finished_parsing_seen_ = false;
 
   bool currently_in_foreground_ = false;
   // The last time the page became foregrounded, or navigation start if the page
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
index c686f54d..cd96738 100644
--- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
@@ -1461,6 +1461,28 @@
               testing::ElementsAre(base::Bucket(25, 1)));
 }
 
+TEST_F(UkmPageLoadMetricsObserverTest,
+       PerfectHeuristicsDelayaAsyncScriptExecution) {
+  NavigateAndCommit(GURL(kTestUrl1));
+
+  page_load_metrics::mojom::FrameMetadata metadata;
+  metadata.behavior_flags |= blink::LoadingBehaviorFlag::
+      kLoadingBehaviorAsyncScriptReadyBeforeDocumentFinishedParsing;
+  tester()->SimulateMetadataUpdate(metadata, web_contents()->GetMainFrame());
+
+  // Simulate closing the tab.
+  DeleteContents();
+
+  auto entries = tester()->test_ukm_recorder().GetEntriesByName(
+      ukm::builders::PerfectHeuristics::kEntryName);
+  EXPECT_EQ(1ul, entries.size());
+  tester()->test_ukm_recorder().ExpectEntryMetric(
+      entries.front(),
+      ukm::builders::PerfectHeuristics::
+          kdelay_async_script_execution_before_finished_parsingName,
+      1);
+}
+
 TEST_F(UkmPageLoadMetricsObserverTest, MHTMLNotTracked) {
   auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
       GURL(kTestUrl1), web_contents());
diff --git a/chrome/browser/payments/android/payment_app_service_bridge.cc b/chrome/browser/payments/android/payment_app_service_bridge.cc
index 50d3d5e5..8a82614 100644
--- a/chrome/browser/payments/android/payment_app_service_bridge.cc
+++ b/chrome/browser/payments/android/payment_app_service_bridge.cc
@@ -87,6 +87,7 @@
     const JavaParamRef<jobject>& jrender_frame_host,
     const JavaParamRef<jstring>& jtop_origin,
     const JavaParamRef<jobject>& jpayment_request_spec,
+    const JavaParamRef<jstring>& jtwa_package_name,
     jboolean jmay_crawl_for_installable_payment_apps,
     const JavaParamRef<jobject>& jcallback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -108,6 +109,7 @@
       service->GetNumberOfFactories(), render_frame_host, GURL(top_origin),
       payments::android::PaymentRequestSpec::FromJavaPaymentRequestSpec(
           env, jpayment_request_spec),
+      jtwa_package_name ? ConvertJavaStringToUTF8(env, jtwa_package_name) : "",
       web_data_service, jmay_crawl_for_installable_payment_apps,
       base::BindOnce(&OnCanMakePaymentCalculated,
                      ScopedJavaGlobalRef<jobject>(env, jcallback)),
@@ -161,15 +163,18 @@
     content::RenderFrameHost* render_frame_host,
     const GURL& top_origin,
     PaymentRequestSpec* spec,
+    const std::string& twa_package_name,
     scoped_refptr<PaymentManifestWebDataService> web_data_service,
     bool may_crawl_for_installable_payment_apps,
     CanMakePaymentCalculatedCallback can_make_payment_calculated_callback,
     PaymentAppCreatedCallback payment_app_created_callback,
     PaymentAppCreationErrorCallback payment_app_creation_error_callback,
     base::OnceClosure done_creating_payment_apps_callback) {
+  // Not using std::make_unique, because that requires a public constructor.
   std::unique_ptr<PaymentAppServiceBridge> bridge(new PaymentAppServiceBridge(
       number_of_factories, render_frame_host, top_origin, spec,
-      std::move(web_data_service), may_crawl_for_installable_payment_apps,
+      twa_package_name, std::move(web_data_service),
+      may_crawl_for_installable_payment_apps,
       std::move(can_make_payment_calculated_callback),
       std::move(payment_app_created_callback),
       std::move(payment_app_creation_error_callback),
@@ -182,6 +187,7 @@
     content::RenderFrameHost* render_frame_host,
     const GURL& top_origin,
     PaymentRequestSpec* spec,
+    const std::string& twa_package_name,
     scoped_refptr<PaymentManifestWebDataService> web_data_service,
     bool may_crawl_for_installable_payment_apps,
     CanMakePaymentCalculatedCallback can_make_payment_calculated_callback,
@@ -197,6 +203,7 @@
           render_frame_host->GetLastCommittedURL())),
       frame_security_origin_(render_frame_host->GetLastCommittedOrigin()),
       spec_(spec),
+      twa_package_name_(twa_package_name),
       payment_manifest_web_data_service_(web_data_service),
       may_crawl_for_installable_payment_apps_(
           may_crawl_for_installable_payment_apps),
@@ -282,6 +289,10 @@
   return spec_;
 }
 
+std::string PaymentAppServiceBridge::GetTwaPackageName() const {
+  return twa_package_name_;
+}
+
 void PaymentAppServiceBridge::OnPaymentAppCreated(
     std::unique_ptr<PaymentApp> app) {
   if (can_make_payment_calculated_callback_)
diff --git a/chrome/browser/payments/android/payment_app_service_bridge.h b/chrome/browser/payments/android/payment_app_service_bridge.h
index 390ce2b1..7e7fb91 100644
--- a/chrome/browser/payments/android/payment_app_service_bridge.h
+++ b/chrome/browser/payments/android/payment_app_service_bridge.h
@@ -44,6 +44,7 @@
       content::RenderFrameHost* render_frame_host,
       const GURL& top_origin,
       PaymentRequestSpec* spec,
+      const std::string& twa_package_name,
       scoped_refptr<PaymentManifestWebDataService> web_data_service,
       bool may_crawl_for_installable_payment_apps,
       CanMakePaymentCalculatedCallback can_make_payment_calculated_callback,
@@ -76,6 +77,7 @@
   ContentPaymentRequestDelegate* GetPaymentRequestDelegate() const override;
   void ShowProcessingSpinner() override;
   PaymentRequestSpec* GetSpec() const override;
+  std::string GetTwaPackageName() const override;
   void OnPaymentAppCreated(std::unique_ptr<PaymentApp> app) override;
   void OnPaymentAppCreationError(const std::string& error_message) override;
   bool SkipCreatingNativePaymentApps() const override;
@@ -88,6 +90,7 @@
       content::RenderFrameHost* render_frame_host,
       const GURL& top_origin,
       PaymentRequestSpec* spec,
+      const std::string& twa_package_name,
       scoped_refptr<PaymentManifestWebDataService> web_data_service,
       bool may_crawl_for_installable_payment_apps,
       CanMakePaymentCalculatedCallback can_make_payment_calculated_callback,
@@ -102,6 +105,7 @@
   const GURL frame_origin_;
   const url::Origin frame_security_origin_;
   PaymentRequestSpec* spec_;
+  const std::string twa_package_name_;
   scoped_refptr<PaymentManifestWebDataService>
       payment_manifest_web_data_service_;
   bool may_crawl_for_installable_payment_apps_;
diff --git a/chrome/browser/payments/android/payment_app_service_bridge_unittest.cc b/chrome/browser/payments/android/payment_app_service_bridge_unittest.cc
index fdc6cb32..88df160 100644
--- a/chrome/browser/payments/android/payment_app_service_bridge_unittest.cc
+++ b/chrome/browser/payments/android/payment_app_service_bridge_unittest.cc
@@ -62,7 +62,8 @@
   MOCK_CONST_METHOD0(HandlesPayerPhone, bool());
 };
 
-class PaymentAppServiceBridgeUnitTest : public ::testing::Test {
+class PaymentAppServiceBridgeUnitTest
+    : public ::testing::TestWithParam<std::string> {
  public:
   PaymentAppServiceBridgeUnitTest()
       : top_origin_("https://shop.example"),
@@ -90,7 +91,7 @@
   scoped_refptr<PaymentManifestWebDataService> web_data_service_;
 };
 
-TEST_F(PaymentAppServiceBridgeUnitTest, Smoke) {
+TEST_P(PaymentAppServiceBridgeUnitTest, Smoke) {
   std::vector<mojom::PaymentMethodDataPtr> method_data;
   method_data.push_back(MakePaymentMethodData("basic-card"));
   method_data.push_back(MakePaymentMethodData("https://ph.example"));
@@ -102,7 +103,7 @@
   base::WeakPtr<PaymentAppServiceBridge> bridge =
       PaymentAppServiceBridge::Create(
           /*number_of_factories=*/3, web_contents_->GetMainFrame(), top_origin_,
-          &spec, web_data_service_,
+          &spec, /*twa_package_name=*/GetParam(), web_data_service_,
           /*may_crawl_for_installable_payment_apps=*/true,
           base::BindRepeating(&MockCallback::NotifyCanMakePaymentCalculated,
                               base::Unretained(&mock_callback)),
@@ -147,4 +148,10 @@
   CHECK_EQ(nullptr, bridge.get());
 }
 
+// An empty string indicates running outside of a TWA. A non-empty string is the
+// package name of the TWA when running in a TWA mode.
+INSTANTIATE_TEST_SUITE_P(WithAndWithoutTwaPackageName,
+                         PaymentAppServiceBridgeUnitTest,
+                         ::testing::Values("", "com.example.twa.app"));
+
 }  // namespace payments
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 55f78c3..f744e4a9 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -567,6 +567,24 @@
   { key::kSerialBlockedForUrls,
     prefs::kManagedSerialBlockedForUrls,
     base::Value::Type::LIST },
+  { key::kDefaultFileSystemReadGuardSetting,
+    prefs::kManagedDefaultFileSystemReadGuardSetting,
+    base::Value::Type::INTEGER },
+  { key::kFileSystemReadAskForUrls,
+    prefs::kManagedFileSystemReadAskForUrls,
+    base::Value::Type::LIST },
+  { key::kFileSystemReadBlockedForUrls,
+    prefs::kManagedFileSystemReadBlockedForUrls,
+    base::Value::Type::LIST },
+  { key::kDefaultFileSystemWriteGuardSetting,
+    prefs::kManagedDefaultFileSystemWriteGuardSetting,
+    base::Value::Type::INTEGER },
+  { key::kFileSystemWriteAskForUrls,
+    prefs::kManagedFileSystemWriteAskForUrls,
+    base::Value::Type::LIST },
+  { key::kFileSystemWriteBlockedForUrls,
+    prefs::kManagedFileSystemWriteBlockedForUrls,
+    base::Value::Type::LIST },
   { key::kTabFreezingEnabled,
     prefs::kTabFreezingEnabled,
     base::Value::Type::BOOLEAN },
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js
index 06c5245..54624c92 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/focus_automation_handler.js
@@ -42,6 +42,7 @@
         EventType.ACTIVEDESCENDANTCHANGED, this.onActiveDescendantChanged);
     this.addListener_(
         EventType.MENU_LIST_ITEM_SELECTED, this.onEventIfSelected);
+    this.addListener_(EventType.TEXT_CHANGED, this.onTextChanged_);
   }
 
   /**
@@ -49,7 +50,18 @@
    * @param {!AutomationEvent} evt
    */
   onActiveDescendantChanged(evt) {
-    if (!evt.target.activeDescendant || !evt.target.state.focused) {
+    if (!evt.target.activeDescendant) {
+      return;
+    }
+
+    let skipFocusCheck = false;
+    chrome.automation.getFocus(focus => {
+      if (focus.role == RoleType.POP_UP_BUTTON) {
+        skipFocusCheck = true;
+      }
+    });
+
+    if (!skipFocusCheck && !evt.target.state.focused) {
       return;
     }
 
@@ -76,6 +88,27 @@
       this.onEventDefault(evt);
     }
   }
+
+  /**
+   * @param {!ChromeVoxEvent} evt
+   */
+  onTextChanged_(evt) {
+    // TODO: listen to value changes instead when they are generated.
+    // Here only to handle popup buttons.
+    if (evt.target.role != RoleType.POP_UP_BUTTON ||
+        evt.target.state.editable) {
+      return;
+    }
+
+    // If it has children, that means a menu is showing.
+    if (evt.target.firstChild) {
+      return;
+    }
+
+    if (evt.target.value) {
+      new Output().withString(evt.target.value).go();
+    }
+  }
 };
 
 });  // goog.scope
diff --git a/chrome/browser/resources/settings/site_settings/site_list_entry.html b/chrome/browser/resources/settings/site_settings/site_list_entry.html
index 817bf1f3..13665a49 100644
--- a/chrome/browser/resources/settings/site_settings/site_list_entry.html
+++ b/chrome/browser/resources/settings/site_settings/site_list_entry.html
@@ -7,10 +7,14 @@
         flex: 1
       }
 
-      .settings-row.discarded {
+      .settings-row.discarded .display-name {
         text-decoration: line-through;
       }
 
+      .settings-row.discarded .discarded-label {
+        margin-inline-start: 8px;
+      }
+
       /* Tooltip is hidden since site-list will display a common tooltip. */
       cr-policy-pref-indicator::part(tooltip) {
         display: none;
@@ -22,7 +26,10 @@
         <site-favicon url="[[model.origin]]"></site-favicon>
         <div class="middle no-min-width">
           <div class="text-elide">
-            <span class="url-directionality">[[computeDisplayName_(model)]]
+            <span class="display-name url-directionality">
+              [[computeDisplayName_(model)]]</span>
+            <span class="discarded-label"
+              hidden="[[!model.isDiscarded]]">$i18n{discardedPerSiteSetting}
             </span>
           </div>
 
diff --git a/chrome/browser/safe_browsing/download_protection/download_feedback_service.cc b/chrome/browser/safe_browsing/download_protection/download_feedback_service.cc
index 28e28eb..e5c2e511 100644
--- a/chrome/browser/safe_browsing/download_protection/download_feedback_service.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_feedback_service.cc
@@ -70,9 +70,9 @@
 }  // namespace
 
 DownloadFeedbackService::DownloadFeedbackService(
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+    DownloadProtectionService* download_protection_service,
     base::TaskRunner* file_task_runner)
-    : url_loader_factory_(url_loader_factory),
+    : download_protection_service_(download_protection_service),
       file_task_runner_(file_task_runner) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
@@ -124,6 +124,7 @@
 }
 
 void DownloadFeedbackService::BeginFeedbackForDownload(
+    Profile* profile,
     download::DownloadItem* download,
     DownloadCommands::Command download_command) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -134,7 +135,7 @@
   download->StealDangerousDownload(
       download_command == DownloadCommands::DISCARD,
       base::BindOnce(&DownloadFeedbackService::BeginFeedbackOrDeleteFile,
-                     file_task_runner_, weak_ptr_factory_.GetWeakPtr(),
+                     file_task_runner_, weak_ptr_factory_.GetWeakPtr(), profile,
                      pings->ping_request(), pings->ping_response()));
   if (download_command == DownloadCommands::KEEP) {
     DownloadItemModel model(download);
@@ -146,13 +147,14 @@
 void DownloadFeedbackService::BeginFeedbackOrDeleteFile(
     const scoped_refptr<base::TaskRunner>& file_task_runner,
     const base::WeakPtr<DownloadFeedbackService>& service,
+    Profile* profile,
     const std::string& ping_request,
     const std::string& ping_response,
     const base::FilePath& path) {
   if (service) {
     if (path.empty())
       return;
-    service->BeginFeedback(ping_request, ping_response, path);
+    service->BeginFeedback(profile, ping_request, ping_response, path);
   } else {
     file_task_runner->PostTask(
         FROM_HERE, base::BindOnce(base::GetDeleteFileCallback(), path));
@@ -165,13 +167,14 @@
       &DownloadFeedbackService::FeedbackComplete, base::Unretained(this)));
 }
 
-void DownloadFeedbackService::BeginFeedback(const std::string& ping_request,
+void DownloadFeedbackService::BeginFeedback(Profile* profile,
+                                            const std::string& ping_request,
                                             const std::string& ping_response,
                                             const base::FilePath& path) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  std::unique_ptr<DownloadFeedback> feedback(
-      DownloadFeedback::Create(url_loader_factory_, file_task_runner_.get(),
-                               path, ping_request, ping_response));
+  std::unique_ptr<DownloadFeedback> feedback(DownloadFeedback::Create(
+      download_protection_service_->GetURLLoaderFactory(profile),
+      file_task_runner_.get(), path, ping_request, ping_response));
   active_feedback_.push(std::move(feedback));
 
   if (active_feedback_.size() == 1)
diff --git a/chrome/browser/safe_browsing/download_protection/download_feedback_service.h b/chrome/browser/safe_browsing/download_protection/download_feedback_service.h
index 65a39836..6a0a1ce 100644
--- a/chrome/browser/safe_browsing/download_protection/download_feedback_service.h
+++ b/chrome/browser/safe_browsing/download_protection/download_feedback_service.h
@@ -24,10 +24,6 @@
 class DownloadItem;
 }
 
-namespace network {
-class SharedURLLoaderFactory;
-}
-
 namespace safe_browsing {
 
 class DownloadFeedback;
@@ -38,7 +34,7 @@
 class DownloadFeedbackService {
  public:
   DownloadFeedbackService(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      DownloadProtectionService* download_protection_service,
       base::TaskRunner* file_task_runner);
   ~DownloadFeedbackService();
 
@@ -64,26 +60,31 @@
       std::string* ping,
       std::string* response);
 
-  // Begin download feedback for |download|. Then delete download file if
-  // |download_command| is DISCARD, or run the KEEP command otherwise.This must
-  // only be called if IsEnabledForDownload is true for |download|.
-  void BeginFeedbackForDownload(download::DownloadItem* download,
+  // Begin download feedback for the given |download| in the given |profile|.
+  // Then delete download file if |download_command| is DISCARD, or run the KEEP
+  // command otherwise. This must only be called if IsEnabledForDownload is true
+  // for |download|.
+  void BeginFeedbackForDownload(Profile* profile,
+                                download::DownloadItem* download,
                                 DownloadCommands::Command download_command);
 
  private:
   static void BeginFeedbackOrDeleteFile(
       const scoped_refptr<base::TaskRunner>& file_task_runner,
       const base::WeakPtr<DownloadFeedbackService>& service,
+      Profile* profile,
       const std::string& ping_request,
       const std::string& ping_response,
       const base::FilePath& path);
   void StartPendingFeedback();
-  void BeginFeedback(const std::string& ping_request,
+  void BeginFeedback(Profile* profile,
+                     const std::string& ping_request,
                      const std::string& ping_response,
                      const base::FilePath& path);
   void FeedbackComplete();
 
-  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+  // Safe because the DownloadProtectionService owns this.
+  DownloadProtectionService* download_protection_service_;
   scoped_refptr<base::TaskRunner> file_task_runner_;
 
   // Currently active & pending uploads. The first item is active, remaining
diff --git a/chrome/browser/safe_browsing/download_protection/download_feedback_service_unittest.cc b/chrome/browser/safe_browsing/download_protection/download_feedback_service_unittest.cc
index 6161f7a..14d1466 100644
--- a/chrome/browser/safe_browsing/download_protection/download_feedback_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_feedback_service_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "chrome/browser/safe_browsing/download_protection/download_feedback.h"
+#include "chrome/test/base/testing_profile.h"
 #include "components/download/public/common/mock_download_item.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/browser_task_environment.h"
@@ -105,6 +106,16 @@
   std::vector<FakeDownloadFeedback*> feedbacks_;
 };
 
+class FakeDownloadProtectionService : public DownloadProtectionService {
+ public:
+  FakeDownloadProtectionService() : DownloadProtectionService(nullptr) {}
+
+  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory(
+      content::BrowserContext* browser_context) override {
+    return nullptr;
+  }
+};
+
 bool WillStorePings(DownloadCheckResult result,
                     bool upload_requested,
                     int64_t size) {
@@ -155,6 +166,8 @@
   content::BrowserTaskEnvironment task_environment_;
   scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
   FakeDownloadFeedbackFactory download_feedback_factory_;
+  TestingProfile profile_;
+  FakeDownloadProtectionService fake_download_service_;
 };
 
 TEST_F(DownloadFeedbackServiceTest, MaybeStorePingsForDownload) {
@@ -216,12 +229,13 @@
         download_discarded_callback = std::move(arg);
       });
 
-  DownloadFeedbackService service(nullptr, file_task_runner_.get());
+  DownloadFeedbackService service(&fake_download_service_,
+                                  file_task_runner_.get());
   service.MaybeStorePingsForDownload(DownloadCheckResult::UNCOMMON,
                                      true /* upload_requested */, &item,
                                      ping_request, ping_response);
   ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item));
-  service.BeginFeedbackForDownload(&item, DownloadCommands::DISCARD);
+  service.BeginFeedbackForDownload(&profile_, &item, DownloadCommands::DISCARD);
   ASSERT_FALSE(download_discarded_callback.is_null());
   EXPECT_EQ(0U, num_feedbacks());
 
@@ -261,12 +275,13 @@
   GURL empty_url;
   EXPECT_CALL(item, GetURL()).WillOnce(ReturnRef(empty_url));
 
-  DownloadFeedbackService service(nullptr, file_task_runner_.get());
+  DownloadFeedbackService service(&fake_download_service_,
+                                  file_task_runner_.get());
   service.MaybeStorePingsForDownload(DownloadCheckResult::UNCOMMON,
                                      true /* upload_requested */, &item,
                                      ping_request, ping_response);
   ASSERT_TRUE(DownloadFeedbackService::IsEnabledForDownload(item));
-  service.BeginFeedbackForDownload(&item, DownloadCommands::KEEP);
+  service.BeginFeedbackForDownload(&profile_, &item, DownloadCommands::KEEP);
   ASSERT_FALSE(download_discarded_callback.is_null());
   EXPECT_EQ(0U, num_feedbacks());
 
@@ -312,10 +327,12 @@
   }
 
   {
-    DownloadFeedbackService service(nullptr, file_task_runner_.get());
+    DownloadFeedbackService service(&fake_download_service_,
+                                    file_task_runner_.get());
     for (size_t i = 0; i < kNumDownloads; ++i) {
       SCOPED_TRACE(i);
-      service.BeginFeedbackForDownload(&item[i], DownloadCommands::DISCARD);
+      service.BeginFeedbackForDownload(&profile_, &item[i],
+                                       DownloadCommands::DISCARD);
       ASSERT_FALSE(download_discarded_callback[i].is_null());
     }
     EXPECT_EQ(0U, num_feedbacks());
@@ -384,10 +401,12 @@
   }
 
   {
-    DownloadFeedbackService service(nullptr, file_task_runner_.get());
+    DownloadFeedbackService service(&fake_download_service_,
+                                    file_task_runner_.get());
     for (size_t i = 0; i < kNumDownloads; ++i) {
       SCOPED_TRACE(i);
-      service.BeginFeedbackForDownload(&item[i], DownloadCommands::DISCARD);
+      service.BeginFeedbackForDownload(&profile_, &item[i],
+                                       DownloadCommands::DISCARD);
       ASSERT_FALSE(download_discarded_callback[i].is_null());
     }
     EXPECT_EQ(0U, num_feedbacks());
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection/download_protection_service.cc
index c59f4fd..1e570fd 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_service.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_service.cc
@@ -109,7 +109,7 @@
       binary_feature_extractor_(new BinaryFeatureExtractor()),
       download_request_timeout_ms_(kDownloadRequestTimeoutMs),
       feedback_service_(new DownloadFeedbackService(
-          sb_service_ ? sb_service_->GetURLLoaderFactory() : nullptr,
+          this,
           base::ThreadPool::CreateSequencedTaskRunner(
               {base::MayBlock(), base::TaskPriority::BEST_EFFORT})
               .get())),
@@ -569,7 +569,8 @@
   bool is_extended_reporting =
       ExtendedReportingPrefExists(*prefs) && IsExtendedReportingEnabled(*prefs);
   if (!profile->IsOffTheRecord() && is_extended_reporting) {
-    feedback_service_->BeginFeedbackForDownload(download, download_command);
+    feedback_service_->BeginFeedbackForDownload(profile, download,
+                                                download_command);
     return true;
   }
   return false;
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_service.h b/chrome/browser/safe_browsing/download_protection/download_protection_service.h
index b7db11c1..c0aec81 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_service.h
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_service.h
@@ -203,7 +203,7 @@
       DeepScanningRequest::DeepScanTrigger trigger,
       enterprise_connectors::AnalysisSettings analysis_settings);
 
-  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory(
+  virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory(
       content::BrowserContext* browser_context);
 
  private:
diff --git a/chrome/browser/search/ntp_features.cc b/chrome/browser/search/ntp_features.cc
index a321e70..5966095 100644
--- a/chrome/browser/search/ntp_features.cc
+++ b/chrome/browser/search/ntp_features.cc
@@ -49,7 +49,7 @@
 // If enabled, the search box in the middle of the NTP will accept input
 // directly (i.e. not be a "fake" box) and search results will show directly
 // below the non-fake input ("realbox").
-const base::Feature kRealbox{"NtpRealbox", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kRealbox{"NtpRealbox", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // If enabled, shows Vasco suggestion chips in the NTP below fakebox/realbox
 // despite other config except DisableSearchSuggestChips below.
diff --git a/chrome/browser/search/ntp_features_unittest.cc b/chrome/browser/search/ntp_features_unittest.cc
index a78c50ad..2c51ded 100644
--- a/chrome/browser/search/ntp_features_unittest.cc
+++ b/chrome/browser/search/ntp_features_unittest.cc
@@ -15,74 +15,11 @@
 
 TEST(NTPFeaturesTest, IsRealboxEnabled) {
   {
-    base::test::ScopedFeatureList feature_list;
-    EXPECT_FALSE(IsRealboxEnabled());
-  }
-  {
-    base::test::ScopedFeatureList feature_list;
-    feature_list.InitAndEnableFeature(kRealbox);
     EXPECT_TRUE(IsRealboxEnabled());
 
+    base::test::ScopedFeatureList feature_list;
     // Realbox is disabled when new search features are disabled.
-    feature_list.Reset();
-    feature_list.InitWithFeatures({kRealbox}, {omnibox::kNewSearchFeatures});
-    EXPECT_FALSE(IsRealboxEnabled());
-  }
-  {
-    base::test::ScopedFeatureList feature_list;
-    feature_list.InitAndEnableFeature(omnibox::kZeroSuggestionsOnNTPRealbox);
-    EXPECT_TRUE(IsRealboxEnabled());
-
-    // Realbox is disabled when new search features are disabled.
-    feature_list.Reset();
-    feature_list.InitWithFeatures({omnibox::kZeroSuggestionsOnNTPRealbox},
-                                  {omnibox::kNewSearchFeatures});
-    EXPECT_FALSE(IsRealboxEnabled());
-  }
-  {
-    base::test::ScopedFeatureList feature_list;
-    feature_list.InitAndEnableFeature(
-        omnibox::kReactiveZeroSuggestionsOnNTPRealbox);
-    EXPECT_TRUE(IsRealboxEnabled());
-
-    // Realbox is disabled when new search features are disabled.
-    feature_list.Reset();
-    feature_list.InitWithFeatures(
-        {omnibox::kReactiveZeroSuggestionsOnNTPRealbox},
-        {omnibox::kNewSearchFeatures});
-    EXPECT_FALSE(IsRealboxEnabled());
-  }
-  {
-    base::test::ScopedFeatureList feature_list;
-    // Reactive zero-prefix suggestions in the NTP Omnibox.
-    feature_list.InitAndEnableFeature(
-        omnibox::kReactiveZeroSuggestionsOnNTPOmnibox);
-    EXPECT_FALSE(IsRealboxEnabled());
-  }
-  {
-    base::test::ScopedFeatureList feature_list;
-    // zero-prefix suggestions are configured for the NTP Omnibox.
-    feature_list.InitWithFeaturesAndParameters(
-        {{omnibox::kOnFocusSuggestions,
-          {{"ZeroSuggestVariant:7:*", "Does not matter"}}}},
-        {});
-    EXPECT_FALSE(IsRealboxEnabled());
-  }
-  {
-    base::test::ScopedFeatureList feature_list;
-    // zero-prefix suggestions are configured for the NTP Realbox.
-    feature_list.InitWithFeaturesAndParameters(
-        {{omnibox::kOnFocusSuggestions,
-          {{"ZeroSuggestVariant:15:*", "Does not matter"}}}},
-        {});
-    EXPECT_TRUE(IsRealboxEnabled());
-
-    // Realbox is disabled when new search features are disabled.
-    feature_list.Reset();
-    feature_list.InitWithFeaturesAndParameters(
-        {{omnibox::kOnFocusSuggestions,
-          {{"ZeroSuggestVariant:15:*", "Does not matter"}}}},
-        {omnibox::kNewSearchFeatures});
+    feature_list.InitAndDisableFeature(omnibox::kNewSearchFeatures);
     EXPECT_FALSE(IsRealboxEnabled());
   }
 }
diff --git a/chrome/browser/search/search_suggest/search_suggest_service_unittest.cc b/chrome/browser/search/search_suggest/search_suggest_service_unittest.cc
index ed9d4cf..732d10d 100644
--- a/chrome/browser/search/search_suggest/search_suggest_service_unittest.cc
+++ b/chrome/browser/search/search_suggest/search_suggest_service_unittest.cc
@@ -207,9 +207,7 @@
     // Note: ZPS variant 15 is NTP Realbox as starting focus.
     feature_params["ZeroSuggestVariant:15:*"] = kRemoteNoUrlLocal;
     feature_list.InitWithFeaturesAndParameters(
-        {{omnibox::kZeroSuggestionsOnNTP, {}},
-         {omnibox::kZeroSuggestionsOnNTPRealbox, {}},
-         {omnibox::kOnFocusSuggestions, feature_params},
+        {{omnibox::kOnFocusSuggestions, feature_params},
          {ntp_features::kSearchSuggestChips, {}}},
         {});
     EXPECT_TRUE(SearchSuggestService::IsEnabled());
@@ -236,9 +234,7 @@
     // Note: ZPS variant 15 is NTP Realbox as starting focus.
     feature_params["ZeroSuggestVariant:15:*"] = kRemoteNoUrlLocal;
     feature_list.InitWithFeaturesAndParameters(
-        {{omnibox::kZeroSuggestionsOnNTP, {}},
-         {omnibox::kZeroSuggestionsOnNTPRealbox, {}},
-         {omnibox::kOnFocusSuggestions, feature_params},
+        {{omnibox::kOnFocusSuggestions, feature_params},
          {ntp_features::kSearchSuggestChips, {}},
          {ntp_features::kDisableSearchSuggestChips, {}}},
         {});
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index 84f62f4..0388d3f 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -3728,8 +3728,17 @@
 // This test checks the behavior of mixed content blocking for the requests
 // from a dedicated worker by changing the settings in WebPreferences
 // with allow_running_insecure_content = false.
-IN_PROC_BROWSER_TEST_P(SSLUIWorkerFetchTest,
-                       MixedContentSettings_DisallowRunningInsecureContent) {
+// Disabled due to being flaky. crbug.com/1116670
+#if defined(OS_MAC)
+#define MAYBE_MixedContentSettings_DisallowRunningInsecureContent \
+  DISABLED_MixedContentSettings_DisallowRunningInsecureContent
+#else
+#define MAYBE_MixedContentSettings_DisallowRunningInsecureContent \
+  MixedContentSettings_DisallowRunningInsecureContent
+#endif
+IN_PROC_BROWSER_TEST_P(
+    SSLUIWorkerFetchTest,
+    MAYBE_MixedContentSettings_DisallowRunningInsecureContent) {
   ChromeContentBrowserClientForMixedContentTest browser_client;
   content::ContentBrowserClient* old_browser_client =
       content::SetBrowserClientForTesting(&browser_client);
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index bbe9474..7ff377c 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -197,11 +197,13 @@
 #include "ui/views/window/dialog_delegate.h"
 
 #if defined(OS_CHROMEOS)
+#include "ash/public/cpp/metrics_util.h"
 #include "ash/public/cpp/accelerators.h"
 #include "ash/public/cpp/desks_helper.h"
 #include "chrome/browser/ui/ash/window_properties.h"
 #include "chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.h"
 #include "chrome/grit/chrome_unscaled_resources.h"
+#include "ui/compositor/throughput_tracker.h"
 #else
 #include "chrome/browser/ui/signin_view_controller.h"
 #endif  // !defined(OS_CHROMEOS)
@@ -253,6 +255,16 @@
 // locate this object using just the handle.
 const char* const kBrowserViewKey = "__BROWSER_VIEW__";
 
+#if defined(OS_CHROMEOS)
+// UMA histograms that record animation smoothness for tab loading animation.
+constexpr char kTabLoadingSmoothnessHistogramName[] =
+    "Chrome.Tabs.AnimationSmoothness.TabLoading";
+
+void RecordTabLoadingSmoothness(int smoothness) {
+  UMA_HISTOGRAM_PERCENTAGE(kTabLoadingSmoothnessHistogramName, smoothness);
+}
+#endif
+
 // See SetDisableRevealerDelayForTesting().
 bool g_disable_revealer_delay_for_testing = false;
 
@@ -1004,6 +1016,12 @@
 void BrowserView::UpdateLoadingAnimations(bool should_animate) {
   if (should_animate) {
     if (!loading_animation_timer_.IsRunning()) {
+#if defined(OS_CHROMEOS)
+      loading_animation_tracker_.emplace(
+        GetWidget()->GetCompositor()->RequestNewThroughputTracker());
+      loading_animation_tracker_->Start(ash::metrics_util::ForSmoothness(
+        base::BindRepeating(&RecordTabLoadingSmoothness)));
+#endif
       // Loads are happening, and the timer isn't running, so start it.
       loading_animation_start_ = base::TimeTicks::Now();
       loading_animation_timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(30),
@@ -1013,6 +1031,9 @@
   } else {
     if (loading_animation_timer_.IsRunning()) {
       loading_animation_timer_.Stop();
+#if defined(OS_CHROMEOS)
+      loading_animation_tracker_->Stop();
+#endif
       // Loads are now complete, update the state if a task was scheduled.
       LoadingAnimationCallback();
     }
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 4a810dd..214b273a8 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -81,6 +81,12 @@
 class Extension;
 }
 
+#if defined(OS_CHROMEOS)
+namespace ui {
+class ThroughputTracker;
+}
+#endif
+
 namespace version_info {
 enum class Channel;
 }
@@ -905,6 +911,12 @@
   std::unique_ptr<TabGroupsIPHController> tab_groups_iph_controller_;
   std::unique_ptr<FeaturePromoControllerViews> feature_promo_controller_;
 
+#if defined(OS_CHROMEOS)
+  // |loading_animation_tracker_| is used to measure animation smoothness for
+  // tab loading animation.
+  base::Optional<ui::ThroughputTracker> loading_animation_tracker_;
+#endif
+
   mutable base::WeakPtrFactory<BrowserView> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(BrowserView);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index a663689..d95371f 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -6,7 +6,7 @@
 
 #include <limits.h>
 
-#include <algorithm>  // NOLINT
+#include <algorithm>
 
 #include "base/macros.h"
 #include "base/strings/string_util.h"
@@ -40,6 +40,7 @@
 #include "ui/views/controls/button/image_button_factory.h"
 #include "ui/views/controls/focus_ring.h"
 #include "ui/views/controls/highlight_path_generator.h"
+
 #if defined(OS_WIN)
 #include "base/win/atl.h"
 #endif
@@ -214,7 +215,10 @@
     suggestion_view_->description()->ReapplyStyling();
   }
 
-  if (keyword_view_->GetVisible()) {
+  if (force_reapply_styles) {
+    keyword_view_->content()->ReapplyStyling();
+    keyword_view_->description()->ReapplyStyling();
+  } else if (keyword_view_->GetVisible()) {
     keyword_view_->description()->ApplyTextColor(
         OmniboxPart::RESULTS_TEXT_DIMMED);
   }
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 38e912025..bd5b41f 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1231,6 +1231,10 @@
   static constexpr webui::LocalizedString kLocalizedStrings[] = {
       {"privacyPageTitle", IDS_SETTINGS_PRIVACY},
       {"privacyPageMore", IDS_SETTINGS_PRIVACY_MORE},
+      // TODO(crbug.com/1116608): This seemingly unrelated string resource is
+      // used because it already has a localized version available in M85, so
+      // we can ship this label in M85 on short notice.
+      {"discardedPerSiteSetting", IDS_POLICY_LABEL_IGNORED},
       {"doNotTrack", IDS_SETTINGS_ENABLE_DO_NOT_TRACK},
       {"doNotTrackDialogTitle", IDS_SETTINGS_ENABLE_DO_NOT_TRACK_DIALOG_TITLE},
       // TODO(crbug.com/1062607): This string is no longer used. Remove.
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 60822dd..af0f2a7 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1597426673-550b761d47e655299dbb3d5b54525f083ab2d05d.profdata
+chrome-mac-master-1597514130-fe0a8d516b962baead2578c487739528f5924993.profdata
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 8c0347f..dbc2879 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -119,6 +119,11 @@
 #include "ui/views/widget/widget.h"
 #endif
 
+#if BUILDFLAG(IS_LACROS)
+#include "ui/aura/test/ui_controls_factory_aura.h"
+#include "ui/base/test/ui_controls.h"
+#endif
+
 namespace {
 
 #if defined(OS_CHROMEOS)
@@ -539,6 +544,19 @@
     auto* tab = browser_->tab_strip_model()->GetActiveWebContents();
     content::WaitForLoadStop(tab);
     SetInitialWebContents(tab);
+
+    // For other platforms, they install ui controls in
+    // interactive_ui_tests_main.cc. We can't add it there because we have no
+    // WindowTreeHost initialized at the test runner level.
+    // The ozone implementation of CreateUIControlsAura differs from other
+    // implementation in that it requires a WindowTreeHost. Thus, it must be
+    // initialized here rather than earlier.
+#if BUILDFLAG(IS_LACROS)
+    BrowserWindow* window = browser_->window();
+    CHECK(window);
+    ui_controls::InstallUIControlsAura(
+        aura::test::CreateUIControlsAura(window->GetNativeWindow()->GetHost()));
+#endif
   }
 
 #if !defined(OS_ANDROID)
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc
index c4d138b5..44e45c6f 100644
--- a/chrome/test/chromedriver/chrome_launcher.cc
+++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -447,9 +447,9 @@
     options.new_process_group = true;
 #endif
 
+  const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
 #if defined(OS_POSIX)
   base::ScopedFD devnull;
-  const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
   if (!cmd_line->HasSwitch("verbose") &&
       !cmd_line->HasSwitch("enable-chrome-logs") &&
       cmd_line->GetSwitchValueASCII("log-level") != "ALL") {
@@ -462,6 +462,17 @@
         std::make_pair(devnull.get(), STDERR_FILENO));
   }
 #elif defined(OS_WIN)
+  if (cmd_line->HasSwitch("enable-chrome-logs")) {
+    // On Windows, we must inherit the stdout/stderr handles, or the output from
+    // the browser will not be part of our output and thus not capturable by
+    // processes that call us.
+    options.stdin_handle = INVALID_HANDLE_VALUE;
+    options.stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+    options.stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
+    options.handles_to_inherit.push_back(options.stdout_handle);
+    options.handles_to_inherit.push_back(options.stderr_handle);
+  }
+
   if (!SwitchToUSKeyboardLayout())
     VLOG(0) << "Cannot switch to US keyboard layout - some keys may be "
         "interpreted incorrectly";
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 98b313e..19e49ab 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -8084,5 +8084,63 @@
         "prefs": { "policy.cct_tos_dialog_enabled": { "local_state": true } }
       }
     ]
+  },
+  "DefaultFileSystemReadGuardSetting": {
+    "os": ["win", "linux", "mac", "chromeos"],
+    "policy_pref_mapping_test": [
+      {
+        "policies": { "DefaultFileSystemReadGuardSetting": 2 },
+        "prefs": { "profile.managed_default_content_settings.file_system_read_guard": {} }
+      }
+    ]
+  },
+  "DefaultFileSystemWriteGuardSetting": {
+    "os": ["win", "linux", "mac", "chromeos"],
+    "policy_pref_mapping_test": [
+      {
+        "policies": { "DefaultFileSystemWriteGuardSetting": 2 },
+        "prefs": { "profile.managed_default_content_settings.file_system_write_guard": {} }
+      }
+    ]
+  },
+  "FileSystemReadAskForUrls": {
+    "os": ["win", "linux", "mac", "chromeos"],
+    "policy_pref_mapping_test": [
+      {
+        "policies": {"FileSystemReadAskForUrls": ["[*.].com"]},
+        "prefs": { "profile.managed_file_system_read_ask_for_urls": {}},
+        "note": "TODO(mek): Add indicator tests. TODO(bartfab): Flag this with can_be_recommended when http://crbug.com/106682 is fixed."
+      }
+    ]
+  },
+  "FileSystemReadBlockedForUrls": {
+    "os": ["win", "linux", "mac", "chromeos"],
+    "policy_pref_mapping_test": [
+      {
+        "policies": {"FileSystemReadBlockedForUrls": ["[*.]google.com"]},
+        "prefs": { "profile.managed_file_system_read_blocked_for_urls": {} },
+        "note": "TODO(mek): Add indicator tests. TODO(bartfab): Flag this with can_be_recommended when http://crbug.com/106682 is fixed."
+      }
+    ]
+  },
+  "FileSystemWriteAskForUrls": {
+    "os": ["win", "linux", "mac", "chromeos"],
+    "policy_pref_mapping_test": [
+      {
+        "policies": {"FileSystemWriteAskForUrls": ["[*.].com"]},
+        "prefs": { "profile.managed_file_system_write_ask_for_urls": {}},
+        "note": "TODO(mek): Add indicator tests. TODO(bartfab): Flag this with can_be_recommended when http://crbug.com/106682 is fixed."
+      }
+    ]
+  },
+  "FileSystemWriteBlockedForUrls": {
+    "os": ["win", "linux", "mac", "chromeos"],
+    "policy_pref_mapping_test": [
+      {
+        "policies": {"FileSystemWriteBlockedForUrls": ["[*.]google.com"]},
+        "prefs": { "profile.managed_file_system_write_blocked_for_urls": {} },
+        "note": "TODO(mek): Add indicator tests. TODO(bartfab): Flag this with can_be_recommended when http://crbug.com/106682 is fixed."
+      }
+    ]
   }
 }
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index c611c2e..a799b28 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -189,9 +189,6 @@
       "//skia",
     ]
     data = [
-      "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/cr_policy_network_behavior_mojo_tests.m.js",
-      "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/cr_policy_network_indicator_mojo_tests.m.js",
-      "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/network_config_element_behavior_test.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_components/managed_footnote_test.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_button_tests.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_container_shadow_behavior_test.m.js",
@@ -244,6 +241,11 @@
     ]
     if (is_chromeos) {
       data += [
+        "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/base_page_test.m.js",
+        "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/cr_policy_network_behavior_mojo_tests.m.js",
+        "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/cr_policy_network_indicator_mojo_tests.m.js",
+        "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/network_config_element_behavior_test.m.js",
+        "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/network_password_input_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_searchable_drop_down_tests.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/ambient_mode_page_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/bluetooth_page_tests.m.js",
diff --git a/chrome/test/data/webui/cr_components/chromeos/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/BUILD.gn
index 18b1686..c28ab4c2 100644
--- a/chrome/test/data/webui/cr_components/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/chromeos/BUILD.gn
@@ -6,8 +6,10 @@
 
 js_modulizer("modulize") {
   input_files = [
+    "base_page_test.js",
     "cr_policy_network_behavior_mojo_tests.js",
     "cr_policy_network_indicator_mojo_tests.js",
     "network_config_element_behavior_test.js",
+    "network_password_input_test.js",
   ]
 }
diff --git a/chrome/test/data/webui/cr_components/chromeos/base_page_test.js b/chrome/test/data/webui/cr_components/chromeos/base_page_test.js
new file mode 100644
index 0000000..997f03a
--- /dev/null
+++ b/chrome/test/data/webui/cr_components/chromeos/base_page_test.js
@@ -0,0 +1,24 @@
+// 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.
+
+// clang-format off
+// #import 'chrome://resources/cr_components/chromeos/cellular_setup/base_page.m.js';
+
+// #import {flush, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+// #import {assertFalse, assertTrue} from '../../chai_assert.js';
+// clang-format on
+
+suite('CrComponentsBasePageTest', function() {
+  let basePage;
+  setup(function() {
+    basePage = document.createElement('base-page');
+    document.body.appendChild(basePage);
+    Polymer.dom.flush();
+  });
+
+  test('Base test', function() {
+    const title = basePage.$$('#title');
+    assertTrue(!!title);
+  });
+});
diff --git a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js
index 9aa2998..06e5748 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js
@@ -41,7 +41,17 @@
   ['NetworkConfigElementBehavior', 'network_config_element_behavior_test.js',
     []
   ],
+  ['NetworkPasswordInput', 'network_password_input_test.js',
+    []
+  ],
 ].forEach(test => registerTest('Network', 'internet-config-dialog', ...test));
+
+[
+  ['BasePage', 'base_page_test.js',
+    []
+  ],
+].forEach(test => registerTest('CellularSetup', 'cellular-setup', ...test));
+
 // clang-format on
 
 function registerTest(componentName, webuiHost, testName, module, deps) {
diff --git a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
index 79db130..a17a30bc 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
@@ -7,11 +7,14 @@
 // Polymer BrowserTest fixture.
 GEN_INCLUDE(['//chrome/test/data/webui/polymer_browser_test_base.js']);
 GEN('#include "content/public/test/browser_test.h"');
+GEN('#include "chromeos/constants/chromeos_features.h"');
 
 // clang-format off
-[['CrPolicyNetworkBehaviorMojo', 'cr_policy_network_behavior_mojo_tests.m.js'],
+[['BasePage', 'base_page_test.m.js'],
+ ['CrPolicyNetworkBehaviorMojo', 'cr_policy_network_behavior_mojo_tests.m.js'],
  ['CrPolicyNetworkIndicatorMojo', 'cr_policy_network_indicator_mojo_tests.m.js'],
  ['NetworkConfigElementBehavior', 'network_config_element_behavior_test.m.js'],
+ ['NetworkPasswordInput', 'network_password_input_test.m.js'],
 ].forEach(test => registerTest('Network', ...test));
 // clang-format on
 
@@ -20,7 +23,9 @@
   this[className] = class extends PolymerTest {
     /** @override */
     get browsePreload() {
-      return `chrome://test?module=cr_components/chromeos/${module}`;
+      // TODO(jhawkins): Set up test_loader.html for internet-config-dialog
+      // and use it here instead of os-settings.
+      return `chrome://os-settings/test_loader.html?module=cr_components/chromeos/${module}`;
     }
 
     /** @override */
@@ -32,8 +37,12 @@
     }
 
     /** @override */
-    get webuiHost() {
-      return 'dummyurl';
+    get featureList() {
+      return {
+        enabled: [
+          'chromeos::features::kOsSettingsPolymer3',
+        ],
+      };
     }
   };
 
diff --git a/chrome/test/data/webui/cr_components/chromeos/network_password_input_test.js b/chrome/test/data/webui/cr_components/chromeos/network_password_input_test.js
new file mode 100644
index 0000000..40cadb3
--- /dev/null
+++ b/chrome/test/data/webui/cr_components/chromeos/network_password_input_test.js
@@ -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.
+
+// clang-format off
+// #import 'chrome://os-settings/strings.m.js';
+// #import 'chrome://resources/cr_components/chromeos/network/network_password_input.m.js';
+//
+// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+// clang-format on
+
+suite('CrComponentsNetworkPasswordInputTest', function() {
+  /** @type {!NetworkPasswordInput|undefined} */
+  let networkPassword;
+
+  setup(function() {
+    networkPassword = document.createElement('network-password-input');
+    document.body.appendChild(networkPassword);
+    Polymer.dom.flush();
+  });
+
+  test('Show password button', function() {
+    let passwordInput = networkPassword.$$('#input');
+    assertTrue(!!passwordInput);
+    assertFalse(networkPassword.showPassword);
+    assertEquals("password", passwordInput.type);
+
+    let showPassword = networkPassword.$$('#icon');
+    showPassword.click();
+
+    assertTrue(networkPassword.showPassword);
+    assertEquals("text", passwordInput.type);
+  });
+});
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index b3ec386..35f7362 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -222,10 +222,6 @@
 const base::Feature kFilesZipUnpack{"FilesZipUnpack",
                                     base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Controls gamepad vibration in Exo.
-const base::Feature kGamepadVibration{"ExoGamepadVibration",
-                                      base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Enables the use of Mojo by Chrome-process code to communicate with Power
 // Manager. In order to use mojo, this feature must be turned on and a callsite
 // must use PowerManagerMojoClient::Get().
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index 27b628d..a9fc225 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -109,8 +109,6 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kGaiaActionButtons;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
-extern const base::Feature kGamepadVibration;
-COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kGesturePropertiesDBusService;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kHelpAppFirstRun;
diff --git a/components/autofill/content/browser/content_autofill_driver.cc b/components/autofill/content/browser/content_autofill_driver.cc
index 1d0096b7..70df4c0 100644
--- a/components/autofill/content/browser/content_autofill_driver.cc
+++ b/components/autofill/content/browser/content_autofill_driver.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
 #include "components/autofill/core/browser/autofill_client.h"
@@ -365,9 +366,43 @@
   GetAutofillAgent()->SetQueryPasswordSuggestion(true);
 }
 
+bool ContentAutofillDriver::DocumentUsedWebOTP() const {
+  return render_frame_host_->DocumentUsedWebOTP();
+}
+
+void ContentAutofillDriver::MaybeReportAutofillWebOTPMetrics() {
+  // In tests, the autofill_manager_ may be unset or destroyed before |this|.
+  if (!autofill_manager_)
+    return;
+  // It's possible that a frame without any form uses WebOTP. e.g. a server may
+  // send the verification code to a phone number that was collected beforehand
+  // and uses the WebOTP API for authentication purpose without user manually
+  // entering the code.
+  if (!autofill_manager_->has_parsed_forms() && !DocumentUsedWebOTP())
+    return;
+
+  ReportAutofillWebOTPMetrics(DocumentUsedWebOTP());
+}
+
+void ContentAutofillDriver::ReportAutofillWebOTPMetrics(
+    bool document_used_webotp) {
+  if (autofill_manager_->has_observed_phone_number_field())
+    phone_collection_metric_state_ |= phone_collection_metric::kPhoneCollected;
+  if (autofill_manager_->has_observed_one_time_code_field())
+    phone_collection_metric_state_ |= phone_collection_metric::kOTCUsed;
+  if (document_used_webotp)
+    phone_collection_metric_state_ |= phone_collection_metric::kWebOTPUsed;
+
+  UMA_HISTOGRAM_ENUMERATION(
+      "Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+      static_cast<PhoneCollectionMetricState>(phone_collection_metric_state_));
+}
+
 void ContentAutofillDriver::SetAutofillProviderForTesting(
     AutofillProvider* provider) {
   SetAutofillProvider(provider);
+  // AutofillManager isn't used if provider is valid.
+  autofill_manager_ = nullptr;
 }
 
 }  // namespace autofill
diff --git a/components/autofill/content/browser/content_autofill_driver.h b/components/autofill/content/browser/content_autofill_driver.h
index f909255..63d1d442 100644
--- a/components/autofill/content/browser/content_autofill_driver.h
+++ b/components/autofill/content/browser/content_autofill_driver.h
@@ -33,6 +33,25 @@
 class AutofillProvider;
 class LogManager;
 
+// Use <Phone><WebOTP><OTC> as the bit pattern to identify the metrics state.
+enum class PhoneCollectionMetricState {
+  kNone = 0,    // Site did not collect phone, not use OTC, not use WebOTP
+  kOTC = 1,     // Site used OTC only
+  kWebOTP = 2,  // Site used WebOTP only
+  kWebOTPPlusOTC = 3,  // Site used WebOTP and OTC
+  kPhone = 4,          // Site collected phone, not used neither WebOTP nor OTC
+  kPhonePlusOTC = 5,   // Site collected phone number and used OTC
+  kPhonePlusWebOTP = 6,         // Site collected phone number and used WebOTP
+  kPhonePlusWebOTPPlusOTC = 7,  // Site collected phone number and used both
+  kMaxValue = kPhonePlusWebOTPPlusOTC,
+};
+
+namespace phone_collection_metric {
+constexpr uint32_t kOTCUsed = 1 << 0;
+constexpr uint32_t kWebOTPUsed = 1 << 1;
+constexpr uint32_t kPhoneCollected = 1 << 2;
+}  // namespace phone_collection_metric
+
 // Class that drives autofill flow in the browser process based on
 // communication from the renderer and from the external world. There is one
 // instance per RenderFrameHost.
@@ -138,6 +157,16 @@
   // to |autofill_external_delegate_|. Takes ownership of |manager|.
   void SetAutofillManager(std::unique_ptr<AutofillManager> manager);
 
+  // Reports whether a document collects phone numbers, uses one time code, uses
+  // WebOTP. There are cases that the reporting is not expected:
+  //   1. some unit tests do not set necessary members, |autofill_manager_|
+  //   2. there is no form and WebOTP is not used
+  // |MaybeReportAutofillWebOTPMetrics| is to exclude the cases above.
+  // |ReportAutofillWebOTPMetrics| is visible for unit tests where the
+  // |render_frame_host_| is not set.
+  void MaybeReportAutofillWebOTPMetrics();
+  void ReportAutofillWebOTPMetrics(bool document_used_webotp);
+
  protected:
   // Constructor for tests.
   ContentAutofillDriver();
@@ -151,6 +180,10 @@
 
   void SetAutofillProvider(AutofillProvider* provider);
 
+  // Returns whether navigator.credentials.get({otp: {transport:"sms"}}) has
+  // been used.
+  bool DocumentUsedWebOTP() const;
+
   // Weak ref to the RenderFrameHost the driver is associated with. Should
   // always be non-NULL and valid for lifetime of |this|.
   content::RenderFrameHost* const render_frame_host_;
@@ -178,6 +211,18 @@
   mojo::AssociatedReceiver<mojom::AutofillDriver> receiver_{this};
 
   mojo::AssociatedRemote<mojom::AutofillAgent> autofill_agent_;
+
+  // Helps with measuring whether phone number is collected and whether it is in
+  // conjunction with WebOTP or OneTimeCode (OTC).
+  // value="0" label="Phone Not Collected, WebOTP Not Used, OTC Not Used"
+  // value="1" label="Phone Not Collected, WebOTP Not Used, OTC Used"
+  // value="2" label="Phone Not Collected, WebOTP Used, OTC Not Used"
+  // value="3" label="Phone Not Collected, WebOTP Used, OTC Used"
+  // value="4" label="Phone Collected, WebOTP Not Used, OTC Not Used"
+  // value="5" label="Phone Collected, WebOTP Not Used, OTC Used"
+  // value="6" label="Phone Collected, WebOTP Used, OTC Not Used"
+  // value="7" label="Phone Collected, WebOTP Used, OTC Used"
+  uint32_t phone_collection_metric_state_ = 0;
 };
 
 }  // namespace autofill
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.cc b/components/autofill/content/browser/content_autofill_driver_factory.cc
index 2738209f..5fa9783 100644
--- a/components/autofill/content/browser/content_autofill_driver_factory.cc
+++ b/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -14,6 +14,7 @@
 #include "components/autofill/core/browser/autofill_manager.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 
 namespace autofill {
@@ -127,6 +128,11 @@
 
 void ContentAutofillDriverFactory::RenderFrameDeleted(
     content::RenderFrameHost* render_frame_host) {
+  AutofillDriver* driver = DriverForKey(render_frame_host);
+  if (driver) {
+    static_cast<ContentAutofillDriver*>(driver)
+        ->MaybeReportAutofillWebOTPMetrics();
+  }
   DeleteForKey(render_frame_host);
 }
 
@@ -147,4 +153,26 @@
     TabHidden();
 }
 
+void ContentAutofillDriverFactory::ReadyToCommitNavigation(
+    content::NavigationHandle* navigation_handle) {
+  content::RenderFrameHost* render_frame_host =
+      navigation_handle->GetRenderFrameHost();
+  content::GlobalFrameRoutingId render_frame_host_id(
+      render_frame_host->GetProcess()->GetID(),
+      render_frame_host->GetRoutingID());
+  // No need to report the metrics here if navigating to a different
+  // RenderFrameHost. It will be reported in |RenderFrameDeleted|.
+  // TODO(crbug.com/936696): Remove this logic when RenderDocument is enabled
+  // everywhere.
+  if (render_frame_host_id !=
+      navigation_handle->GetPreviousRenderFrameHostId()) {
+    return;
+  }
+  AutofillDriver* driver = DriverForFrame(render_frame_host);
+  if (!driver)
+    return;
+  static_cast<ContentAutofillDriver*>(driver)
+      ->MaybeReportAutofillWebOTPMetrics();
+}
+
 }  // namespace autofill
diff --git a/components/autofill/content/browser/content_autofill_driver_factory.h b/components/autofill/content/browser/content_autofill_driver_factory.h
index ddd66b7..23c877c 100644
--- a/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -67,6 +67,8 @@
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
   void OnVisibilityChanged(content::Visibility visibility) override;
+  void ReadyToCommitNavigation(
+      content::NavigationHandle* navigation_handle) override;
 
   static const char kContentAutofillDriverFactoryWebContentsUserDataKey[];
 
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index c8889cf..84e75e81 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -465,7 +465,7 @@
                       enable_download_manager) {}
 
 AutofillManager::~AutofillManager() {
-  if (frame_has_parsed_forms_) {
+  if (has_parsed_forms_) {
     base::UmaHistogramBoolean(
         "Autofill.WebOTP.PhoneNumberCollection.ParseResult",
         has_observed_phone_number_field_);
@@ -2040,7 +2040,7 @@
 void AutofillManager::OnFormsParsed(const std::vector<const FormData*>& forms,
                                     const base::TimeTicks timestamp) {
   DCHECK(!forms.empty());
-  frame_has_parsed_forms_ = true;
+  has_parsed_forms_ = true;
 
   // Record the current sync state to be used for metrics on this page.
   sync_state_ = personal_data_->GetSyncSigninState();
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index de418c6a..1d150a4 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -262,6 +262,15 @@
   // Returns the last form the autofill manager considered in this frame.
   virtual const FormData& last_query_form() const;
 
+  // Exposed to ContentAutofillDriver to help with recording WebOTP metrics.
+  bool has_parsed_forms() const { return has_parsed_forms_; }
+  bool has_observed_phone_number_field() const {
+    return has_observed_phone_number_field_;
+  }
+  bool has_observed_one_time_code_field() const {
+    return has_observed_one_time_code_field_;
+  }
+
 #if defined(UNIT_TEST)
   // A public wrapper that calls |DeterminePossibleFieldTypesForUpload| for
   // testing purposes only.
@@ -657,8 +666,8 @@
   // Has the user edited a field that was previously autofilled?
   bool user_did_edit_autofilled_field_ = false;
 
-  // Does the frame has any parsed forms?
-  bool frame_has_parsed_forms_ = false;
+  // Does |this| have any parsed forms?
+  bool has_parsed_forms_ = false;
   // Is there a field with autocomplete="one-time-code" observed?
   bool has_observed_one_time_code_field_ = false;
   // Is there a field with phone number collection observed?
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index f75f6d0c..9814ba8 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -296,6 +296,21 @@
   histogram_tester->ExpectBucketCount(histogram, metric, 1);
 }
 
+void CreateSimpleForm(const GURL& origin, FormData& form) {
+  form.unique_renderer_id = MakeFormRendererId();
+  form.name = ASCIIToUTF16("TestForm");
+  form.url = GURL("http://example.com/form.html");
+  form.action = GURL("http://example.com/submit.html");
+  form.main_frame_origin = url::Origin::Create(origin);
+}
+
+void AddAutoCompleteFieldToForm(const std::string& type, FormData& form) {
+  FormFieldData field;
+  test::CreateTestFormField("", "", "", "", &field);
+  field.autocomplete_attribute = type;
+  form.fields.push_back(field);
+}
+
 class MockAutofillClient : public TestAutofillClient {
  public:
   MockAutofillClient() {}
@@ -10538,20 +10553,10 @@
 // autocomplete attribute.
 TEST_F(AutofillMetricsTest, FrameHasPhoneNumberFieldWithAutocomplete) {
   FormData form;
-  form.unique_renderer_id = MakeFormRendererId();
-  form.name = ASCIIToUTF16("TestForm");
-  form.url = GURL("http://example.com/form.html");
-  form.action = GURL("http://example.com/submit.html");
-  form.main_frame_origin = url::Origin::Create(autofill_client_.form_origin());
-
-  FormFieldData field;
-
+  CreateSimpleForm(autofill_client_.form_origin(), form);
+  AddAutoCompleteFieldToForm("phone", form);
   std::vector<FormData> forms_with_phone_number(1, form);
 
-  test::CreateTestFormField("Phone", "phone", "", "tel", &field);
-  field.autocomplete_attribute = "phone";
-  forms_with_phone_number.back().fields.push_back(field);
-
   base::HistogramTester histogram_tester;
   autofill_manager_->OnFormsSeen(forms_with_phone_number, TimeTicks());
   autofill_manager_.reset();
@@ -10590,6 +10595,158 @@
       "Autofill.WebOTP.PhoneNumberCollection.ParseResult", 1);
 }
 
+// ContentAutofillDriver is not visible to TestAutofillDriver on iOS.
+// In addition, WebOTP will not ship on iOS.
+#if !defined(OS_IOS)
+// Verify that we correctly log PhoneCollectionMetricState::kNone.
+TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStateNone) {
+  FormData form;
+  CreateSimpleForm(autofill_client_.form_origin(), form);
+  AddAutoCompleteFieldToForm("password", form);
+
+  std::vector<FormData> forms(1, form);
+  base::HistogramTester histogram_tester;
+  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+  static_cast<ContentAutofillDriver*>(autofill_driver_.get())
+      ->ReportAutofillWebOTPMetrics(false);
+  histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                     PhoneCollectionMetricState::kNone, 1);
+  histogram_tester.ExpectTotalCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                    1);
+}
+
+// Verify that we correctly log PhoneCollectionMetricState::kOTC.
+TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStateOTC) {
+  FormData form;
+  CreateSimpleForm(autofill_client_.form_origin(), form);
+  AddAutoCompleteFieldToForm("one-time-code", form);
+
+  std::vector<FormData> forms(1, form);
+  base::HistogramTester histogram_tester;
+  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+  static_cast<ContentAutofillDriver*>(autofill_driver_.get())
+      ->ReportAutofillWebOTPMetrics(false);
+  histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                     PhoneCollectionMetricState::kOTC, 1);
+  histogram_tester.ExpectTotalCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                    1);
+}
+
+// Verify that we correctly log PhoneCollectionMetricState::kWebOTP.
+TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStateWebOTP) {
+  // If WebOTP is used, even if there is no form on the page we still need to
+  // report it.
+  base::HistogramTester histogram_tester;
+  autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+  static_cast<ContentAutofillDriver*>(autofill_driver_.get())
+      ->ReportAutofillWebOTPMetrics(true);
+  histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                     PhoneCollectionMetricState::kWebOTP, 1);
+  histogram_tester.ExpectTotalCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                    1);
+}
+
+// Verify that we correctly log PhoneCollectionMetricState::kWebOTPPlusOTC.
+TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStateWebOTPPlusOTC) {
+  FormData form;
+  CreateSimpleForm(autofill_client_.form_origin(), form);
+  AddAutoCompleteFieldToForm("one-time-code", form);
+
+  std::vector<FormData> forms(1, form);
+  base::HistogramTester histogram_tester;
+  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+  static_cast<ContentAutofillDriver*>(autofill_driver_.get())
+      ->ReportAutofillWebOTPMetrics(true);
+  histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                     PhoneCollectionMetricState::kWebOTPPlusOTC,
+                                     1);
+  histogram_tester.ExpectTotalCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                    1);
+}
+
+// Verify that we correctly log PhoneCollectionMetricState::kPhone.
+TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStatePhone) {
+  FormData form;
+  CreateSimpleForm(autofill_client_.form_origin(), form);
+  AddAutoCompleteFieldToForm("tel", form);
+
+  std::vector<FormData> forms(1, form);
+  base::HistogramTester histogram_tester;
+  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+  static_cast<ContentAutofillDriver*>(autofill_driver_.get())
+      ->ReportAutofillWebOTPMetrics(false);
+  histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                     PhoneCollectionMetricState::kPhone, 1);
+  histogram_tester.ExpectTotalCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                    1);
+}
+
+// Verify that we correctly log PhoneCollectionMetricState::kPhonePlusOTC.
+TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStatePhonePlusOTC) {
+  FormData form;
+  CreateSimpleForm(autofill_client_.form_origin(), form);
+  AddAutoCompleteFieldToForm("tel", form);
+  AddAutoCompleteFieldToForm("one-time-code", form);
+
+  std::vector<FormData> forms(1, form);
+  base::HistogramTester histogram_tester;
+  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+  static_cast<ContentAutofillDriver*>(autofill_driver_.get())
+      ->ReportAutofillWebOTPMetrics(false);
+  histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                     PhoneCollectionMetricState::kPhonePlusOTC,
+                                     1);
+  histogram_tester.ExpectTotalCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                    1);
+}
+
+// Verify that we correctly log PhoneCollectionMetricState::kPhonePlusWebOTP.
+TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStatePhonePlusWebOTP) {
+  FormData form;
+  CreateSimpleForm(autofill_client_.form_origin(), form);
+  AddAutoCompleteFieldToForm("tel", form);
+
+  std::vector<FormData> forms(1, form);
+  base::HistogramTester histogram_tester;
+  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+  static_cast<ContentAutofillDriver*>(autofill_driver_.get())
+      ->ReportAutofillWebOTPMetrics(true);
+  histogram_tester.ExpectBucketCount(
+      "Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+      PhoneCollectionMetricState::kPhonePlusWebOTP, 1);
+  histogram_tester.ExpectTotalCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                    1);
+}
+
+// Verify that we correctly log
+// PhoneCollectionMetricState::kPhonePlusWebOTPPlusOTC.
+TEST_F(AutofillMetricsTest,
+       WebOTPPhoneCollectionMetricsStatePhonePlusWebOTPPlusOTC) {
+  FormData form;
+  CreateSimpleForm(autofill_client_.form_origin(), form);
+  AddAutoCompleteFieldToForm("tel", form);
+  AddAutoCompleteFieldToForm("one-time-code", form);
+
+  std::vector<FormData> forms(1, form);
+  base::HistogramTester histogram_tester;
+  autofill_manager_->OnFormsSeen(forms, TimeTicks());
+  autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+  static_cast<ContentAutofillDriver*>(autofill_driver_.get())
+      ->ReportAutofillWebOTPMetrics(true);
+  histogram_tester.ExpectBucketCount(
+      "Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+      PhoneCollectionMetricState::kPhonePlusWebOTPPlusOTC, 1);
+  histogram_tester.ExpectTotalCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
+                                    1);
+}
+#endif  // !defined(OS_IOS)
+
 TEST_F(AutofillMetricsTest, LogAutocompleteSuggestionAcceptedIndex_WithIndex) {
   base::HistogramTester histogram_tester;
   const int test_index = 3;
diff --git a/components/content_settings/core/browser/content_settings_policy_provider.cc b/components/content_settings/core/browser/content_settings_policy_provider.cc
index 600ce70..9792e532 100644
--- a/components/content_settings/core/browser/content_settings_policy_provider.cc
+++ b/components/content_settings/core/browser/content_settings_policy_provider.cc
@@ -75,6 +75,14 @@
          CONTENT_SETTING_ASK},
         {prefs::kManagedWebUsbBlockedForUrls, ContentSettingsType::USB_GUARD,
          CONTENT_SETTING_BLOCK},
+        {prefs::kManagedFileSystemReadAskForUrls,
+         ContentSettingsType::FILE_SYSTEM_READ_GUARD, CONTENT_SETTING_ASK},
+        {prefs::kManagedFileSystemReadBlockedForUrls,
+         ContentSettingsType::FILE_SYSTEM_READ_GUARD, CONTENT_SETTING_BLOCK},
+        {prefs::kManagedFileSystemWriteAskForUrls,
+         ContentSettingsType::FILE_SYSTEM_WRITE_GUARD, CONTENT_SETTING_ASK},
+        {prefs::kManagedFileSystemWriteBlockedForUrls,
+         ContentSettingsType::FILE_SYSTEM_WRITE_GUARD, CONTENT_SETTING_BLOCK},
         {prefs::kManagedLegacyCookieAccessAllowedForDomains,
          ContentSettingsType::LEGACY_COOKIE_ACCESS, CONTENT_SETTING_ALLOW},
         {prefs::kManagedSerialAskForUrls, ContentSettingsType::SERIAL_GUARD,
@@ -145,6 +153,10 @@
          prefs::kManagedDefaultWebBluetoothGuardSetting},
         {ContentSettingsType::USB_GUARD,
          prefs::kManagedDefaultWebUsbGuardSetting},
+        {ContentSettingsType::FILE_SYSTEM_READ_GUARD,
+         prefs::kManagedDefaultFileSystemReadGuardSetting},
+        {ContentSettingsType::FILE_SYSTEM_WRITE_GUARD,
+         prefs::kManagedDefaultFileSystemWriteGuardSetting},
         {ContentSettingsType::LEGACY_COOKIE_ACCESS,
          prefs::kManagedDefaultLegacyCookieAccessSetting},
         {ContentSettingsType::SERIAL_GUARD,
@@ -176,6 +188,10 @@
   registry->RegisterListPref(prefs::kManagedWebUsbAllowDevicesForUrls);
   registry->RegisterListPref(prefs::kManagedWebUsbAskForUrls);
   registry->RegisterListPref(prefs::kManagedWebUsbBlockedForUrls);
+  registry->RegisterListPref(prefs::kManagedFileSystemReadAskForUrls);
+  registry->RegisterListPref(prefs::kManagedFileSystemReadBlockedForUrls);
+  registry->RegisterListPref(prefs::kManagedFileSystemWriteAskForUrls);
+  registry->RegisterListPref(prefs::kManagedFileSystemWriteBlockedForUrls);
   registry->RegisterListPref(
       prefs::kManagedLegacyCookieAccessAllowedForDomains);
   registry->RegisterListPref(prefs::kManagedSerialAskForUrls);
@@ -211,6 +227,12 @@
                                 CONTENT_SETTING_DEFAULT);
   registry->RegisterIntegerPref(prefs::kManagedDefaultWebUsbGuardSetting,
                                 CONTENT_SETTING_DEFAULT);
+  registry->RegisterIntegerPref(
+      prefs::kManagedDefaultFileSystemReadGuardSetting,
+      CONTENT_SETTING_DEFAULT);
+  registry->RegisterIntegerPref(
+      prefs::kManagedDefaultFileSystemWriteGuardSetting,
+      CONTENT_SETTING_DEFAULT);
   registry->RegisterIntegerPref(prefs::kManagedDefaultLegacyCookieAccessSetting,
                                 CONTENT_SETTING_DEFAULT);
   registry->RegisterIntegerPref(prefs::kManagedDefaultSerialGuardSetting,
@@ -253,6 +275,13 @@
   pref_change_registrar_.Add(prefs::kManagedPopupsBlockedForUrls, callback);
   pref_change_registrar_.Add(prefs::kManagedWebUsbAskForUrls, callback);
   pref_change_registrar_.Add(prefs::kManagedWebUsbBlockedForUrls, callback);
+  pref_change_registrar_.Add(prefs::kManagedFileSystemReadAskForUrls, callback);
+  pref_change_registrar_.Add(prefs::kManagedFileSystemReadBlockedForUrls,
+                             callback);
+  pref_change_registrar_.Add(prefs::kManagedFileSystemWriteAskForUrls,
+                             callback);
+  pref_change_registrar_.Add(prefs::kManagedFileSystemWriteBlockedForUrls,
+                             callback);
   pref_change_registrar_.Add(prefs::kManagedLegacyCookieAccessAllowedForDomains,
                              callback);
   pref_change_registrar_.Add(prefs::kManagedSerialAskForUrls, callback);
@@ -287,6 +316,10 @@
                              callback);
   pref_change_registrar_.Add(prefs::kManagedDefaultWebUsbGuardSetting,
                              callback);
+  pref_change_registrar_.Add(prefs::kManagedDefaultFileSystemReadGuardSetting,
+                             callback);
+  pref_change_registrar_.Add(prefs::kManagedDefaultFileSystemWriteGuardSetting,
+                             callback);
   pref_change_registrar_.Add(prefs::kManagedDefaultLegacyCookieAccessSetting,
                              callback);
   pref_change_registrar_.Add(prefs::kManagedDefaultSerialGuardSetting,
@@ -580,6 +613,10 @@
       name == prefs::kManagedCookiesAllowedForUrls ||
       name == prefs::kManagedCookiesBlockedForUrls ||
       name == prefs::kManagedCookiesSessionOnlyForUrls ||
+      name == prefs::kManagedFileSystemReadAskForUrls ||
+      name == prefs::kManagedFileSystemReadBlockedForUrls ||
+      name == prefs::kManagedFileSystemWriteAskForUrls ||
+      name == prefs::kManagedFileSystemWriteBlockedForUrls ||
       name == prefs::kManagedImagesAllowedForUrls ||
       name == prefs::kManagedImagesBlockedForUrls ||
       name == prefs::kManagedInsecureContentAllowedForUrls ||
diff --git a/components/content_settings/core/common/pref_names.cc b/components/content_settings/core/common/pref_names.cc
index f5922009b9..1bd17d8 100644
--- a/components/content_settings/core/common/pref_names.cc
+++ b/components/content_settings/core/common/pref_names.cc
@@ -51,6 +51,10 @@
     "profile.managed_default_content_settings.web_bluetooth_guard";
 const char kManagedDefaultWebUsbGuardSetting[] =
     "profile.managed_default_content_settings.web_usb_guard";
+const char kManagedDefaultFileSystemReadGuardSetting[] =
+    "profile.managed_default_content_settings.file_system_read_guard";
+const char kManagedDefaultFileSystemWriteGuardSetting[] =
+    "profile.managed_default_content_settings.file_system_write_guard";
 const char kManagedDefaultLegacyCookieAccessSetting[] =
     "profile.managed_default_content_settings.legacy_cookie_access";
 const char kManagedDefaultSerialGuardSetting[] =
@@ -101,6 +105,14 @@
 const char kManagedWebUsbAskForUrls[] = "profile.managed_web_usb_ask_for_urls";
 const char kManagedWebUsbBlockedForUrls[] =
     "profile.managed_web_usb_blocked_for_urls";
+const char kManagedFileSystemReadAskForUrls[] =
+    "profile.managed_file_system_read_ask_for_urls";
+const char kManagedFileSystemReadBlockedForUrls[] =
+    "profile.managed_file_system_read_blocked_for_urls";
+const char kManagedFileSystemWriteAskForUrls[] =
+    "profile.managed_file_system_write_ask_for_urls";
+const char kManagedFileSystemWriteBlockedForUrls[] =
+    "profile.managed_file_system_write_blocked_for_urls";
 const char kManagedLegacyCookieAccessAllowedForDomains[] =
     "profile.managed_legacy_cookie_access_allowed_for_domains";
 const char kManagedSerialAskForUrls[] = "profile.managed_serial_ask_for_urls";
diff --git a/components/content_settings/core/common/pref_names.h b/components/content_settings/core/common/pref_names.h
index 82a0049..746509c 100644
--- a/components/content_settings/core/common/pref_names.h
+++ b/components/content_settings/core/common/pref_names.h
@@ -34,6 +34,8 @@
 extern const char kManagedDefaultSensorsSetting[];
 extern const char kManagedDefaultWebBluetoothGuardSetting[];
 extern const char kManagedDefaultWebUsbGuardSetting[];
+extern const char kManagedDefaultFileSystemReadGuardSetting[];
+extern const char kManagedDefaultFileSystemWriteGuardSetting[];
 extern const char kManagedDefaultLegacyCookieAccessSetting[];
 extern const char kManagedDefaultSerialGuardSetting[];
 extern const char kManagedDefaultInsecurePrivateNetworkSetting[];
@@ -59,6 +61,10 @@
 extern const char kManagedWebUsbAllowDevicesForUrls[];
 extern const char kManagedWebUsbAskForUrls[];
 extern const char kManagedWebUsbBlockedForUrls[];
+extern const char kManagedFileSystemReadAskForUrls[];
+extern const char kManagedFileSystemReadBlockedForUrls[];
+extern const char kManagedFileSystemWriteAskForUrls[];
+extern const char kManagedFileSystemWriteBlockedForUrls[];
 extern const char kManagedLegacyCookieAccessAllowedForDomains[];
 extern const char kManagedSerialAskForUrls[];
 extern const char kManagedSerialBlockedForUrls[];
diff --git a/components/data_reduction_proxy/OWNERS b/components/data_reduction_proxy/OWNERS
index b684162..ce288ae1 100644
--- a/components/data_reduction_proxy/OWNERS
+++ b/components/data_reduction_proxy/OWNERS
@@ -8,10 +8,6 @@
 sclittle@chromium.org
 sophiechang@chromium.org
 
-# Secondary
-bengr@chromium.org
-dougarnett@chromium.org
-
 per-file *_messages.cc=set noparent
 per-file *_messages.cc=file://ipc/SECURITY_OWNERS
 
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index 8304eacd..5799987 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -121,9 +121,6 @@
       "client_controlled_accelerators.h",
       "client_controlled_shell_surface.cc",
       "client_controlled_shell_surface.h",
-      "gamepad.cc",
-      "gamepad.h",
-      "gamepad_observer.h",
       "gaming_seat.cc",
       "gaming_seat.h",
       "input_method_surface.cc",
@@ -253,7 +250,6 @@
       "data_source_unittest.cc",
       "display_unittest.cc",
       "drag_drop_operation_unittest.cc",
-      "gamepad_unittest.cc",
       "gaming_seat_unittest.cc",
       "input_method_surface_unittest.cc",
       "keyboard_unittest.cc",
diff --git a/components/exo/gamepad.cc b/components/exo/gamepad.cc
deleted file mode 100644
index d360518..0000000
--- a/components/exo/gamepad.cc
+++ /dev/null
@@ -1,158 +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 "components/exo/gamepad.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "chromeos/constants/chromeos_features.h"
-
-namespace exo {
-
-Gamepad::Gamepad(const ui::GamepadDevice& gamepad_device)
-    : device(gamepad_device),
-      input_controller_(
-          ui::OzonePlatform::GetInstance()->GetInputController()) {}
-
-Gamepad::~Gamepad() {
-  for (GamepadObserver& observer : observer_list_)
-    observer.OnGamepadDestroying(this);
-
-  if (delegate_)
-    delegate_->OnRemoved();
-}
-
-void Gamepad::Vibrate(const std::vector<int64_t>& duration_millis,
-                      const std::vector<uint8_t>& amplitudes,
-                      int32_t repeat) {
-  if (!device.supports_vibration_rumble) {
-    VLOG(2) << "Vibrate failed because gamepad does not support vibration.";
-    return;
-  }
-
-  if (duration_millis.size() != amplitudes.size()) {
-    VLOG(2) << "Vibrate failed because the amplitudes vector and "
-               "duration_millis vector are not the same size.";
-    return;
-  }
-
-  vibration_timer_.Stop();
-  vibration_timer_.Start(
-      FROM_HERE, base::TimeDelta::FromMilliseconds(0),
-      base::BindOnce(&Gamepad::HandleVibrate, base::Unretained(this),
-                     duration_millis, amplitudes, repeat, /*index=*/0,
-                     /*duration_already_vibrated=*/0));
-}
-
-void Gamepad::HandleVibrate(const std::vector<int64_t>& duration_millis,
-                            const std::vector<uint8_t>& amplitudes,
-                            int32_t repeat,
-                            size_t index,
-                            int64_t duration_already_vibrated) {
-  size_t vector_size = duration_millis.size();
-  if (index >= vector_size)
-    return;
-
-  if (!can_vibrate_) {
-    VLOG(2) << "Gamepad is not allowed to vibrate because it is not in focus.";
-    return;
-  }
-
-  int64_t duration_left_to_vibrate =
-      duration_millis[index] - duration_already_vibrated;
-
-  if (duration_left_to_vibrate > kMaxDurationMillis) {
-    //  The device does not support effects this long. Issue periodic vibration
-    //  commands until the effect is complete.
-    SendVibrate(amplitudes[index], kMaxDurationMillis);
-    vibration_timer_.Start(
-        FROM_HERE, base::TimeDelta::FromMilliseconds(kMaxDurationMillis),
-        base::BindOnce(&Gamepad::HandleVibrate, base::Unretained(this),
-                       duration_millis, amplitudes, repeat, index,
-                       /*duration_already_vibrated=*/duration_already_vibrated +
-                           kMaxDurationMillis));
-  } else {
-    SendVibrate(amplitudes[index], duration_left_to_vibrate);
-    index++;
-    bool needs_to_repeat = index >= vector_size && repeat >= 0 &&
-                           repeat < static_cast<int32_t>(vector_size);
-    if (needs_to_repeat)
-      index = repeat;
-
-    vibration_timer_.Start(
-        FROM_HERE, base::TimeDelta::FromMilliseconds(duration_left_to_vibrate),
-        base::BindOnce(&Gamepad::HandleVibrate, base::Unretained(this),
-                       duration_millis, amplitudes, repeat, index,
-                       /*duration_already_vibrated=*/0));
-  }
-}
-
-void Gamepad::SendVibrate(uint8_t amplitude, int64_t duration_millis) {
-  // |duration_millis| is always <= |kMaxDurationMillis|, which is the max value
-  // for uint16_t, so it is safe to cast it to uint16_t here.
-  input_controller_->PlayVibrationEffect(
-      device.id, amplitude, static_cast<uint16_t>(duration_millis));
-}
-
-void Gamepad::CancelVibration() {
-  if (!device.supports_vibration_rumble) {
-    VLOG(2)
-        << "CancelVibration failed because gamepad does not support vibration.";
-    return;
-  }
-
-  if (!vibration_timer_.IsRunning())
-    return;
-
-  vibration_timer_.Stop();
-  SendCancelVibration();
-}
-
-void Gamepad::SendCancelVibration() {
-  input_controller_->StopVibration(device.id);
-}
-
-void Gamepad::SetDelegate(std::unique_ptr<GamepadDelegate> delegate) {
-  DCHECK(!delegate_);
-  delegate_ = std::move(delegate);
-}
-
-void Gamepad::AddObserver(GamepadObserver* observer) {
-  observer_list_.AddObserver(observer);
-}
-
-bool Gamepad::HasObserver(GamepadObserver* observer) const {
-  return observer_list_.HasObserver(observer);
-}
-
-void Gamepad::RemoveObserver(GamepadObserver* observer) {
-  observer_list_.RemoveObserver(observer);
-}
-
-void Gamepad::OnGamepadFocused() {
-  can_vibrate_ =
-      base::FeatureList::IsEnabled(chromeos::features::kGamepadVibration);
-}
-
-void Gamepad::OnGamepadFocusLost() {
-  can_vibrate_ = false;
-  CancelVibration();
-}
-
-void Gamepad::OnGamepadEvent(const ui::GamepadEvent& event) {
-  DCHECK(delegate_);
-  switch (event.type()) {
-    case ui::GamepadEventType::BUTTON:
-      delegate_->OnButton(event.code(), event.value(), event.timestamp());
-      break;
-    case ui::GamepadEventType::AXIS:
-      delegate_->OnAxis(event.code(), event.value(), event.timestamp());
-      break;
-    case ui::GamepadEventType::FRAME:
-      delegate_->OnFrame(event.timestamp());
-      break;
-  }
-}
-
-}  // namespace exo
diff --git a/components/exo/gamepad.h b/components/exo/gamepad.h
deleted file mode 100644
index 6bf7d5ff..0000000
--- a/components/exo/gamepad.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_EXO_GAMEPAD_H_
-#define COMPONENTS_EXO_GAMEPAD_H_
-
-#include <vector>
-
-#include "base/observer_list.h"
-#include "base/timer/timer.h"
-#include "components/exo/gamepad_delegate.h"
-#include "components/exo/gamepad_observer.h"
-#include "ui/events/devices/gamepad_device.h"
-#include "ui/events/ozone/gamepad/gamepad_event.h"
-#include "ui/ozone/public/input_controller.h"
-#include "ui/ozone/public/ozone_platform.h"
-
-namespace exo {
-
-// Maximum force feedback duration supported by Linux.
-constexpr int64_t kMaxDurationMillis = 0xFFFF;
-
-// This class represents one gamepad. It allows control over the gamepad's
-// vibration and provides focus tracking for the gamepad.
-class Gamepad {
- public:
-  explicit Gamepad(const ui::GamepadDevice& gamepad_device);
-  Gamepad(const Gamepad& other) = delete;
-  Gamepad& operator=(const Gamepad& other) = delete;
-
-  // The destructor also informs GamepadObservers and GamepadDelegate when a
-  // gamepad has been disconnected.
-  virtual ~Gamepad();
-
-  // Controls vibration effects on the gamepad.
-  // The duration_millis/amplitude pairs determine the duration and strength of
-  // the vibration. Note that the two vectors have to be the same size.
-  // The repeat value determines the index of the duration_millis (or
-  // amplitudes) vector at which the pattern to repeat begins. If repeat is
-  // enabled, the vibration pattern will repeat indefinitely until the vibration
-  // event is canceled. A repeat value of -1 disables repeat.
-  // The user does not have to explicitly call CancelVibration() at the end of
-  // every vibration call. However, if Vibrate() is called when there is an
-  // ongoing vibration, the existing vibration is automatically interrupted and
-  // canceled. The gamepad has to be focused in order for the gamepad to
-  // vibrate. If focus is lost when there is an ongoing vibration, the vibration
-  // is canceled automatically.
-  void Vibrate(const std::vector<int64_t>& duration_millis,
-               const std::vector<uint8_t>& amplitudes,
-               int32_t repeat);
-  void CancelVibration();
-
-  // The GamepadDelegate is not owned by Gamepad. The delegate must stay alive
-  // until OnRemoved is called.
-  void SetDelegate(std::unique_ptr<GamepadDelegate> delegate);
-
-  // Manages the GamepadObserver list. GamepadObservers are notified when the
-  // gamepad is being destroyed.
-  void AddObserver(GamepadObserver* observer);
-  bool HasObserver(GamepadObserver* observer) const;
-  void RemoveObserver(GamepadObserver* observer);
-
-  // Informs the gamepad when window focus changes; focus changes determine
-  // whether a gamepad is allowed to vibrate at any given time.
-  void OnGamepadFocused();
-  void OnGamepadFocusLost();
-
-  // Forwards gamepad events to the corresponding GamepadDelegate calls.
-  void OnGamepadEvent(const ui::GamepadEvent& event);
-
-  const ui::GamepadDevice device;
-
- private:
-  // Private method for handling vibration patterns. Handles repeat and
-  // breaking down of vibration events by iterating through duration/amplitude
-  // vectors. Also provides handling for a vibration event that exceeds the
-  // maximum force feedback duration supported by Linux.
-  void HandleVibrate(const std::vector<int64_t>& duration_millis,
-                     const std::vector<uint8_t>& amplitudes,
-                     int32_t repeat,
-                     size_t start_index,
-                     int64_t duration_already_vibrated);
-
-  // These methods forward vibration calls to |input_controller_|.
-  // They are virtual for testing purposes.
-  virtual void SendVibrate(uint8_t amplitude, int64_t duration_millis);
-  virtual void SendCancelVibration();
-
-  // Keeps track of whether the gamepad is allowed to vibrate at any given
-  // time.
-  bool can_vibrate_ = false;
-
-  std::unique_ptr<GamepadDelegate> delegate_;
-
-  base::ObserverList<GamepadObserver>::Unchecked observer_list_;
-
-  // Methods to control gamepad vibration are routed through InputController.
-  ui::InputController* input_controller_;
-
-  // A timer to keep track of vibration requests.
-  base::OneShotTimer vibration_timer_;
-};
-
-}  // namespace exo
-
-#endif  // COMPONENTS_EXO_GAMEPAD_H_
diff --git a/components/exo/gamepad_delegate.h b/components/exo/gamepad_delegate.h
index ea97624c..bb698612 100644
--- a/components/exo/gamepad_delegate.h
+++ b/components/exo/gamepad_delegate.h
@@ -12,7 +12,6 @@
 // Handles events for a specific gamepad.
 class GamepadDelegate {
  public:
-  virtual ~GamepadDelegate() {}
   // Called when the gamepad has been removed.
   virtual void OnRemoved() = 0;
 
@@ -27,6 +26,9 @@
   // Called after all gamepad information of this frame has been set and the
   // client should evaluate the updated state.
   virtual void OnFrame(base::TimeTicks timestamp) = 0;
+
+ protected:
+  virtual ~GamepadDelegate() {}
 };
 
 }  // namespace exo
diff --git a/components/exo/gamepad_observer.h b/components/exo/gamepad_observer.h
deleted file mode 100644
index f864b99a..0000000
--- a/components/exo/gamepad_observer.h
+++ /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.
-
-#ifndef COMPONENTS_EXO_GAMEPAD_OBSERVER_H_
-#define COMPONENTS_EXO_GAMEPAD_OBSERVER_H_
-
-namespace exo {
-
-class Gamepad;
-
-// Observers to the gamepad are notified when the gamepad destructs.
-class GamepadObserver {
- public:
-  virtual ~GamepadObserver() = default;
-
-  // Called at the top of the gamepad's destructor, to give observers a change
-  // to remove themselves.
-  virtual void OnGamepadDestroying(Gamepad* gamepad) = 0;
-};
-
-}  // namespace exo
-
-#endif  // COMPONENTS_EXO_GAMEPAD_OBSERVER_H_
diff --git a/components/exo/gamepad_unittest.cc b/components/exo/gamepad_unittest.cc
deleted file mode 100644
index e570306..0000000
--- a/components/exo/gamepad_unittest.cc
+++ /dev/null
@@ -1,328 +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 "components/exo/gamepad.h"
-
-#include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
-#include "chromeos/constants/chromeos_features.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace exo {
-
-namespace {
-
-constexpr int64_t kDurationMillis = 0x8000;
-constexpr base::TimeDelta kPendingTaskDuration =
-    base::TimeDelta::FromMillisecondsD(kDurationMillis);
-constexpr base::TimeDelta kPendingMaxTaskDuration =
-    base::TimeDelta::FromMillisecondsD(kMaxDurationMillis);
-constexpr uint8_t kAmplitude = 128;
-
-class TestGamepad : public Gamepad {
- public:
-  TestGamepad(const ui::GamepadDevice& device)
-      : Gamepad(device),
-        send_vibrate_count_(0),
-        send_cancel_vibration_count_(0) {}
-
-  TestGamepad(const TestGamepad&) = delete;
-  TestGamepad& operator=(const TestGamepad& other) = delete;
-
-  void SendVibrate(uint8_t amplitude, int64_t duration_millis) override {
-    send_vibrate_count_++;
-    last_vibrate_amplitude_ = amplitude;
-    last_vibrate_duration_ = duration_millis;
-  }
-
-  void SendCancelVibration() override { send_cancel_vibration_count_++; }
-
-  uint8_t last_vibrate_amplitude_;
-  int64_t last_vibrate_duration_;
-  int send_vibrate_count_;
-  int send_cancel_vibration_count_;
-};
-
-class MockGamepadObserver : public GamepadObserver {
- public:
-  MockGamepadObserver() {}
-  // Overridden from GamepadObserver:
-  MOCK_METHOD(void, OnGamepadDestroying, (Gamepad * gamepad), (override));
-};
-
-class MockGamepadDelegate : public GamepadDelegate {
- public:
-  MockGamepadDelegate() {}
-
-  // Overridden from GamepadDelegate:
-  MOCK_METHOD(void, OnRemoved, (), (override));
-  MOCK_METHOD(void,
-              OnAxis,
-              (int axis, double value, base::TimeTicks timestamp),
-              (override));
-  MOCK_METHOD(void,
-              OnButton,
-              (int button, bool pressed, base::TimeTicks timestamp),
-              (override));
-  MOCK_METHOD(void, OnFrame, (base::TimeTicks timestamp), (override));
-};
-
-class GamepadTest : public testing::Test {
- public:
-  GamepadTest() {
-    ui::GamepadDevice device(
-        ui::InputDevice(0, ui::InputDeviceType::INPUT_DEVICE_USB, "gamepad"),
-        std::vector<ui::GamepadDevice::Axis>(), true);
-    gamepad_ = std::make_unique<TestGamepad>(device);
-  }
-
-  void SetUp() override {
-    testing::Test::SetUp();
-    // Allow test to signal to gamepad that it can vibrate.
-    scoped_feature_list_.InitAndEnableFeature(
-        chromeos::features::kGamepadVibration);
-    gamepad_->OnGamepadFocused();
-  }
-
-  std::unique_ptr<TestGamepad> gamepad_;
-  base::test::TaskEnvironment task_environment_{
-      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
-  base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(GamepadTest);
-};
-
-TEST_F(GamepadTest, OneShotVibrationTest) {
-  EXPECT_EQ(0, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(0, gamepad_->send_cancel_vibration_count_);
-
-  gamepad_->Vibrate({kDurationMillis}, {kAmplitude}, -1);
-  task_environment_.FastForwardBy(
-      base::TimeDelta::FromMillisecondsD(kDurationMillis / 2));
-  EXPECT_EQ(1, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kDurationMillis, gamepad_->last_vibrate_duration_);
-
-  // Cancel vibration when it's halfway through.
-  gamepad_->CancelVibration();
-  EXPECT_EQ(1, gamepad_->send_cancel_vibration_count_);
-}
-
-TEST_F(GamepadTest, OneShotVibrationTooLongTest) {
-  EXPECT_EQ(0, gamepad_->send_vibrate_count_);
-
-  gamepad_->Vibrate({kMaxDurationMillis * 3}, {kAmplitude}, -1);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kMaxDurationMillis, gamepad_->last_vibrate_duration_);
-
-  EXPECT_TRUE(task_environment_.NextTaskIsDelayed());
-  task_environment_.FastForwardBy(kPendingMaxTaskDuration);
-  EXPECT_EQ(2, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kMaxDurationMillis, gamepad_->last_vibrate_duration_);
-
-  EXPECT_TRUE(task_environment_.NextTaskIsDelayed());
-  task_environment_.FastForwardBy(kPendingMaxTaskDuration);
-  EXPECT_EQ(3, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kMaxDurationMillis, gamepad_->last_vibrate_duration_);
-
-  // Complete the last vibration and make sure no more vibration is scheduled.
-  task_environment_.FastForwardBy(kPendingMaxTaskDuration);
-  EXPECT_FALSE(task_environment_.NextTaskIsDelayed());
-}
-
-TEST_F(GamepadTest, WaveformVibrationTest) {
-  EXPECT_EQ(0, gamepad_->send_vibrate_count_);
-
-  gamepad_->Vibrate({kDurationMillis, kDurationMillis}, {kAmplitude, 0}, -1);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kDurationMillis, gamepad_->last_vibrate_duration_);
-
-  EXPECT_TRUE(task_environment_.NextTaskIsDelayed());
-  task_environment_.FastForwardBy(kPendingTaskDuration);
-  EXPECT_EQ(2, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(0, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kDurationMillis, gamepad_->last_vibrate_duration_);
-
-  // Complete the last vibration and make sure no more vibration is scheduled.
-  task_environment_.FastForwardBy(kPendingTaskDuration);
-  EXPECT_FALSE(task_environment_.NextTaskIsDelayed());
-}
-
-TEST_F(GamepadTest, VibrationWithRepeatTest) {
-  EXPECT_EQ(0, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(0, gamepad_->send_cancel_vibration_count_);
-
-  gamepad_->Vibrate({kMaxDurationMillis, kDurationMillis}, {kAmplitude, 0}, 0);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kMaxDurationMillis, gamepad_->last_vibrate_duration_);
-
-  EXPECT_TRUE(task_environment_.NextTaskIsDelayed());
-  task_environment_.FastForwardBy(kPendingMaxTaskDuration);
-  EXPECT_EQ(2, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(0, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kDurationMillis, gamepad_->last_vibrate_duration_);
-
-  EXPECT_TRUE(task_environment_.NextTaskIsDelayed());
-  task_environment_.FastForwardBy(kPendingTaskDuration);
-  EXPECT_EQ(3, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kMaxDurationMillis, gamepad_->last_vibrate_duration_);
-
-  EXPECT_TRUE(task_environment_.NextTaskIsDelayed());
-  task_environment_.FastForwardBy(kPendingTaskDuration);
-  gamepad_->CancelVibration();
-
-  EXPECT_EQ(1, gamepad_->send_cancel_vibration_count_);
-  EXPECT_EQ(3, gamepad_->send_vibrate_count_);
-}
-
-TEST_F(GamepadTest, OverrideVibrationTest) {
-  EXPECT_EQ(0, gamepad_->send_vibrate_count_);
-
-  gamepad_->Vibrate({kDurationMillis, kDurationMillis}, {kAmplitude, 0}, -1);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kDurationMillis, gamepad_->last_vibrate_duration_);
-
-  EXPECT_TRUE(task_environment_.NextTaskIsDelayed());
-  task_environment_.FastForwardBy(kPendingTaskDuration / 2);
-
-  // At this point, we're halfway through the first OneShot vibration in the
-  // duration vector.
-  gamepad_->Vibrate({kMaxDurationMillis}, {kAmplitude / 2}, -1);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(2, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude / 2, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kMaxDurationMillis, gamepad_->last_vibrate_duration_);
-
-  // Make sure that the remaining vibration from the first call is no longer in
-  // the queue.
-  task_environment_.FastForwardBy(kPendingMaxTaskDuration);
-  EXPECT_FALSE(task_environment_.NextTaskIsDelayed());
-  // Verify that no extra vibration calls were made.
-  EXPECT_EQ(2, gamepad_->send_vibrate_count_);
-}
-
-TEST_F(GamepadTest, NoFocusTest) {
-  EXPECT_EQ(0, gamepad_->send_vibrate_count_);
-  gamepad_->OnGamepadFocusLost();
-
-  gamepad_->Vibrate({kDurationMillis}, {kAmplitude}, -1);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(0, gamepad_->send_vibrate_count_);
-}
-
-TEST_F(GamepadTest, FocusLostTest) {
-  EXPECT_EQ(0, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(0, gamepad_->send_cancel_vibration_count_);
-
-  gamepad_->Vibrate({kDurationMillis, kDurationMillis}, {kAmplitude, 0}, -1);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kDurationMillis, gamepad_->last_vibrate_duration_);
-
-  EXPECT_TRUE(task_environment_.NextTaskIsDelayed());
-  gamepad_->OnGamepadFocusLost();
-  task_environment_.FastForwardBy(kPendingTaskDuration);
-
-  // When focus is lost, CancelVibration is sent, and no more vibration can be
-  // scheduled.
-  EXPECT_EQ(1, gamepad_->send_cancel_vibration_count_);
-  EXPECT_EQ(1, gamepad_->send_vibrate_count_);
-
-  // While focus is not regained, gamepad cannot vibrate.
-  gamepad_->Vibrate({kDurationMillis}, {kAmplitude}, -1);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(1, gamepad_->send_vibrate_count_);
-
-  // If focus is regained, gamepad can vibrate again.
-  gamepad_->OnGamepadFocused();
-  gamepad_->Vibrate({kDurationMillis / 2}, {kAmplitude / 2}, -1);
-  task_environment_.RunUntilIdle();
-  EXPECT_EQ(2, gamepad_->send_vibrate_count_);
-  EXPECT_EQ(kAmplitude / 2, gamepad_->last_vibrate_amplitude_);
-  EXPECT_EQ(kDurationMillis / 2, gamepad_->last_vibrate_duration_);
-}
-
-TEST_F(GamepadTest, GamepadObserverTest) {
-  MockGamepadObserver observer1;
-  MockGamepadObserver observer2;
-
-  gamepad_->AddObserver(&observer1);
-  gamepad_->AddObserver(&observer2);
-  EXPECT_TRUE(gamepad_->HasObserver(&observer1));
-  EXPECT_TRUE(gamepad_->HasObserver(&observer2));
-
-  gamepad_->RemoveObserver(&observer1);
-  EXPECT_FALSE(gamepad_->HasObserver(&observer1));
-  EXPECT_TRUE(gamepad_->HasObserver(&observer2));
-
-  EXPECT_CALL(observer1, OnGamepadDestroying(gamepad_.get())).Times(0);
-  EXPECT_CALL(observer2, OnGamepadDestroying(gamepad_.get()));
-  gamepad_.reset();
-}
-
-TEST_F(GamepadTest, GamepadDelegateTest) {
-  auto delegate = std::make_unique<MockGamepadDelegate>();
-  EXPECT_CALL(*delegate, OnRemoved()).Times(1);
-
-  gamepad_->SetDelegate(std::move(delegate));
-
-  gamepad_.reset();
-}
-
-TEST_F(GamepadTest, OnGamepadEventTest) {
-  constexpr int gamepad_id = 0;
-  constexpr uint16_t code = 310;
-  constexpr double value = 1;
-  base::TimeTicks expected_time = base::TimeTicks::Now();
-
-  auto delegate = std::make_unique<MockGamepadDelegate>();
-  EXPECT_CALL(*delegate, OnButton(code, value, expected_time)).Times(1);
-  EXPECT_CALL(*delegate, OnAxis(code, value, expected_time)).Times(1);
-  EXPECT_CALL(*delegate, OnFrame(expected_time)).Times(1);
-  EXPECT_CALL(*delegate, OnRemoved()).Times(1);
-
-  gamepad_->SetDelegate(std::move(delegate));
-
-  gamepad_->OnGamepadEvent(ui::GamepadEvent(
-      gamepad_id, ui::GamepadEventType::BUTTON, code, value, expected_time));
-  gamepad_->OnGamepadEvent(ui::GamepadEvent(
-      gamepad_id, ui::GamepadEventType::AXIS, code, value, expected_time));
-  gamepad_->OnGamepadEvent(ui::GamepadEvent(
-      gamepad_id, ui::GamepadEventType::FRAME, code, value, expected_time));
-
-  gamepad_.reset();
-}
-
-TEST_F(GamepadTest, GamepadDestroyedTest) {
-  MockGamepadObserver observer1;
-  MockGamepadObserver observer2;
-  gamepad_->AddObserver(&observer1);
-  gamepad_->AddObserver(&observer2);
-  EXPECT_TRUE(gamepad_->HasObserver(&observer1));
-  EXPECT_TRUE(gamepad_->HasObserver(&observer2));
-
-  auto delegate = std::make_unique<MockGamepadDelegate>();
-  EXPECT_CALL(*delegate, OnRemoved()).Times(1);
-
-  gamepad_->SetDelegate(std::move(delegate));
-
-  EXPECT_CALL(observer1, OnGamepadDestroying(gamepad_.get())).Times(1);
-  EXPECT_CALL(observer2, OnGamepadDestroying(gamepad_.get())).Times(1);
-  gamepad_.reset();
-}
-}  // namespace
-}  // namespace exo
diff --git a/components/exo/gaming_seat.cc b/components/exo/gaming_seat.cc
index 72ea93e..f63b2fa 100644
--- a/components/exo/gaming_seat.cc
+++ b/components/exo/gaming_seat.cc
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "components/exo/gamepad.h"
 #include "components/exo/gamepad_delegate.h"
 #include "components/exo/gaming_seat_delegate.h"
 #include "components/exo/shell_surface_util.h"
@@ -28,6 +27,9 @@
   if (focused_)
     ui::GamepadProviderOzone::GetInstance()->RemoveGamepadObserver(this);
   delegate_->OnGamingSeatDestroying(this);
+  // Disconnect all the gamepads.
+  for (auto& entry : gamepads_)
+    entry.second->OnRemoved();
 
   WMHelper::GetInstance()->RemoveFocusObserver(this);
 }
@@ -53,12 +55,8 @@
     if (focused) {
       ui::GamepadProviderOzone::GetInstance()->AddGamepadObserver(this);
       OnGamepadDevicesUpdated();
-      for (auto& entry : gamepads_)
-        entry.second->OnGamepadFocused();
     } else {
       ui::GamepadProviderOzone::GetInstance()->RemoveGamepadObserver(this);
-      for (auto& entry : gamepads_)
-        entry.second->OnGamepadFocusLost();
     }
   }
 }
@@ -70,26 +68,25 @@
   std::vector<ui::GamepadDevice> gamepad_devices =
       ui::GamepadProviderOzone::GetInstance()->GetGamepadDevices();
 
-  base::flat_map<int, std::unique_ptr<Gamepad>> new_gamepads;
+  base::flat_map<int, GamepadDelegate*> new_gamepads;
 
   // Copy the "still connected gamepads".
   for (auto& device : gamepad_devices) {
     auto it = gamepads_.find(device.id);
     if (it != gamepads_.end()) {
-      new_gamepads[device.id] = std::move(it->second);
+      new_gamepads[device.id] = it->second;
       gamepads_.erase(it);
     }
   }
 
+  // Remove each disconected gamepad.
+  for (auto& entry : gamepads_)
+    entry.second->OnRemoved();
+
   // Add each new connected gamepad.
   for (auto& device : gamepad_devices) {
-    if (new_gamepads.find(device.id) == new_gamepads.end()) {
-      std::unique_ptr<Gamepad> gamepad = std::make_unique<Gamepad>(device);
-      if (focused_)
-        gamepad->OnGamepadFocused();
-      delegate_->GamepadAdded(*gamepad);
-      new_gamepads[device.id] = std::move(gamepad);
-    }
+    if (new_gamepads.find(device.id) == new_gamepads.end())
+      new_gamepads[device.id] = delegate_->GamepadAdded(device);
   }
 
   new_gamepads.swap(gamepads_);
@@ -100,7 +97,17 @@
   if (it == gamepads_.end())
     return;
 
-  it->second->OnGamepadEvent(event);
+  switch (event.type()) {
+    case ui::GamepadEventType::BUTTON:
+      it->second->OnButton(event.code(), event.value(), event.timestamp());
+      break;
+    case ui::GamepadEventType::AXIS:
+      it->second->OnAxis(event.code(), event.value(), event.timestamp());
+      break;
+    case ui::GamepadEventType::FRAME:
+      it->second->OnFrame(event.timestamp());
+      break;
+  }
 }
 
 }  // namespace exo
diff --git a/components/exo/gaming_seat.h b/components/exo/gaming_seat.h
index c75cf15..312e5f3 100644
--- a/components/exo/gaming_seat.h
+++ b/components/exo/gaming_seat.h
@@ -12,7 +12,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
 #include "base/synchronization/lock.h"
-#include "components/exo/gamepad.h"
 #include "components/exo/wm_helper.h"
 #include "ui/aura/client/focus_change_observer.h"
 #include "ui/events/ozone/gamepad/gamepad_observer.h"
@@ -27,7 +26,8 @@
 class GamingSeat : public aura::client::FocusChangeObserver,
                    public ui::GamepadObserver {
  public:
-  // This class will monitor gamepad connection changes and manage gamepads.
+  // This class will monitor gamepad connection changes and manage gamepad
+  // returned by gaming_seat_delegate.
   GamingSeat(GamingSeatDelegate* gaming_seat_delegate);
 
   ~GamingSeat() override;
@@ -45,7 +45,7 @@
   GamingSeatDelegate* const delegate_;
 
   // Contains the delegate for each gamepad device.
-  base::flat_map<int, std::unique_ptr<Gamepad>> gamepads_;
+  base::flat_map<int, GamepadDelegate*> gamepads_;
 
   // The flag if a valid target for gaming seat is focused. In other words, if
   // it's true, this class is observing gamepad events.
diff --git a/components/exo/gaming_seat_delegate.h b/components/exo/gaming_seat_delegate.h
index 11371aa..61d6f53 100644
--- a/components/exo/gaming_seat_delegate.h
+++ b/components/exo/gaming_seat_delegate.h
@@ -5,11 +5,14 @@
 #ifndef COMPONENTS_EXO_GAMING_SEAT_DELEGATE_H_
 #define COMPONENTS_EXO_GAMING_SEAT_DELEGATE_H_
 
+namespace ui {
+struct GamepadDevice;
+}  // namespace ui
+
 namespace exo {
 class Surface;
 class GamepadDelegate;
 class GamingSeat;
-class Gamepad;
 
 // It send gamepad_added event and generate the GamepadDelegate.
 class GamingSeatDelegate {
@@ -22,9 +25,9 @@
   // seat. E.g. the surface is owned by the same client as the gaming seat.
   virtual bool CanAcceptGamepadEventsForSurface(Surface* surface) const = 0;
 
-  // When a new gamepad is connected, gaming seat call this to assign a
-  // gamepad delegate to the gamepad.
-  virtual void GamepadAdded(Gamepad& gamepad) = 0;
+  // When a new gamepad is connected, gaming seat call this to get the
+  // gamepad delegate.
+  virtual GamepadDelegate* GamepadAdded(const ui::GamepadDevice& device) = 0;
 
  protected:
   virtual ~GamingSeatDelegate() {}
diff --git a/components/exo/gaming_seat_unittest.cc b/components/exo/gaming_seat_unittest.cc
index cbc2040..c64c93e 100644
--- a/components/exo/gaming_seat_unittest.cc
+++ b/components/exo/gaming_seat_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "components/exo/buffer.h"
-#include "components/exo/gamepad.h"
 #include "components/exo/gamepad_delegate.h"
 #include "components/exo/gaming_seat_delegate.h"
 #include "components/exo/shell_surface.h"
@@ -27,33 +26,24 @@
 namespace exo {
 namespace {
 
+class MockGamingSeatDelegate : public GamingSeatDelegate {
+ public:
+  MOCK_CONST_METHOD1(CanAcceptGamepadEventsForSurface, bool(Surface*));
+  MOCK_METHOD1(GamepadAdded, GamepadDelegate*(const ui::GamepadDevice&));
+  MOCK_METHOD0(Die, void());
+  void OnGamingSeatDestroying(GamingSeat*) override { delete this; }
+  ~MockGamingSeatDelegate() { Die(); }
+};
+
 class MockGamepadDelegate : public GamepadDelegate {
  public:
   MockGamepadDelegate() {}
 
   // Overridden from GamepadDelegate:
-  MOCK_METHOD(void, OnRemoved, (), (override));
-  MOCK_METHOD(void,
-              OnAxis,
-              (int axis, double value, base::TimeTicks timestamp),
-              (override));
-  MOCK_METHOD(void,
-              OnButton,
-              (int button, bool pressed, base::TimeTicks timestamp),
-              (override));
-  MOCK_METHOD(void, OnFrame, (base::TimeTicks timestamp), (override));
-};
-
-class MockGamingSeatDelegate : public GamingSeatDelegate {
- public:
-  MOCK_METHOD(bool,
-              CanAcceptGamepadEventsForSurface,
-              (Surface * surface),
-              (const, override));
-  MOCK_METHOD(void, GamepadAdded, (Gamepad & gamepad), (override));
-  MOCK_METHOD(void, Die, (), ());
-  void OnGamingSeatDestroying(GamingSeat*) override { delete this; }
-  ~MockGamingSeatDelegate() { Die(); }
+  MOCK_METHOD0(OnRemoved, void());
+  MOCK_METHOD3(OnAxis, void(int, double, base::TimeTicks));
+  MOCK_METHOD3(OnButton, void(int, bool, base::TimeTicks));
+  MOCK_METHOD1(OnFrame, void(base::TimeTicks));
 };
 
 class GamingSeatTest : public test::ExoTestBase {
@@ -99,6 +89,7 @@
 
  protected:
   std::unique_ptr<GamingSeat> gaming_seat_;
+
   DISALLOW_COPY_AND_ASSIGN(GamingSeatTest);
 };
 
@@ -118,63 +109,44 @@
       .WillOnce(testing::Return(true));
 
   InitializeGamingSeat(gaming_seat_delegate);
-  std::unique_ptr<MockGamepadDelegate> gamepad_delegates[6];
-  for (auto& delegate : gamepad_delegates)
-    delegate = std::make_unique<testing::StrictMock<MockGamepadDelegate>>();
+  testing::StrictMock<MockGamepadDelegate> gamepad_delegate[6];
 
   {  // Test sequence
     testing::InSequence s;
     // Connect 2 gamepads.
     EXPECT_CALL(*gaming_seat_delegate, GamepadAdded(testing::_))
-        .WillOnce(testing::Invoke([&gamepad_delegates](auto& gamepad) {
-          gamepad.SetDelegate(std::move(gamepad_delegates[0]));
-        }));
-    EXPECT_CALL(*gaming_seat_delegate, GamepadAdded(testing::_))
-        .WillOnce(testing::Invoke([&gamepad_delegates](auto& gamepad) {
-          gamepad.SetDelegate(std::move(gamepad_delegates[1]));
-        }));
+        .WillOnce(testing::Return(&gamepad_delegate[0]))
+        .WillOnce(testing::Return(&gamepad_delegate[1]));
     // Send frame to connected gamepad.
-    EXPECT_CALL(*gamepad_delegates[0], OnFrame(testing::_)).Times(1);
-    EXPECT_CALL(*gamepad_delegates[1], OnFrame(testing::_)).Times(1);
+    EXPECT_CALL(gamepad_delegate[0], OnFrame(testing::_)).Times(1);
+    EXPECT_CALL(gamepad_delegate[1], OnFrame(testing::_)).Times(1);
     // Connect 3 more.
     EXPECT_CALL(*gaming_seat_delegate, GamepadAdded(testing::_))
-        .WillOnce(testing::Invoke([&gamepad_delegates](auto& gamepad) {
-          gamepad.SetDelegate(std::move(gamepad_delegates[2]));
-        }));
-    EXPECT_CALL(*gaming_seat_delegate, GamepadAdded(testing::_))
-        .WillOnce(testing::Invoke([&gamepad_delegates](auto& gamepad) {
-          gamepad.SetDelegate(std::move(gamepad_delegates[3]));
-        }));
-    EXPECT_CALL(*gaming_seat_delegate, GamepadAdded(testing::_))
-        .WillOnce(testing::Invoke([&gamepad_delegates](auto& gamepad) {
-          gamepad.SetDelegate(std::move(gamepad_delegates[4]));
-        }));
+        .WillOnce(testing::Return(&gamepad_delegate[2]))
+        .WillOnce(testing::Return(&gamepad_delegate[3]))
+        .WillOnce(testing::Return(&gamepad_delegate[4]));
     // Send frame to all gamepads.
-    EXPECT_CALL(*gamepad_delegates[0], OnFrame(testing::_)).Times(1);
-    EXPECT_CALL(*gamepad_delegates[1], OnFrame(testing::_)).Times(1);
-    EXPECT_CALL(*gamepad_delegates[2], OnFrame(testing::_)).Times(1);
-    EXPECT_CALL(*gamepad_delegates[3], OnFrame(testing::_)).Times(1);
-    EXPECT_CALL(*gamepad_delegates[4], OnFrame(testing::_)).Times(1);
+    EXPECT_CALL(gamepad_delegate[0], OnFrame(testing::_)).Times(1);
+    EXPECT_CALL(gamepad_delegate[1], OnFrame(testing::_)).Times(1);
+    EXPECT_CALL(gamepad_delegate[2], OnFrame(testing::_)).Times(1);
+    EXPECT_CALL(gamepad_delegate[3], OnFrame(testing::_)).Times(1);
+    EXPECT_CALL(gamepad_delegate[4], OnFrame(testing::_)).Times(1);
     // Disconnect gamepad 0 and gamepad 2 and connect a new gamepad.
+    EXPECT_CALL(gamepad_delegate[0], OnRemoved()).Times(1);
+    EXPECT_CALL(gamepad_delegate[2], OnRemoved()).Times(1);
+    EXPECT_CALL(gamepad_delegate[4], OnRemoved()).Times(1);
     EXPECT_CALL(*gaming_seat_delegate, GamepadAdded(testing::_))
-        .WillOnce(testing::Invoke([&gamepad_delegates](auto& gamepad) {
-          gamepad.SetDelegate(std::move(gamepad_delegates[5]));
-        }));
+        .WillOnce(testing::Return(&gamepad_delegate[5]));
     // Send frame to all gamepads.
-    EXPECT_CALL(*gamepad_delegates[1], OnFrame(testing::_)).Times(1);
-    EXPECT_CALL(*gamepad_delegates[3], OnFrame(testing::_)).Times(1);
-    EXPECT_CALL(*gamepad_delegates[5], OnFrame(testing::_)).Times(1);
+    EXPECT_CALL(gamepad_delegate[1], OnFrame(testing::_)).Times(1);
+    EXPECT_CALL(gamepad_delegate[3], OnFrame(testing::_)).Times(1);
+    EXPECT_CALL(gamepad_delegate[5], OnFrame(testing::_)).Times(1);
+
+    // disconnect other gamepads
+    EXPECT_CALL(gamepad_delegate[1], OnRemoved()).Times(1);
+    EXPECT_CALL(gamepad_delegate[3], OnRemoved()).Times(1);
+    EXPECT_CALL(gamepad_delegate[5], OnRemoved()).Times(1);
   }
-
-  EXPECT_CALL(*gamepad_delegates[0], OnRemoved()).Times(1);
-  EXPECT_CALL(*gamepad_delegates[2], OnRemoved()).Times(1);
-  EXPECT_CALL(*gamepad_delegates[4], OnRemoved()).Times(1);
-  // The rest of gamepads should be disconnected after GamingSeat is
-  // destroyed.
-  EXPECT_CALL(*gamepad_delegates[1], OnRemoved()).Times(1);
-  EXPECT_CALL(*gamepad_delegates[3], OnRemoved()).Times(1);
-  EXPECT_CALL(*gamepad_delegates[5], OnRemoved()).Times(1);
-
   // Gamepad connected.
   UpdateGamepadDevice({0, 1});
   SendFrameToGamepads({0, 1});
@@ -182,8 +154,8 @@
   SendFrameToGamepads({0, 1, 2, 3, 4});
   UpdateGamepadDevice({1, 3, 5});
   SendFrameToGamepads({1, 2, 3, 4, 5});
-  DestroyGamingSeat(gaming_seat_delegate);
   UpdateGamepadDevice({});
+  DestroyGamingSeat(gaming_seat_delegate);
 }
 
 TEST_F(GamingSeatTest, Timestamp) {
@@ -202,8 +174,8 @@
       .WillOnce(testing::Return(true));
 
   InitializeGamingSeat(gaming_seat_delegate);
-  auto gamepad_delegate =
-      std::make_unique<testing::StrictMock<MockGamepadDelegate>>();
+  testing::StrictMock<MockGamepadDelegate> gamepad_delegate;
+
   base::TimeTicks expected_time = base::TimeTicks::Now();
 
   {  // Test sequence
@@ -211,18 +183,14 @@
 
     // Connect gamepad.
     EXPECT_CALL(*gaming_seat_delegate, GamepadAdded(testing::_))
-        .WillOnce(testing::Invoke([&gamepad_delegate](auto& gamepad) {
-          gamepad.SetDelegate(std::move(gamepad_delegate));
-        }));
+        .WillOnce(testing::Return(&gamepad_delegate));
     // Send button to connected gamepad. Expect correct timestamp.
-    EXPECT_CALL(*gamepad_delegate,
+    EXPECT_CALL(gamepad_delegate,
                 OnButton(testing::_, testing::_, testing::Eq(expected_time)))
         .Times(1);
+    // Disconnect gamepad.
+    EXPECT_CALL(gamepad_delegate, OnRemoved()).Times(1);
   }
-
-  // Disconnect gamepad.
-  EXPECT_CALL(*gamepad_delegate, OnRemoved()).Times(1);
-
   // Gamepad connected.
   UpdateGamepadDevice({1});
   SendButtonToGamepads({1}, expected_time);
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 9eafe4f..a34bb2d5 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -181,7 +181,7 @@
                    bind_shell);
   wl_global_create(wl_display_.get(), &zcr_cursor_shapes_v1_interface, 1,
                    display_, bind_cursor_shapes);
-  wl_global_create(wl_display_.get(), &zcr_gaming_input_v2_interface, 2,
+  wl_global_create(wl_display_.get(), &zcr_gaming_input_v2_interface, 1,
                    display_, bind_gaming_input);
   wl_global_create(wl_display_.get(), &zcr_keyboard_configuration_v1_interface,
                    zcr_keyboard_configuration_v1_interface.version, display_,
diff --git a/components/exo/wayland/zcr_gaming_input.cc b/components/exo/wayland/zcr_gaming_input.cc
index 06b41af..a8d61c0 100644
--- a/components/exo/wayland/zcr_gaming_input.cc
+++ b/components/exo/wayland/zcr_gaming_input.cc
@@ -12,9 +12,7 @@
 
 #include "base/feature_list.h"
 #include "base/macros.h"
-#include "components/exo/gamepad.h"
 #include "components/exo/gamepad_delegate.h"
-#include "components/exo/gamepad_observer.h"
 #include "components/exo/gaming_seat.h"
 #include "components/exo/gaming_seat_delegate.h"
 #include "components/exo/wayland/server_util.h"
@@ -38,89 +36,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 // gaming_input_interface:
 
-// Handles the vibration requests sent by the client for a gamepad.
-class WaylandGamepadVibratorImpl : public GamepadObserver {
- public:
-  explicit WaylandGamepadVibratorImpl(Gamepad* gamepad) : gamepad_(gamepad) {
-    gamepad_->AddObserver(this);
-  }
-
-  WaylandGamepadVibratorImpl(const WaylandGamepadVibratorImpl& other) = delete;
-  WaylandGamepadVibratorImpl& operator=(
-      const WaylandGamepadVibratorImpl& other) = delete;
-
-  ~WaylandGamepadVibratorImpl() override {
-    if (gamepad_)
-      gamepad_->RemoveObserver(this);
-  }
-
-  void OnVibrate(wl_array* duration_millis,
-                 wl_array* amplitudes,
-                 int32_t repeat) {
-    std::vector<int64_t> extracted_durations;
-    int64_t* p;
-    const uint8_t* duration_millis_end =
-        static_cast<uint8_t*>(duration_millis->data) + duration_millis->size;
-    for (p = static_cast<int64_t*>(duration_millis->data);
-         (const uint8_t*)p < duration_millis_end; p++) {
-      extracted_durations.emplace_back(*p);
-    }
-
-    const uint8_t* amplitudes_start = static_cast<uint8_t*>(amplitudes->data);
-    size_t amplitude_size = amplitudes->size / sizeof(uint8_t);
-    const uint8_t* amplitudes_end = amplitudes_start + amplitude_size;
-    std::vector<uint8_t> extracted_amplitudes(amplitudes_start, amplitudes_end);
-
-    if (gamepad_)
-      gamepad_->Vibrate(extracted_durations, extracted_amplitudes, repeat);
-  }
-
-  void OnCancelVibration() {
-    if (gamepad_)
-      gamepad_->CancelVibration();
-  }
-
-  // Overridden from GamepadObserver
-  void OnGamepadDestroying(Gamepad* gamepad) override {
-    DCHECK_EQ(gamepad_, gamepad);
-    gamepad_ = nullptr;
-  }
-
- private:
-  Gamepad* gamepad_;
-};
-
-void gamepad_vibrator_vibrate(wl_client* client,
-                              wl_resource* resource,
-                              wl_array* duration_millis,
-                              wl_array* amplitudes,
-                              int32_t repeat) {
-  GetUserDataAs<WaylandGamepadVibratorImpl>(resource)->OnVibrate(
-      duration_millis, amplitudes, repeat);
-}
-
-void gamepad_vibrator_cancel_vibration(wl_client* client,
-                                       wl_resource* resource) {
-  GetUserDataAs<WaylandGamepadVibratorImpl>(resource)->OnCancelVibration();
-}
-
-void gamepad_vibrator_destroy(wl_client* client, wl_resource* resource) {
-  wl_resource_destroy(resource);
-}
-
-const struct zcr_gamepad_vibrator_v2_interface gamepad_vibrator_implementation =
-    {gamepad_vibrator_vibrate, gamepad_vibrator_cancel_vibration,
-     gamepad_vibrator_destroy};
-
 // Gamepad delegate class that forwards gamepad events to the client resource.
 class WaylandGamepadDelegate : public GamepadDelegate {
  public:
   explicit WaylandGamepadDelegate(wl_resource* gamepad_resource)
       : gamepad_resource_(gamepad_resource) {}
 
-  // The object should be deleted by OnRemoved().
-  ~WaylandGamepadDelegate() override = default;
-
   // If gamepad_resource_ is destroyed first, ResetGamepadResource will
   // be called to remove the resource from delegate, and delegate won't
   // do anything after that. If delegate is destructed first, it will
@@ -172,33 +93,10 @@
     wl_client_flush(client());
   }
 
-  void ConfigureDevice(Gamepad* gamepad) {
-    for (const auto& axis : gamepad->device.axes) {
-      zcr_gamepad_v2_send_axis_added(gamepad_resource_, axis.code,
-                                     axis.min_value, axis.max_value, axis.flat,
-                                     axis.fuzz, axis.resolution);
-    }
-
-    if (gamepad->device.supports_vibration_rumble &&
-        wl_resource_get_version(gamepad_resource_) >=
-            ZCR_GAMEPAD_V2_VIBRATOR_ADDED_SINCE_VERSION) {
-      wl_resource* gamepad_vibrator_resource =
-          wl_resource_create(wl_resource_get_client(gamepad_resource_),
-                             &zcr_gamepad_vibrator_v2_interface,
-                             wl_resource_get_version(gamepad_resource_), 0);
-
-      SetImplementation(gamepad_vibrator_resource,
-                        &gamepad_vibrator_implementation,
-                        std::make_unique<WaylandGamepadVibratorImpl>(gamepad));
-
-      zcr_gamepad_v2_send_vibrator_added(gamepad_resource_,
-                                         gamepad_vibrator_resource);
-    }
-
-    zcr_gamepad_v2_send_activated(gamepad_resource_);
-  }
-
  private:
+  // The object should be deleted by OnRemoved().
+  ~WaylandGamepadDelegate() override {}
+
   // The client who own this gamepad instance.
   wl_client* client() const {
     return wl_resource_get_client(gamepad_resource_);
@@ -231,28 +129,33 @@
            wl_resource_get_client(surface_resource) ==
                wl_resource_get_client(gaming_seat_resource_);
   }
-  void GamepadAdded(Gamepad& gamepad) override {
+  GamepadDelegate* GamepadAdded(const ui::GamepadDevice& device) override {
     wl_resource* gamepad_resource =
         wl_resource_create(wl_resource_get_client(gaming_seat_resource_),
                            &zcr_gamepad_v2_interface,
                            wl_resource_get_version(gaming_seat_resource_), 0);
 
-    zcr_gaming_seat_v2_send_gamepad_added_with_device_info(
-        gaming_seat_resource_, gamepad_resource, gamepad.device.name.c_str(),
-        GetGamepadBusType(gamepad.device.type), gamepad.device.vendor_id,
-        gamepad.device.product_id, gamepad.device.version);
-
-    std::unique_ptr<WaylandGamepadDelegate> gamepad_delegate =
-        std::make_unique<WaylandGamepadDelegate>(gamepad_resource);
+    GamepadDelegate* gamepad_delegate =
+        new WaylandGamepadDelegate(gamepad_resource);
 
     wl_resource_set_implementation(
-        gamepad_resource, &gamepad_implementation, gamepad_delegate.get(),
+        gamepad_resource, &gamepad_implementation, gamepad_delegate,
         &WaylandGamepadDelegate::ResetGamepadResource);
 
-    gamepad_delegate->ConfigureDevice(&gamepad);
-    gamepad.SetDelegate(std::move(gamepad_delegate));
+    zcr_gaming_seat_v2_send_gamepad_added_with_device_info(
+        gaming_seat_resource_, gamepad_resource, device.name.c_str(),
+        GetGamepadBusType(device.type), device.vendor_id, device.product_id,
+        device.version);
 
+    for (const auto& axis : device.axes) {
+      zcr_gamepad_v2_send_axis_added(gamepad_resource, axis.code,
+                                     axis.min_value, axis.max_value, axis.flat,
+                                     axis.fuzz, axis.resolution);
+    }
+    zcr_gamepad_v2_send_activated(gamepad_resource);
     wl_client_flush(wl_resource_get_client(gaming_seat_resource_));
+
+    return gamepad_delegate;
   }
 
  private:
diff --git a/components/metal_util/BUILD.gn b/components/metal_util/BUILD.gn
index 86b8df4..f417026 100644
--- a/components/metal_util/BUILD.gn
+++ b/components/metal_util/BUILD.gn
@@ -27,6 +27,7 @@
   deps = [
     "//base",
     "//components/crash/core/common:crash_key",
+    "//ui/gfx",
   ]
 
   frameworks = [
diff --git a/components/metal_util/DEPS b/components/metal_util/DEPS
index 90e574c..54bf698 100644
--- a/components/metal_util/DEPS
+++ b/components/metal_util/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
   "+components/crash/core/common/crash_key.h",
+  "+ui/gfx",
 ]
diff --git a/components/metal_util/hdr_copier_layer.h b/components/metal_util/hdr_copier_layer.h
index f1cf0be..98bda00 100644
--- a/components/metal_util/hdr_copier_layer.h
+++ b/components/metal_util/hdr_copier_layer.h
@@ -7,19 +7,29 @@
 
 #include "components/metal_util/metal_util_export.h"
 
+#include <IOSurface/IOSurface.h>
+
+namespace gfx {
+class ColorSpace;
+}  // namespace gfx
+
 @class CALayer;
 
 namespace metal {
 
+// Return true if we should use the HDRCopier for the specified content.
+bool METAL_UTIL_EXPORT ShouldUseHDRCopier(IOSurfaceRef buffer,
+                                          const gfx::ColorSpace& color_space);
+
 // Create a layer which may have its contents set an HDR IOSurface via
-// the -[CALayer setContents:] method.
-// - The IOSurface specified to setContents must have pixel format
-//   kCVPixelFormatType_64RGBAHalf or kCVPixelFormatType_ARGB2101010LEPacked,
-//   any other pixel formats will be NOTREACHED.
-// - This layer will, in setContents, blit the contents of the specified
-//   IOSurface to an HDR-capable CAMetalLayer.
+// UpdateHDRCopierLayer.
 CALayer* METAL_UTIL_EXPORT CreateHDRCopierLayer();
 
+// Update the contents of |layer| to the specified IOSurface and color space.
+void METAL_UTIL_EXPORT UpdateHDRCopierLayer(CALayer* layer,
+                                            IOSurfaceRef buffer,
+                                            const gfx::ColorSpace& color_space);
+
 }  // namespace metal
 
 #endif  // COMPONENTS_METAL_UTIL_HDR_COPIER_LAYER_H_
diff --git a/components/metal_util/hdr_copier_layer.mm b/components/metal_util/hdr_copier_layer.mm
index f360913..189d18eb 100644
--- a/components/metal_util/hdr_copier_layer.mm
+++ b/components/metal_util/hdr_copier_layer.mm
@@ -14,9 +14,47 @@
 #include "base/notreached.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/metal_util/device.h"
+#include "ui/gfx/color_space.h"
 
 namespace {
 
+// Source of the shader to perform tonemapping.
+// TODO(https://crbug.com/1101041): This shader just does a copy for now.
+const char* tonemapping_shader_source =
+    "#include <metal_stdlib>\n"
+    "#include <simd/simd.h>\n"
+    "using metal::float2;\n"
+    "using metal::float3x3;\n"
+    "using metal::float4;\n"
+    "using metal::sampler;\n"
+    "using metal::texture2d;\n"
+    "\n"
+    "typedef struct {\n"
+    "    float4 clipSpacePosition [[position]];\n"
+    "    float2 texcoord;\n"
+    "} RasterizerData;\n"
+    "\n"
+    "vertex RasterizerData vertexShader(\n"
+    "    uint vertexID [[vertex_id]],\n"
+    "    constant float2 *positions[[buffer(0)]]) {\n"
+    "  RasterizerData out;\n"
+    "  out.clipSpacePosition = vector_float4(0.f, 0.f, 0.f, 1.f);\n"
+    "  out.clipSpacePosition.x = 2.f * positions[vertexID].x - 1.f;\n"
+    "  out.clipSpacePosition.y = -2.f * positions[vertexID].y + 1.f;\n"
+    "  out.texcoord = positions[vertexID];\n"
+    "  return out;\n"
+    "}\n"
+    "\n"
+    "fragment float4 fragmentShader(RasterizerData in [[stage_in]],\n"
+    "                               texture2d<float> t [[texture(0)]],\n"
+    "                               constant float3x3& m [[buffer(0)]],\n"
+    "                               constant uint32_t& f [[buffer(1)]]) {\n"
+    "    constexpr sampler s(metal::mag_filter::nearest,\n"
+    "                        metal::min_filter::nearest);\n"
+    "    float4 color = t.sample(s, in.texcoord);\n"
+    "    return color;\n"
+    "}\n";
+
 // Convert from an IOSurface's pixel format to a MTLPixelFormat. Crash on any
 // unsupported formats.
 MTLPixelFormat IOSurfaceGetMTLPixelFormat(IOSurfaceRef buffer)
@@ -30,7 +68,6 @@
     default:
       break;
   }
-  NOTREACHED();
   return MTLPixelFormatInvalid;
 }
 
@@ -52,6 +89,49 @@
   return color_space.release();
 }
 
+base::scoped_nsprotocol<id<MTLRenderPipelineState>> CreateRenderPipelineState(
+    id<MTLDevice> device) API_AVAILABLE(macos(10.13)) {
+  base::scoped_nsprotocol<id<MTLRenderPipelineState>> render_pipeline_state;
+
+  base::scoped_nsprotocol<id<MTLLibrary>> library;
+  {
+    NSError* error = nil;
+    base::scoped_nsobject<NSString> source([[NSString alloc]
+        initWithCString:tonemapping_shader_source
+               encoding:NSASCIIStringEncoding]);
+    base::scoped_nsobject<MTLCompileOptions> options(
+        [[MTLCompileOptions alloc] init]);
+    library.reset([device newLibraryWithSource:source
+                                       options:options
+                                         error:&error]);
+    if (error) {
+      NSLog(@"Failed to compile shader: %@", error);
+      return render_pipeline_state;
+    }
+  }
+
+  {
+    base::scoped_nsprotocol<id<MTLFunction>> vertex_function(
+        [library newFunctionWithName:@"vertexShader"]);
+    base::scoped_nsprotocol<id<MTLFunction>> fragment_function(
+        [library newFunctionWithName:@"fragmentShader"]);
+    NSError* error = nil;
+    base::scoped_nsobject<MTLRenderPipelineDescriptor> desc(
+        [[MTLRenderPipelineDescriptor alloc] init]);
+    [desc setVertexFunction:vertex_function];
+    [desc setFragmentFunction:fragment_function];
+    [[desc colorAttachments][0] setPixelFormat:MTLPixelFormatRGBA16Float];
+    render_pipeline_state.reset(
+        [device newRenderPipelineStateWithDescriptor:desc error:&error]);
+    if (error) {
+      NSLog(@"Failed to create render pipeline state: %@", error);
+      return render_pipeline_state;
+    }
+  }
+
+  return render_pipeline_state;
+}
+
 }  // namespace
 
 #if !defined(MAC_OS_X_VERSION_10_15)
@@ -62,9 +142,12 @@
 #endif
 
 API_AVAILABLE(macos(10.15))
-@interface HDRCopierLayer : CAMetalLayer
+@interface HDRCopierLayer : CAMetalLayer {
+  base::scoped_nsprotocol<id<MTLRenderPipelineState>> _render_pipeline_state;
+}
 - (id)init;
-- (void)setContents:(id)contents;
+- (void)setHDRContents:(IOSurfaceRef)buffer
+        withColorSpace:(gfx::ColorSpace)color_space;
 @end
 
 @implementation HDRCopierLayer
@@ -72,9 +155,6 @@
   if (self = [super init]) {
     base::scoped_nsprotocol<id<MTLDevice>> device(metal::CreateDefaultDevice());
     [self setWantsExtendedDynamicRangeContent:YES];
-    [self setEDRMetadata:[CAEDRMetadata HDR10MetadataWithMinLuminance:0.005
-                                                         maxLuminance:1000
-                                                   opticalOutputScale:100]];
     [self setDevice:device];
     [self setOpaque:NO];
     [self setPresentsWithTransaction:YES];
@@ -82,9 +162,8 @@
   return self;
 }
 
-- (void)setContents:(id)contents {
-  IOSurfaceRef buffer = reinterpret_cast<IOSurfaceRef>(contents);
-
+- (void)setHDRContents:(IOSurfaceRef)buffer
+        withColorSpace:(gfx::ColorSpace)color_space {
   // Retrieve information about the IOSurface.
   size_t width = IOSurfaceGetWidth(buffer);
   size_t height = IOSurfaceGetHeight(buffer);
@@ -108,9 +187,15 @@
   }
   id<MTLDevice> device = [self device];
 
+  // When the device changes, rebuild the RenderPipelineState.
+  if (device != [_render_pipeline_state device])
+    _render_pipeline_state = CreateRenderPipelineState(device);
+  if (!_render_pipeline_state)
+    return;
+
   // Update the layer's properties to match the IOSurface.
   [self setDrawableSize:CGSizeMake(width, height)];
-  [self setPixelFormat:mtl_format];
+  [self setPixelFormat:MTLPixelFormatRGBA16Float];
   [self setColorspace:cg_color_space];
 
   // Create a texture to wrap the IOSurface.
@@ -141,16 +226,42 @@
   base::scoped_nsprotocol<id<MTLCommandQueue>> command_queue(
       [device newCommandQueue]);
   id<MTLCommandBuffer> command_buffer = [command_queue commandBuffer];
-  id<MTLBlitCommandEncoder> encoder = [command_buffer blitCommandEncoder];
-  [encoder copyFromTexture:buffer_texture
-               sourceSlice:0
-               sourceLevel:0
-              sourceOrigin:MTLOriginMake(0, 0, 0)
-                sourceSize:MTLSizeMake(width, height, 1)
-                 toTexture:drawable_texture
-          destinationSlice:0
-          destinationLevel:0
-         destinationOrigin:MTLOriginMake(0, 0, 0)];
+  id<MTLRenderCommandEncoder> encoder = nil;
+  {
+    MTLRenderPassDescriptor* desc =
+        [MTLRenderPassDescriptor renderPassDescriptor];
+    desc.colorAttachments[0].texture = drawable_texture;
+    desc.colorAttachments[0].loadAction = MTLLoadActionClear;
+    desc.colorAttachments[0].storeAction = MTLStoreActionStore;
+    desc.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 0.0);
+    encoder = [command_buffer renderCommandEncoderWithDescriptor:desc];
+
+    MTLViewport viewport;
+    viewport.originX = 0;
+    viewport.originY = 0;
+    viewport.width = width;
+    viewport.height = height;
+    viewport.znear = -1.0;
+    viewport.zfar = 1.0;
+    [encoder setViewport:viewport];
+    [encoder setRenderPipelineState:_render_pipeline_state];
+    [encoder setFragmentTexture:buffer_texture atIndex:0];
+  }
+  {
+    simd::float2 positions[6] = {
+        simd::make_float2(0, 0), simd::make_float2(0, 1),
+        simd::make_float2(1, 1), simd::make_float2(1, 1),
+        simd::make_float2(1, 0), simd::make_float2(0, 0),
+    };
+    simd::float3x3 matrix(simd::make_float3(1, 0, 0),
+                          simd::make_float3(0, 1, 0),
+                          simd::make_float3(0, 0, 1));
+    [encoder setVertexBytes:positions length:sizeof(positions) atIndex:0];
+    [encoder setFragmentBytes:&matrix length:sizeof(matrix) atIndex:0];
+    [encoder drawPrimitives:MTLPrimitiveTypeTriangle
+                vertexStart:0
+                vertexCount:6];
+  }
   [encoder endEncoding];
   [command_buffer commit];
   [command_buffer waitUntilScheduled];
@@ -166,8 +277,29 @@
   // (HDR content will be clipped, but that would have happened anyway).
   if (@available(macos 10.15, *))
     return [[HDRCopierLayer alloc] init];
-  else
-    return [[CALayer alloc] init];
+  NOTREACHED();
+  return nil;
+}
+
+void UpdateHDRCopierLayer(CALayer* layer,
+                          IOSurfaceRef buffer,
+                          const gfx::ColorSpace& color_space) {
+  if (@available(macos 10.15, *)) {
+    if (auto* hdr_copier_layer = base::mac::ObjCCast<HDRCopierLayer>(layer)) {
+      [hdr_copier_layer setHDRContents:buffer withColorSpace:color_space];
+      return;
+    }
+  }
+  NOTREACHED();
+}
+
+bool ShouldUseHDRCopier(IOSurfaceRef buffer,
+                        const gfx::ColorSpace& color_space) {
+  if (@available(macos 10.15, *)) {
+    return color_space.IsHDR() &&
+           IOSurfaceGetMTLPixelFormat(buffer) != MTLPixelFormatInvalid;
+  }
+  return false;
 }
 
 }  // namespace metal
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc
index 6fe6155..23427eeb 100644
--- a/components/omnibox/common/omnibox_features.cc
+++ b/components/omnibox/common/omnibox_features.cc
@@ -283,12 +283,12 @@
 // Allow suggestions to be shown to the user on the New Tab Page upon focusing
 // URL bar (the omnibox).
 const base::Feature kZeroSuggestionsOnNTP{"OmniboxZeroSuggestionsOnNTP",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
+                                          base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Allow suggestions to be shown to the user on the New Tab Page upon focusing
 // the real search box.
 const base::Feature kZeroSuggestionsOnNTPRealbox{
-    "OmniboxZeroSuggestionsOnNTPRealbox", base::FEATURE_DISABLED_BY_DEFAULT};
+    "OmniboxZeroSuggestionsOnNTPRealbox", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Allow on-focus query refinements to be shown on the default SERP.
 const base::Feature kZeroSuggestionsOnSERP{"OmniboxZeroSuggestionsOnSERP",
diff --git a/components/optimization_guide/OWNERS b/components/optimization_guide/OWNERS
index 5ade4011..39af85a 100644
--- a/components/optimization_guide/OWNERS
+++ b/components/optimization_guide/OWNERS
@@ -1,3 +1,5 @@
-file://components/previews/OWNERS
+sophiechang@chromium.org
+mcrouse@chromium.org
+tbansal@chromium.org
 
 # COMPONENT: Internals>OptimizationGuide
diff --git a/components/payments/content/BUILD.gn b/components/payments/content/BUILD.gn
index 53bb352..47fa732 100644
--- a/components/payments/content/BUILD.gn
+++ b/components/payments/content/BUILD.gn
@@ -8,6 +8,8 @@
     "android_app_communication.h",
     "android_payment_app.cc",
     "android_payment_app.h",
+    "android_payment_app_factory.cc",
+    "android_payment_app_factory.h",
     "autofill_payment_app.cc",
     "autofill_payment_app.h",
     "autofill_payment_app_factory.cc",
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentAppFactoryParams.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentAppFactoryParams.java
index 911fc24..57a9817f 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentAppFactoryParams.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentAppFactoryParams.java
@@ -77,8 +77,8 @@
     }
 
     /**
-     * @return The Android package name of the Trusted Web Activity that invoked Chrome, if any.
-     * Otherwise null or empty string.
+     * @return The Android package name of the Trusted Web Activity that invoked Chrome, if running
+     * in TWA mode. Otherwise null or empty string.
      */
     @Nullable
     default String getTwaPackageName() {
diff --git a/components/payments/content/android_payment_app_factory.cc b/components/payments/content/android_payment_app_factory.cc
new file mode 100644
index 0000000..52cc539
--- /dev/null
+++ b/components/payments/content/android_payment_app_factory.cc
@@ -0,0 +1,73 @@
+// 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/content/android_payment_app_factory.h"
+
+#include <utility>
+
+#include "base/memory/weak_ptr.h"
+#include "base/supports_user_data.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+
+namespace payments {
+namespace {
+
+class AppFinder : public base::SupportsUserData::Data {
+ public:
+  static base::WeakPtr<AppFinder> CreateAndSetOwnedBy(
+      base::SupportsUserData* owner) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    DCHECK(owner);
+    auto owned = std::make_unique<AppFinder>(owner);
+    auto weak_ptr = owned->weak_ptr_factory_.GetWeakPtr();
+    const void* key = owned.get();
+    owner->SetUserData(key, std::move(owned));
+    return weak_ptr;
+  }
+
+  explicit AppFinder(base::SupportsUserData* owner) : owner_(owner) {}
+  ~AppFinder() override = default;
+
+  AppFinder(const AppFinder& other) = delete;
+  AppFinder& operator=(const AppFinder& other) = delete;
+
+  void FindApps(base::WeakPtr<PaymentAppFactory::Delegate> delegate) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    DCHECK_EQ(nullptr, delegate_.get());
+    DCHECK_NE(nullptr, delegate.get());
+
+    delegate_ = delegate;
+
+    OnDoneCreatingPaymentApps();
+  }
+
+ private:
+  void OnDoneCreatingPaymentApps() {
+    if (delegate_)
+      delegate_->OnDoneCreatingPaymentApps();
+
+    owner_->RemoveUserData(this);
+  }
+
+  base::SupportsUserData* owner_;
+  base::WeakPtr<PaymentAppFactory::Delegate> delegate_;
+
+  base::WeakPtrFactory<AppFinder> weak_ptr_factory_{this};
+};
+
+}  // namespace
+
+AndroidPaymentAppFactory::AndroidPaymentAppFactory()
+    : PaymentAppFactory(PaymentApp::Type::NATIVE_MOBILE_APP) {}
+
+AndroidPaymentAppFactory::~AndroidPaymentAppFactory() = default;
+
+void AndroidPaymentAppFactory::Create(base::WeakPtr<Delegate> delegate) {
+  auto app_finder = AppFinder::CreateAndSetOwnedBy(delegate->GetWebContents());
+  app_finder->FindApps(delegate);
+}
+
+}  // namespace payments
diff --git a/components/payments/content/android_payment_app_factory.h b/components/payments/content/android_payment_app_factory.h
new file mode 100644
index 0000000..0c8e8149
--- /dev/null
+++ b/components/payments/content/android_payment_app_factory.h
@@ -0,0 +1,28 @@
+// 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_CONTENT_ANDROID_PAYMENT_APP_FACTORY_H_
+#define COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_APP_FACTORY_H_
+
+#include "components/payments/content/payment_app_factory.h"
+
+namespace payments {
+
+// Retrieves Android payment apps.
+class AndroidPaymentAppFactory : public PaymentAppFactory {
+ public:
+  AndroidPaymentAppFactory();
+  ~AndroidPaymentAppFactory() override;
+
+  AndroidPaymentAppFactory(const AndroidPaymentAppFactory& other) = delete;
+  AndroidPaymentAppFactory& operator=(const AndroidPaymentAppFactory& other) =
+      delete;
+
+  // PaymentAppFactory:
+  void Create(base::WeakPtr<Delegate> delegate) override;
+};
+
+}  // namespace payments
+
+#endif  // COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_APP_FACTORY_H_
diff --git a/components/payments/content/payment_app_factory.h b/components/payments/content/payment_app_factory.h
index be8a773..b9e95236 100644
--- a/components/payments/content/payment_app_factory.h
+++ b/components/payments/content/payment_app_factory.h
@@ -57,6 +57,10 @@
     virtual bool IsOffTheRecord() const = 0;
     virtual PaymentRequestSpec* GetSpec() const = 0;
 
+    // Returns the Android package name of the Trusted Web Activity that invoked
+    // this browser, if any. Otherwise, an empty string.
+    virtual std::string GetTwaPackageName() const = 0;
+
     // Tells the UI to show the processing spinner. Only desktop UI needs this
     // notification.
     virtual void ShowProcessingSpinner() = 0;
diff --git a/components/payments/content/payment_app_service.cc b/components/payments/content/payment_app_service.cc
index 1dc68fb0..94c35c9 100644
--- a/components/payments/content/payment_app_service.cc
+++ b/components/payments/content/payment_app_service.cc
@@ -5,9 +5,12 @@
 #include "components/payments/content/payment_app_service.h"
 
 #include "base/feature_list.h"
+#include "components/payments/content/android_payment_app_factory.h"
 #include "components/payments/content/autofill_payment_app_factory.h"
 #include "components/payments/content/payment_app.h"
 #include "components/payments/content/service_worker_payment_app_factory.h"
+#include "components/payments/core/features.h"
+#include "components/payments/core/payments_experimental_features.h"
 #include "content/public/common/content_features.h"
 
 namespace payments {
@@ -15,8 +18,17 @@
 PaymentAppService::PaymentAppService() {
   factories_.emplace_back(std::make_unique<AutofillPaymentAppFactory>());
 
-  if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps))
+  if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) {
     factories_.emplace_back(std::make_unique<ServiceWorkerPaymentAppFactory>());
+  }
+
+  // TODO(https://crbug.com/1022512): Review the feature flag name when
+  // AndroidPaymentAppFactory works on Android OS with generic 3rd party payment
+  // apps. (Currently it works only on Chrome OS with app store billing payment
+  // methods.)
+  if (PaymentsExperimentalFeatures::IsEnabled(features::kAppStoreBilling)) {
+    factories_.emplace_back(std::make_unique<AndroidPaymentAppFactory>());
+  }
 }
 
 PaymentAppService::~PaymentAppService() = default;
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc
index 0de5a47..b5068ca 100644
--- a/components/payments/content/payment_request_state.cc
+++ b/components/payments/content/payment_request_state.cc
@@ -111,6 +111,10 @@
   return spec_;
 }
 
+std::string PaymentRequestState::GetTwaPackageName() const {
+  return GetPaymentRequestDelegate()->GetTwaPackageName();
+}
+
 const GURL& PaymentRequestState::GetTopOrigin() {
   return top_origin_;
 }
diff --git a/components/payments/content/payment_request_state.h b/components/payments/content/payment_request_state.h
index 41efb2eef..f401aa8f 100644
--- a/components/payments/content/payment_request_state.h
+++ b/components/payments/content/payment_request_state.h
@@ -132,6 +132,7 @@
   ContentPaymentRequestDelegate* GetPaymentRequestDelegate() const override;
   void ShowProcessingSpinner() override;
   PaymentRequestSpec* GetSpec() const override;
+  std::string GetTwaPackageName() const override;
   const GURL& GetTopOrigin() override;
   const GURL& GetFrameOrigin() override;
   const url::Origin& GetFrameSecurityOrigin() override;
diff --git a/components/payments/core/BUILD.gn b/components/payments/core/BUILD.gn
index d153d4d..2dfd44e3 100644
--- a/components/payments/core/BUILD.gn
+++ b/components/payments/core/BUILD.gn
@@ -6,6 +6,8 @@
   sources = [
     "android_app_description.cc",
     "android_app_description.h",
+    "android_app_description_tools.cc",
+    "android_app_description_tools.h",
     "autofill_card_validation.cc",
     "autofill_card_validation.h",
     "basic_card_response.cc",
@@ -151,6 +153,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "android_app_description_tools_unittest.cc",
     "can_make_payment_query_unittest.cc",
     "currency_formatter_unittest.cc",
     "journey_logger_unittest.cc",
diff --git a/components/payments/core/android_app_description_tools.cc b/components/payments/core/android_app_description_tools.cc
new file mode 100644
index 0000000..7183601d
--- /dev/null
+++ b/components/payments/core/android_app_description_tools.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/android_app_description_tools.h"
+
+#include <utility>
+
+#include "base/check.h"
+#include "components/payments/core/android_app_description.h"
+
+namespace payments {
+
+void SplitPotentiallyMultipleActivities(
+    std::unique_ptr<AndroidAppDescription> app,
+    std::vector<std::unique_ptr<AndroidAppDescription>>* destination) {
+  DCHECK(destination);
+  if (app->activities.empty())
+    return;
+  destination->emplace_back(std::move(app));
+  for (size_t i = 1; i < destination->front()->activities.size(); ++i) {
+    auto single_activity_app = std::make_unique<AndroidAppDescription>();
+    single_activity_app->package = destination->front()->package;
+    single_activity_app->service_names = destination->front()->service_names;
+    single_activity_app->activities.emplace_back(
+        std::move(destination->front()->activities[i]));
+    destination->emplace_back(std::move(single_activity_app));
+  }
+  destination->front()->activities.resize(1);
+}
+
+}  // namespace payments
diff --git a/components/payments/core/android_app_description_tools.h b/components/payments/core/android_app_description_tools.h
new file mode 100644
index 0000000..53036905
--- /dev/null
+++ b/components/payments/core/android_app_description_tools.h
@@ -0,0 +1,29 @@
+// 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_ANDROID_APP_DESCRIPTION_TOOLS_H_
+#define COMPONENTS_PAYMENTS_CORE_ANDROID_APP_DESCRIPTION_TOOLS_H_
+
+#include <memory>
+#include <vector>
+
+namespace payments {
+
+struct AndroidAppDescription;
+
+// Moves each activity in the given |app| into its own AndroidAppDescription in
+// |destination|, so the code can treat each PAY intent target as its own
+// payment app.
+//
+// The function does not clear |destination|, so the results of multiple calls
+// can be appended to the same |destination|, e.g., in a loop.
+//
+// The |destination| should not be null.
+void SplitPotentiallyMultipleActivities(
+    std::unique_ptr<AndroidAppDescription> app,
+    std::vector<std::unique_ptr<AndroidAppDescription>>* destination);
+
+}  // namespace payments
+
+#endif  // COMPONENTS_PAYMENTS_CORE_ANDROID_APP_DESCRIPTION_TOOLS_H_
diff --git a/components/payments/core/android_app_description_tools_unittest.cc b/components/payments/core/android_app_description_tools_unittest.cc
new file mode 100644
index 0000000..e769773
--- /dev/null
+++ b/components/payments/core/android_app_description_tools_unittest.cc
@@ -0,0 +1,85 @@
+// 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/android_app_description_tools.h"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "components/payments/core/android_app_description.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace payments {
+namespace {
+
+// Absence of activities should result in zero apps.
+TEST(AndroidAppDescriptionToolsTest, SplitNoActivities) {
+  std::vector<std::unique_ptr<AndroidAppDescription>> destination;
+  SplitPotentiallyMultipleActivities(std::make_unique<AndroidAppDescription>(),
+                                     &destination);
+  EXPECT_TRUE(destination.empty());
+}
+
+// One activity should result in one app.
+TEST(AndroidAppDescriptionToolsTest, SplitOneActivity) {
+  std::vector<std::unique_ptr<AndroidAppDescription>> destination;
+  auto app = std::make_unique<AndroidAppDescription>();
+  app->package = "com.example.app";
+  app->service_names = {"com.example.app.Service"};
+  app->activities.emplace_back(std::make_unique<AndroidActivityDescription>());
+  app->activities.back()->name = "com.example.app.Activity";
+  app->activities.back()->default_payment_method = "https://example.test";
+
+  SplitPotentiallyMultipleActivities(std::move(app), &destination);
+
+  ASSERT_EQ(1U, destination.size());
+  EXPECT_EQ("com.example.app", destination.back()->package);
+  EXPECT_EQ(std::vector<std::string>{"com.example.app.Service"},
+            destination.back()->service_names);
+  ASSERT_EQ(1U, destination.back()->activities.size());
+  EXPECT_EQ("com.example.app.Activity",
+            destination.back()->activities.back()->name);
+  EXPECT_EQ("https://example.test",
+            destination.back()->activities.back()->default_payment_method);
+}
+
+// Two activities should result in two apps.
+TEST(AndroidAppDescriptionToolsTest, SplitTwoActivities) {
+  std::vector<std::unique_ptr<AndroidAppDescription>> destination;
+  auto app = std::make_unique<AndroidAppDescription>();
+  app->package = "com.example.app";
+  app->service_names = {"com.example.app.Service"};
+  app->activities.emplace_back(std::make_unique<AndroidActivityDescription>());
+  app->activities.back()->name = "com.example.app.ActivityOne";
+  app->activities.back()->default_payment_method = "https://one.test";
+  app->activities.emplace_back(std::make_unique<AndroidActivityDescription>());
+  app->activities.back()->name = "com.example.app.ActivityTwo";
+  app->activities.back()->default_payment_method = "https://two.test";
+
+  SplitPotentiallyMultipleActivities(std::move(app), &destination);
+
+  ASSERT_EQ(2U, destination.size());
+
+  EXPECT_EQ("com.example.app", destination.front()->package);
+  EXPECT_EQ(std::vector<std::string>{"com.example.app.Service"},
+            destination.front()->service_names);
+  ASSERT_EQ(1U, destination.front()->activities.size());
+  EXPECT_EQ("com.example.app.ActivityOne",
+            destination.front()->activities.back()->name);
+  EXPECT_EQ("https://one.test",
+            destination.front()->activities.back()->default_payment_method);
+
+  EXPECT_EQ("com.example.app", destination.back()->package);
+  EXPECT_EQ(std::vector<std::string>{"com.example.app.Service"},
+            destination.back()->service_names);
+  ASSERT_EQ(1U, destination.back()->activities.size());
+  EXPECT_EQ("com.example.app.ActivityTwo",
+            destination.back()->activities.back()->name);
+  EXPECT_EQ("https://two.test",
+            destination.back()->activities.back()->default_payment_method);
+}
+
+}  // namespace
+}  // namespace payments
diff --git a/components/payments/core/payment_request_data_util.cc b/components/payments/core/payment_request_data_util.cc
index 9d7766d..5d5049533 100644
--- a/components/payments/core/payment_request_data_util.cc
+++ b/components/payments/core/payment_request_data_util.cc
@@ -166,5 +166,17 @@
   return number;
 }
 
+std::map<std::string, std::set<std::string>> FilterStringifiedMethodData(
+    const std::map<std::string, std::set<std::string>>& stringified_method_data,
+    const std::set<std::string>& supported_payment_method_names) {
+  std::map<std::string, std::set<std::string>> result;
+  for (const auto& pair : stringified_method_data) {
+    if (base::Contains(supported_payment_method_names, pair.first)) {
+      result[pair.first] = pair.second;
+    }
+  }
+  return result;
+}
+
 }  // namespace data_util
 }  // namespace payments
diff --git a/components/payments/core/payment_request_data_util.h b/components/payments/core/payment_request_data_util.h
index 633d517..f8d3c18 100644
--- a/components/payments/core/payment_request_data_util.h
+++ b/components/payments/core/payment_request_data_util.h
@@ -64,6 +64,23 @@
 // numbers, which start with a letter.
 base::string16 FormatCardNumberForDisplay(const base::string16& card_number);
 
+// Returns the subset of |stringified_method_data| map where the keys are in the
+// |supported_payment_method_names| set. Used for ensuring that a payment app
+// will not be queried about payment method names that it does not support.
+//
+// FilterStringifiedMethodData({"a": {"b"}: "c": {"d"}}, {"a"}) -> {"a": {"b"}}
+//
+// Both the return value and the first parameter to the function have the
+// following format:
+// Key: Payment method identifier, such as "example-test" or
+//      "https://example.test".
+// Value: The set of all payment method specific parameters for the given
+//        payment method identifier, each one serialized into a JSON string,
+//        e.g., '{"key": "value"}'.
+std::map<std::string, std::set<std::string>> FilterStringifiedMethodData(
+    const std::map<std::string, std::set<std::string>>& stringified_method_data,
+    const std::set<std::string>& supported_payment_method_names);
+
 }  // namespace data_util
 }  // namespace payments
 
diff --git a/components/payments/core/payment_request_data_util_unittest.cc b/components/payments/core/payment_request_data_util_unittest.cc
index b034fca..4ed42179 100644
--- a/components/payments/core/payment_request_data_util_unittest.cc
+++ b/components/payments/core/payment_request_data_util_unittest.cc
@@ -4,7 +4,10 @@
 
 #include "components/payments/core/payment_request_data_util.h"
 
+#include <map>
 #include <memory>
+#include <set>
+#include <string>
 
 #include "base/json/json_writer.h"
 #include "base/macros.h"
@@ -274,5 +277,25 @@
               UnorderedElementsAre(kBasicCardMethodName, kBobPayMethod));
 }
 
+TEST(PaymentRequestDataUtil, FilterStringifiedMethodData) {
+  std::map<std::string, std::set<std::string>> requested;
+  std::set<std::string> supported;
+  EXPECT_TRUE(FilterStringifiedMethodData(requested, supported).empty());
+
+  requested["a"].insert("{\"b\": \"c\"}");
+  EXPECT_TRUE(FilterStringifiedMethodData(requested, supported).empty());
+
+  requested["x"].insert("{\"y\": \"z\"}");
+  EXPECT_TRUE(FilterStringifiedMethodData(requested, supported).empty());
+
+  supported.insert("x");
+  std::map<std::string, std::set<std::string>> expected;
+  expected["x"].insert("{\"y\": \"z\"}");
+  EXPECT_EQ(expected, FilterStringifiedMethodData(requested, supported));
+
+  supported.insert("g");
+  EXPECT_EQ(expected, FilterStringifiedMethodData(requested, supported));
+}
+
 }  // namespace data_util
 }  // namespace payments
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 9753d4c..fa11993 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -499,6 +499,8 @@
       'desc': '''Content settings allow you to specify how contents of a specific type (for example Cookies, Images or JavaScript) is handled.''',
       'policies': [
         'DefaultCookiesSetting',
+        'DefaultFileSystemReadGuardSetting',
+        'DefaultFileSystemWriteGuardSetting',
         'DefaultImagesSetting',
         'DefaultInsecureContentSetting',
         'DefaultJavaScriptSetting',
@@ -516,6 +518,10 @@
         'CookiesAllowedForUrls',
         'CookiesBlockedForUrls',
         'CookiesSessionOnlyForUrls',
+        'FileSystemReadAskForUrls',
+        'FileSystemReadBlockedForUrls',
+        'FileSystemWriteAskForUrls',
+        'FileSystemWriteBlockedForUrls',
         'ImagesAllowedForUrls',
         'ImagesBlockedForUrls',
         'InsecureContentAllowedForUrls',
@@ -5992,7 +5998,174 @@
       URL patterns can't conflict with <ph name="SERIAL_ASK_FOR_URLS_POLICY_NAME">SerialAskForUrls</ph>. Neither policy takes precedence if a URL matches with both.
 
       For detailed information on valid <ph name="URL_LABEL">url</ph> patterns, please see https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns.''',
-    },{
+    },
+    {
+      'name': 'DefaultFileSystemReadGuardSetting',
+      'owners': ['mek@chromium.org', 'file://content/browser/native_file_system/OWNERS'],
+      'type': 'int-enum',
+      'schema': {
+        'type': 'integer',
+        'enum': [ 2, 3 ],
+      },
+      'items': [
+        {
+          'name': 'BlockFileSystemRead',
+          'value': 2,
+          'caption': '''Do not allow any site to request read access to files and directories via the File System API''',
+        },
+        {
+          'name': 'AskFileSystemRead',
+          'value': 3,
+          'caption': '''Allow sites to ask the user to grant read access to files and directories via the File System API''',
+        },
+      ],
+      'supported_on': ['chrome_os:86-', 'chrome.*:86-'],
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': True,
+      },
+      'example_value': 2,
+      'id': 773,
+      'caption': '''Control use of the File System API for reading''',
+      'tags': ['website-sharing'],
+      'desc': '''Setting the policy to 3 lets websites ask for read access to files and directories in the host operating system's file system via the File System API. Setting the policy to 2 denies access.
+
+      Leaving it unset lets websites ask for access, but users can change this setting.''',
+    },
+    {
+      'name': 'DefaultFileSystemWriteGuardSetting',
+      'owners': ['mek@chromium.org', 'file://content/browser/native_file_system/OWNERS'],
+      'type': 'int-enum',
+      'schema': {
+        'type': 'integer',
+        'enum': [ 2, 3 ],
+      },
+      'items': [
+        {
+          'name': 'BlockFileSystemWrite',
+          'value': 2,
+          'caption': '''Do not allow any site to request write access to files and directories''',
+        },
+        {
+          'name': 'AskFileSystemWrite',
+          'value': 3,
+          'caption': '''Allow sites to ask the user to grant write access to files and directories''',
+        },
+      ],
+      'supported_on': ['chrome_os:86-', 'chrome.*:86-'],
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': True,
+      },
+      'example_value': 2,
+      'id': 774,
+      'caption': '''Control use of the File System API for writing''',
+      'tags': ['website-sharing'],
+      'desc': '''Setting the policy to 3 lets websites ask for write access to files and directories in the host operating system's file system. Setting the policy to 2 denies access.
+
+      Leaving it unset lets websites ask for access, but users can change this setting.''',
+    },
+    {
+      'name': 'FileSystemReadAskForUrls',
+      'owners': ['mek@chromium.org', 'file://content/browser/native_file_system/OWNERS'],
+      'type': 'list',
+      'schema': {
+        'type': 'array',
+        'items': { 'type': 'string' },
+      },
+      'supported_on': ['chrome_os:86-', 'chrome.*:86-'],
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': True,
+      },
+      'example_value': ['https://www.example.com', '[*.]example.edu'],
+      'id': 775,
+      'caption': '''Allow read access via the File System API on these sites''',
+      'tags': ['website-sharing'],
+      'desc': '''Setting the policy lets you list the URL patterns that specify which sites can ask users to grant them read access to files or directories in the host operating system's file system via the File System API.
+
+      Leaving the policy unset means <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME">DefaultFileSystemReadGuardSetting</ph> applies for all sites, if it's set. If not, users' personal settings apply.
+
+      URL patterns must not conflict with <ph name="FILE_SYSTEM_READ_BLOCKED_FOR_URLS_POLICY_NAME">FileSystemReadBlockedForUrls</ph>. Neither policy takes precedence if a URL matches with both.
+
+      For detailed information on valid <ph name="URL_LABEL">url</ph> patterns, please see https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns.''',
+    },
+    {
+      'name': 'FileSystemReadBlockedForUrls',
+      'owners': ['mek@chromium.org', 'file://content/browser/native_file_system/OWNERS'],
+      'type': 'list',
+      'schema': {
+        'type': 'array',
+        'items': { 'type': 'string' },
+      },
+      'supported_on': ['chrome_os:86-', 'chrome.*:86-'],
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': True,
+      },
+      'example_value': ['https://www.example.com', '[*.]example.edu'],
+      'id': 776,
+      'caption': '''Block read access via the File System API on these sites''',
+      'tags': [],
+      'desc': '''Setting the policy lets you list the URL patterns that specify which sites can't ask users to grant them read access to files or directories in the host operating system's file system via the File System API.
+
+      Leaving the policy unset means <ph name="DEFAULT_FILE_SYSTEM_READ_GUARD_SETTING_POLICY_NAME">DefaultFileSystemReadGuardSetting</ph> applies for all sites, if it's set. If not, users' personal settings apply.
+
+      URL patterns can't conflict with <ph name="FILE_SYSTEM_READ_ASK_FOR_URLS_POLICY_NAME">FileSystemReadAskForUrls</ph>. Neither policy takes precedence if a URL matches with both.
+
+      For detailed information on valid <ph name="URL_LABEL">url</ph> patterns, please see https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns.''',
+    },
+    {
+      'name': 'FileSystemWriteAskForUrls',
+      'owners': ['mek@chromium.org', 'file://content/browser/native_file_system/OWNERS'],
+      'type': 'list',
+      'schema': {
+        'type': 'array',
+        'items': { 'type': 'string' },
+      },
+      'supported_on': ['chrome_os:86-', 'chrome.*:86-'],
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': True,
+      },
+      'example_value': ['https://www.example.com', '[*.]example.edu'],
+      'id': 777,
+      'caption': '''Allow write access to files and directories on these sites''',
+      'tags': ['website-sharing'],
+      'desc': '''Setting the policy lets you list the URL patterns that specify which sites can ask users to grant them write access to files or directories in the host operating system's file system.
+
+      Leaving the policy unset means <ph name="DEFAULT_FILE_SYSTEM_WRITE_GUARD_SETTING_POLICY_NAME">DefaultFileSystemWriteGuardSetting</ph> applies for all sites, if it's set. If not, users' personal settings apply.
+
+      URL patterns must not conflict with <ph name="FILE_SYSTEM_WRITE_BLOCKED_FOR_URLS_POLICY_NAME">FileSystemWriteBlockedForUrls</ph>. Neither policy takes precedence if a URL matches with both.
+
+      For detailed information on valid <ph name="URL_LABEL">url</ph> patterns, please see https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns.''',
+    },
+    {
+      'name': 'FileSystemWriteBlockedForUrls',
+      'owners': ['mek@chromium.org', 'file://content/browser/native_file_system/OWNERS'],
+      'type': 'list',
+      'schema': {
+        'type': 'array',
+        'items': { 'type': 'string' },
+      },
+      'supported_on': ['chrome_os:86-', 'chrome.*:86-'],
+      'features': {
+        'dynamic_refresh': True,
+        'per_profile': True,
+      },
+      'example_value': ['https://www.example.com', '[*.]example.edu'],
+      'id': 778,
+      'caption': '''Block write access to files and directories on these sites''',
+      'tags': [],
+      'desc': '''Setting the policy lets you list the URL patterns that specify which sites can't ask users to grant them write access to files or directories in the host operating system's file system.
+
+      Leaving the policy unset means <ph name="DEFAULT_FILE_SYSTEM_WRITE_GUARD_SETTING_POLICY_NAME">DefaultFileSystemWriteGuardSetting</ph> applies for all sites, if it's set. If not, users' personal settings apply.
+
+      URL patterns can't conflict with <ph name="FILE_SYSTEM_WRITE_ASK_FOR_URLS_POLICY_NAME">FileSystemWriteAskForUrls</ph>. Neither policy takes precedence if a URL matches with both.
+
+      For detailed information on valid <ph name="URL_LABEL">url</ph> patterns, please see https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns.''',
+    },
+    {
       'name': 'AutoSelectCertificateForUrls',
       'owners': ['file://components/policy/resources/OWNERS'],
       'type': 'list',
@@ -23952,6 +24125,6 @@
   ],
   'placeholders': [],
   'deleted_policy_ids': [412, 476, 546, 562, 569, 578],
-  'highest_id_currently_used': 772,
+  'highest_id_currently_used': 778,
   'highest_atomic_group_id_currently_used': 40
 }
diff --git a/components/previews/OWNERS b/components/previews/OWNERS
index 75baba8..39bc744 100644
--- a/components/previews/OWNERS
+++ b/components/previews/OWNERS
@@ -1,3 +1,7 @@
-file://components/data_reduction_proxy/OWNERS
+mcrouse@chromium.org
+robertogden@chromium.org
+ryansturm@chromium.org
+sophiechang@chromium.org
+tbansal@chromium.org
 
-# COMPONENT: Blink>Previews
\ No newline at end of file
+# COMPONENT: Blink>Previews
diff --git a/content/browser/accessibility/accessibility_tree_formatter_base.cc b/content/browser/accessibility/accessibility_tree_formatter_base.cc
index a8f3c180..c7b0358 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_base.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_base.cc
@@ -43,21 +43,23 @@
   // Property invocation: property_str expected format is
   // prop_name or prop_name(arg1, ... argN).
   PropertyNode root;
-  Parse(&root, filter.property_str.begin(), filter.property_str.end());
+  std::string property_str = base::UTF16ToUTF8(filter.property_str);
+  Parse(&root, property_str.begin(), property_str.end());
 
   PropertyNode* node = &root.parameters[0];
 
   // Expel a trailing wildcard if any.
   node->original_property =
-      filter.property_str.substr(0, filter.property_str.find_last_of('*'));
+      property_str.substr(0, property_str.find_last_of('*'));
 
   // Line indexes filter: filter_str expected format is
   // :line_num_1, ... :line_num_N, a comma separated list of line indexes
   // the property should be queried for. For example, ":1,:5,:7" indicates that
   // the property should called for objects placed on 1, 5 and 7 lines only.
-  if (!filter.filter_str.empty()) {
+  std::string filter_str = base::UTF16ToUTF8(filter.filter_str);
+  if (!filter_str.empty()) {
     node->line_indexes =
-        base::SplitString(filter.filter_str, base::string16(1, ','),
+        base::SplitString(filter_str, std::string(1, ','),
                           base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
   }
 
@@ -86,7 +88,7 @@
   return !name_or_value.empty();
 }
 
-bool PropertyNode::IsMatching(const base::string16& pattern) const {
+bool PropertyNode::IsMatching(const std::string& pattern) const {
   // Looking for exact property match. Expel a trailing whildcard from
   // the property filter to handle filters like AXRole*.
   return name_or_value.compare(0, name_or_value.find_last_of('*'), pattern) ==
@@ -94,11 +96,11 @@
 }
 
 bool PropertyNode::IsArray() const {
-  return name_or_value == base::ASCIIToUTF16("[]");
+  return name_or_value == "[]";
 }
 
 bool PropertyNode::IsDict() const {
-  return name_or_value == base::ASCIIToUTF16("{}");
+  return name_or_value == "{}";
 }
 
 base::Optional<int> PropertyNode::AsInt() const {
@@ -111,17 +113,17 @@
 
 const PropertyNode* PropertyNode::FindKey(const char* refkey) const {
   for (const auto& param : parameters) {
-    if (param.key == base::ASCIIToUTF16(refkey)) {
+    if (param.key == refkey) {
       return &param;
     }
   }
   return nullptr;
 }
 
-base::Optional<base::string16> PropertyNode::FindStringKey(
+base::Optional<std::string> PropertyNode::FindStringKey(
     const char* refkey) const {
   for (const auto& param : parameters) {
-    if (param.key == base::ASCIIToUTF16(refkey)) {
+    if (param.key == refkey) {
       return param.name_or_value;
     }
   }
@@ -130,7 +132,7 @@
 
 base::Optional<int> PropertyNode::FindIntKey(const char* refkey) const {
   for (const auto& param : parameters) {
-    if (param.key == base::ASCIIToUTF16(refkey)) {
+    if (param.key == refkey) {
       return param.AsInt();
     }
   }
@@ -143,16 +145,16 @@
     if (!out.empty()) {
       out += ',';
     }
-    out += base::UTF16ToUTF8(index);
+    out += index;
   }
   if (!out.empty()) {
     out += ';';
   }
 
   if (!key.empty()) {
-    out += base::UTF16ToUTF8(key) + ": ";
+    out += key + ": ";
   }
-  out += base::UTF16ToUTF8(name_or_value);
+  out += name_or_value;
   if (parameters.size()) {
     out += '(';
     for (size_t i = 0; i < parameters.size(); i++) {
@@ -169,7 +171,7 @@
 // private
 PropertyNode::PropertyNode(PropertyNode::iterator key_begin,
                            PropertyNode::iterator key_end,
-                           const base::string16& name_or_value)
+                           const std::string& name_or_value)
     : key(key_begin, key_end), name_or_value(name_or_value) {}
 PropertyNode::PropertyNode(PropertyNode::iterator begin,
                            PropertyNode::iterator end)
@@ -199,8 +201,7 @@
     // Subnode begins: a special case for arrays, which have [arg1, ..., argN]
     // form.
     if (*iter == '[') {
-      node->parameters.push_back(
-          PropertyNode(key_begin, key_end, base::UTF8ToUTF16("[]")));
+      node->parameters.push_back(PropertyNode(key_begin, key_end, "[]"));
       key_begin = key_end = end;
       begin = iter = Parse(&node->parameters.back(), ++iter, end);
       continue;
@@ -209,8 +210,7 @@
     // Subnode begins: a special case for dictionaries of {key1: value1, ...,
     // key2: value2} form.
     if (*iter == '{') {
-      node->parameters.push_back(
-          PropertyNode(key_begin, key_end, base::UTF8ToUTF16("{}")));
+      node->parameters.push_back(PropertyNode(key_begin, key_end, "{}"));
       key_begin = key_end = end;
       begin = iter = Parse(&node->parameters.back(), ++iter, end);
       continue;
@@ -451,7 +451,7 @@
 
 std::vector<PropertyNode>
 AccessibilityTreeFormatterBase::PropertyFilterNodesFor(
-    const base::string16& line_index) const {
+    const std::string& line_index) const {
   std::vector<PropertyNode> list;
   for (const auto& filter : property_filters_) {
     PropertyNode property_node = PropertyNode::FromPropertyFilter(filter);
diff --git a/content/browser/accessibility/accessibility_tree_formatter_base.h b/content/browser/accessibility/accessibility_tree_formatter_base.h
index e2cf123..ab84184 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_base.h
+++ b/content/browser/accessibility/accessibility_tree_formatter_base.h
@@ -48,10 +48,10 @@
   explicit operator bool() const;
 
   // Key name in case of { key: value } dictionary.
-  base::string16 key;
+  std::string key;
 
   // Value or a property name, for example 3 or AXLineForIndex
-  base::string16 name_or_value;
+  std::string name_or_value;
 
   // Parameters if it's a property, for example, it is a vector of a single
   // value 3 in case of AXLineForIndex(3)
@@ -59,30 +59,30 @@
 
   // Used to store the origianl unparsed property including invocation
   // parameters if any.
-  base::string16 original_property;
+  std::string original_property;
 
   // The list of line indexes of accessible objects the property is allowed to
   // be called for.
-  std::vector<base::string16> line_indexes;
+  std::vector<std::string> line_indexes;
 
-  bool IsMatching(const base::string16& pattern) const;
+  bool IsMatching(const std::string& pattern) const;
 
   // Argument conversion methods.
   bool IsArray() const;
   bool IsDict() const;
   base::Optional<int> AsInt() const;
   const PropertyNode* FindKey(const char* refkey) const;
-  base::Optional<base::string16> FindStringKey(const char* refkey) const;
+  base::Optional<std::string> FindStringKey(const char* refkey) const;
   base::Optional<int> FindIntKey(const char* key) const;
 
   std::string ToString() const;
 
  private:
-  using iterator = base::string16::const_iterator;
+  using iterator = std::string::const_iterator;
 
   explicit PropertyNode(iterator key_begin,
                         iterator key_end,
-                        const base::string16&);
+                        const std::string&);
   PropertyNode(iterator begin, iterator end);
   PropertyNode(iterator key_begin,
                iterator key_end,
@@ -156,7 +156,7 @@
   // Returns property nodes complying to the line index filter for all
   // allow/allow_empty property filters.
   std::vector<PropertyNode> PropertyFilterNodesFor(
-      const base::string16& line_index) const;
+      const std::string& line_index) const;
 
   // Return true if match-all filter is present.
   bool HasMatchAllPropertyFilter() const;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_base_unittest.cc b/content/browser/accessibility/accessibility_tree_formatter_base_unittest.cc
index be85b706..f66f5c9 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_base_unittest.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_base_unittest.cc
@@ -92,10 +92,10 @@
   // Dict: FindStringKey
   EXPECT_EQ(
       GetArgumentNode("Text({start: :1, dir: forward})").FindStringKey("start"),
-      base::ASCIIToUTF16(":1"));
+      ":1");
   EXPECT_EQ(
       GetArgumentNode("Text({start: :1, dir: forward})").FindStringKey("dir"),
-      base::ASCIIToUTF16("forward"));
+      "forward");
   EXPECT_EQ(GetArgumentNode("Text({start: :1, dir: forward})")
                 .FindStringKey("notexists"),
             base::nullopt);
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index 3846ac2..f60a93dd 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -216,9 +216,7 @@
   }
 
   // Otherwise dump attributes matching allow filters only.
-  base::string16 line_index =
-      base::UTF8ToUTF16(line_indexes_map.IndexBy(cocoa_node));
-
+  std::string line_index = line_indexes_map.IndexBy(cocoa_node);
   for (const PropertyNode& property_node : PropertyFilterNodesFor(line_index)) {
     AttributeInvoker invoker(cocoa_node, line_indexes_map);
     OptionalNSObject value = invoker.Invoke(property_node);
@@ -226,11 +224,11 @@
       continue;
     }
     if (value.IsError()) {
-      dict->SetPath(base::UTF16ToUTF8(property_node.original_property),
+      dict->SetPath(property_node.original_property,
                     base::Value(kFailedToParseArgsError));
       continue;
     }
-    dict->SetPath(base::UTF16ToUTF8(property_node.original_property),
+    dict->SetPath(property_node.original_property,
                   PopulateObject(*value, line_indexes_map));
   }
 
diff --git a/content/browser/accessibility/accessibility_tree_formatter_utils_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_utils_mac.mm
index a6d1fc76..71126d0 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_utils_mac.mm
+++ b/content/browser/accessibility/accessibility_tree_formatter_utils_mac.mm
@@ -12,7 +12,7 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
 
-using base::SysNSStringToUTF16;
+using base::SysNSStringToUTF8;
 
 namespace content {
 namespace a11y {
@@ -99,7 +99,7 @@
     const PropertyNode& property_node) const {
   // Attributes
   for (NSString* attribute : attributes) {
-    if (property_node.IsMatching(SysNSStringToUTF16(attribute))) {
+    if (property_node.IsMatching(SysNSStringToUTF8(attribute))) {
       return OptionalNSObject::NotNullOrNotApplicable(
           [cocoa_node accessibilityAttributeValue:attribute]);
     }
@@ -107,7 +107,7 @@
 
   // Parameterized attributes
   for (NSString* attribute : parameterized_attributes) {
-    if (property_node.IsMatching(SysNSStringToUTF16(attribute))) {
+    if (property_node.IsMatching(SysNSStringToUTF8(attribute))) {
       OptionalNSObject param = ParamByPropertyNode(property_node);
       if (param.IsNotNil()) {
         return OptionalNSObject([cocoa_node
@@ -138,8 +138,7 @@
   }
 
   // Otherwise parse argument node value.
-  std::string property_name = base::UTF16ToASCII(property_node.name_or_value);
-
+  const std::string& property_name = property_node.name_or_value;
   if (property_name == "AXLineForIndex" ||
       property_name == "AXTextMarkerForIndex") {  // Int
     return OptionalNSObject::NotNilOrError(PropertyNodeToInt(arg_node));
@@ -177,7 +176,7 @@
 // NSArray of two NSNumber. Format: [integer, integer].
 NSArray* AttributeInvoker::PropertyNodeToIntArray(
     const PropertyNode& arraynode) const {
-  if (arraynode.name_or_value != base::ASCIIToUTF16("[]")) {
+  if (arraynode.name_or_value != "[]") {
     INTARRAY_FAIL(arraynode, "not array")
   }
 
@@ -186,8 +185,7 @@
   for (const auto& paramnode : arraynode.parameters) {
     base::Optional<int> param = paramnode.AsInt();
     if (!param) {
-      INTARRAY_FAIL(arraynode, paramnode.name_or_value +
-                                   base::UTF8ToUTF16(" is not a number"))
+      INTARRAY_FAIL(arraynode, paramnode.name_or_value + " is not a number")
     }
     [array addObject:@(*param)];
   }
@@ -218,7 +216,7 @@
 gfx::NativeViewAccessible AttributeInvoker::PropertyNodeToUIElement(
     const PropertyNode& uielement_node) const {
   gfx::NativeViewAccessible uielement =
-      line_indexes_map.NodeBy(base::UTF16ToUTF8(uielement_node.name_or_value));
+      line_indexes_map.NodeBy(uielement_node.name_or_value);
   if (!uielement) {
     UIELEMENT_FAIL(uielement_node,
                    "no corresponding UIElement was found in the tree")
@@ -234,8 +232,8 @@
     TEXTMARKER_FAIL(dictnode, "wrong number of dictionary elements")
   }
 
-  BrowserAccessibilityCocoa* anchor_cocoa = line_indexes_map.NodeBy(
-      base::UTF16ToUTF8(dictnode.parameters[0].name_or_value));
+  BrowserAccessibilityCocoa* anchor_cocoa =
+      line_indexes_map.NodeBy(dictnode.parameters[0].name_or_value);
   if (!anchor_cocoa) {
     TEXTMARKER_FAIL(dictnode, "1st argument: wrong anchor")
   }
@@ -246,12 +244,12 @@
   }
 
   ax::mojom::TextAffinity affinity;
-  const base::string16& affinity_str = dictnode.parameters[2].name_or_value;
-  if (affinity_str == base::UTF8ToUTF16("none")) {
+  const std::string& affinity_str = dictnode.parameters[2].name_or_value;
+  if (affinity_str == "none") {
     affinity = ax::mojom::TextAffinity::kNone;
-  } else if (affinity_str == base::UTF8ToUTF16("down")) {
+  } else if (affinity_str == "down") {
     affinity = ax::mojom::TextAffinity::kDownstream;
-  } else if (affinity_str == base::UTF8ToUTF16("up")) {
+  } else if (affinity_str == "up") {
     affinity = ax::mojom::TextAffinity::kUpstream;
   } else {
     TEXTMARKER_FAIL(dictnode, "3rd argument: wrong affinity")
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index e613f9a2..d7589cd9 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -2343,6 +2343,11 @@
   RunHtmlTest(FILE_PATH_LITERAL("ul.html"));
 }
 
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+                       AccessibilityNotUserSelectable) {
+  RunCSSTest(FILE_PATH_LITERAL("user-select.html"));
+}
+
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityVar) {
   RunHtmlTest(FILE_PATH_LITERAL("var.html"));
 }
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index a34d51b..dba5ff9 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -7586,6 +7586,7 @@
   }
   auto* fetcher = SmsFetcher::Get(GetProcess()->GetBrowserContext());
   SmsService::Create(fetcher, this, std::move(receiver));
+  document_used_web_otp_ = true;
 }
 
 void RenderFrameHostImpl::BindRestrictedCookieManager(
@@ -8308,6 +8309,10 @@
     for (auto& receiver : navigation_request->TakeCookieObservers()) {
       cookie_observers_.Add(this, std::move(receiver));
     }
+
+    // Resets when navigating to a new document. This is needed because
+    // RenderFrameHost might be reused for a new document
+    document_used_web_otp_ = false;
   }
 
   // Keep track of the sandbox policy of the document that has just committed.
@@ -9382,6 +9387,10 @@
   }
 }
 
+bool RenderFrameHostImpl::DocumentUsedWebOTP() {
+  return document_used_web_otp_;
+}
+
 std::ostream& operator<<(std::ostream& o,
                          const RenderFrameHostImpl::LifecycleState& s) {
   return o << LifecycleStateToString(s);
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 4ab89d4..714cd99 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1528,6 +1528,8 @@
   }
   bool IsOuterDelegateFrame() { return is_outer_delegate_frame_; }
 
+  bool DocumentUsedWebOTP() override;
+
   scoped_refptr<WebAuthRequestSecurityChecker>
   GetWebAuthRequestSecurityChecker();
 
@@ -3155,6 +3157,14 @@
   // RenderFrameHost.
   bool is_outer_delegate_frame_ = false;
 
+  // Indicates whether navigator.credentials.get({otp: {transport:"sms"}}) has
+  // been used on a document (regardless of the outcome).
+  // Note that WebOTP is not allowed in iframes for security reasons. i.e. this
+  // will not be set in such case which is expected. In addition, since the
+  // RenderFrameHost may persist across navigations, we need to reset the bit
+  // to make sure that it's used per document.
+  bool document_used_web_otp_ = false;
+
   // The browsing context's required CSP as defined by
   // https://w3c.github.io/webappsec-cspee/#required-csp,
   // stored when the frame commits the navigation.
diff --git a/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
index 858f7a9c..f510f16 100644
--- a/content/browser/frame_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -199,6 +199,9 @@
     // is integrated into WebView.
     base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
         switches::kJavaScriptFlags, "--expose_gc");
+
+    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+        switches::kEnableBlinkFeatures, "SmsReceiver");
   }
   net::EmbeddedTestServer* https_server() { return &https_server_; }
 
@@ -3789,6 +3792,25 @@
   EXPECT_EQ(LifecycleState::kActive, current_rfh->lifecycle_state());
 }
 
+// Check that same site navigation correctly resets document_used_web_otp_.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+                       SameSiteNavigationResetsDocumentUsedWebOTP) {
+  const GURL first_url(
+      embedded_test_server()->GetURL("/page_with_webotp.html"));
+  const GURL second_url(embedded_test_server()->GetURL("/empty.html"));
+
+  // Load a URL that maps to the same SiteInstance as the second URL, to make
+  // sure the second navigation will not be cross-process.
+  ASSERT_TRUE(NavigateToURL(shell(), first_url));
+
+  RenderFrameHostImpl* main_rfh =
+      static_cast<RenderFrameHostImpl*>(web_contents()->GetMainFrame());
+  EXPECT_TRUE(main_rfh->DocumentUsedWebOTP());
+
+  ASSERT_TRUE(NavigateToURL(shell(), second_url));
+  EXPECT_FALSE(main_rfh->DocumentUsedWebOTP());
+}
+
 // It is hard to test this feature fully at the integration test level. Indeed,
 // there is no good way to inject a fake endpoint value into the URLLoader code
 // that performs the CORS-RFC1918 checks. The most intrusive injection
diff --git a/content/browser/sms/sms_browsertest.cc b/content/browser/sms/sms_browsertest.cc
index 8c8271e4..289f2cc 100644
--- a/content/browser/sms/sms_browsertest.cc
+++ b/content/browser/sms/sms_browsertest.cc
@@ -750,4 +750,36 @@
       1);
 }
 
+IN_PROC_BROWSER_TEST_F(SmsBrowserTest, UpdateRenderFrameHostWithWebOTPUsage) {
+  base::HistogramTester histogram_tester;
+  GURL url = GetTestUrl(nullptr, "simple_page.html");
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+
+  shell()->web_contents()->SetDelegate(&delegate_);
+
+  ExpectSmsPrompt();
+  auto provider = std::make_unique<MockSmsProvider>();
+  MockSmsProvider* mock_provider_ptr = provider.get();
+  BrowserMainLoop::GetInstance()->SetSmsProviderForTesting(std::move(provider));
+
+  EXPECT_CALL(*mock_provider_ptr, Retrieve(_)).WillOnce(Invoke([&]() {
+    mock_provider_ptr->NotifyReceive(url::Origin::Create(url), "hello");
+    ConfirmPrompt();
+  }));
+
+  RenderFrameHost* render_frame_host = shell()->web_contents()->GetMainFrame();
+  EXPECT_FALSE(render_frame_host->DocumentUsedWebOTP());
+  // navigator.credentials.get() creates an SmsService which will notify the
+  // RenderFrameHost that WebOTP has been used.
+  std::string script = R"(
+    (async () => {
+      let cred = await navigator.credentials.get({otp: {transport: ["sms"]}});
+      return cred.code;
+    }) ();
+  )";
+  EXPECT_EQ("hello", EvalJs(shell(), script));
+
+  EXPECT_TRUE(render_frame_host->DocumentUsedWebOTP());
+}
+
 }  // namespace content
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index d428cf2..7a72e40 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -607,6 +607,10 @@
       blink::mojom::HeavyAdResolutionStatus resolution,
       blink::mojom::HeavyAdReason reason) = 0;
 
+  // Returns whether a document uses WebOTP. Returns true if an SmsService is
+  // created on the document.
+  virtual bool DocumentUsedWebOTP() = 0;
+
   // Write a description of this RenderFrameHost into provided |traced_value|.
   // The caller is responsible for ensuring that key-value pairs can be written
   // into |traced_value| — either by creating a new TracedValue or calling
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index a27721ce5..d13b2c8 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -627,14 +627,9 @@
 // Controls whether Site Isolation protects against spoofing of origin in
 // mojom::FileSystemManager::Open IPC from compromised renderer processes.  See
 // also https://crbug.com/917457.
-//
-// TODO(lukasza, nasko): Make that feature below enabled by default, after
-// coordinating with the remaining consumers of PPAPI.  This should be possible
-// at the end of 2020, when most PPAPI consumers (Flash, most Chrome Apps) will
-// be gone.
 const base::Feature kSiteIsolationEnforcementForFileSystemApi{
     "SiteIsolationEnforcementForFileSystemApi",
-    base::FEATURE_DISABLED_BY_DEFAULT};
+    base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Controls whether SpareRenderProcessHostManager tries to always have a warm
 // spare renderer process around for the most recently requested BrowserContext.
diff --git a/content/test/data/accessibility/css/user-select-expected-blink.txt b/content/test/data/accessibility/css/user-select-expected-blink.txt
new file mode 100644
index 0000000..9cfb8e9
--- /dev/null
+++ b/content/test/data/accessibility/css/user-select-expected-blink.txt
@@ -0,0 +1,26 @@
+rootWebArea
+++genericContainer ignored
+++++genericContainer ignored
+++++++genericContainer notUserSelectableStyle=true
+++++++++staticText name='1. unselectable' notUserSelectableStyle=true
+++++++++++inlineTextBox name='1. unselectable'
+++++++genericContainer
+++++++++staticText name='2. Selectable'
+++++++++++inlineTextBox name='2. Selectable'
+++++++genericContainer notUserSelectableStyle=true
+++++++++staticText name='3. unselectable' notUserSelectableStyle=true
+++++++++++inlineTextBox name='3. unselectable'
+++++++genericContainer
+++++++++staticText name='4. Selectable'
+++++++++++inlineTextBox name='4. Selectable'
+++++++list
+++++++++listItem
+++++++++++listMarker name='• '
+++++++++++++staticText name='• '
+++++++++++++++inlineTextBox name='• '
+++++++++++staticText name='One'
+++++++++++++inlineTextBox name='One'
+++++++genericContainer ignored notUserSelectableStyle=true
+++++++++genericContainer notUserSelectableStyle=true
+++++++++++staticText name='Inner' notUserSelectableStyle=true
+++++++++++++inlineTextBox name='Inner'
diff --git a/content/test/data/accessibility/css/user-select.html b/content/test/data/accessibility/css/user-select.html
new file mode 100644
index 0000000..ec4c9de
--- /dev/null
+++ b/content/test/data/accessibility/css/user-select.html
@@ -0,0 +1,16 @@
+<!--
+@BLINK-ALLOW:notUserSelectableStyle*
+-->
+<div style="user-select:none">1. unselectable </div>
+<div style="user-select:text"> 2. Selectable </div>
+<div style="user-select:none"> 3. unselectable </div>
+<div style="user-select:text"> 4. Selectable </div>
+<!-- List bullets are not selectable, but that is not due to user-select, 
+    so they will not have the notUserSelectableStyle attribute -->
+<ul>
+    <li>One</li>
+</ul>
+<!-- Should inherit -->
+<div style="user-select:none">
+    <div style="user-select:inherit">Inner</div>
+</div>
\ No newline at end of file
diff --git a/content/test/data/page_with_webotp.html b/content/test/data/page_with_webotp.html
new file mode 100644
index 0000000..415146b
--- /dev/null
+++ b/content/test/data/page_with_webotp.html
@@ -0,0 +1,9 @@
+<input autocomplete="one-time-code">
+<script>
+  const ac = document.querySelector('input[autocomplete="one-time-code"]');
+  navigator.credentials.get({
+    otp: {transport:['sms']}
+  })
+  .then(content => ac.value = content.code);
+</script>
+
diff --git a/device/fido/cros/authenticator.cc b/device/fido/cros/authenticator.cc
index 27e0e45..7dc8225 100644
--- a/device/fido/cros/authenticator.cc
+++ b/device/fido/cros/authenticator.cc
@@ -36,6 +36,8 @@
 
 namespace {
 
+constexpr int kHasCredentialsTimeoutMs = 3000;
+
 AuthenticatorSupportedOptions ChromeOSAuthenticatorOptions() {
   AuthenticatorSupportedOptions options;
   options.is_platform_device = true;
@@ -260,6 +262,50 @@
                           std::move(response));
 }
 
+bool ChromeOSAuthenticator::HasCredentialForGetAssertionRequest(
+    const CtapGetAssertionRequest& request) {
+  dbus::Bus::Options dbus_options;
+  dbus_options.bus_type = dbus::Bus::SYSTEM;
+  scoped_refptr<dbus::Bus> bus = new dbus::Bus(dbus_options);
+  dbus::ObjectProxy* u2f_proxy = bus->GetObjectProxy(
+      u2f::kU2FServiceName, dbus::ObjectPath(u2f::kU2FServicePath));
+
+  if (!u2f_proxy) {
+    FIDO_LOG(ERROR) << "Couldn't get u2f proxy";
+    return false;
+  }
+
+  u2f::HasCredentialsRequest req;
+  req.set_rp_id(request.rp_id);
+  for (const PublicKeyCredentialDescriptor& descriptor : request.allow_list) {
+    const std::vector<uint8_t>& id = descriptor.id();
+    req.add_credential_id(std::string(id.begin(), id.end()));
+  }
+
+  dbus::MethodCall method_call(u2f::kU2FInterface, u2f::kU2FHasCredentials);
+  dbus::MessageWriter writer(&method_call);
+  writer.AppendProtoAsArrayOfBytes(req);
+
+  std::unique_ptr<dbus::Response> dbus_response =
+      u2f_proxy->CallMethodAndBlock(&method_call, kHasCredentialsTimeoutMs);
+
+  if (!dbus_response) {
+    FIDO_LOG(ERROR) << "HasCredentials dbus call had no response or timed out";
+    return false;
+  }
+
+  dbus::MessageReader reader(dbus_response.get());
+  u2f::HasCredentialsResponse resp;
+  if (!reader.PopArrayOfBytesAsProto(&resp)) {
+    FIDO_LOG(ERROR) << "Failed to parse reply for call to HasCredentials";
+    return false;
+  }
+
+  return resp.status() ==
+             u2f::HasCredentialsResponse_HasCredentialsStatus_SUCCESS &&
+         resp.credential_id().size() > 0;
+}
+
 bool ChromeOSAuthenticator::IsInPairingMode() const {
   return false;
 }
diff --git a/device/fido/cros/authenticator.h b/device/fido/cros/authenticator.h
index 3e13f5e..1e4a898 100644
--- a/device/fido/cros/authenticator.h
+++ b/device/fido/cros/authenticator.h
@@ -27,6 +27,9 @@
   ChromeOSAuthenticator();
   ~ChromeOSAuthenticator() override;
 
+  bool HasCredentialForGetAssertionRequest(
+      const CtapGetAssertionRequest& request);
+
   // FidoAuthenticator
   void InitializeAuthenticator(base::OnceClosure callback) override;
   void MakeCredential(CtapMakeCredentialRequest request,
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc
index 2fffce7..51a01754 100644
--- a/device/fido/get_assertion_request_handler.cc
+++ b/device/fido/get_assertion_request_handler.cc
@@ -33,6 +33,10 @@
 #include "device/fido/win/type_conversions.h"
 #endif
 
+#if defined(OS_CHROMEOS)
+#include "device/fido/cros/authenticator.h"
+#endif
+
 namespace device {
 
 namespace {
@@ -374,6 +378,16 @@
   }
 #endif  // defined(OS_MAC)
 
+#if defined(OS_CHROMEOS)
+  // TODO(martinkr): Put this boolean in a ChromeOS equivalent of
+  // "has_recognized_mac_touch_id_credential".
+  if (authenticator->IsChromeOSAuthenticator()) {
+    transport_availability_info().has_recognized_mac_touch_id_credential =
+        static_cast<ChromeOSAuthenticator*>(authenticator)
+            ->HasCredentialForGetAssertionRequest(request_);
+  }
+#endif  // defined(OS_CHROMEOS)
+
   FidoRequestHandlerBase::AuthenticatorAdded(discovery, authenticator);
 }
 
diff --git a/docs/security/compromised-renderers.md b/docs/security/compromised-renderers.md
index ffee9902..f426d5dd4 100644
--- a/docs/security/compromised-renderers.md
+++ b/docs/security/compromised-renderers.md
@@ -214,9 +214,6 @@
   information in `RenderFrameHost::GetLastCommittedOrigin()`
   (e.g. see `RenderFrameHostImpl::CreateIDBFactory`).
 
-**Known gaps in protection**:
-- https://crbug.com/917457: FileSystem API (deprecated, Chrome-only).
-
 
 ## Messaging
 
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc
index 975709d..7fe591f 100644
--- a/gpu/config/gpu_finch_features.cc
+++ b/gpu/config/gpu_finch_features.cc
@@ -13,13 +13,15 @@
 namespace features {
 
 #if defined(OS_ANDROID)
-// Used only by webview to disable SurfaceControl.
-const base::Feature kDisableSurfaceControlForWebview{
-    "DisableSurfaceControlForWebview", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Used to limit GL version to 2.0 for skia raster on Android.
 const base::Feature kUseGles2ForOopR{"UseGles2ForOopR",
                                      base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Use android SurfaceControl API for managing display compositor's buffer queue
+// and using overlays on Android. Also used by webview to disable surface
+// SurfaceControl.
+const base::Feature kAndroidSurfaceControl{"AndroidSurfaceControl",
+                                           base::FEATURE_ENABLED_BY_DEFAULT};
 #endif
 
 // Enable GPU Rasterization by default. This can still be overridden by
@@ -118,10 +120,8 @@
 
 #if defined(OS_ANDROID)
 bool IsAndroidSurfaceControlEnabled() {
-  if (base::FeatureList::IsEnabled(kDisableSurfaceControlForWebview))
-    return false;
-
-  return gl::SurfaceControl::IsSupported();
+  return base::FeatureList::IsEnabled(kAndroidSurfaceControl) &&
+         gl::SurfaceControl::IsSupported();
 }
 #endif
 
diff --git a/gpu/config/gpu_finch_features.h b/gpu/config/gpu_finch_features.h
index 7211df57..24c9a2b 100644
--- a/gpu/config/gpu_finch_features.h
+++ b/gpu/config/gpu_finch_features.h
@@ -17,9 +17,8 @@
 // All features in alphabetical order. The features should be documented
 // alongside the definition of their values in the .cc file.
 #if defined(OS_ANDROID)
-GPU_EXPORT extern const base::Feature kDisableSurfaceControlForWebview;
-
 GPU_EXPORT extern const base::Feature kUseGles2ForOopR;
+GPU_EXPORT extern const base::Feature kAndroidSurfaceControl;
 #endif  // defined(OS_ANDROID)
 
 GPU_EXPORT extern const base::Feature kDefaultEnableGpuRasterization;
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn
index 0e8a590..f5279e1 100644
--- a/media/audio/BUILD.gn
+++ b/media/audio/BUILD.gn
@@ -254,15 +254,26 @@
 
   if (use_cras) {
     sources += [
-      "cras/audio_manager_cras.cc",
-      "cras/audio_manager_cras.h",
+      "cras/audio_manager_cras_base.cc",
+      "cras/audio_manager_cras_base.h",
       "cras/cras_input.cc",
       "cras/cras_input.h",
       "cras/cras_unified.cc",
       "cras/cras_unified.h",
     ]
     configs += [ ":libcras" ]
-    deps += [ "//chromeos/audio" ]
+    if (is_chromeos) {
+      sources += [
+        "cras/audio_manager_chromeos.cc",
+        "cras/audio_manager_chromeos.h",
+      ]
+      deps += [ "//chromeos/audio" ]
+    } else if (is_linux) {
+        sources += [
+          "cras/audio_manager_cras.cc",
+          "cras/audio_manager_cras.h",
+        ]
+    }
   }
 
   if (use_pulseaudio) {
diff --git a/media/audio/alsa/audio_manager_alsa.cc b/media/audio/alsa/audio_manager_alsa.cc
index 3f0c60e..2e5a6f5 100644
--- a/media/audio/alsa/audio_manager_alsa.cc
+++ b/media/audio/alsa/audio_manager_alsa.cc
@@ -13,9 +13,6 @@
 #include "base/stl_util.h"
 #include "media/audio/audio_device_description.h"
 #include "media/audio/audio_output_dispatcher.h"
-#if defined(USE_CRAS)
-#include "media/audio/cras/audio_manager_cras.h"
-#endif
 #include "media/audio/alsa/alsa_input.h"
 #include "media/audio/alsa/alsa_output.h"
 #include "media/audio/alsa/alsa_wrapper.h"
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc
index 0624621..1dd8e736 100644
--- a/media/audio/audio_manager_unittest.cc
+++ b/media/audio/audio_manager_unittest.cc
@@ -54,12 +54,14 @@
 #include "media/audio/pulse/pulse_util.h"
 #endif  // defined(USE_PULSEAUDIO)
 
-#if defined(USE_CRAS)
+#if defined(USE_CRAS) && defined(OS_CHROMEOS)
 #include "chromeos/audio/audio_devices_pref_handler_stub.h"
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/dbus/audio/fake_cras_audio_client.h"
+#include "media/audio/cras/audio_manager_chromeos.h"
+#elif  defined(USE_CRAS) && defined(OS_LINUX)
 #include "media/audio/cras/audio_manager_cras.h"
-#endif  // defined(USE_CRAS)
+#endif
 
 namespace media {
 
@@ -98,7 +100,7 @@
   }
 };
 
-#if defined(USE_CRAS)
+#if defined(USE_CRAS) && defined(OS_CHROMEOS)
 using chromeos::AudioNode;
 using chromeos::AudioNodeList;
 
@@ -294,7 +296,7 @@
         device_info_accessor_->GetAssociatedOutputDeviceID(input_device_id);
   }
 
-#if defined(USE_CRAS)
+#if defined(USE_CRAS) && defined(OS_CHROMEOS)
   void TearDown() override {
     chromeos::CrasAudioHandler::Shutdown();
     audio_pref_handler_ = nullptr;
@@ -331,7 +333,7 @@
         AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
                                               limits::kMaxAudioBufferSize));
   }
-#endif  // defined(USE_CRAS)
+#endif  // defined(USE_CRAS) && defined(OS_CHROMEOS)
 
  protected:
   AudioManagerTest() {
@@ -375,7 +377,7 @@
     }
   }
 
-#if defined(USE_CRAS)
+#if defined(USE_CRAS) && defined(OS_CHROMEOS)
   // Helper method for (USE_CRAS) which verifies that the device list starts
   // with a valid default record followed by physical device names.
   static void CheckDeviceDescriptionsCras(
@@ -431,7 +433,7 @@
     EXPECT_NE(it, device_descriptions.end());
     return it->group_id;
   }
-#endif  // defined(USE_CRAS)
+#endif  // defined(USE_CRAS) && defined(OS_CHROMEOS)
 
   bool InputDevicesAvailable() {
     return device_info_accessor_->HasAudioInputDevices();
@@ -466,13 +468,13 @@
   std::unique_ptr<AudioManager> audio_manager_;
   std::unique_ptr<AudioDeviceInfoAccessorForTests> device_info_accessor_;
 
-#if defined(USE_CRAS)
+#if defined(USE_CRAS) && defined(OS_CHROMEOS)
   chromeos::CrasAudioHandler* cras_audio_handler_ = nullptr;  // Not owned.
   scoped_refptr<chromeos::AudioDevicesPrefHandlerStub> audio_pref_handler_;
-#endif  // defined(USE_CRAS)
+#endif  // defined(USE_CRAS) && defined(OS_CHROMEOS)
 };
 
-#if defined(USE_CRAS)
+#if defined(USE_CRAS) && defined(OS_CHROMEOS)
 TEST_F(AudioManagerTest, EnumerateInputDevicesCras) {
   // Setup the devices without internal mic, so that it doesn't exist
   // beamforming capable mic.
@@ -496,7 +498,7 @@
       cras_audio_handler_->GetDeviceFromId(kUSBCameraMic.id)->display_name;
 
   DVLOG(2) << "Testing AudioManagerCras.";
-  CreateAudioManagerForTesting<AudioManagerCras>();
+  CreateAudioManagerForTesting<AudioManagerChromeOS>();
   AudioDeviceDescriptions device_descriptions;
   device_info_accessor_->GetAudioInputDeviceDescriptions(&device_descriptions);
   CheckDeviceDescriptionsCras(device_descriptions, expectation);
@@ -523,7 +525,7 @@
       cras_audio_handler_->GetDeviceFromId(kJabraSpeaker1.id)->display_name;
 
   DVLOG(2) << "Testing AudioManagerCras.";
-  CreateAudioManagerForTesting<AudioManagerCras>();
+  CreateAudioManagerForTesting<AudioManagerChromeOS>();
   AudioDeviceDescriptions device_descriptions;
   device_info_accessor_->GetAudioOutputDeviceDescriptions(&device_descriptions);
   CheckDeviceDescriptionsCras(device_descriptions, expectation);
@@ -545,7 +547,7 @@
   ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable());
 
   DVLOG(2) << "Testing AudioManagerCras.";
-  CreateAudioManagerForTesting<AudioManagerCras>();
+  CreateAudioManagerForTesting<AudioManagerChromeOS>();
   AudioParameters params, golden_params;
 
   // channel_layout:
@@ -627,7 +629,7 @@
   expectation[kJabraMic1.id] =
       cras_audio_handler_->GetDeviceFromId(kJabraMic1.id)->display_name;
 
-  CreateAudioManagerForTesting<AudioManagerCras>();
+  CreateAudioManagerForTesting<AudioManagerChromeOS>();
   auto previous_default_device_id =
       device_info_accessor_->GetDefaultInputDeviceID();
   EXPECT_EQ(base::NumberToString(kJabraMic1.id), previous_default_device_id);
@@ -671,7 +673,7 @@
   expectation[kJabraSpeaker1.id] =
       cras_audio_handler_->GetDeviceFromId(kJabraSpeaker1.id)->display_name;
 
-  CreateAudioManagerForTesting<AudioManagerCras>();
+  CreateAudioManagerForTesting<AudioManagerChromeOS>();
   auto previous_default_device_id =
       device_info_accessor_->GetDefaultOutputDeviceID();
   EXPECT_EQ(base::NumberToString(kJabraSpeaker1.id),
@@ -697,7 +699,7 @@
   EXPECT_EQ(default_device_group_id, speaker_group_id);
   EXPECT_EQ(base::NumberToString(kInternalSpeaker.id), new_default_device_id);
 }
-#else  // !defined(USE_CRAS)
+#else  // !(defined(USE_CRAS) && defined(OS_CHROMEOS))
 
 TEST_F(AudioManagerTest, HandleDefaultDeviceIDs) {
   // Use a fake manager so we can makeup device ids, this will still use the
@@ -841,7 +843,7 @@
   EXPECT_TRUE(found_an_associated_device);
 #endif  // defined(OS_WIN) || defined(OS_MAC)
 }
-#endif  // defined(USE_CRAS)
+#endif  // defined(USE_CRAS) && defined(OS_CHROMEOS)
 
 class TestAudioManager : public FakeAudioManager {
   // For testing the default implementation of GetGroupId(Input|Output)
@@ -1004,8 +1006,8 @@
 
 #if defined(OS_MAC)
   CreateAudioManagerForTesting<AudioManagerMac>();
-#elif defined(USE_CRAS)
-  CreateAudioManagerForTesting<AudioManagerCras>();
+#elif defined(USE_CRAS) && defined(OS_CHROMEOS)
+  CreateAudioManagerForTesting<AudioManagerChromeOS>();
 #endif
 
   DCHECK(audio_manager_);
diff --git a/media/audio/cras/audio_manager_chromeos.cc b/media/audio/cras/audio_manager_chromeos.cc
new file mode 100644
index 0000000..f2fbb4d
--- /dev/null
+++ b/media/audio/cras/audio_manager_chromeos.cc
@@ -0,0 +1,540 @@
+// 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 "media/audio/cras/audio_manager_chromeos.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <map>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/check_op.h"
+#include "base/command_line.h"
+#include "base/environment.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/nix/xdg_util.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/system/sys_info.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chromeos/audio/audio_device.h"
+#include "chromeos/audio/cras_audio_handler.h"
+#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_features.h"
+#include "media/audio/cras/cras_input.h"
+#include "media/audio/cras/cras_unified.h"
+#include "media/base/channel_layout.h"
+#include "media/base/limits.h"
+#include "media/base/localized_strings.h"
+
+namespace media {
+namespace {
+
+// Default sample rate for input and output streams.
+const int kDefaultSampleRate = 48000;
+
+// Default input buffer size.
+const int kDefaultInputBufferSize = 1024;
+
+const char kInternalInputVirtualDevice[] = "Built-in mic";
+const char kInternalOutputVirtualDevice[] = "Built-in speaker";
+const char kHeadphoneLineOutVirtualDevice[] = "Headphone/Line Out";
+
+// Used for the Media.CrosBeamformingDeviceState histogram, currently not used
+// since beamforming is disabled.
+enum CrosBeamformingDeviceState {
+  BEAMFORMING_DEFAULT_ENABLED = 0,
+  BEAMFORMING_USER_ENABLED,
+  BEAMFORMING_DEFAULT_DISABLED,
+  BEAMFORMING_USER_DISABLED,
+  BEAMFORMING_STATE_MAX = BEAMFORMING_USER_DISABLED
+};
+
+bool HasKeyboardMic(const chromeos::AudioDeviceList& devices) {
+  for (const auto& device : devices) {
+    if (device.is_input && device.type == chromeos::AUDIO_TYPE_KEYBOARD_MIC) {
+      return true;
+    }
+  }
+  return false;
+}
+
+const chromeos::AudioDevice* GetDeviceFromId(
+    const chromeos::AudioDeviceList& devices,
+    uint64_t id) {
+  for (const auto& device : devices) {
+    if (device.id == id) {
+      return &device;
+    }
+  }
+  return nullptr;
+}
+
+// Process |device_list| that two shares the same dev_index by creating a
+// virtual device name for them.
+void ProcessVirtualDeviceName(AudioDeviceNames* device_names,
+                              const chromeos::AudioDeviceList& device_list) {
+  DCHECK_EQ(2U, device_list.size());
+  if (device_list[0].type == chromeos::AUDIO_TYPE_LINEOUT ||
+      device_list[1].type == chromeos::AUDIO_TYPE_LINEOUT) {
+    device_names->emplace_back(kHeadphoneLineOutVirtualDevice,
+                               base::NumberToString(device_list[0].id));
+  } else if (device_list[0].type == chromeos::AUDIO_TYPE_INTERNAL_SPEAKER ||
+             device_list[1].type == chromeos::AUDIO_TYPE_INTERNAL_SPEAKER) {
+    device_names->emplace_back(kInternalOutputVirtualDevice,
+                               base::NumberToString(device_list[0].id));
+  } else {
+    DCHECK(device_list[0].IsInternalMic() || device_list[1].IsInternalMic());
+    device_names->emplace_back(kInternalInputVirtualDevice,
+                               base::NumberToString(device_list[0].id));
+  }
+}
+
+}  // namespace
+
+bool AudioManagerChromeOS::HasAudioOutputDevices() {
+  return true;
+}
+
+bool AudioManagerChromeOS::HasAudioInputDevices() {
+  chromeos::AudioDeviceList devices;
+  GetAudioDevices(&devices);
+  for (size_t i = 0; i < devices.size(); ++i) {
+    if (devices[i].is_input && devices[i].is_for_simple_usage())
+      return true;
+  }
+  return false;
+}
+
+AudioManagerChromeOS::AudioManagerChromeOS(
+    std::unique_ptr<AudioThread> audio_thread,
+    AudioLogFactory* audio_log_factory)
+    : AudioManagerCrasBase(std::move(audio_thread), audio_log_factory),
+      on_shutdown_(base::WaitableEvent::ResetPolicy::MANUAL,
+                   base::WaitableEvent::InitialState::NOT_SIGNALED),
+      main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      weak_ptr_factory_(this) {
+  weak_this_ = weak_ptr_factory_.GetWeakPtr();
+}
+
+AudioManagerChromeOS::~AudioManagerChromeOS() = default;
+
+void AudioManagerChromeOS::GetAudioDeviceNamesImpl(
+    bool is_input,
+    AudioDeviceNames* device_names) {
+  DCHECK(device_names->empty());
+
+  device_names->push_back(AudioDeviceName::CreateDefault());
+
+  chromeos::AudioDeviceList devices;
+  GetAudioDevices(&devices);
+
+  // |dev_idx_map| is a map of dev_index and their audio devices.
+  std::map<int, chromeos::AudioDeviceList> dev_idx_map;
+  for (const auto& device : devices) {
+    if (device.is_input != is_input || !device.is_for_simple_usage())
+      continue;
+
+    dev_idx_map[dev_index_of(device.id)].push_back(device);
+  }
+
+  for (const auto& item : dev_idx_map) {
+    if (1 == item.second.size()) {
+      const chromeos::AudioDevice& device = item.second.front();
+      device_names->emplace_back(device.display_name,
+                                 base::NumberToString(device.id));
+    } else {
+      // Create virtual device name for audio nodes that share the same device
+      // index.
+      ProcessVirtualDeviceName(device_names, item.second);
+    }
+  }
+}
+
+void AudioManagerChromeOS::GetAudioInputDeviceNames(
+    AudioDeviceNames* device_names) {
+  GetAudioDeviceNamesImpl(true, device_names);
+}
+
+void AudioManagerChromeOS::GetAudioOutputDeviceNames(
+    AudioDeviceNames* device_names) {
+  GetAudioDeviceNamesImpl(false, device_names);
+}
+
+AudioParameters AudioManagerChromeOS::GetInputStreamParameters(
+    const std::string& device_id) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+
+  int user_buffer_size = GetUserBufferSize();
+  int buffer_size =
+      user_buffer_size ? user_buffer_size : kDefaultInputBufferSize;
+
+  // TODO(hshi): Fine-tune audio parameters based on |device_id|. The optimal
+  // parameters for the loopback stream may differ from the default.
+  AudioParameters params(
+      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
+      kDefaultSampleRate, buffer_size,
+      AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
+                                            limits::kMaxAudioBufferSize));
+  chromeos::AudioDeviceList devices;
+  GetAudioDevices(&devices);
+  if (HasKeyboardMic(devices))
+    params.set_effects(AudioParameters::KEYBOARD_MIC);
+
+  // Allow experimentation with system echo cancellation with all devices,
+  // but enable it by default on devices that actually support it.
+  params.set_effects(params.effects() |
+                     AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
+  if (base::FeatureList::IsEnabled(features::kCrOSSystemAEC)) {
+    if (GetSystemAecSupportedPerBoard()) {
+      const int32_t aec_group_id = GetSystemAecGroupIdPerBoard();
+
+      // Check if the system AEC has a group ID which is flagged to be
+      // deactivated by the field trial.
+      const bool system_aec_deactivated =
+          base::GetFieldTrialParamByFeatureAsBool(
+              features::kCrOSSystemAECDeactivatedGroups,
+              std::to_string(aec_group_id), false);
+
+      if (!system_aec_deactivated) {
+        params.set_effects(params.effects() | AudioParameters::ECHO_CANCELLER);
+      }
+    }
+  }
+
+  return params;
+}
+
+std::string AudioManagerChromeOS::GetAssociatedOutputDeviceID(
+    const std::string& input_device_id) {
+  chromeos::AudioDeviceList devices;
+  GetAudioDevices(&devices);
+
+  if (input_device_id == AudioDeviceDescription::kDefaultDeviceId) {
+    // Note: the default input should not be associated to any output, as this
+    // may lead to accidental uses of a pinned stream.
+    return "";
+  }
+
+  const std::string device_name =
+      GetHardwareDeviceFromDeviceId(devices, true, input_device_id);
+
+  if (device_name.empty())
+    return "";
+
+  // Now search for an output device with the same device name.
+  auto output_device_it = std::find_if(
+      devices.begin(), devices.end(),
+      [device_name](const chromeos::AudioDevice& device) {
+        return !device.is_input && device.device_name == device_name;
+      });
+  return output_device_it == devices.end()
+             ? ""
+             : base::NumberToString(output_device_it->id);
+}
+
+std::string AudioManagerChromeOS::GetDefaultInputDeviceID() {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  return base::NumberToString(GetPrimaryActiveInputNode());
+}
+
+std::string AudioManagerChromeOS::GetDefaultOutputDeviceID() {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  return base::NumberToString(GetPrimaryActiveOutputNode());
+}
+
+std::string AudioManagerChromeOS::GetGroupIDOutput(
+    const std::string& output_device_id) {
+  chromeos::AudioDeviceList devices;
+  GetAudioDevices(&devices);
+
+  return GetHardwareDeviceFromDeviceId(devices, false, output_device_id);
+}
+
+std::string AudioManagerChromeOS::GetGroupIDInput(
+    const std::string& input_device_id) {
+  chromeos::AudioDeviceList devices;
+  GetAudioDevices(&devices);
+
+  return GetHardwareDeviceFromDeviceId(devices, true, input_device_id);
+}
+
+bool AudioManagerChromeOS::Shutdown() {
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
+  weak_ptr_factory_.InvalidateWeakPtrs();
+  on_shutdown_.Signal();
+  return AudioManager::Shutdown();
+}
+
+int AudioManagerChromeOS::GetDefaultOutputBufferSizePerBoard() {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  int32_t buffer_size = 512;
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  if (main_task_runner_->BelongsToCurrentThread()) {
+    // Unittest may use the same thread for audio thread.
+    GetDefaultOutputBufferSizeOnMainThread(&buffer_size, &event);
+  } else {
+    main_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &AudioManagerChromeOS::GetDefaultOutputBufferSizeOnMainThread,
+            weak_this_, base::Unretained(&buffer_size),
+            base::Unretained(&event)));
+  }
+  WaitEventOrShutdown(&event);
+  return static_cast<int>(buffer_size);
+}
+
+bool AudioManagerChromeOS::GetSystemAecSupportedPerBoard() {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  bool system_aec_supported = false;
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  if (main_task_runner_->BelongsToCurrentThread()) {
+    // Unittest may use the same thread for audio thread.
+    GetSystemAecSupportedOnMainThread(&system_aec_supported, &event);
+  } else {
+    // Using base::Unretained is safe here because we wait for callback be
+    // executed in main thread before local variables are destructed.
+    main_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AudioManagerChromeOS::GetSystemAecSupportedOnMainThread,
+                       weak_this_, base::Unretained(&system_aec_supported),
+                       base::Unretained(&event)));
+  }
+  WaitEventOrShutdown(&event);
+  return system_aec_supported;
+}
+
+int32_t AudioManagerChromeOS::GetSystemAecGroupIdPerBoard() {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  int32_t group_id = chromeos::CrasAudioHandler::kSystemAecGroupIdNotAvailable;
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  if (main_task_runner_->BelongsToCurrentThread()) {
+    // Unittest may use the same thread for audio thread.
+    GetSystemAecGroupIdOnMainThread(&group_id, &event);
+  } else {
+    // Using base::Unretained is safe here because we wait for callback be
+    // executed in main thread before local variables are destructed.
+    main_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AudioManagerChromeOS::GetSystemAecGroupIdOnMainThread,
+                       weak_this_, base::Unretained(&group_id),
+                       base::Unretained(&event)));
+  }
+  WaitEventOrShutdown(&event);
+  return group_id;
+}
+
+AudioParameters AudioManagerChromeOS::GetPreferredOutputStreamParameters(
+    const std::string& output_device_id,
+    const AudioParameters& input_params) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+
+  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
+  int sample_rate = kDefaultSampleRate;
+  int buffer_size = GetUserBufferSize();
+  if (input_params.IsValid()) {
+    channel_layout = input_params.channel_layout();
+    sample_rate = input_params.sample_rate();
+    if (!buffer_size)  // Not user-provided.
+      buffer_size =
+          std::min(static_cast<int>(limits::kMaxAudioBufferSize),
+                   std::max(static_cast<int>(limits::kMinAudioBufferSize),
+                            input_params.frames_per_buffer()));
+    return AudioParameters(
+        AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, sample_rate,
+        buffer_size,
+        AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
+                                              limits::kMaxAudioBufferSize));
+  }
+
+  // Get max supported channels from |output_device_id| or the primary active
+  // one if |output_device_id| is the default device.
+  uint64_t preferred_device_id;
+  if (AudioDeviceDescription::IsDefaultDevice(output_device_id)) {
+    preferred_device_id = GetPrimaryActiveOutputNode();
+  } else {
+    if (!base::StringToUint64(output_device_id, &preferred_device_id))
+      preferred_device_id = 0;  // 0 represents invalid |output_device_id|.
+  }
+
+  if (preferred_device_id) {
+    chromeos::AudioDeviceList devices;
+    GetAudioDevices(&devices);
+    const chromeos::AudioDevice* device =
+        GetDeviceFromId(devices, preferred_device_id);
+    if (device && device->is_input == false) {
+      channel_layout =
+          GuessChannelLayout(static_cast<int>(device->max_supported_channels));
+      // Fall-back to old fashion: always fixed to STEREO layout.
+      if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
+        channel_layout = CHANNEL_LAYOUT_STEREO;
+      }
+    }
+  }
+
+  if (!buffer_size)  // Not user-provided.
+    buffer_size = GetDefaultOutputBufferSizePerBoard();
+
+  return AudioParameters(
+      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, sample_rate,
+      buffer_size,
+      AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
+                                            limits::kMaxAudioBufferSize));
+}
+
+bool AudioManagerChromeOS::IsDefault(const std::string& device_id,
+                                     bool is_input) {
+  AudioDeviceNames device_names;
+  GetAudioDeviceNamesImpl(is_input, &device_names);
+  DCHECK(!device_names.empty());
+  const AudioDeviceName& device_name = device_names.front();
+  return device_name.unique_id == device_id;
+}
+
+std::string AudioManagerChromeOS::GetHardwareDeviceFromDeviceId(
+    const chromeos::AudioDeviceList& devices,
+    bool is_input,
+    const std::string& device_id) {
+  uint64_t u64_device_id = 0;
+  if (AudioDeviceDescription::IsDefaultDevice(device_id)) {
+    u64_device_id =
+        is_input ? GetPrimaryActiveInputNode() : GetPrimaryActiveOutputNode();
+  } else {
+    if (!base::StringToUint64(device_id, &u64_device_id))
+      return "";
+  }
+
+  const chromeos::AudioDevice* device = GetDeviceFromId(devices, u64_device_id);
+
+  return device ? device->device_name : "";
+}
+
+void AudioManagerChromeOS::GetAudioDevices(chromeos::AudioDeviceList* devices) {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  if (main_task_runner_->BelongsToCurrentThread()) {
+    GetAudioDevicesOnMainThread(devices, &event);
+  } else {
+    main_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&AudioManagerChromeOS::GetAudioDevicesOnMainThread,
+                       weak_this_, base::Unretained(devices),
+                       base::Unretained(&event)));
+  }
+  WaitEventOrShutdown(&event);
+}
+
+void AudioManagerChromeOS::GetAudioDevicesOnMainThread(
+    chromeos::AudioDeviceList* devices,
+    base::WaitableEvent* event) {
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
+  // CrasAudioHandler is shut down before AudioManagerChromeOS.
+  if (chromeos::CrasAudioHandler::Get())
+    chromeos::CrasAudioHandler::Get()->GetAudioDevices(devices);
+  event->Signal();
+}
+
+uint64_t AudioManagerChromeOS::GetPrimaryActiveInputNode() {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  uint64_t device_id = 0;
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  if (main_task_runner_->BelongsToCurrentThread()) {
+    GetPrimaryActiveInputNodeOnMainThread(&device_id, &event);
+  } else {
+    main_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &AudioManagerChromeOS::GetPrimaryActiveInputNodeOnMainThread,
+            weak_this_, &device_id, &event));
+  }
+  WaitEventOrShutdown(&event);
+  return device_id;
+}
+
+uint64_t AudioManagerChromeOS::GetPrimaryActiveOutputNode() {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  uint64_t device_id = 0;
+  if (main_task_runner_->BelongsToCurrentThread()) {
+    // Unittest may use the same thread for audio thread.
+    GetPrimaryActiveOutputNodeOnMainThread(&device_id, &event);
+  } else {
+    main_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &AudioManagerChromeOS::GetPrimaryActiveOutputNodeOnMainThread,
+            weak_this_, base::Unretained(&device_id),
+            base::Unretained(&event)));
+  }
+  WaitEventOrShutdown(&event);
+  return device_id;
+}
+
+void AudioManagerChromeOS::GetPrimaryActiveInputNodeOnMainThread(
+    uint64_t* active_input_node_id,
+    base::WaitableEvent* event) {
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
+  if (chromeos::CrasAudioHandler::Get()) {
+    *active_input_node_id =
+        chromeos::CrasAudioHandler::Get()->GetPrimaryActiveInputNode();
+  }
+  event->Signal();
+}
+
+void AudioManagerChromeOS::GetPrimaryActiveOutputNodeOnMainThread(
+    uint64_t* active_output_node_id,
+    base::WaitableEvent* event) {
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
+  if (chromeos::CrasAudioHandler::Get()) {
+    *active_output_node_id =
+        chromeos::CrasAudioHandler::Get()->GetPrimaryActiveOutputNode();
+  }
+  event->Signal();
+}
+
+void AudioManagerChromeOS::GetDefaultOutputBufferSizeOnMainThread(
+    int32_t* buffer_size,
+    base::WaitableEvent* event) {
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
+  if (chromeos::CrasAudioHandler::Get())
+    chromeos::CrasAudioHandler::Get()->GetDefaultOutputBufferSize(buffer_size);
+  event->Signal();
+}
+
+void AudioManagerChromeOS::GetSystemAecSupportedOnMainThread(
+    bool* system_aec_supported,
+    base::WaitableEvent* event) {
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
+  if (chromeos::CrasAudioHandler::Get()) {
+    *system_aec_supported =
+        chromeos::CrasAudioHandler::Get()->system_aec_supported();
+  }
+  event->Signal();
+}
+
+void AudioManagerChromeOS::GetSystemAecGroupIdOnMainThread(
+    int32_t* group_id,
+    base::WaitableEvent* event) {
+  DCHECK(main_task_runner_->BelongsToCurrentThread());
+  if (chromeos::CrasAudioHandler::Get())
+    *group_id = chromeos::CrasAudioHandler::Get()->system_aec_group_id();
+  event->Signal();
+}
+
+void AudioManagerChromeOS::WaitEventOrShutdown(base::WaitableEvent* event) {
+  base::WaitableEvent* waitables[] = {event, &on_shutdown_};
+  base::WaitableEvent::WaitMany(waitables, base::size(waitables));
+}
+
+}  // namespace media
diff --git a/media/audio/cras/audio_manager_chromeos.h b/media/audio/cras/audio_manager_chromeos.h
new file mode 100644
index 0000000..be0282d0
--- /dev/null
+++ b/media/audio/cras/audio_manager_chromeos.h
@@ -0,0 +1,104 @@
+// 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 MEDIA_AUDIO_CRAS_AUDIO_MANAGER_CHROMEOS_H_
+#define MEDIA_AUDIO_CRAS_AUDIO_MANAGER_CHROMEOS_H_
+
+#include <cras_types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "chromeos/audio/audio_device.h"
+#include "media/audio/audio_manager_base.h"
+#include "media/audio/cras/audio_manager_cras_base.h"
+
+namespace media {
+
+class MEDIA_EXPORT AudioManagerChromeOS : public AudioManagerCrasBase {
+ public:
+  AudioManagerChromeOS(std::unique_ptr<AudioThread> audio_thread,
+                   AudioLogFactory* audio_log_factory);
+  ~AudioManagerChromeOS() override;
+
+  // AudioManager implementation.
+  bool HasAudioOutputDevices() override;
+  bool HasAudioInputDevices() override;
+  void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
+  void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
+  AudioParameters GetInputStreamParameters(
+      const std::string& device_id) override;
+  std::string GetAssociatedOutputDeviceID(
+      const std::string& input_device_id) override;
+  std::string GetDefaultInputDeviceID() override;
+  std::string GetDefaultOutputDeviceID() override;
+  std::string GetGroupIDOutput(const std::string& output_device_id) override;
+  std::string GetGroupIDInput(const std::string& input_device_id) override;
+  bool Shutdown() override;
+
+  // AudioManagerCras implementation.
+  bool IsDefault(const std::string& device_id, bool is_input) override;
+
+ protected:
+  AudioParameters GetPreferredOutputStreamParameters(
+      const std::string& output_device_id,
+      const AudioParameters& input_params) override;
+
+ private:
+  // Get default output buffer size for this board.
+  int GetDefaultOutputBufferSizePerBoard();
+
+  // Get if system AEC is supported or not for this board.
+  bool GetSystemAecSupportedPerBoard();
+
+  // Get what the system AEC group ID is for this board.
+  int32_t GetSystemAecGroupIdPerBoard();
+
+  void GetAudioDeviceNamesImpl(bool is_input, AudioDeviceNames* device_names);
+
+  std::string GetHardwareDeviceFromDeviceId(
+      const chromeos::AudioDeviceList& devices,
+      bool is_input,
+      const std::string& device_id);
+
+  void GetAudioDevices(chromeos::AudioDeviceList* devices);
+  void GetAudioDevicesOnMainThread(chromeos::AudioDeviceList* devices,
+                                   base::WaitableEvent* event);
+  uint64_t GetPrimaryActiveInputNode();
+  uint64_t GetPrimaryActiveOutputNode();
+  void GetPrimaryActiveInputNodeOnMainThread(uint64_t* active_input_node_id,
+                                             base::WaitableEvent* event);
+  void GetPrimaryActiveOutputNodeOnMainThread(uint64_t* active_output_node_id,
+                                              base::WaitableEvent* event);
+  void GetDefaultOutputBufferSizeOnMainThread(int32_t* buffer_size,
+                                              base::WaitableEvent* event);
+  void GetSystemAecSupportedOnMainThread(bool* system_aec_supported,
+                                         base::WaitableEvent* event);
+  void GetSystemAecGroupIdOnMainThread(int32_t* group_id,
+                                       base::WaitableEvent* event);
+
+  void WaitEventOrShutdown(base::WaitableEvent* event);
+
+  // Signaled if AudioManagerCras is shutting down.
+  base::WaitableEvent on_shutdown_;
+
+  // Task runner of browser main thread. CrasAudioHandler should be only
+  // accessed on this thread.
+  scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+
+  // For posting tasks from audio thread to |main_task_runner_|.
+  base::WeakPtr<AudioManagerChromeOS> weak_this_;
+
+  base::WeakPtrFactory<AudioManagerChromeOS> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(AudioManagerChromeOS);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_CRAS_AUDIO_MANAGER_CHROMEOS_H_
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc
index 24540cb..0b8bf31 100644
--- a/media/audio/cras/audio_manager_cras.cc
+++ b/media/audio/cras/audio_manager_cras.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -18,11 +18,8 @@
 #include "base/nix/xdg_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/synchronization/waitable_event.h"
 #include "base/system/sys_info.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "chromeos/audio/audio_device.h"
-#include "chromeos/audio/cras_audio_handler.h"
 #include "media/audio/audio_device_description.h"
 #include "media/audio/audio_features.h"
 #include "media/audio/cras/cras_input.h"
@@ -34,68 +31,14 @@
 namespace media {
 namespace {
 
-// Maximum number of output streams that can be open simultaneously.
-const int kMaxOutputStreams = 50;
-
 // Default sample rate for input and output streams.
 const int kDefaultSampleRate = 48000;
 
 // Default input buffer size.
 const int kDefaultInputBufferSize = 1024;
 
-const char kInternalInputVirtualDevice[] = "Built-in mic";
-const char kInternalOutputVirtualDevice[] = "Built-in speaker";
-const char kHeadphoneLineOutVirtualDevice[] = "Headphone/Line Out";
-
-// Used for the Media.CrosBeamformingDeviceState histogram, currently not used
-// since beamforming is disabled.
-enum CrosBeamformingDeviceState {
-  BEAMFORMING_DEFAULT_ENABLED = 0,
-  BEAMFORMING_USER_ENABLED,
-  BEAMFORMING_DEFAULT_DISABLED,
-  BEAMFORMING_USER_DISABLED,
-  BEAMFORMING_STATE_MAX = BEAMFORMING_USER_DISABLED
-};
-
-bool HasKeyboardMic(const chromeos::AudioDeviceList& devices) {
-  for (const auto& device : devices) {
-    if (device.is_input && device.type == chromeos::AUDIO_TYPE_KEYBOARD_MIC) {
-      return true;
-    }
-  }
-  return false;
-}
-
-const chromeos::AudioDevice* GetDeviceFromId(
-    const chromeos::AudioDeviceList& devices,
-    uint64_t id) {
-  for (const auto& device : devices) {
-    if (device.id == id) {
-      return &device;
-    }
-  }
-  return nullptr;
-}
-
-// Process |device_list| that two shares the same dev_index by creating a
-// virtual device name for them.
-void ProcessVirtualDeviceName(AudioDeviceNames* device_names,
-                              const chromeos::AudioDeviceList& device_list) {
-  DCHECK_EQ(2U, device_list.size());
-  if (device_list[0].type == chromeos::AUDIO_TYPE_LINEOUT ||
-      device_list[1].type == chromeos::AUDIO_TYPE_LINEOUT) {
-    device_names->emplace_back(kHeadphoneLineOutVirtualDevice,
-                               base::NumberToString(device_list[0].id));
-  } else if (device_list[0].type == chromeos::AUDIO_TYPE_INTERNAL_SPEAKER ||
-             device_list[1].type == chromeos::AUDIO_TYPE_INTERNAL_SPEAKER) {
-    device_names->emplace_back(kInternalOutputVirtualDevice,
-                               base::NumberToString(device_list[0].id));
-  } else {
-    DCHECK(device_list[0].IsInternalMic() || device_list[1].IsInternalMic());
-    device_names->emplace_back(kInternalInputVirtualDevice,
-                               base::NumberToString(device_list[0].id));
-  }
-}
+// Default output buffer size.
+const int kDefaultOutputBufferSize = 512;
 
 }  // namespace
 
@@ -104,67 +47,28 @@
 }
 
 bool AudioManagerCras::HasAudioInputDevices() {
-  chromeos::AudioDeviceList devices;
-  GetAudioDevices(&devices);
-  for (size_t i = 0; i < devices.size(); ++i) {
-    if (devices[i].is_input && devices[i].is_for_simple_usage())
-      return true;
-  }
-  return false;
+  return true;
 }
 
-AudioManagerCras::AudioManagerCras(std::unique_ptr<AudioThread> audio_thread,
-                                   AudioLogFactory* audio_log_factory)
-    : AudioManagerBase(std::move(audio_thread), audio_log_factory),
-      on_shutdown_(base::WaitableEvent::ResetPolicy::MANUAL,
-                   base::WaitableEvent::InitialState::NOT_SIGNALED),
+AudioManagerCras::AudioManagerCras(
+    std::unique_ptr<AudioThread> audio_thread,
+    AudioLogFactory* audio_log_factory)
+    : AudioManagerCrasBase(std::move(audio_thread), audio_log_factory),
       main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       weak_ptr_factory_(this) {
   weak_this_ = weak_ptr_factory_.GetWeakPtr();
-  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
 }
 
 AudioManagerCras::~AudioManagerCras() = default;
 
-void AudioManagerCras::GetAudioDeviceNamesImpl(bool is_input,
-                                               AudioDeviceNames* device_names) {
-  DCHECK(device_names->empty());
-
-  device_names->push_back(AudioDeviceName::CreateDefault());
-
-  chromeos::AudioDeviceList devices;
-  GetAudioDevices(&devices);
-
-  // |dev_idx_map| is a map of dev_index and their audio devices.
-  std::map<int, chromeos::AudioDeviceList> dev_idx_map;
-  for (const auto& device : devices) {
-    if (device.is_input != is_input || !device.is_for_simple_usage())
-      continue;
-
-    dev_idx_map[dev_index_of(device.id)].push_back(device);
-  }
-
-  for (const auto& item : dev_idx_map) {
-    if (1 == item.second.size()) {
-      const chromeos::AudioDevice& device = item.second.front();
-      device_names->emplace_back(device.display_name,
-                                 base::NumberToString(device.id));
-    } else {
-      // Create virtual device name for audio nodes that share the same device
-      // index.
-      ProcessVirtualDeviceName(device_names, item.second);
-    }
-  }
-}
-
 void AudioManagerCras::GetAudioInputDeviceNames(
     AudioDeviceNames* device_names) {
-  GetAudioDeviceNamesImpl(true, device_names);
+  device_names->push_back(AudioDeviceName::CreateDefault());
 }
 
 void AudioManagerCras::GetAudioOutputDeviceNames(
     AudioDeviceNames* device_names) {
-  GetAudioDeviceNamesImpl(false, device_names);
+  device_names->push_back(AudioDeviceName::CreateDefault());
 }
 
 AudioParameters AudioManagerCras::GetInputStreamParameters(
@@ -172,73 +76,17 @@
   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
 
   int user_buffer_size = GetUserBufferSize();
-  int buffer_size = user_buffer_size ?
-      user_buffer_size : kDefaultInputBufferSize;
+  int buffer_size =
+      user_buffer_size ? user_buffer_size : kDefaultInputBufferSize;
 
-  // TODO(hshi): Fine-tune audio parameters based on |device_id|. The optimal
-  // parameters for the loopback stream may differ from the default.
   AudioParameters params(
       AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
       kDefaultSampleRate, buffer_size,
       AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
                                             limits::kMaxAudioBufferSize));
-  chromeos::AudioDeviceList devices;
-  GetAudioDevices(&devices);
-  if (HasKeyboardMic(devices))
-    params.set_effects(AudioParameters::KEYBOARD_MIC);
-
-  // Allow experimentation with system echo cancellation with all devices,
-  // but enable it by default on devices that actually support it.
-  params.set_effects(params.effects() |
-                     AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
-  if (base::FeatureList::IsEnabled(features::kCrOSSystemAEC)) {
-    if (GetSystemAecSupportedPerBoard()) {
-      const int32_t aec_group_id = GetSystemAecGroupIdPerBoard();
-
-      // Check if the system AEC has a group ID which is flagged to be
-      // deactivated by the field trial.
-      const bool system_aec_deactivated =
-          base::GetFieldTrialParamByFeatureAsBool(
-              features::kCrOSSystemAECDeactivatedGroups,
-              std::to_string(aec_group_id), false);
-
-      if (!system_aec_deactivated) {
-        params.set_effects(params.effects() | AudioParameters::ECHO_CANCELLER);
-      }
-    }
-  }
-
   return params;
 }
 
-std::string AudioManagerCras::GetAssociatedOutputDeviceID(
-    const std::string& input_device_id) {
-  chromeos::AudioDeviceList devices;
-  GetAudioDevices(&devices);
-
-  if (input_device_id == AudioDeviceDescription::kDefaultDeviceId) {
-    // Note: the default input should not be associated to any output, as this
-    // may lead to accidental uses of a pinned stream.
-    return "";
-  }
-
-  const std::string device_name =
-      GetHardwareDeviceFromDeviceId(devices, true, input_device_id);
-
-  if (device_name.empty())
-    return "";
-
-  // Now search for an output device with the same device name.
-  auto output_device_it = std::find_if(
-      devices.begin(), devices.end(),
-      [device_name](const chromeos::AudioDevice& device) {
-        return !device.is_input && device.device_name == device_name;
-      });
-  return output_device_it == devices.end()
-             ? ""
-             : base::NumberToString(output_device_it->id);
-}
-
 std::string AudioManagerCras::GetDefaultInputDeviceID() {
   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
   return base::NumberToString(GetPrimaryActiveInputNode());
@@ -249,133 +97,10 @@
   return base::NumberToString(GetPrimaryActiveOutputNode());
 }
 
-std::string AudioManagerCras::GetGroupIDOutput(
-    const std::string& output_device_id) {
-  chromeos::AudioDeviceList devices;
-  GetAudioDevices(&devices);
-
-  return GetHardwareDeviceFromDeviceId(devices, false, output_device_id);
-}
-
-std::string AudioManagerCras::GetGroupIDInput(
-    const std::string& input_device_id) {
-  chromeos::AudioDeviceList devices;
-  GetAudioDevices(&devices);
-
-  return GetHardwareDeviceFromDeviceId(devices, true, input_device_id);
-}
-
-const char* AudioManagerCras::GetName() {
-  return "CRAS";
-}
-
-bool AudioManagerCras::Shutdown() {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  weak_ptr_factory_.InvalidateWeakPtrs();
-  on_shutdown_.Signal();
-  return AudioManager::Shutdown();
-}
-
-AudioOutputStream* AudioManagerCras::MakeLinearOutputStream(
-    const AudioParameters& params,
-    const LogCallback& log_callback) {
-  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
-  // Pinning stream is not supported for MakeLinearOutputStream.
-  return MakeOutputStream(params, AudioDeviceDescription::kDefaultDeviceId);
-}
-
-AudioOutputStream* AudioManagerCras::MakeLowLatencyOutputStream(
-    const AudioParameters& params,
-    const std::string& device_id,
-    const LogCallback& log_callback) {
-  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
-  // TODO(dgreid): Open the correct input device for unified IO.
-  return MakeOutputStream(params, device_id);
-}
-
-AudioInputStream* AudioManagerCras::MakeLinearInputStream(
-    const AudioParameters& params,
-    const std::string& device_id,
-    const LogCallback& log_callback) {
-  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
-  return MakeInputStream(params, device_id);
-}
-
-AudioInputStream* AudioManagerCras::MakeLowLatencyInputStream(
-    const AudioParameters& params,
-    const std::string& device_id,
-    const LogCallback& log_callback) {
-  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
-  return MakeInputStream(params, device_id);
-}
-
-int AudioManagerCras::GetDefaultOutputBufferSizePerBoard() {
-  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
-  int32_t buffer_size = 512;
-  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
-                            base::WaitableEvent::InitialState::NOT_SIGNALED);
-  if (main_task_runner_->BelongsToCurrentThread()) {
-    // Unittest may use the same thread for audio thread.
-    GetDefaultOutputBufferSizeOnMainThread(&buffer_size, &event);
-  } else {
-    main_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            &AudioManagerCras::GetDefaultOutputBufferSizeOnMainThread,
-            weak_this_, base::Unretained(&buffer_size),
-            base::Unretained(&event)));
-  }
-  WaitEventOrShutdown(&event);
-  return static_cast<int>(buffer_size);
-}
-
-bool AudioManagerCras::GetSystemAecSupportedPerBoard() {
-  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
-  bool system_aec_supported = false;
-  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
-                            base::WaitableEvent::InitialState::NOT_SIGNALED);
-  if (main_task_runner_->BelongsToCurrentThread()) {
-    // Unittest may use the same thread for audio thread.
-    GetSystemAecSupportedOnMainThread(&system_aec_supported, &event);
-  } else {
-    // Using base::Unretained is safe here because we wait for callback be
-    // executed in main thread before local variables are destructed.
-    main_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AudioManagerCras::GetSystemAecSupportedOnMainThread,
-                       weak_this_, base::Unretained(&system_aec_supported),
-                       base::Unretained(&event)));
-  }
-  WaitEventOrShutdown(&event);
-  return system_aec_supported;
-}
-
-int32_t AudioManagerCras::GetSystemAecGroupIdPerBoard() {
-  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
-  int32_t group_id = chromeos::CrasAudioHandler::kSystemAecGroupIdNotAvailable;
-  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
-                            base::WaitableEvent::InitialState::NOT_SIGNALED);
-  if (main_task_runner_->BelongsToCurrentThread()) {
-    // Unittest may use the same thread for audio thread.
-    GetSystemAecGroupIdOnMainThread(&group_id, &event);
-  } else {
-    // Using base::Unretained is safe here because we wait for callback be
-    // executed in main thread before local variables are destructed.
-    main_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AudioManagerCras::GetSystemAecGroupIdOnMainThread,
-                       weak_this_, base::Unretained(&group_id),
-                       base::Unretained(&event)));
-  }
-  WaitEventOrShutdown(&event);
-  return group_id;
-}
-
 AudioParameters AudioManagerCras::GetPreferredOutputStreamParameters(
     const std::string& output_device_id,
     const AudioParameters& input_params) {
   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
-
   ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
   int sample_rate = kDefaultSampleRate;
   int buffer_size = GetUserBufferSize();
@@ -387,40 +112,10 @@
           std::min(static_cast<int>(limits::kMaxAudioBufferSize),
                    std::max(static_cast<int>(limits::kMinAudioBufferSize),
                             input_params.frames_per_buffer()));
-    return AudioParameters(
-        AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, sample_rate,
-        buffer_size,
-        AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
-                                              limits::kMaxAudioBufferSize));
-  }
-
-  // Get max supported channels from |output_device_id| or the primary active
-  // one if |output_device_id| is the default device.
-  uint64_t preferred_device_id;
-  if (AudioDeviceDescription::IsDefaultDevice(output_device_id)) {
-    preferred_device_id = GetPrimaryActiveOutputNode();
-  } else {
-    if (!base::StringToUint64(output_device_id, &preferred_device_id))
-      preferred_device_id = 0;  // 0 represents invalid |output_device_id|.
-  }
-
-  if (preferred_device_id) {
-    chromeos::AudioDeviceList devices;
-    GetAudioDevices(&devices);
-    const chromeos::AudioDevice* device =
-        GetDeviceFromId(devices, preferred_device_id);
-    if (device && device->is_input == false) {
-      channel_layout = GuessChannelLayout(
-          static_cast<int>(device->max_supported_channels));
-      // Fall-back to old fashion: always fixed to STEREO layout.
-      if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
-        channel_layout = CHANNEL_LAYOUT_STEREO;
-      }
-    }
   }
 
   if (!buffer_size)  // Not user-provided.
-    buffer_size = GetDefaultOutputBufferSizePerBoard();
+    buffer_size = kDefaultOutputBufferSize;
 
   return AudioParameters(
       AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, sample_rate,
@@ -429,160 +124,18 @@
                                             limits::kMaxAudioBufferSize));
 }
 
-AudioOutputStream* AudioManagerCras::MakeOutputStream(
-    const AudioParameters& params,
-    const std::string& device_id) {
-  return new CrasUnifiedStream(params, this, device_id);
-}
-
-AudioInputStream* AudioManagerCras::MakeInputStream(
-    const AudioParameters& params, const std::string& device_id) {
-  return new CrasInputStream(params, this, device_id);
-}
-
-bool AudioManagerCras::IsDefault(const std::string& device_id, bool is_input) {
-  AudioDeviceNames device_names;
-  GetAudioDeviceNamesImpl(is_input, &device_names);
-  DCHECK(!device_names.empty());
-  const AudioDeviceName& device_name = device_names.front();
-  return device_name.unique_id == device_id;
-}
-
-std::string AudioManagerCras::GetHardwareDeviceFromDeviceId(
-    const chromeos::AudioDeviceList& devices,
-    bool is_input,
-    const std::string& device_id) {
-  uint64_t u64_device_id = 0;
-  if (AudioDeviceDescription::IsDefaultDevice(device_id)) {
-    u64_device_id =
-        is_input ? GetPrimaryActiveInputNode() : GetPrimaryActiveOutputNode();
-  } else {
-    if (!base::StringToUint64(device_id, &u64_device_id))
-      return "";
-  }
-
-  const chromeos::AudioDevice* device = GetDeviceFromId(devices, u64_device_id);
-
-  return device ? device->device_name : "";
-}
-
-void AudioManagerCras::GetAudioDevices(chromeos::AudioDeviceList* devices) {
-  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
-  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
-                            base::WaitableEvent::InitialState::NOT_SIGNALED);
-  if (main_task_runner_->BelongsToCurrentThread()) {
-    GetAudioDevicesOnMainThread(devices, &event);
-  } else {
-    main_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AudioManagerCras::GetAudioDevicesOnMainThread,
-                       weak_this_, base::Unretained(devices),
-                       base::Unretained(&event)));
-  }
-  WaitEventOrShutdown(&event);
-}
-
-void AudioManagerCras::GetAudioDevicesOnMainThread(
-    chromeos::AudioDeviceList* devices,
-    base::WaitableEvent* event) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  // CrasAudioHandler is shut down before AudioManagerCras.
-  if (chromeos::CrasAudioHandler::Get())
-    chromeos::CrasAudioHandler::Get()->GetAudioDevices(devices);
-  event->Signal();
-}
-
 uint64_t AudioManagerCras::GetPrimaryActiveInputNode() {
   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
-  uint64_t device_id = 0;
-  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
-                            base::WaitableEvent::InitialState::NOT_SIGNALED);
-  if (main_task_runner_->BelongsToCurrentThread()) {
-    GetPrimaryActiveInputNodeOnMainThread(&device_id, &event);
-  } else {
-    main_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AudioManagerCras::GetPrimaryActiveInputNodeOnMainThread,
-                       weak_this_, &device_id, &event));
-  }
-  WaitEventOrShutdown(&event);
-  return device_id;
+  return 0;
 }
 
 uint64_t AudioManagerCras::GetPrimaryActiveOutputNode() {
   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
-  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
-                            base::WaitableEvent::InitialState::NOT_SIGNALED);
-  uint64_t device_id = 0;
-  if (main_task_runner_->BelongsToCurrentThread()) {
-    // Unittest may use the same thread for audio thread.
-    GetPrimaryActiveOutputNodeOnMainThread(&device_id, &event);
-  } else {
-    main_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            &AudioManagerCras::GetPrimaryActiveOutputNodeOnMainThread,
-            weak_this_, base::Unretained(&device_id),
-            base::Unretained(&event)));
-  }
-  WaitEventOrShutdown(&event);
-  return device_id;
+  return 0;
 }
 
-void AudioManagerCras::GetPrimaryActiveInputNodeOnMainThread(
-    uint64_t* active_input_node_id,
-    base::WaitableEvent* event) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  if (chromeos::CrasAudioHandler::Get()) {
-    *active_input_node_id =
-        chromeos::CrasAudioHandler::Get()->GetPrimaryActiveInputNode();
-  }
-  event->Signal();
-}
-
-void AudioManagerCras::GetPrimaryActiveOutputNodeOnMainThread(
-    uint64_t* active_output_node_id,
-    base::WaitableEvent* event) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  if (chromeos::CrasAudioHandler::Get()) {
-    *active_output_node_id =
-        chromeos::CrasAudioHandler::Get()->GetPrimaryActiveOutputNode();
-  }
-  event->Signal();
-}
-
-void AudioManagerCras::GetDefaultOutputBufferSizeOnMainThread(
-    int32_t* buffer_size,
-    base::WaitableEvent* event) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  if (chromeos::CrasAudioHandler::Get())
-    chromeos::CrasAudioHandler::Get()->GetDefaultOutputBufferSize(buffer_size);
-  event->Signal();
-}
-
-void AudioManagerCras::GetSystemAecSupportedOnMainThread(
-    bool* system_aec_supported,
-    base::WaitableEvent* event) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  if (chromeos::CrasAudioHandler::Get()) {
-    *system_aec_supported =
-        chromeos::CrasAudioHandler::Get()->system_aec_supported();
-  }
-  event->Signal();
-}
-
-void AudioManagerCras::GetSystemAecGroupIdOnMainThread(
-    int32_t* group_id,
-    base::WaitableEvent* event) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  if (chromeos::CrasAudioHandler::Get())
-    *group_id = chromeos::CrasAudioHandler::Get()->system_aec_group_id();
-  event->Signal();
-}
-
-void AudioManagerCras::WaitEventOrShutdown(base::WaitableEvent* event) {
-  base::WaitableEvent* waitables[] = {event, &on_shutdown_};
-  base::WaitableEvent::WaitMany(waitables, base::size(waitables));
+bool AudioManagerCras::IsDefault(const std::string& device_id, bool is_input) {
+  return true;
 }
 
 }  // namespace media
diff --git a/media/audio/cras/audio_manager_cras.h b/media/audio/cras/audio_manager_cras.h
index dda6df3..ef9c945 100644
--- a/media/audio/cras/audio_manager_cras.h
+++ b/media/audio/cras/audio_manager_cras.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -14,12 +14,11 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "chromeos/audio/audio_device.h"
-#include "media/audio/audio_manager_base.h"
+#include "media/audio/cras/audio_manager_cras_base.h"
 
 namespace media {
 
-class MEDIA_EXPORT AudioManagerCras : public AudioManagerBase {
+class MEDIA_EXPORT AudioManagerCras : public AudioManagerCrasBase {
  public:
   AudioManagerCras(std::unique_ptr<AudioThread> audio_thread,
                    AudioLogFactory* audio_log_factory);
@@ -32,35 +31,11 @@
   void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
   AudioParameters GetInputStreamParameters(
       const std::string& device_id) override;
-  std::string GetAssociatedOutputDeviceID(
-      const std::string& input_device_id) override;
   std::string GetDefaultInputDeviceID() override;
   std::string GetDefaultOutputDeviceID() override;
-  std::string GetGroupIDOutput(const std::string& output_device_id) override;
-  std::string GetGroupIDInput(const std::string& input_device_id) override;
-  const char* GetName() override;
-  bool Shutdown() override;
 
-  // AudioManagerBase implementation.
-  AudioOutputStream* MakeLinearOutputStream(
-      const AudioParameters& params,
-      const LogCallback& log_callback) override;
-  AudioOutputStream* MakeLowLatencyOutputStream(
-      const AudioParameters& params,
-      const std::string& device_id,
-      const LogCallback& log_callback) override;
-  AudioInputStream* MakeLinearInputStream(
-      const AudioParameters& params,
-      const std::string& device_id,
-      const LogCallback& log_callback) override;
-  AudioInputStream* MakeLowLatencyInputStream(
-      const AudioParameters& params,
-      const std::string& device_id,
-      const LogCallback& log_callback) override;
-
-  // Checks if |device_id| corresponds to the default device.
-  // Set |is_input| to true for capture devices, false for output.
-  bool IsDefault(const std::string& device_id, bool is_input);
+  // AudioManagerCras implementation.
+  bool IsDefault(const std::string& device_id, bool is_input) override;
 
  protected:
   AudioParameters GetPreferredOutputStreamParameters(
@@ -68,33 +43,6 @@
       const AudioParameters& input_params) override;
 
  private:
-  // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
-  AudioOutputStream* MakeOutputStream(const AudioParameters& params,
-                                      const std::string& device_id);
-
-  // Called by MakeLinearInputStream and MakeLowLatencyInputStream.
-  AudioInputStream* MakeInputStream(const AudioParameters& params,
-                                    const std::string& device_id);
-
-  // Get default output buffer size for this board.
-  int GetDefaultOutputBufferSizePerBoard();
-
-  // Get if system AEC is supported or not for this board.
-  bool GetSystemAecSupportedPerBoard();
-
-  // Get what the system AEC group ID is for this board.
-  int32_t GetSystemAecGroupIdPerBoard();
-
-  void GetAudioDeviceNamesImpl(bool is_input, AudioDeviceNames* device_names);
-
-  std::string GetHardwareDeviceFromDeviceId(
-      const chromeos::AudioDeviceList& devices,
-      bool is_input,
-      const std::string& device_id);
-
-  void GetAudioDevices(chromeos::AudioDeviceList* devices);
-  void GetAudioDevicesOnMainThread(chromeos::AudioDeviceList* devices,
-                                   base::WaitableEvent* event);
   uint64_t GetPrimaryActiveInputNode();
   uint64_t GetPrimaryActiveOutputNode();
   void GetPrimaryActiveInputNodeOnMainThread(uint64_t* active_input_node_id,
@@ -103,15 +51,6 @@
                                               base::WaitableEvent* event);
   void GetDefaultOutputBufferSizeOnMainThread(int32_t* buffer_size,
                                               base::WaitableEvent* event);
-  void GetSystemAecSupportedOnMainThread(bool* system_aec_supported,
-                                         base::WaitableEvent* event);
-  void GetSystemAecGroupIdOnMainThread(int32_t* group_id,
-                                       base::WaitableEvent* event);
-
-  void WaitEventOrShutdown(base::WaitableEvent* event);
-
-  // Signaled if AudioManagerCras is shutting down.
-  base::WaitableEvent on_shutdown_;
 
   // Task runner of browser main thread. CrasAudioHandler should be only
   // accessed on this thread.
diff --git a/media/audio/cras/audio_manager_cras_base.cc b/media/audio/cras/audio_manager_cras_base.cc
new file mode 100644
index 0000000..5c57e1a
--- /dev/null
+++ b/media/audio/cras/audio_manager_cras_base.cc
@@ -0,0 +1,96 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/audio/cras/audio_manager_cras_base.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <map>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/check_op.h"
+#include "base/command_line.h"
+#include "base/environment.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/nix/xdg_util.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/system/sys_info.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_features.h"
+#include "media/audio/cras/cras_input.h"
+#include "media/audio/cras/cras_unified.h"
+#include "media/base/channel_layout.h"
+#include "media/base/limits.h"
+#include "media/base/localized_strings.h"
+
+namespace media {
+namespace {
+
+// Maximum number of output streams that can be open simultaneously.
+const int kMaxOutputStreams = 50;
+
+}  // namespace
+
+AudioManagerCrasBase::AudioManagerCrasBase(
+    std::unique_ptr<AudioThread> audio_thread,
+    AudioLogFactory* audio_log_factory)
+    : AudioManagerBase(std::move(audio_thread), audio_log_factory) {
+  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
+}
+
+AudioManagerCrasBase::~AudioManagerCrasBase() = default;
+
+const char* AudioManagerCrasBase::GetName() {
+  return "CRAS";
+}
+
+AudioOutputStream* AudioManagerCrasBase::MakeLinearOutputStream(
+    const AudioParameters& params,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+  // Pinning stream is not supported for MakeLinearOutputStream.
+  return MakeOutputStream(params, AudioDeviceDescription::kDefaultDeviceId);
+}
+
+AudioOutputStream* AudioManagerCrasBase::MakeLowLatencyOutputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+  return MakeOutputStream(params, device_id);
+}
+
+AudioInputStream* AudioManagerCrasBase::MakeLinearInputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+  return MakeInputStream(params, device_id);
+}
+
+AudioInputStream* AudioManagerCrasBase::MakeLowLatencyInputStream(
+    const AudioParameters& params,
+    const std::string& device_id,
+    const LogCallback& log_callback) {
+  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+  return MakeInputStream(params, device_id);
+}
+
+AudioOutputStream* AudioManagerCrasBase::MakeOutputStream(
+    const AudioParameters& params,
+    const std::string& device_id) {
+  return new CrasUnifiedStream(params, this, device_id);
+}
+
+AudioInputStream* AudioManagerCrasBase::MakeInputStream(
+    const AudioParameters& params, const std::string& device_id) {
+  return new CrasInputStream(params, this, device_id);
+}
+
+}  // namespace media
diff --git a/media/audio/cras/audio_manager_cras_base.h b/media/audio/cras/audio_manager_cras_base.h
new file mode 100644
index 0000000..eff016fe
--- /dev/null
+++ b/media/audio/cras/audio_manager_cras_base.h
@@ -0,0 +1,66 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_AUDIO_CRAS_AUDIO_MANAGER_CRAS_BASE_H_
+#define MEDIA_AUDIO_CRAS_AUDIO_MANAGER_CRAS_BASE_H_
+
+#include <cras_types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "media/audio/audio_manager_base.h"
+
+namespace media {
+
+class MEDIA_EXPORT AudioManagerCrasBase : public AudioManagerBase {
+ public:
+  AudioManagerCrasBase(std::unique_ptr<AudioThread> audio_thread,
+                   AudioLogFactory* audio_log_factory);
+  ~AudioManagerCrasBase() override;
+
+  // AudioManager implementation.
+  const char* GetName() override;
+
+  // AudioManagerBase implementation.
+  AudioOutputStream* MakeLinearOutputStream(
+      const AudioParameters& params,
+      const LogCallback& log_callback) override;
+  AudioOutputStream* MakeLowLatencyOutputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  AudioInputStream* MakeLinearInputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+  AudioInputStream* MakeLowLatencyInputStream(
+      const AudioParameters& params,
+      const std::string& device_id,
+      const LogCallback& log_callback) override;
+
+  // Checks if |device_id| corresponds to the default device.
+  // Set |is_input| to true for capture devices, false for output.
+  virtual bool IsDefault(const std::string& device_id, bool is_input) = 0;
+
+ protected:
+  // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
+  AudioOutputStream* MakeOutputStream(const AudioParameters& params,
+                                      const std::string& device_id);
+
+  // Called by MakeLinearInputStream and MakeLowLatencyInputStream.
+  AudioInputStream* MakeInputStream(const AudioParameters& params,
+                                    const std::string& device_id);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AudioManagerCrasBase);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_AUDIO_CRAS_AUDIO_MANAGER_CRAS_BASE_H_
diff --git a/media/audio/cras/cras_input.cc b/media/audio/cras/cras_input.cc
index 44a59c2c..539b327 100644
--- a/media/audio/cras/cras_input.cc
+++ b/media/audio/cras/cras_input.cc
@@ -12,12 +12,12 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
 #include "media/audio/audio_device_description.h"
-#include "media/audio/cras/audio_manager_cras.h"
+#include "media/audio/cras/audio_manager_cras_base.h"
 
 namespace media {
 
 CrasInputStream::CrasInputStream(const AudioParameters& params,
-                                 AudioManagerCras* manager,
+                                 AudioManagerCrasBase* manager,
                                  const std::string& device_id)
     : audio_manager_(manager),
       bytes_per_frame_(0),
diff --git a/media/audio/cras/cras_input.h b/media/audio/cras/cras_input.h
index ed0815e6..f9ebad9 100644
--- a/media/audio/cras/cras_input.h
+++ b/media/audio/cras/cras_input.h
@@ -21,7 +21,7 @@
 
 namespace media {
 
-class AudioManagerCras;
+class AudioManagerCrasBase;
 
 // Provides an input stream for audio capture based on CRAS, the ChromeOS Audio
 // Server.  This object is not thread safe and all methods should be invoked in
@@ -31,7 +31,7 @@
   // The ctor takes all the usual parameters, plus |manager| which is the
   // audio manager who is creating this object.
   CrasInputStream(const AudioParameters& params,
-                  AudioManagerCras* manager,
+                  AudioManagerCrasBase* manager,
                   const std::string& device_id);
 
   // The dtor is typically called by the AudioManager only and it is usually
@@ -86,7 +86,7 @@
   // want circular references.  Additionally, stream objects live on the audio
   // thread, which is owned by the audio manager and we don't want to addref
   // the manager from that thread.
-  AudioManagerCras* const audio_manager_;
+  AudioManagerCrasBase* const audio_manager_;
 
   // Size of frame in bytes.
   uint32_t bytes_per_frame_;
diff --git a/media/audio/cras/cras_input_unittest.cc b/media/audio/cras/cras_input_unittest.cc
index fc1ce1b2..9aedd49 100644
--- a/media/audio/cras/cras_input_unittest.cc
+++ b/media/audio/cras/cras_input_unittest.cc
@@ -17,7 +17,7 @@
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/dbus/audio/fake_cras_audio_client.h"
 #include "media/audio/audio_device_description.h"
-#include "media/audio/cras/audio_manager_cras.h"
+#include "media/audio/cras/audio_manager_chromeos.h"
 #include "media/audio/fake_audio_log_factory.h"
 #include "media/audio/test_audio_thread.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -43,11 +43,11 @@
   MOCK_METHOD0(OnError, void());
 };
 
-class MockAudioManagerCrasInput : public AudioManagerCras {
+class MockAudioManagerCrasInput : public AudioManagerChromeOS {
  public:
   MockAudioManagerCrasInput()
-      : AudioManagerCras(std::make_unique<TestAudioThread>(),
-                         &fake_audio_log_factory_) {}
+      : AudioManagerChromeOS(std::make_unique<TestAudioThread>(),
+                             &fake_audio_log_factory_) {}
 
   // We need to override this function in order to skip checking the number
   // of active output streams. It is because the number of active streams
diff --git a/media/audio/cras/cras_unified.cc b/media/audio/cras/cras_unified.cc
index fc44faa1a..d946fb8 100644
--- a/media/audio/cras/cras_unified.cc
+++ b/media/audio/cras/cras_unified.cc
@@ -9,13 +9,13 @@
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
-#include "media/audio/cras/audio_manager_cras.h"
+#include "media/audio/cras/audio_manager_cras_base.h"
 
 namespace media {
 
 namespace {
 
-int GetDevicePin(AudioManagerCras* manager, const std::string& device_id) {
+int GetDevicePin(AudioManagerCrasBase* manager, const std::string& device_id) {
   if (!manager->IsDefault(device_id, false)) {
     uint64_t cras_node_id;
     base::StringToUint64(device_id, &cras_node_id);
@@ -66,7 +66,7 @@
 // of audio.
 
 CrasUnifiedStream::CrasUnifiedStream(const AudioParameters& params,
-                                     AudioManagerCras* manager,
+                                     AudioManagerCrasBase* manager,
                                      const std::string& device_id)
     : client_(NULL),
       stream_id_(0),
diff --git a/media/audio/cras/cras_unified.h b/media/audio/cras/cras_unified.h
index c857ac4..f5732d4 100644
--- a/media/audio/cras/cras_unified.h
+++ b/media/audio/cras/cras_unified.h
@@ -24,7 +24,7 @@
 
 namespace media {
 
-class AudioManagerCras;
+class AudioManagerCrasBase;
 
 // Implementation of AudioOuputStream for Chrome OS using the Chrome OS audio
 // server.
@@ -36,7 +36,7 @@
   // The ctor takes all the usual parameters, plus |manager| which is the
   // audio manager who is creating this object.
   CrasUnifiedStream(const AudioParameters& params,
-                    AudioManagerCras* manager,
+                    AudioManagerCrasBase* manager,
                     const std::string& device_id);
 
   // The dtor is typically called by the AudioManager only and it is usually
@@ -103,7 +103,7 @@
   float volume_;
 
   // Audio manager that created us.  Used to report that we've been closed.
-  AudioManagerCras* manager_;
+  AudioManagerCrasBase* manager_;
 
   // Callback to get audio samples.
   AudioSourceCallback* source_callback_;
diff --git a/media/audio/cras/cras_unified_unittest.cc b/media/audio/cras/cras_unified_unittest.cc
index 9f036f6..d6a8ca7 100644
--- a/media/audio/cras/cras_unified_unittest.cc
+++ b/media/audio/cras/cras_unified_unittest.cc
@@ -17,7 +17,7 @@
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/dbus/audio/cras_audio_client.h"
 #include "media/audio/audio_device_description.h"
-#include "media/audio/cras/audio_manager_cras.h"
+#include "media/audio/cras/audio_manager_chromeos.h"
 #include "media/audio/fake_audio_log_factory.h"
 #include "media/audio/mock_audio_source_callback.h"
 #include "media/audio/test_audio_thread.h"
@@ -39,11 +39,11 @@
 
 namespace media {
 
-class MockAudioManagerCras : public AudioManagerCras {
+class MockAudioManagerCras : public AudioManagerChromeOS {
  public:
   MockAudioManagerCras()
-      : AudioManagerCras(std::make_unique<TestAudioThread>(),
-                         &fake_audio_log_factory_) {}
+      : AudioManagerChromeOS(std::make_unique<TestAudioThread>(),
+                             &fake_audio_log_factory_) {}
 
   // We need to override this function in order to skip the checking the number
   // of active output streams. It is because the number of active streams
diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc
index cb8f271..efa8732 100644
--- a/media/audio/linux/audio_manager_linux.cc
+++ b/media/audio/linux/audio_manager_linux.cc
@@ -13,9 +13,13 @@
 #if defined(USE_ALSA)
 #include "media/audio/alsa/audio_manager_alsa.h"
 #endif
-#if defined(USE_CRAS)
+
+#if defined(USE_CRAS) && defined(OS_CHROMEOS)
+#include "media/audio/cras/audio_manager_chromeos.h"
+#elif defined(USE_CRAS)
 #include "media/audio/cras/audio_manager_cras.h"
 #endif
+
 #if defined(USE_PULSEAUDIO)
 #include "media/audio/pulse/audio_manager_pulse.h"
 #include "media/audio/pulse/pulse_util.h"
@@ -43,10 +47,15 @@
 #if defined(USE_CRAS)
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseCras)) {
     UMA_HISTOGRAM_ENUMERATION("Media.LinuxAudioIO", kCras, kAudioIOMax + 1);
+#if defined(OS_CHROMEOS)
+    return std::make_unique<AudioManagerChromeOS>(std::move(audio_thread),
+                                                  audio_log_factory);
+#else
     return std::make_unique<AudioManagerCras>(std::move(audio_thread),
-                                              audio_log_factory);
-  }
+                                                   audio_log_factory);
 #endif
+  }
+#endif // defined(USE_CRAS)
 
 #if defined(USE_PULSEAUDIO)
   pa_threaded_mainloop* pa_mainloop = nullptr;
diff --git a/media/gpu/mac/BUILD.gn b/media/gpu/mac/BUILD.gn
index 8a4010a..d845229 100644
--- a/media/gpu/mac/BUILD.gn
+++ b/media/gpu/mac/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/config/features.gni")
 import("//build/config/ui.gni")
 import("//media/gpu/args.gni")
+import("//media/media_options.gni")
 import("//tools/generate_stubs/rules.gni")
 import("//ui/gl/features.gni")
 import("//ui/ozone/ozone.gni")
@@ -24,6 +25,8 @@
   visibility = [ "//media/gpu" ]
 
   sources = [
+    "vp9_super_frame_bitstream_filter.cc",
+    "vp9_super_frame_bitstream_filter.h",
     "vt_config_util.h",
     "vt_config_util.mm",
     "vt_video_decode_accelerator_mac.cc",
@@ -59,8 +62,17 @@
     "CoreMedia.framework",
   ]
   deps = [
+    "//media:test_support",
     "//media/gpu:test_support",
     "//testing/gtest",
   ]
-  sources = [ "vt_config_util_unittest.cc" ]
+
+  if (media_use_ffmpeg) {
+    deps += [ "//third_party/ffmpeg" ]
+  }
+
+  sources = [
+    "vp9_super_frame_bitstream_filter_unittest.cc",
+    "vt_config_util_unittest.cc",
+  ]
 }
diff --git a/media/gpu/mac/vp9_super_frame_bitstream_filter.cc b/media/gpu/mac/vp9_super_frame_bitstream_filter.cc
new file mode 100644
index 0000000..ab01992
--- /dev/null
+++ b/media/gpu/mac/vp9_super_frame_bitstream_filter.cc
@@ -0,0 +1,211 @@
+// 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 "media/gpu/mac/vp9_super_frame_bitstream_filter.h"
+
+#include "base/bits.h"
+#include "base/check.h"
+#include "base/logging.h"
+#include "base/mac/mac_logging.h"
+#include "media/filters/vp9_raw_bits_reader.h"
+
+namespace {
+
+void ReleaseDecoderBuffer(void* refcon,
+                          void* doomed_memory_block,
+                          size_t size_in_bytes) {
+  if (refcon)
+    static_cast<media::DecoderBuffer*>(refcon)->Release();
+}
+
+// See Annex B of the VP9 specification for details.
+// https://www.webmproject.org/vp9/
+constexpr uint8_t kSuperFrameMarker = 0b11000000;
+
+}  // namespace
+
+namespace media {
+
+VP9SuperFrameBitstreamFilter::VP9SuperFrameBitstreamFilter() = default;
+VP9SuperFrameBitstreamFilter::~VP9SuperFrameBitstreamFilter() = default;
+
+bool VP9SuperFrameBitstreamFilter::EnqueueBuffer(
+    scoped_refptr<DecoderBuffer> buffer) {
+  DCHECK(!buffer->end_of_stream());
+
+  Vp9RawBitsReader reader;
+  reader.Initialize(buffer->data(), buffer->data_size());
+  const bool show_frame = ShouldShowFrame(&reader);
+  if (!reader.IsValid()) {
+    DLOG(ERROR) << "Bitstream reading failed.";
+    return false;
+  }
+
+  // See Vp9Parser::ParseSuperframe() for more details.
+  const bool is_superframe =
+      (buffer->data()[buffer->data_size() - 1] & 0xE0) == kSuperFrameMarker;
+  if (is_superframe && data_) {
+    DLOG(WARNING) << "Mixing of superframe and raw frames not supported";
+    return false;
+  }
+
+  // Passthrough.
+  if ((show_frame || is_superframe) && partial_buffers_.empty()) {
+    DCHECK(!data_);
+    return PreparePassthroughBuffer(std::move(buffer));
+  }
+
+  partial_buffers_.emplace_back(std::move(buffer));
+  if (!show_frame)
+    return true;
+
+  // Time to merge buffers into one superframe.
+  return BuildSuperFrame();
+}
+
+void VP9SuperFrameBitstreamFilter::Flush() {
+  partial_buffers_.clear();
+  data_.reset();
+}
+
+bool VP9SuperFrameBitstreamFilter::ShouldShowFrame(Vp9RawBitsReader* reader) {
+  // See section 6.2 of the VP9 specification.
+  reader->ReadLiteral(2);  // frame_marker
+
+  uint8_t profile = 0;
+  if (reader->ReadBool())  // profile_low_bit
+    profile |= 1;
+  if (reader->ReadBool())  // profile_high_bit
+    profile |= 2;
+  if (profile > 2 && reader->ReadBool())  // reserved_zero
+    profile += 1;
+
+  if (reader->ReadBool())  // show_existing_frame
+    return true;
+
+  reader->ReadBool();         // frame_type
+  return reader->ReadBool();  // show_frame
+}
+
+bool VP9SuperFrameBitstreamFilter::PreparePassthroughBuffer(
+    scoped_refptr<DecoderBuffer> buffer) {
+  // The created CMBlockBuffer owns a ref on DecoderBuffer to avoid a copy.
+  CMBlockBufferCustomBlockSource source = {0};
+  source.refCon = buffer.get();
+  source.FreeBlock = &ReleaseDecoderBuffer;
+
+  // Create a memory-backed CMBlockBuffer for the translated data.
+  OSStatus status = CMBlockBufferCreateWithMemoryBlock(
+      kCFAllocatorDefault, static_cast<void*>(buffer->writable_data()),
+      buffer->data_size(), kCFAllocatorDefault, &source, 0, buffer->data_size(),
+      0, data_.InitializeInto());
+  if (status != noErr) {
+    OSSTATUS_DLOG(ERROR, status)
+        << "CMBlockBufferCreateWithMemoryBlock failed.";
+    return false;
+  }
+
+  buffer->AddRef();
+  return true;
+}
+
+bool VP9SuperFrameBitstreamFilter::AllocateCombinedBlock(size_t total_size) {
+  DCHECK(!data_);
+
+  OSStatus status = CMBlockBufferCreateWithMemoryBlock(
+      kCFAllocatorDefault, nullptr, total_size, kCFAllocatorDefault, nullptr, 0,
+      total_size, 0, data_.InitializeInto());
+  if (status != noErr) {
+    OSSTATUS_DLOG(ERROR, status)
+        << "CMBlockBufferCreateWithMemoryBlock failed.";
+    return false;
+  }
+
+  status = CMBlockBufferAssureBlockMemory(data_);
+  if (status != noErr) {
+    OSSTATUS_DLOG(ERROR, status) << "CMBlockBufferAssureBlockMemory failed.";
+    return false;
+  }
+
+  return true;
+}
+
+bool VP9SuperFrameBitstreamFilter::MergeBuffer(const DecoderBuffer& buffer,
+                                               size_t offset) {
+  OSStatus status = CMBlockBufferReplaceDataBytes(buffer.data(), data_, offset,
+                                                  buffer.data_size());
+  if (status != noErr) {
+    OSSTATUS_DLOG(ERROR, status) << "CMBlockBufferReplaceDataBytes failed.";
+    return false;
+  }
+
+  return true;
+}
+
+bool VP9SuperFrameBitstreamFilter::BuildSuperFrame() {
+  DCHECK(!partial_buffers_.empty());
+
+  // See Annex B of the VP9 specification for details on this process.
+
+  // Calculate maximum and total size.
+  size_t total_size = 0, max_size = 0;
+  for (const auto& b : partial_buffers_) {
+    total_size += b->data_size();
+    if (b->data_size() > max_size)
+      max_size = b->data_size();
+  }
+
+  const uint8_t bytes_per_frame_size =
+      base::bits::Align(
+          base::bits::Log2Ceiling(base::checked_cast<uint32_t>(max_size)), 8) /
+      8;
+  DCHECK_GT(bytes_per_frame_size, 0);
+  DCHECK_LE(bytes_per_frame_size, 4u);
+
+  // A leading and trailing marker byte plus storage for each frame size.
+  total_size += 2 + bytes_per_frame_size * partial_buffers_.size();
+
+  // Allocate a block to hold the superframe.
+  if (!AllocateCombinedBlock(total_size))
+    return false;
+
+  // Merge each buffer into our superframe.
+  size_t offset = 0;
+  for (const auto& b : partial_buffers_) {
+    if (!MergeBuffer(*b, offset))
+      return false;
+    offset += b->data_size();
+  }
+
+  // Write superframe trailer which has size information for each buffer.
+  size_t trailer_offset = 0;
+  const size_t trailer_size = total_size - offset;
+  std::unique_ptr<uint8_t[]> trailer(new uint8_t[trailer_size]);
+
+  const uint8_t marker = kSuperFrameMarker + ((bytes_per_frame_size - 1) << 3) +
+                         (partial_buffers_.size() - 1);
+
+  trailer[trailer_offset++] = marker;
+  for (const auto& b : partial_buffers_) {
+    const uint32_t s = base::checked_cast<uint32_t>(b->data_size());
+    DCHECK_LE(s, (1ULL << (bytes_per_frame_size * 8)) - 1);
+
+    memcpy(&trailer[trailer_offset], &s, bytes_per_frame_size);
+    trailer_offset += bytes_per_frame_size;
+  }
+  DCHECK_EQ(trailer_offset, trailer_size - 1);
+  trailer[trailer_offset] = marker;
+
+  OSStatus status =
+      CMBlockBufferReplaceDataBytes(trailer.get(), data_, offset, trailer_size);
+  if (status != noErr) {
+    OSSTATUS_DLOG(ERROR, status) << "CMBlockBufferReplaceDataBytes failed.";
+    return false;
+  }
+
+  partial_buffers_.clear();
+  return true;
+}
+
+}  // namespace media
diff --git a/media/gpu/mac/vp9_super_frame_bitstream_filter.h b/media/gpu/mac/vp9_super_frame_bitstream_filter.h
new file mode 100644
index 0000000..5019fe8
--- /dev/null
+++ b/media/gpu/mac/vp9_super_frame_bitstream_filter.h
@@ -0,0 +1,59 @@
+// 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 MEDIA_GPU_MAC_VP9_SUPER_FRAME_BITSTREAM_FILTER_H_
+#define MEDIA_GPU_MAC_VP9_SUPER_FRAME_BITSTREAM_FILTER_H_
+
+#include <vector>
+
+#include <CoreMedia/CoreMedia.h>
+
+#include "base/mac/scoped_cftyperef.h"
+#include "media/base/decoder_buffer.h"
+#include "media/gpu/media_gpu_export.h"
+
+namespace media {
+class Vp9RawBitsReader;
+
+// Combines alt-ref VP9 buffers into super frames and passes through non-alt-ref
+// buffers without modification.
+class MEDIA_GPU_EXPORT VP9SuperFrameBitstreamFilter {
+ public:
+  VP9SuperFrameBitstreamFilter();
+  ~VP9SuperFrameBitstreamFilter();
+
+  // Adds a buffer for processing. Clients must call take_buffer() after this
+  // to see if a buffer is ready for processing.
+  bool EnqueueBuffer(scoped_refptr<DecoderBuffer> buffer);
+
+  // Releases any pending data.
+  void Flush();
+
+  // Releases any prepared buffer. Returns null if no buffers are available.
+  base::ScopedCFTypeRef<CMBlockBufferRef> take_buffer() {
+    return std::move(data_);
+  }
+
+  bool has_buffers_for_testing() const {
+    return data_ || !partial_buffers_.empty();
+  }
+
+ private:
+  bool ShouldShowFrame(Vp9RawBitsReader* reader);
+  bool PreparePassthroughBuffer(scoped_refptr<DecoderBuffer> buffer);
+  bool AllocateCombinedBlock(size_t total_size);
+  bool MergeBuffer(const DecoderBuffer& buffer, size_t offset);
+  bool BuildSuperFrame();
+
+  // Prepared CMBlockBuffer -- either by assembling |partial_buffers_| or when
+  // a super frame is unnecessary, just by passing through DecoderBuffer.
+  base::ScopedCFTypeRef<CMBlockBufferRef> data_;
+
+  // Partial buffers which need to be assembled into a super frame.
+  std::vector<scoped_refptr<DecoderBuffer>> partial_buffers_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_MAC_VP9_SUPER_FRAME_BITSTREAM_FILTER_H_
diff --git a/media/gpu/mac/vp9_super_frame_bitstream_filter_unittest.cc b/media/gpu/mac/vp9_super_frame_bitstream_filter_unittest.cc
new file mode 100644
index 0000000..22286d7f
--- /dev/null
+++ b/media/gpu/mac/vp9_super_frame_bitstream_filter_unittest.cc
@@ -0,0 +1,180 @@
+// 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 "media/gpu/mac/vp9_super_frame_bitstream_filter.h"
+
+#include <CoreMedia/CoreMedia.h>
+
+#include "media/base/media.h"
+#include "media/base/test_data_util.h"
+#include "media/ffmpeg/ffmpeg_common.h"
+#include "media/filters/ffmpeg_glue.h"
+#include "media/filters/in_memory_url_protocol.h"
+#include "media/filters/vp9_parser.h"
+#include "media/media_buildflags.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+#if BUILDFLAG(ENABLE_FFMPEG)
+
+class VP9SuperFrameBitstreamFilterTest : public testing::Test {
+ public:
+  VP9SuperFrameBitstreamFilterTest()
+      : parser_(/*parsing_compressed_header=*/false) {
+    InitializeMediaLibrary();
+  }
+
+  ~VP9SuperFrameBitstreamFilterTest() override = default;
+
+  void LoadTestData(const char* file_name) {
+    buffer_ = ReadTestDataFile(file_name);
+    ASSERT_TRUE(buffer_);
+
+    // Initialize ffmpeg with the file data.
+    protocol_ = std::make_unique<InMemoryUrlProtocol>(
+        buffer_->data(), buffer_->data_size(), false);
+    glue_ = std::make_unique<FFmpegGlue>(protocol_.get());
+    ASSERT_TRUE(glue_->OpenContext());
+  }
+
+  scoped_refptr<DecoderBuffer> ReadPacket(int stream_index = 0) {
+    AVPacket packet = {0};
+    while (av_read_frame(glue_->format_context(), &packet) >= 0) {
+      if (packet.stream_index == stream_index) {
+        auto buffer = DecoderBuffer::CopyFrom(packet.data, packet.size);
+        av_packet_unref(&packet);
+        return buffer;
+      }
+      av_packet_unref(&packet);
+    }
+    return nullptr;
+  }
+
+  Vp9Parser::Result ParseNextFrame() {
+    // Temporaries for the Vp9Parser.
+    Vp9FrameHeader fhdr;
+    gfx::Size coded_size;
+    std::unique_ptr<DecryptConfig> null_config;
+    return parser_.ParseNextFrame(&fhdr, &coded_size, &null_config);
+  }
+
+ protected:
+  Vp9Parser parser_;
+
+ private:
+  scoped_refptr<DecoderBuffer> buffer_;
+  std::unique_ptr<InMemoryUrlProtocol> protocol_;
+  std::unique_ptr<FFmpegGlue> glue_;
+};
+
+TEST_F(VP9SuperFrameBitstreamFilterTest, Passthrough) {
+  // This test file has no super frames.
+  ASSERT_NO_FATAL_FAILURE(LoadTestData("bear-vp9.webm"));
+
+  // Run through a few packets for good measure.
+  VP9SuperFrameBitstreamFilter bsf;
+  for (int i = 0; i < 16; ++i) {
+    auto buffer = ReadPacket();
+    EXPECT_TRUE(buffer->HasOneRef());
+
+    // Passthrough buffers should be zero-copy, so a ref should be added.
+    bsf.EnqueueBuffer(buffer);
+    EXPECT_FALSE(buffer->HasOneRef());
+
+    auto cm_block = bsf.take_buffer();
+    ASSERT_TRUE(cm_block);
+
+    ASSERT_EQ(buffer->data_size(), CMBlockBufferGetDataLength(cm_block));
+
+    std::unique_ptr<uint8_t> block_data(new uint8_t[buffer->data_size()]);
+    ASSERT_EQ(noErr, CMBlockBufferCopyDataBytes(
+                         cm_block, 0, buffer->data_size(), block_data.get()));
+
+    // Verify that the block is valid.
+    parser_.SetStream(block_data.get(), buffer->data_size(), nullptr);
+    EXPECT_EQ(Vp9Parser::kOk, ParseNextFrame());
+    EXPECT_EQ(Vp9Parser::kEOStream, ParseNextFrame());
+
+    // Releasing the block should bring our ref count back down.
+    cm_block.reset();
+    ASSERT_TRUE(buffer->HasOneRef());
+  }
+}
+
+TEST_F(VP9SuperFrameBitstreamFilterTest, Superframe) {
+  ASSERT_NO_FATAL_FAILURE(LoadTestData("buck-1280x720-vp9.webm"));
+
+  VP9SuperFrameBitstreamFilter bsf;
+
+  // The first packet in this file is not part of a super frame. We still need
+  // to send it to the VP9 parser so that the superframe can reference it.
+  auto buffer = ReadPacket();
+  parser_.SetStream(buffer->data(), buffer->data_size(), nullptr);
+  EXPECT_EQ(Vp9Parser::kOk, ParseNextFrame());
+  bsf.EnqueueBuffer(std::move(buffer));
+  ASSERT_TRUE(bsf.take_buffer());
+
+  // The second and third belong to a super frame.
+  buffer = ReadPacket();
+  size_t total_size = buffer->data_size();
+  bsf.EnqueueBuffer(std::move(buffer));
+  ASSERT_FALSE(bsf.take_buffer());
+  buffer = ReadPacket();
+  total_size += buffer->data_size();
+  bsf.EnqueueBuffer(std::move(buffer));
+
+  auto cm_block = bsf.take_buffer();
+  ASSERT_TRUE(cm_block);
+
+  // Two marker bytes and 2x 16-bit sizes.
+  const size_t kExpectedTotalSize = 1 + 2 + 2 + 1 + total_size;
+  EXPECT_EQ(kExpectedTotalSize, CMBlockBufferGetDataLength(cm_block));
+
+  std::unique_ptr<uint8_t> block_data(new uint8_t[kExpectedTotalSize]);
+  ASSERT_EQ(noErr, CMBlockBufferCopyDataBytes(cm_block, 0, kExpectedTotalSize,
+                                              block_data.get()));
+
+  parser_.SetStream(block_data.get(), kExpectedTotalSize, nullptr);
+  EXPECT_EQ(Vp9Parser::kOk, ParseNextFrame());
+  EXPECT_EQ(Vp9Parser::kOk, ParseNextFrame());
+  EXPECT_EQ(Vp9Parser::kEOStream, ParseNextFrame());
+}
+
+TEST_F(VP9SuperFrameBitstreamFilterTest, FlushPassthroughFrame) {
+  ASSERT_NO_FATAL_FAILURE(LoadTestData("buck-1280x720-vp9.webm"));
+
+  VP9SuperFrameBitstreamFilter bsf;
+
+  // The first packet in this file is not part of a super frame.
+  bsf.EnqueueBuffer(ReadPacket());
+  ASSERT_TRUE(bsf.has_buffers_for_testing());
+  bsf.Flush();
+  ASSERT_FALSE(bsf.has_buffers_for_testing());
+  ASSERT_FALSE(bsf.take_buffer());
+}
+
+TEST_F(VP9SuperFrameBitstreamFilterTest, FlushPartialSuperFrame) {
+  ASSERT_NO_FATAL_FAILURE(LoadTestData("buck-1280x720-vp9.webm"));
+
+  VP9SuperFrameBitstreamFilter bsf;
+
+  // The first packet in this file is not part of a super frame.
+  bsf.EnqueueBuffer(ReadPacket());
+  ASSERT_TRUE(bsf.has_buffers_for_testing());
+  ASSERT_TRUE(bsf.take_buffer());
+
+  // The second and third belong to a super frame.
+  bsf.EnqueueBuffer(ReadPacket());
+  ASSERT_FALSE(bsf.take_buffer());
+  ASSERT_TRUE(bsf.has_buffers_for_testing());
+
+  bsf.Flush();
+  ASSERT_FALSE(bsf.has_buffers_for_testing());
+  ASSERT_FALSE(bsf.take_buffer());
+}
+
+#endif  // BUILDFLAG(ENABLE_FFMPEG)
+
+}  // namespace media
diff --git a/media/gpu/mac/vt_video_decode_accelerator_mac.cc b/media/gpu/mac/vt_video_decode_accelerator_mac.cc
index 62cc62d51..19a72339 100644
--- a/media/gpu/mac/vt_video_decode_accelerator_mac.cc
+++ b/media/gpu/mac/vt_video_decode_accelerator_mac.cc
@@ -37,6 +37,7 @@
 #include "media/base/limits.h"
 #include "media/base/media_switches.h"
 #include "media/filters/vp9_parser.h"
+#include "media/gpu/mac/vp9_super_frame_bitstream_filter.h"
 #include "media/gpu/mac/vt_beta_stubs.h"
 #include "media/gpu/mac/vt_config_util.h"
 #include "ui/gfx/geometry/rect.h"
@@ -377,13 +378,6 @@
   vda->Output(source_frame_refcon, status, image_buffer);
 }
 
-void ReleaseDecoderBuffer(void* refcon,
-                          void* doomed_memory_block,
-                          size_t size_in_bytes) {
-  if (refcon)
-    static_cast<DecoderBuffer*>(refcon)->Release();
-}
-
 }  // namespace
 
 // Detects coded size and color space changes. Also indicates when a frame won't
@@ -403,7 +397,6 @@
     while (parser_.ParseNextFrame(&fhdr, &allocate_size, &null_config) ==
            Vp9Parser::kOk) {
       color_space_ = fhdr.GetColorSpace();
-      show_frame_ = fhdr.show_frame;
 
       gfx::Size new_size(fhdr.frame_width, fhdr.frame_height);
       if (!size_.IsEmpty() && !pending_config_changed_ && !config_changed_ &&
@@ -433,14 +426,12 @@
     return container_cs.IsSpecified() ? container_cs : color_space_;
   }
 
-  bool show_frame() const { return show_frame_; }
   bool config_changed() const { return config_changed_; }
 
  private:
   gfx::Size size_;
   bool config_changed_ = false;
   bool pending_config_changed_ = false;
-  bool show_frame_ = false;
   VideoColorSpace color_space_;
   Vp9Parser parser_;
 };
@@ -716,6 +707,9 @@
   }
   UMA_HISTOGRAM_BOOLEAN("Media.VTVDA.HardwareAccelerated", using_hardware);
 
+  if (codec_ == kCodecVP9 && !vp9_bsf_)
+    vp9_bsf_ = std::make_unique<VP9SuperFrameBitstreamFilter>();
+
   // Record that the configuration change is complete.
   configured_sps_ = active_sps_;
   configured_spsext_ = active_spsext_;
@@ -743,45 +737,33 @@
   // Now that the configuration is up to date, copy it into the frame.
   frame->image_size = configured_size_;
 
-  // The created CMBlockBuffer owns a ref on DecoderBuffer to avoid a copy.
-  CMBlockBufferCustomBlockSource source = {0};
-  source.refCon = buffer.get();
-  source.FreeBlock = &ReleaseDecoderBuffer;
-
-  // Create a memory-backed CMBlockBuffer for the translated data.
-  base::ScopedCFTypeRef<CMBlockBufferRef> data;
-  OSStatus status = CMBlockBufferCreateWithMemoryBlock(
-      kCFAllocatorDefault,
-      static_cast<void*>(buffer->writable_data()),  // &memory_block
-      buffer->data_size(),                          // block_length
-      kCFAllocatorDefault,                          // block_allocator
-      &source,                                      // &custom_block_source
-      0,                                            // offset_to_data
-      buffer->data_size(),                          // data_length
-      0,                                            // flags
-      data.InitializeInto());
-  if (status) {
-    NOTIFY_STATUS("CMBlockBufferCreateWithMemoryBlock()", status,
-                  SFT_PLATFORM_ERROR);
+  if (!vp9_bsf_->EnqueueBuffer(std::move(buffer))) {
+    WriteToMediaLog(MediaLogMessageLevel::kERROR, "Unsupported VP9 stream");
+    NotifyError(UNREADABLE_INPUT, SFT_INVALID_STREAM);
     return;
   }
 
-  // Buffer creation was successful so add ref to |buffer| for CMBlockBuffer.
-  buffer->AddRef();
-
-  const size_t buffer_size = buffer->data_size();
+  // If we have no buffer this bitstream buffer is part of a super frame that we
+  // need to assemble before giving to VideoToolbox.
+  auto data = vp9_bsf_->take_buffer();
+  if (!data) {
+    gpu_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&VTVideoDecodeAccelerator::DecodeDone,
+                                  weak_this_, frame));
+    return;
+  }
 
   // Package the data in a CMSampleBuffer.
   base::ScopedCFTypeRef<CMSampleBufferRef> sample;
-  status = CMSampleBufferCreateReady(kCFAllocatorDefault,
-                                     data,          // data_buffer
-                                     format_,       // format_description
-                                     1,             // num_samples
-                                     0,             // num_sample_timing_entries
-                                     nullptr,       // &sample_timing_array
-                                     1,             // num_sample_size_entries
-                                     &buffer_size,  // &sample_size_array
-                                     sample.InitializeInto());
+  OSStatus status = CMSampleBufferCreateReady(kCFAllocatorDefault,
+                                              data,     // data_buffer
+                                              format_,  // format_description
+                                              1,        // num_samples
+                                              0,  // num_sample_timing_entries
+                                              nullptr,  // &sample_timing_array
+                                              0,  // num_sample_size_entries
+                                              nullptr,  // &sample_size_array
+                                              sample.InitializeInto());
   if (status) {
     NOTIFY_STATUS("CMSampleBufferCreate()", status, SFT_PLATFORM_ERROR);
     return;
@@ -805,13 +787,6 @@
                   SFT_DECODE_ERROR);
     return;
   }
-
-  // No image will be produced for this frame, so mark it as done.
-  if (!cc_detector_->show_frame()) {
-    gpu_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&VTVideoDecodeAccelerator::DecodeDone,
-                                  weak_this_, frame));
-  }
 }
 
 void VTVideoDecodeAccelerator::DecodeTask(scoped_refptr<DecoderBuffer> buffer,
@@ -1182,6 +1157,11 @@
 
   FinishDelayedFrames();
 
+  // All the frames that are going to be sent must have been sent by now. So
+  // clear any state in the bitstream filter.
+  if (vp9_bsf_)
+    vp9_bsf_->Flush();
+
   if (type == TASK_DESTROY && session_) {
     // Destroy the decoding session before returning from the decoder thread.
     VTDecompressionSessionInvalidate(session_);
diff --git a/media/gpu/mac/vt_video_decode_accelerator_mac.h b/media/gpu/mac/vt_video_decode_accelerator_mac.h
index eda859a5c..ff8ada5 100644
--- a/media/gpu/mac/vt_video_decode_accelerator_mac.h
+++ b/media/gpu/mac/vt_video_decode_accelerator_mac.h
@@ -30,6 +30,7 @@
 
 namespace media {
 class VP9ConfigChangeDetector;
+class VP9SuperFrameBitstreamFilter;
 
 // Preload VideoToolbox libraries, needed for sandbox warmup.
 MEDIA_GPU_EXPORT bool InitializeVideoToolbox();
@@ -221,6 +222,7 @@
   std::deque<std::unique_ptr<Frame>> output_queue_;
 
   std::unique_ptr<VP9ConfigChangeDetector> cc_detector_;
+  std::unique_ptr<VP9SuperFrameBitstreamFilter> vp9_bsf_;
 
   // Size of assigned picture buffers.
   gfx::Size picture_size_;
diff --git a/media/test/data/README.md b/media/test/data/README.md
index 013692f..fb7d226 100644
--- a/media/test/data/README.md
+++ b/media/test/data/README.md
@@ -684,6 +684,13 @@
 md5 checksums of individual video frames when converted to the I420 format.
 
 
+### VP9 video with raw vp9 frames
+
+#### buck-1280x720-vp9.webm
+1280x720 version of Big Buck Bunny https://peach.blender.org/ muxed with raw
+vp9 frames (versus superframes).
+
+
 ### VP9 video with show_existing_frame flag
 
 #### vp90_2_10_show_existing_frame2.vp9.ivf
diff --git a/media/test/data/buck-1280x720-vp9.webm b/media/test/data/buck-1280x720-vp9.webm
new file mode 100644
index 0000000..a9930595
--- /dev/null
+++ b/media/test/data/buck-1280x720-vp9.webm
Binary files differ
diff --git a/media/video/vpx_video_encoder.cc b/media/video/vpx_video_encoder.cc
index d35d6253..4bedf955 100644
--- a/media/video/vpx_video_encoder.cc
+++ b/media/video/vpx_video_encoder.cc
@@ -65,8 +65,9 @@
   vpx_codec_iface_t* iface = nullptr;
   if (profile == media::VP8PROFILE_ANY) {
     iface = vpx_codec_vp8_cx();
-  } else if (profile >= media::VP9PROFILE_PROFILE0 &&
-             profile <= media::VP9PROFILE_PROFILE3) {
+  } else if (profile == media::VP9PROFILE_PROFILE0 ||
+             profile == media::VP9PROFILE_PROFILE2) {
+    // TODO(https://crbug.com/1116617): Consider support for profiles 1 and 3.
     iface = vpx_codec_vp9_cx();
   } else {
     auto status = Status(StatusCode::kEncoderUnsupportedProfile)
@@ -123,8 +124,9 @@
       codec_, iface, &codec_config_,
       codec_config_.g_bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH);
   if (vpx_error != VPX_CODEC_OK) {
-    std::string msg = base::StringPrintf("VPX encoder initialization error: %s",
-                                         vpx_codec_err_to_string(vpx_error));
+    std::string msg = base::StringPrintf(
+        "VPX encoder initialization error: %s %s",
+        vpx_codec_err_to_string(vpx_error), codec_->err_detail);
 
     status = Status(StatusCode::kEncoderInitializationError, msg);
     std::move(done_cb).Run(status);
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index 004c790..7f4298d 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -862,7 +862,6 @@
       max_allowed_push_id_(max_allowed_push_id),
       attempted_zero_rtt_(false),
       num_pings_sent_(0),
-      handshake_completion_timestamp_(base::TimeTicks()),
       push_promise_index_(std::move(push_promise_index)) {
   // Make sure connection migration and goaway on path degrading are not turned
   // on at the same time.
@@ -1611,7 +1610,6 @@
 
   OnCryptoHandshakeComplete();
   LogZeroRttStats();
-  handshake_completion_timestamp_ = tick_clock_->NowTicks();
   quic::QuicSpdySession::OnOneRttKeysAvailable();
 }
 
@@ -1800,7 +1798,7 @@
     UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.NumPingsSent", num_pings_sent_);
     UMA_HISTOGRAM_LONG_TIMES_100(
         "Net.QuicSession.ConnectionDuration",
-        tick_clock_->NowTicks() - handshake_completion_timestamp_);
+        tick_clock_->NowTicks() - connect_timing_.connect_end);
   } else {
     if (error == quic::QUIC_PUBLIC_RESET) {
       RecordHandshakeFailureReason(HANDSHAKE_FAILURE_PUBLIC_RESET);
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h
index 20f617a..60d6f1cd 100644
--- a/net/quic/quic_chromium_client_session.h
+++ b/net/quic/quic_chromium_client_session.h
@@ -929,8 +929,6 @@
 
   size_t num_pings_sent_;
 
-  base::TimeTicks handshake_completion_timestamp_;
-
   std::unique_ptr<quic::QuicClientPushPromiseIndex> push_promise_index_;
 
   base::WeakPtrFactory<QuicChromiumClientSession> weak_factory_{this};
diff --git a/services/network/resource_scheduler/OWNERS b/services/network/resource_scheduler/OWNERS
index 6fa38ee..bd5f1d8 100644
--- a/services/network/resource_scheduler/OWNERS
+++ b/services/network/resource_scheduler/OWNERS
@@ -1,4 +1,4 @@
 tbansal@chromium.org
-dougarnett@chromium.org
+ryansturm@chromium.org
 
 # COMPONENT: Internals>Network>NetworkQuality
\ No newline at end of file
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 53aad99..df91ab12 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -694,7 +694,7 @@
   },
   "cronet_unittests_ios": {
     "label": "//components/cronet/ios:cronet_unittests_ios",
-    "type": "raw",
+    "type": "console_test_launcher",
   },
   "cros_browser_sanity_test": {
     "args": [
@@ -729,7 +729,7 @@
   },
   "delayloads_unittests": {
     "label": "//chrome/test:delayloads_unittests",
-    "type": "raw",
+    "type": "console_test_launcher",
   },
   "device_junit_tests": {
     "label": "//device:device_junit_tests",
@@ -1463,7 +1463,7 @@
   },
   "profile_provider_unittest": {
     "label": "//chrome/browser/metrics/perf:profile_provider_unittest",
-    "type": "raw",
+    "type": "console_test_launcher",
   },
   "remoting/client:client": {
     "label": "//remoting/client:client",
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index cf3cedca3..d023f96 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -4889,14 +4889,15 @@
                 {
                     "name": "DesktopExperiments",
                     "params": {
+                        "MaxZeroSuggestMatches": "10",
                         "OmniboxMaxURLMatches": "7",
                         "UIMaxAutocompleteMatches": "8"
                     },
                     "enable_features": [
-                        "NtpRealbox",
                         "OmniboxDisplayTitleForCurrentUrl",
                         "OmniboxDocumentProvider",
                         "OmniboxMaxURLMatches",
+                        "OmniboxMaxZeroSuggestMatches",
                         "OmniboxRemoveSuggestionsFromClipboard",
                         "OmniboxRichEntitySuggestions",
                         "OmniboxUIExperimentMaxAutocompleteMatches",
diff --git a/third_party/blink/public/common/loader/loading_behavior_flag.h b/third_party/blink/public/common/loader/loading_behavior_flag.h
index 7cc3c69..e49df091 100644
--- a/third_party/blink/public/common/loader/loading_behavior_flag.h
+++ b/third_party/blink/public/common/loader/loading_behavior_flag.h
@@ -44,6 +44,9 @@
   // Indicates that the page uses the Next.js JavaScript framework (via a
   // window variable)
   kLoadingBehaviorNextJSFrameworkUsed = 1 << 9,
+  // Indicates that an async script was ready to execute before the script
+  // element's node document has finished parsing.
+  kLoadingBehaviorAsyncScriptReadyBeforeDocumentFinishedParsing = 1 << 10,
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/mojom/frame/fullscreen.mojom b/third_party/blink/public/mojom/frame/fullscreen.mojom
index 9e77621..d70dba7 100644
--- a/third_party/blink/public/mojom/frame/fullscreen.mojom
+++ b/third_party/blink/public/mojom/frame/fullscreen.mojom
@@ -16,5 +16,10 @@
   // True if this should be treated as a "webkit"-prefixed fullscreen request.
   // These don't return promises, and fire "webkit"-prefixed events.
   bool is_prefixed = false;
+
+  // True if this fullscreen request is for WebXR DOM Overlay mode. In that case,
+  // if a subframe is requesting fullscreen mode, the parent frames need to use
+  // a transparent backdrop to keep content visible.
+  bool is_xr_overlay = false;
 };
 
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 4193084..5055655 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2729,6 +2729,12 @@
   kMediaRecorder_MimeType = 3399,
   kMediaRecorder_VideoBitsPerSecond = 3400,
   kMediaRecorder_AudioBitsPerSecond = 3401,
+  kBluetoothRemoteGATTCharacteristic_Uuid = 3402,
+  kBluetoothRemoteGATTDescriptor_Uuid = 3403,
+  kBluetoothRemoteGATTService_Uuid = 3404,
+  kGPUAdapter_Name = 3405,
+  kWindowScreenInternal = 3406,
+  kWindowScreenPrimary = 3407,
 
   // 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/renderer/core/css/mathml.css b/third_party/blink/renderer/core/css/mathml.css
index 994d94c3..357f6093 100644
--- a/third_party/blink/renderer/core/css/mathml.css
+++ b/third_party/blink/renderer/core/css/mathml.css
@@ -47,7 +47,7 @@
     outline: auto 1px -webkit-focus-ring-color;
 }
 
-maction, merror, mfrac, mphantom, mrow, mspace, mstyle, msub, msup, msubsup, munder, mover, munderover, msqrt, mroot, mmultiscripts, mprescripts, none
+maction, merror, mfrac, mmultiscripts, mover, mpadded, mphantom, mprescripts, mroot, mrow, msqrt, mspace, mstyle, msub, msup, msubsup, munder, munderover, none
 {
     display: math;
 }
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
index 4411e86..a19743f 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -55,6 +55,7 @@
 #include "third_party/blink/renderer/core/layout/layout_theme.h"
 #include "third_party/blink/renderer/core/layout/list_marker.h"
 #include "third_party/blink/renderer/core/mathml/mathml_fraction_element.h"
+#include "third_party/blink/renderer/core/mathml/mathml_padded_element.h"
 #include "third_party/blink/renderer/core/mathml/mathml_space_element.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
@@ -748,6 +749,14 @@
     }
     if (auto* space = DynamicTo<MathMLSpaceElement>(*element)) {
       space->AddMathBaselineIfNeeded(style, state.CssToLengthConversionData());
+    } else if (auto* padded = DynamicTo<MathMLPaddedElement>(*element)) {
+      padded->AddMathBaselineIfNeeded(style, state.CssToLengthConversionData());
+      padded->AddMathPaddedDepthIfNeeded(style,
+                                         state.CssToLengthConversionData());
+      padded->AddMathPaddedLSpaceIfNeeded(style,
+                                          state.CssToLengthConversionData());
+      padded->AddMathPaddedVOffsetIfNeeded(style,
+                                           state.CssToLengthConversionData());
     } else if (auto* fraction = DynamicTo<MathMLFractionElement>(*element)) {
       fraction->AddMathFractionBarThicknessIfNeeded(
           style, state.CssToLengthConversionData());
diff --git a/third_party/blink/renderer/core/frame/fullscreen_controller.cc b/third_party/blink/renderer/core/frame/fullscreen_controller.cc
index 8234f45..b52361d 100644
--- a/third_party/blink/renderer/core/frame/fullscreen_controller.cc
+++ b/third_party/blink/renderer/core/frame/fullscreen_controller.cc
@@ -160,13 +160,16 @@
   // fullscreen events.
   fullscreen_options->is_prefixed =
       request_type & FullscreenRequestType::kPrefixed;
+  fullscreen_options->is_xr_overlay =
+      request_type & FullscreenRequestType::kForXrOverlay;
 
 #if DCHECK_IS_ON()
   DVLOG(2) << __func__ << ": request_type="
            << FullscreenRequestTypeToDebugString(request_type)
            << " fullscreen_options={display_id="
            << fullscreen_options->display_id
-           << ", is_prefixed=" << fullscreen_options->is_prefixed << "}";
+           << ", is_prefixed=" << fullscreen_options->is_prefixed
+           << ", is_xr_overlay=" << fullscreen_options->is_xr_overlay << "}";
 #endif
 
   // Don't send redundant EnterFullscreen message to the browser for the
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index de560a0..213a50d 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2669,8 +2669,9 @@
   // is done into a special canvas. There is no point doing a normal paint step
   // (or animations update) when in this mode.
   bool is_capturing_layout = frame_->GetDocument()->IsCapturingLayout();
+  HashSet<const GraphicsLayer*> repainted_layers;
   if (!is_capturing_layout)
-    PaintTree();
+    PaintTree(repainted_layers);
 
   if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
     if (GetLayoutView()->Compositor()->InCompositingMode()) {
@@ -2681,7 +2682,7 @@
   if (!is_capturing_layout) {
     bool needed_update = !paint_artifact_compositor_ ||
                          paint_artifact_compositor_->NeedsUpdate();
-    PushPaintArtifactToCompositor();
+    PushPaintArtifactToCompositor(repainted_layers);
     ForAllNonThrottledLocalFrameViews([this](LocalFrameView& frame_view) {
       frame_view.GetScrollableArea()->UpdateCompositorScrollAnimations();
       if (const auto* animating_scrollable_areas =
@@ -2822,15 +2823,17 @@
       });
 }
 
-static bool PaintGraphicsLayerRecursively(GraphicsLayer* layer) {
-  bool painted = layer->PaintRecursively();
+static void PaintGraphicsLayerRecursively(
+    GraphicsLayer* layer,
+    HashSet<const GraphicsLayer*>& repainted_layers) {
+  layer->PaintRecursively(repainted_layers);
 #if DCHECK_IS_ON()
   VerboseLogGraphicsLayerTree(layer);
 #endif
-  return painted;
 }
 
-void LocalFrameView::PaintTree() {
+void LocalFrameView::PaintTree(
+    HashSet<const GraphicsLayer*>& repainted_layers) {
   SCOPED_UMA_AND_UKM_TIMER(EnsureUkmAggregator(),
                            LocalFrameUkmAggregator::kPaint);
 
@@ -2915,8 +2918,8 @@
     // the host page and will be painted during painting of the host page.
     if (GraphicsLayer* root_graphics_layer =
             layout_view->Compositor()->PaintRootGraphicsLayer()) {
-      bool painted = PaintGraphicsLayerRecursively(root_graphics_layer);
-      if (painted) {
+      PaintGraphicsLayerRecursively(root_graphics_layer, repainted_layers);
+      if (!repainted_layers.IsEmpty()) {
         // If the painted result changed, the recorded hit test data may have
         // changed which will affect the mapped hit test geometry.
         if (GetScrollingCoordinator())
@@ -2946,7 +2949,8 @@
                                     : nullptr;
 }
 
-void LocalFrameView::PushPaintArtifactToCompositor() {
+void LocalFrameView::PushPaintArtifactToCompositor(
+    const HashSet<const GraphicsLayer*>& repainted_layers) {
   TRACE_EVENT0("blink", "LocalFrameView::pushPaintArtifactToCompositor");
   if (!frame_->GetSettings()->GetAcceleratedCompositingEnabled())
     return;
@@ -2973,7 +2977,11 @@
 
   // Skip updating property trees, pushing cc::Layers, and issuing raster
   // invalidations if possible.
-  if (!paint_artifact_compositor_->NeedsUpdate()) {
+  // TODO(paint-team): In CompositeAfterPaint mode, repainted_layers will always
+  // be empty, even if painted output has changed. We need an equivalent signal
+  // to indicate that PAC doesn't need to run the layerization algorithm, but it
+  // does need to update properties on layers that depend on painted output.
+  if (!paint_artifact_compositor_->NeedsUpdate() && !repainted_layers.size()) {
     DCHECK(paint_controller_);
     return;
   }
@@ -3012,6 +3020,7 @@
     // affect caching status of DisplayItemClients because FinishCycle() is
     // not synchronized with other PaintControllers. This may live across frame
     // updates until SetForeignLayerListNeedsUpdate() is called.
+    paint_artifact_compositor_->SetNeedsUpdate();
     paint_controller_ =
         std::make_unique<PaintController>(PaintController::kTransient);
 
@@ -3045,7 +3054,7 @@
 
   paint_artifact_compositor_->Update(
       paint_controller_->GetPaintArtifactShared(), viewport_properties,
-      scroll_translation_nodes);
+      scroll_translation_nodes, repainted_layers);
 
   probe::LayerTreePainted(&GetFrame());
 }
@@ -4706,10 +4715,19 @@
 }
 
 PaintLayer* LocalFrameView::GetFullScreenOverlayLayer() const {
+  Document* doc = frame_->GetDocument();
+  DCHECK(doc);
+
+  // For WebXR DOM Overlay, the fullscreen overlay layer comes from either the
+  // overlay element itself, or from an iframe element if the overlay element is
+  // in an OOPIF. This layer is needed even for non-main-frame scenarios to
+  // ensure the background remains transparent.
+  if (doc->IsXrOverlay())
+    return GetXrOverlayLayer(*doc);
+
+  // Fullscreen overlay video layers are only used for the main frame.
   DCHECK(frame_->IsMainFrame());
-  if (auto* layer = GetXrOverlayLayer(*frame_->GetDocument()))
-    return layer;
-  return GetFullScreenOverlayVideoLayer(*frame_->GetDocument());
+  return GetFullScreenOverlayVideoLayer(*doc);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h
index 3e099dda..a2644a57 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.h
+++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -74,6 +74,7 @@
 class FragmentAnchor;
 class Frame;
 class FrameViewAutoSizeInfo;
+class GraphicsLayer;
 class HTMLVideoElement;
 class JSONObject;
 class KURL;
@@ -786,10 +787,11 @@
       DocumentLifecycle::LifecycleState target_state);
   void RunPaintLifecyclePhase();
 
-  void PaintTree();
+  void PaintTree(HashSet<const GraphicsLayer*>& repainted_layers);
   void UpdateStyleAndLayoutIfNeededRecursive();
 
-  void PushPaintArtifactToCompositor();
+  void PushPaintArtifactToCompositor(
+      const HashSet<const GraphicsLayer*>& repainted_layers);
 
   void ClearLayoutSubtreeRootsAndMarkContainingBlocks();
 
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc
index a607c06..922908f 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -420,6 +420,8 @@
   FullscreenRequestType request_type =
       (request_options->is_prefixed ? FullscreenRequestType::kPrefixed
                                     : FullscreenRequestType::kUnprefixed) |
+      (request_options->is_xr_overlay ? FullscreenRequestType::kForXrOverlay
+                                      : FullscreenRequestType::kNull) |
       FullscreenRequestType::kForCrossProcessDescendant;
 
   Fullscreen::RequestFullscreen(*owner_element, FullscreenOptions::Create(),
diff --git a/third_party/blink/renderer/core/frame/screen.idl b/third_party/blink/renderer/core/frame/screen.idl
index 3c2ef7d..ee69dad4 100644
--- a/third_party/blink/renderer/core/frame/screen.idl
+++ b/third_party/blink/renderer/core/frame/screen.idl
@@ -47,8 +47,8 @@
     // https://github.com/webscreens/screen-enumeration
     [HighEntropy=Direct, MeasureAs=WindowScreenLeft, RuntimeEnabled=WindowPlacement] readonly attribute long left;
     [HighEntropy=Direct, MeasureAs=WindowScreenTop, RuntimeEnabled=WindowPlacement] readonly attribute long top;
-    [RuntimeEnabled=WindowPlacement] readonly attribute boolean internal;
-    [RuntimeEnabled=WindowPlacement] readonly attribute boolean primary;
+    [HighEntropy=Direct, MeasureAs=WindowScreenInternal, RuntimeEnabled=WindowPlacement] readonly attribute boolean internal;
+    [HighEntropy=Direct, MeasureAs=WindowScreenPrimary, RuntimeEnabled=WindowPlacement] readonly attribute boolean primary;
     [RuntimeEnabled=WindowPlacement] readonly attribute float scaleFactor;
     [RuntimeEnabled=WindowPlacement] readonly attribute DOMString id;
     [RuntimeEnabled=WindowPlacement] readonly attribute boolean touchSupport;
diff --git a/third_party/blink/renderer/core/frame/window.idl b/third_party/blink/renderer/core/frame/window.idl
index 339b2f3..c332c0d 100644
--- a/third_party/blink/renderer/core/frame/window.idl
+++ b/third_party/blink/renderer/core/frame/window.idl
@@ -134,9 +134,9 @@
     [Affects=Nothing, HighEntropy=Direct, MeasureAs=WindowInnerHeight, Replaceable] readonly attribute long innerHeight;
 
     // viewport scrolling
-    [HighEntropy, MeasureAs=WindowScrollX, Replaceable] readonly attribute double scrollX;
+    [HighEntropy=Direct, MeasureAs=WindowScrollX, Replaceable] readonly attribute double scrollX;
     [HighEntropy, MeasureAs=WindowPageXOffset, Replaceable] readonly attribute double pageXOffset;
-    [HighEntropy, MeasureAs=WindowScrollY, Replaceable] readonly attribute double scrollY;
+    [HighEntropy=Direct, MeasureAs=WindowScrollY, Replaceable] readonly attribute double scrollY;
     [HighEntropy, MeasureAs=WindowPageYOffset, Replaceable] readonly attribute double pageYOffset;
     void scroll(optional ScrollToOptions options = {});
     void scroll(unrestricted double x, unrestricted double y);
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn
index 104937e..738a786 100644
--- a/third_party/blink/renderer/core/layout/BUILD.gn
+++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -443,12 +443,14 @@
     "ng/list/ng_unpositioned_list_marker.h",
     "ng/mathml/layout_ng_mathml_block.cc",
     "ng/mathml/layout_ng_mathml_block.h",
-    "ng/mathml/layout_ng_mathml_square_root.cc",
-    "ng/mathml/layout_ng_mathml_square_root.h",
+    "ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.cc",
+    "ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.h",
     "ng/mathml/ng_math_fraction_layout_algorithm.cc",
     "ng/mathml/ng_math_fraction_layout_algorithm.h",
     "ng/mathml/ng_math_layout_utils.cc",
     "ng/mathml/ng_math_layout_utils.h",
+    "ng/mathml/ng_math_padded_layout_algorithm.cc",
+    "ng/mathml/ng_math_padded_layout_algorithm.h",
     "ng/mathml/ng_math_radical_layout_algorithm.cc",
     "ng/mathml/ng_math_radical_layout_algorithm.h",
     "ng/mathml/ng_math_row_layout_algorithm.cc",
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_square_root.cc b/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.cc
similarity index 78%
rename from third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_square_root.cc
rename to third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.cc
index 5e592f5..0e87e65 100644
--- a/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_square_root.cc
+++ b/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.cc
@@ -2,17 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_square_root.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.h"
 
 namespace blink {
 
-LayoutNGMathMLSquareRoot::LayoutNGMathMLSquareRoot(Element* element)
+LayoutNGMathMLBlockWithAnonymousMrow::LayoutNGMathMLBlockWithAnonymousMrow(
+    Element* element)
     : LayoutNGMathMLBlock(element) {
   DCHECK(element);
 }
 
-void LayoutNGMathMLSquareRoot::AddChild(LayoutObject* new_child,
-                                        LayoutObject* before_child) {
+void LayoutNGMathMLBlockWithAnonymousMrow::AddChild(
+    LayoutObject* new_child,
+    LayoutObject* before_child) {
   LayoutBlock* anonymous_mrow = To<LayoutBlock>(FirstChild());
   if (!anonymous_mrow) {
     scoped_refptr<ComputedStyle> new_style =
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.h b/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.h
new file mode 100644
index 0000000..18af3720
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.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 THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_LAYOUT_NG_MATHML_BLOCK_WITH_ANONYMOUS_MROW_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_LAYOUT_NG_MATHML_BLOCK_WITH_ANONYMOUS_MROW_H_
+
+#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h"
+
+namespace blink {
+
+class LayoutNGMathMLBlockWithAnonymousMrow : public LayoutNGMathMLBlock {
+ public:
+  explicit LayoutNGMathMLBlockWithAnonymousMrow(Element*);
+
+  void AddChild(LayoutObject* new_child,
+                LayoutObject* before_child = nullptr) override;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_LAYOUT_NG_MATHML_BLOCK_WITH_ANONYMOUS_MROW_H_
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_square_root.h b/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_square_root.h
deleted file mode 100644
index 7de7bd1..0000000
--- a/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_square_root.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_LAYOUT_NG_MATHML_SQUARE_ROOT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_LAYOUT_NG_MATHML_SQUARE_ROOT_H_
-
-#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h"
-
-namespace blink {
-
-// FIXME: should probably be called LayoutNGMathMLBlockWithAnonymousMrow
-// when there are multiple users of this class.
-class LayoutNGMathMLSquareRoot : public LayoutNGMathMLBlock {
- public:
-  explicit LayoutNGMathMLSquareRoot(Element*);
-
-  void AddChild(LayoutObject* new_child,
-                LayoutObject* before_child = nullptr) override;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_LAYOUT_NG_MATHML_SQUARE_ROOT_H_
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc
new file mode 100644
index 0000000..dd29026
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc
@@ -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.
+
+#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h"
+
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
+#include "third_party/blink/renderer/core/mathml_names.h"
+
+namespace blink {
+
+NGMathPaddedLayoutAlgorithm::NGMathPaddedLayoutAlgorithm(
+    const NGLayoutAlgorithmParams& params)
+    : NGLayoutAlgorithm(params) {
+  container_builder_.SetIsNewFormattingContext(
+      params.space.IsNewFormattingContext());
+}
+
+LayoutUnit NGMathPaddedLayoutAlgorithm::RequestedLSpace() const {
+  return std::max(LayoutUnit(),
+                  ValueForLength(Style().GetMathPaddedLSpace(), LayoutUnit()));
+}
+
+LayoutUnit NGMathPaddedLayoutAlgorithm::RequestedVOffset() const {
+  return ValueForLength(Style().GetMathPaddedVOffset(), LayoutUnit());
+}
+
+base::Optional<LayoutUnit> NGMathPaddedLayoutAlgorithm::RequestedAscent(
+    LayoutUnit content_ascent) const {
+  if (Style().GetMathBaseline().IsAuto())
+    return base::nullopt;
+  return std::max(LayoutUnit(),
+                  ValueForLength(Style().GetMathBaseline(), content_ascent));
+}
+
+base::Optional<LayoutUnit> NGMathPaddedLayoutAlgorithm::RequestedDescent(
+    LayoutUnit content_descent) const {
+  if (Style().GetMathPaddedDepth().IsAuto())
+    return base::nullopt;
+  return std::max(LayoutUnit(), ValueForLength(Style().GetMathPaddedDepth(),
+                                               content_descent));
+}
+
+void NGMathPaddedLayoutAlgorithm::GatherChildren(
+    NGBlockNode* content,
+    NGBoxFragmentBuilder* container_builder) const {
+  for (NGLayoutInputNode child = Node().FirstChild(); child;
+       child = child.NextSibling()) {
+    NGBlockNode block_child = To<NGBlockNode>(child);
+    if (child.IsOutOfFlowPositioned()) {
+      if (container_builder) {
+        container_builder->AddOutOfFlowChildCandidate(
+            block_child, BorderScrollbarPadding().StartOffset());
+      }
+      continue;
+    }
+    if (!*content) {
+      *content = block_child;
+      continue;
+    }
+
+    NOTREACHED();
+  }
+}
+
+scoped_refptr<const NGLayoutResult> NGMathPaddedLayoutAlgorithm::Layout() {
+  DCHECK(!BreakToken());
+
+  NGBlockNode content = nullptr;
+  GatherChildren(&content, &container_builder_);
+  LayoutUnit content_ascent, content_descent;
+  NGBoxStrut content_margins;
+  scoped_refptr<const NGPhysicalBoxFragment> content_fragment;
+  if (content) {
+    NGConstraintSpace constraint_space = CreateConstraintSpaceForMathChild(
+        Node(), ChildAvailableSize(), ConstraintSpace(), content);
+    scoped_refptr<const NGLayoutResult> content_layout_result =
+        content.Layout(constraint_space);
+    content_fragment =
+        &To<NGPhysicalBoxFragment>(content_layout_result->PhysicalFragment());
+    content_margins =
+        ComputeMarginsFor(constraint_space, content.Style(), ConstraintSpace());
+    NGBoxFragment fragment(ConstraintSpace().GetWritingMode(),
+                           ConstraintSpace().Direction(), *content_fragment);
+    content_ascent = content_margins.block_start +
+                     fragment.Baseline().value_or(fragment.BlockSize());
+    content_descent =
+        fragment.BlockSize() + content_margins.BlockSum() - content_ascent;
+  }
+  // width/height/depth attributes can override width/ascent/descent.
+  LayoutUnit ascent = BorderScrollbarPadding().block_start +
+                      RequestedAscent(content_ascent).value_or(content_ascent);
+  LayoutUnit descent =
+      RequestedDescent(content_descent).value_or(content_descent);
+  if (content_fragment) {
+    // Need to take into account border/padding, lspace and voffset.
+    LogicalOffset content_offset = {
+        BorderScrollbarPadding().inline_start + RequestedLSpace(),
+        (ascent - content_ascent) - RequestedVOffset()};
+    container_builder_.AddChild(*content_fragment, content_offset);
+    content.StoreMargins(ConstraintSpace(), content_margins);
+  }
+
+  auto total_block_size = ascent + descent + BorderScrollbarPadding().block_end;
+  container_builder_.SetIntrinsicBlockSize(total_block_size);
+  container_builder_.SetFragmentsTotalBlockSize(total_block_size);
+
+  container_builder_.SetBaseline(ascent);
+
+  NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), &container_builder_).Run();
+
+  return container_builder_.ToBoxFragment();
+}
+
+MinMaxSizesResult NGMathPaddedLayoutAlgorithm::ComputeMinMaxSizes(
+    const MinMaxSizesInput& input) const {
+  if (auto result = CalculateMinMaxSizesIgnoringChildren(
+          Node(), BorderScrollbarPadding()))
+    return *result;
+
+  MinMaxSizes sizes;
+  bool depends_on_percentage_block_size = false;
+  sizes += BorderScrollbarPadding().InlineSum();
+
+  NGBlockNode content = nullptr;
+  GatherChildren(&content);
+
+  MinMaxSizesResult content_result =
+      ComputeMinAndMaxContentContribution(Style(), content, input);
+  NGBoxStrut content_margins = ComputeMinMaxMargins(Style(), content);
+  content_result.sizes += content_margins.InlineSum();
+  depends_on_percentage_block_size |=
+      content_result.depends_on_percentage_block_size;
+  sizes += content_result.sizes;
+
+  return {sizes, depends_on_percentage_block_size};
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h
new file mode 100644
index 0000000..845b691
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_PADDED_LAYOUT_ALGORITHM_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_PADDED_LAYOUT_ALGORITHM_H_
+
+#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h"
+
+namespace blink {
+
+class CORE_EXPORT NGMathPaddedLayoutAlgorithm
+    : public NGLayoutAlgorithm<NGBlockNode,
+                               NGBoxFragmentBuilder,
+                               NGBlockBreakToken> {
+ public:
+  explicit NGMathPaddedLayoutAlgorithm(const NGLayoutAlgorithmParams& params);
+
+  scoped_refptr<const NGLayoutResult> Layout() final;
+
+  MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesInput&) const final;
+
+ private:
+  LayoutUnit RequestedLSpace() const;
+  LayoutUnit RequestedVOffset() const;
+  base::Optional<LayoutUnit> RequestedAscent(LayoutUnit content_ascent) const;
+  base::Optional<LayoutUnit> RequestedDescent(LayoutUnit content_descent) const;
+
+  void GatherChildren(NGBlockNode* base, NGBoxFragmentBuilder* = nullptr) const;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_MATHML_NG_MATH_PADDED_LAYOUT_ALGORITHM_H_
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 8743f3c..18e3913 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -32,6 +32,7 @@
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
 #include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.h"
 #include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.h"
 #include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.h"
 #include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.h"
 #include "third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.h"
@@ -59,6 +60,7 @@
 #include "third_party/blink/renderer/core/layout/text_autosizer.h"
 #include "third_party/blink/renderer/core/mathml/mathml_element.h"
 #include "third_party/blink/renderer/core/mathml/mathml_fraction_element.h"
+#include "third_party/blink/renderer/core/mathml/mathml_padded_element.h"
 #include "third_party/blink/renderer/core/mathml/mathml_radical_element.h"
 #include "third_party/blink/renderer/core/mathml/mathml_scripts_element.h"
 #include "third_party/blink/renderer/core/mathml/mathml_space_element.h"
@@ -124,6 +126,9 @@
                IsValidMathMLRadical(params.node)) {
       CreateAlgorithmAndRun<NGMathRadicalLayoutAlgorithm>(params, callback);
       return;
+    } else if (IsA<MathMLPaddedElement>(element)) {
+      CreateAlgorithmAndRun<NGMathPaddedLayoutAlgorithm>(params, callback);
+      return;
     } else if (IsA<MathMLScriptsElement>(element) &&
                IsValidMathMLScript(params.node)) {
       // TODO(rbuis): take into account movablelimits.
diff --git a/third_party/blink/renderer/core/mathml/BUILD.gn b/third_party/blink/renderer/core/mathml/BUILD.gn
index c3ad347..b50e31c 100644
--- a/third_party/blink/renderer/core/mathml/BUILD.gn
+++ b/third_party/blink/renderer/core/mathml/BUILD.gn
@@ -10,6 +10,8 @@
     "mathml_element.h",
     "mathml_fraction_element.cc",
     "mathml_fraction_element.h",
+    "mathml_padded_element.cc",
+    "mathml_padded_element.h",
     "mathml_radical_element.cc",
     "mathml_radical_element.h",
     "mathml_row_element.cc",
diff --git a/third_party/blink/renderer/core/mathml/mathml_attribute_names.json5 b/third_party/blink/renderer/core/mathml/mathml_attribute_names.json5
index 63ae8384..6491011 100644
--- a/third_party/blink/renderer/core/mathml/mathml_attribute_names.json5
+++ b/third_party/blink/renderer/core/mathml/mathml_attribute_names.json5
@@ -14,11 +14,13 @@
     "encoding",
     "height",
     "linethickness",
+    "lspace",
     "mathbackground",
     "mathcolor",
     "mathsize",
     "mathvariant",
     "scriptlevel",
+    "voffset",
     "width",
   ],
 }
diff --git a/third_party/blink/renderer/core/mathml/mathml_element.cc b/third_party/blink/renderer/core/mathml/mathml_element.cc
index dd78a14e..bdfd5c5 100644
--- a/third_party/blink/renderer/core/mathml/mathml_element.cc
+++ b/third_party/blink/renderer/core/mathml/mathml_element.cc
@@ -111,16 +111,18 @@
 }
 
 base::Optional<Length> MathMLElement::AddMathLengthToComputedStyle(
-    ComputedStyle& style,
     const CSSToLengthConversionData& conversion_data,
-    const QualifiedName& attr_name) {
+    const QualifiedName& attr_name,
+    AllowPercentages allow_percentages) {
   if (!FastHasAttribute(attr_name))
     return base::nullopt;
   auto value = FastGetAttribute(attr_name);
   const CSSPrimitiveValue* parsed_value = CSSParser::ParseLengthPercentage(
       value,
       StrictCSSParserContext(GetExecutionContext()->GetSecureContextMode()));
-  if (!parsed_value || parsed_value->IsCalculated())
+  if (!parsed_value || parsed_value->IsCalculated() ||
+      (parsed_value->IsPercentage() &&
+       (!value.EndsWith('%') || allow_percentages == AllowPercentages::kNo)))
     return base::nullopt;
   return parsed_value->ConvertToLength(conversion_data);
 }
diff --git a/third_party/blink/renderer/core/mathml/mathml_element.h b/third_party/blink/renderer/core/mathml/mathml_element.h
index a83de75..0df1c7f 100644
--- a/third_party/blink/renderer/core/mathml/mathml_element.h
+++ b/third_party/blink/renderer/core/mathml/mathml_element.h
@@ -37,13 +37,13 @@
       const AtomicString&,
       MutableCSSPropertyValueSet*) override;
 
+  enum class AllowPercentages { kYes, kNo };
   base::Optional<Length> AddMathLengthToComputedStyle(
-      ComputedStyle&,
       const CSSToLengthConversionData&,
-      const QualifiedName&);
+      const QualifiedName&,
+      AllowPercentages allow_percentages = AllowPercentages::kYes);
 
- private:
-  void ParseAttribute(const AttributeModificationParams&) final;
+  void ParseAttribute(const AttributeModificationParams&) override;
 
   bool IsMathMLElement() const =
       delete;  // This will catch anyone doing an unnecessary check.
diff --git a/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc b/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc
index 74210eb..29147feb 100644
--- a/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc
+++ b/third_party/blink/renderer/core/mathml/mathml_fraction_element.cc
@@ -15,7 +15,7 @@
     ComputedStyle& style,
     const CSSToLengthConversionData& conversion_data) {
   if (auto length_or_percentage_value = AddMathLengthToComputedStyle(
-          style, conversion_data, mathml_names::kLinethicknessAttr))
+          conversion_data, mathml_names::kLinethicknessAttr))
     style.SetMathFractionBarThickness(std::move(*length_or_percentage_value));
 }
 
diff --git a/third_party/blink/renderer/core/mathml/mathml_padded_element.cc b/third_party/blink/renderer/core/mathml/mathml_padded_element.cc
new file mode 100644
index 0000000..9d1b4cf
--- /dev/null
+++ b/third_party/blink/renderer/core/mathml/mathml_padded_element.cc
@@ -0,0 +1,95 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/mathml/mathml_padded_element.h"
+
+#include "third_party/blink/renderer/core/css/style_change_reason.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.h"
+
+namespace blink {
+
+MathMLPaddedElement::MathMLPaddedElement(Document& document)
+    : MathMLRowElement(mathml_names::kMpaddedTag, document) {}
+
+void MathMLPaddedElement::AddMathBaselineIfNeeded(
+    ComputedStyle& style,
+    const CSSToLengthConversionData& conversion_data) {
+  if (auto length_or_percentage_value = AddMathLengthToComputedStyle(
+          conversion_data, mathml_names::kHeightAttr, AllowPercentages::kNo))
+    style.SetMathBaseline(std::move(*length_or_percentage_value));
+}
+
+void MathMLPaddedElement::AddMathPaddedDepthIfNeeded(
+    ComputedStyle& style,
+    const CSSToLengthConversionData& conversion_data) {
+  if (auto length_or_percentage_value = AddMathLengthToComputedStyle(
+          conversion_data, mathml_names::kDepthAttr, AllowPercentages::kNo))
+    style.SetMathPaddedDepth(std::move(*length_or_percentage_value));
+}
+
+void MathMLPaddedElement::AddMathPaddedLSpaceIfNeeded(
+    ComputedStyle& style,
+    const CSSToLengthConversionData& conversion_data) {
+  if (auto length_or_percentage_value = AddMathLengthToComputedStyle(
+          conversion_data, mathml_names::kLspaceAttr))
+    style.SetMathPaddedLSpace(std::move(*length_or_percentage_value));
+}
+
+void MathMLPaddedElement::AddMathPaddedVOffsetIfNeeded(
+    ComputedStyle& style,
+    const CSSToLengthConversionData& conversion_data) {
+  if (auto length_or_percentage_value = AddMathLengthToComputedStyle(
+          conversion_data, mathml_names::kVoffsetAttr))
+    style.SetMathPaddedVOffset(std::move(*length_or_percentage_value));
+}
+
+void MathMLPaddedElement::ParseAttribute(
+    const AttributeModificationParams& param) {
+  if (param.name == mathml_names::kLspaceAttr ||
+      param.name == mathml_names::kVoffsetAttr) {
+    SetNeedsStyleRecalc(
+        kLocalStyleChange,
+        StyleChangeReasonForTracing::Create(style_change_reason::kAttribute));
+    if (GetLayoutObject() && GetLayoutObject()->IsMathML()) {
+      GetLayoutObject()
+          ->SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation(
+              layout_invalidation_reason::kAttributeChanged);
+    }
+  }
+
+  MathMLRowElement::ParseAttribute(param);
+}
+
+bool MathMLPaddedElement::IsPresentationAttribute(
+    const QualifiedName& name) const {
+  if (name == mathml_names::kWidthAttr)
+    return true;
+  return MathMLElement::IsPresentationAttribute(name);
+}
+
+void MathMLPaddedElement::CollectStyleForPresentationAttribute(
+    const QualifiedName& name,
+    const AtomicString& value,
+    MutableCSSPropertyValueSet* style) {
+  if (name == mathml_names::kWidthAttr) {
+    if (!value.EndsWith('%')) {
+      AddPropertyToPresentationAttributeStyle(style, CSSPropertyID::kWidth,
+                                              value);
+    }
+  } else {
+    MathMLElement::CollectStyleForPresentationAttribute(name, value, style);
+  }
+}
+
+LayoutObject* MathMLPaddedElement::CreateLayoutObject(
+    const ComputedStyle& style,
+    LegacyLayout legacy) {
+  // TODO(rbuis): legacy check should be removed.
+  if (!RuntimeEnabledFeatures::MathMLCoreEnabled() ||
+      legacy == LegacyLayout::kForce || !style.IsDisplayMathType())
+    return MathMLElement::CreateLayoutObject(style, legacy);
+  return new LayoutNGMathMLBlockWithAnonymousMrow(this);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/mathml/mathml_padded_element.h b/third_party/blink/renderer/core/mathml/mathml_padded_element.h
new file mode 100644
index 0000000..975d2d6
--- /dev/null
+++ b/third_party/blink/renderer/core/mathml/mathml_padded_element.h
@@ -0,0 +1,39 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_PADDED_ELEMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_PADDED_ELEMENT_H_
+
+#include "third_party/blink/renderer/core/mathml/mathml_row_element.h"
+
+namespace blink {
+
+class ComputedStyle;
+class Document;
+
+class CORE_EXPORT MathMLPaddedElement final : public MathMLRowElement {
+ public:
+  explicit MathMLPaddedElement(Document&);
+
+  void AddMathBaselineIfNeeded(ComputedStyle&,
+                               const CSSToLengthConversionData&);
+  void AddMathPaddedDepthIfNeeded(ComputedStyle&,
+                                  const CSSToLengthConversionData&);
+  void AddMathPaddedLSpaceIfNeeded(ComputedStyle&,
+                                   const CSSToLengthConversionData&);
+  void AddMathPaddedVOffsetIfNeeded(ComputedStyle&,
+                                    const CSSToLengthConversionData&);
+
+ private:
+  void ParseAttribute(const AttributeModificationParams&) final;
+  bool IsPresentationAttribute(const QualifiedName&) const final;
+  void CollectStyleForPresentationAttribute(const QualifiedName&,
+                                            const AtomicString&,
+                                            MutableCSSPropertyValueSet*) final;
+  LayoutObject* CreateLayoutObject(const ComputedStyle&,
+                                   LegacyLayout legacy) final;
+};
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_PADDED_ELEMENT_H_
diff --git a/third_party/blink/renderer/core/mathml/mathml_radical_element.cc b/third_party/blink/renderer/core/mathml/mathml_radical_element.cc
index dcfc0b0..92ae3b5 100644
--- a/third_party/blink/renderer/core/mathml/mathml_radical_element.cc
+++ b/third_party/blink/renderer/core/mathml/mathml_radical_element.cc
@@ -4,7 +4,7 @@
 
 #include "third_party/blink/renderer/core/mathml/mathml_radical_element.h"
 
-#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_square_root.h"
+#include "third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_with_anonymous_mrow.h"
 
 namespace blink {
 
@@ -24,7 +24,7 @@
       legacy == LegacyLayout::kForce || !style.IsDisplayMathType())
     return MathMLElement::CreateLayoutObject(style, legacy);
   if (HasTagName(mathml_names::kMsqrtTag))
-    return new LayoutNGMathMLSquareRoot(this);
+    return new LayoutNGMathMLBlockWithAnonymousMrow(this);
   return new LayoutNGMathMLBlock(this);
 }
 
diff --git a/third_party/blink/renderer/core/mathml/mathml_space_element.cc b/third_party/blink/renderer/core/mathml/mathml_space_element.cc
index 76f3558..bba0432 100644
--- a/third_party/blink/renderer/core/mathml/mathml_space_element.cc
+++ b/third_party/blink/renderer/core/mathml/mathml_space_element.cc
@@ -15,7 +15,7 @@
     ComputedStyle& style,
     const CSSToLengthConversionData& conversion_data) {
   if (auto length_or_percentage_value = AddMathLengthToComputedStyle(
-          style, conversion_data, mathml_names::kHeightAttr))
+          conversion_data, mathml_names::kHeightAttr))
     style.SetMathBaseline(std::move(*length_or_percentage_value));
 }
 
diff --git a/third_party/blink/renderer/core/mathml/mathml_tag_names.json5 b/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
index dcc7157e..476a1a3 100644
--- a/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
+++ b/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
@@ -80,6 +80,10 @@
       interfaceName: "MathMLElement",
     },
     {
+      name: "mpadded",
+      interfaceName: "MathMLPaddedElement",
+    },
+    {
       name: "mphantom",
       interfaceName: "MathMLRowElement",
     },
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
index 1d9569dd..b4edc9f7 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -404,8 +404,6 @@
   if (layer_config_changed)
     UpdateInternalHierarchy();
 
-  UpdateBackgroundColor();
-
   if (layout_object.IsLayoutEmbeddedContent()) {
     if (WebPluginContainerImpl* plugin = GetPluginContainer(layout_object)) {
       graphics_layer_->SetContentsToCcLayer(
@@ -701,7 +699,6 @@
     owning_layer_.GetScrollableArea()->PositionOverflowControls();
 
   UpdateContentsRect();
-  UpdateBackgroundColor();
   UpdateDrawsContentAndPaintsHitTest();
   UpdateElementId();
   UpdateContentsOpaque();
@@ -974,19 +971,19 @@
   }
 
   draws_background_onto_content_layer_ = false;
-
   if (has_painted_content && IsTextureLayerCanvas(GetLayoutObject())) {
     CanvasRenderingContext* context =
         To<HTMLCanvasElement>(GetLayoutObject().GetNode())->RenderingContext();
     // Content layer may be null if context is lost.
     if (cc::Layer* content_layer = context->CcLayer()) {
-      Color bg_color(Color::kTransparent);
       if (ContentLayerSupportsDirectBackgroundComposition(GetLayoutObject())) {
-        bg_color = LayoutObjectBackgroundColor();
         has_painted_content = false;
         draws_background_onto_content_layer_ = true;
+        Color contents_layer_background_color =
+            GetLayoutObject().ResolveColor(GetCSSPropertyBackgroundColor());
+        graphics_layer_->SetContentsLayerBackgroundColor(
+            contents_layer_background_color);
       }
-      content_layer->SetBackgroundColor(bg_color.Rgb());
     }
   }
 
@@ -1315,28 +1312,6 @@
   return static_cast<GraphicsLayerPaintingPhase>(phase);
 }
 
-Color CompositedLayerMapping::LayoutObjectBackgroundColor() const {
-  const auto& object = GetLayoutObject();
-  auto background_color = object.ResolveColor(GetCSSPropertyBackgroundColor());
-  auto* layout_view = DynamicTo<LayoutView>(object);
-  if (layout_view && object.GetDocument().IsInMainFrame()) {
-    return layout_view->GetFrameView()->BaseBackgroundColor().Blend(
-        background_color);
-  }
-  return background_color;
-}
-
-void CompositedLayerMapping::UpdateBackgroundColor() {
-  auto color = LayoutObjectBackgroundColor().Rgb();
-  graphics_layer_->SetBackgroundColor(
-      BackgroundPaintsOntoGraphicsLayer() ? color : SK_ColorTRANSPARENT);
-  if (scrolling_contents_layer_) {
-    scrolling_contents_layer_->SetBackgroundColor(
-        BackgroundPaintsOntoScrollingContentsLayer() ? color
-                                                     : SK_ColorTRANSPARENT);
-  }
-}
-
 bool CompositedLayerMapping::PaintsChildren() const {
   if (owning_layer_.HasVisibleContent() &&
       owning_layer_.HasNonEmptyChildLayoutObjects())
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
index ec51c85e..0415ccc0 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
@@ -369,8 +369,6 @@
   // painting into the backing store.
   bool ContainsPaintedContent() const;
 
-  Color LayoutObjectBackgroundColor() const;
-  void UpdateBackgroundColor();
   void UpdateContentsRect();
   void UpdateCompositingReasons();
 
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
index 2a01f3877..999510e 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
@@ -19,7 +19,9 @@
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
 #include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
+#include "third_party/blink/renderer/platform/testing/find_cc_layer.h"
 
 #include "third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h"
 
@@ -1380,9 +1382,10 @@
 TEST_F(CompositedLayerMappingTest, MainFrameLayerBackgroundColor) {
   UpdateAllLifecyclePhasesForTest();
   EXPECT_EQ(Color::kWhite, GetDocument().View()->BaseBackgroundColor());
-  auto* view_layer =
-      GetDocument().GetLayoutView()->Layer()->GraphicsLayerBacking();
-  EXPECT_EQ(Color::kWhite, view_layer->BackgroundColor());
+  auto* view_cc_layer = ScrollingContentsCcLayerByScrollElementId(
+      GetFrame().View()->RootCcLayer(),
+      GetFrame().View()->LayoutViewport()->GetScrollElementId());
+  EXPECT_EQ(SK_ColorWHITE, view_cc_layer->background_color());
 
   Color base_background(255, 0, 0);
   GetDocument().View()->SetBaseBackgroundColor(base_background);
@@ -1390,33 +1393,8 @@
                                      "background: rgba(0, 255, 0, 0.5)");
   UpdateAllLifecyclePhasesForTest();
   EXPECT_EQ(base_background, GetDocument().View()->BaseBackgroundColor());
-  EXPECT_EQ(Color(127, 128, 0, 255), view_layer->BackgroundColor());
-}
-
-TEST_F(CompositedLayerMappingTest, ScrollingLayerBackgroundColor) {
-  SetBodyInnerHTML(R"HTML(
-    <style>.color {background-color: blue}</style>
-    <div id='target' style='width: 100px; height: 100px;
-         overflow: scroll; will-change: transform'>
-      <div style='height: 200px'></div>
-    </div>
-  )HTML");
-
-  auto* target = GetDocument().getElementById("target");
-  auto* mapping = ToLayoutBoxModelObject(target->GetLayoutObject())
-                      ->Layer()
-                      ->GetCompositedLayerMapping();
-  auto* graphics_layer = mapping->MainGraphicsLayer();
-  auto* scrolling_contents_layer = mapping->ScrollingContentsLayer();
-  ASSERT_TRUE(graphics_layer);
-  ASSERT_TRUE(scrolling_contents_layer);
-  EXPECT_EQ(Color::kTransparent, graphics_layer->BackgroundColor());
-  EXPECT_EQ(Color::kTransparent, scrolling_contents_layer->BackgroundColor());
-
-  target->setAttribute(html_names::kClassAttr, "color");
-  UpdateAllLifecyclePhasesForTest();
-  EXPECT_EQ(Color::kTransparent, graphics_layer->BackgroundColor());
-  EXPECT_EQ(Color(0, 0, 255), scrolling_contents_layer->BackgroundColor());
+  EXPECT_EQ(SkColorSetARGB(255, 127, 128, 0),
+            view_cc_layer->background_color());
 }
 
 TEST_F(CompositedLayerMappingTest, ScrollLayerSizingSubpixelAccumulation) {
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
index 90ecc85..bd0357f2 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -385,11 +385,13 @@
   ASSERT_TRUE(scroller_box->GetBackgroundPaintLocation() ==
               kBackgroundPaintInGraphicsLayer);
 
-  // The root layer and root scrolling contents layer get background_color by
-  // blending the CSS background-color of the <html> element with
-  // LocalFrameView::BaseBackgroundColor(), which is white by default. In this
-  // case, because the background is a gradient, it will blend transparent with
-  // white, resulting in white.
+  // The root layer gets background_color by blending the CSS background-color
+  // of the <html> element with LocalFrameView::BaseBackgroundColor(), which is
+  // white by default. In this case, because the background is a gradient, it
+  // will blend transparent with white, resulting in white. Because the
+  // background is painted into the root graphics layer, the root scrolling
+  // contents layer should not checkerboard, so its background color should be
+  // transparent.
   auto* layer = CcLayersByName(RootCcLayer(), "LayoutView #document")[0];
   EXPECT_EQ(layer->background_color(), SK_ColorWHITE);
   auto* scrollable_area = GetLocalFrameView()->LayoutViewport();
diff --git a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
index 980ceef..d37845a 100644
--- a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
+++ b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
@@ -510,9 +510,14 @@
 }
 
 GraphicsLayer* PaintLayerCompositor::PaintRootGraphicsLayer() const {
-  if (layout_view_->GetDocument().GetPage()->GetChromeClient().IsPopup() ||
-      !IsMainFrame())
+  // Shortcut: skip the fullscreen checks for popups, and for not-main-frame
+  // ordinary fullscreen mode. Don't use the shortcut for WebXR DOM overlay mode
+  // since that requires ancestor frames to be rendered as transparent.
+  Document& doc = layout_view_->GetDocument();
+  if (doc.GetPage()->GetChromeClient().IsPopup() ||
+      (!IsMainFrame() && !doc.IsXrOverlay())) {
     return RootGraphicsLayer();
+  }
 
   // Start from the full screen overlay layer if exists. Other layers will be
   // skipped during painting.
diff --git a/third_party/blink/renderer/core/paint/table_row_painter.cc b/third_party/blink/renderer/core/paint/table_row_painter.cc
index cc18edcf..faaf7e6f3 100644
--- a/third_party/blink/renderer/core/paint/table_row_painter.cc
+++ b/third_party/blink/renderer/core/paint/table_row_painter.cc
@@ -109,6 +109,10 @@
             paint_info_for_cells, layout_table_row_);
       }
     }
+    paint_info.context.GetPaintController().SetPossibleBackgroundColor(
+        layout_table_row_,
+        layout_table_row_.ResolveColor(GetCSSPropertyBackgroundColor()).Rgb(),
+        paint_rect.Width().ToUnsigned() * paint_rect.Height().ToUnsigned());
   }
 
   if (has_box_shadow) {
diff --git a/third_party/blink/renderer/core/paint/table_section_painter.cc b/third_party/blink/renderer/core/paint/table_section_painter.cc
index 43bf5c58..7a8cf15 100644
--- a/third_party/blink/renderer/core/paint/table_section_painter.cc
+++ b/third_party/blink/renderer/core/paint/table_section_painter.cc
@@ -307,6 +307,11 @@
         }
       }
     }
+    paint_info.context.GetPaintController().SetPossibleBackgroundColor(
+        layout_table_section_,
+        layout_table_section_.ResolveColor(GetCSSPropertyBackgroundColor())
+            .Rgb(),
+        paint_rect.Width().ToUnsigned() * paint_rect.Height().ToUnsigned());
   }
 
   if (has_box_shadow) {
diff --git a/third_party/blink/renderer/core/script/script_runner.cc b/third_party/blink/renderer/core/script/script_runner.cc
index 920ebaa8..f2951bb 100644
--- a/third_party/blink/renderer/core/script/script_runner.cc
+++ b/third_party/blink/renderer/core/script/script_runner.cc
@@ -32,6 +32,7 @@
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/script/script_loader.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -147,6 +148,10 @@
           DelayAsyncScriptExecutionUntilFinishedParsingEnabled() ||
       RuntimeEnabledFeatures::
           DelayAsyncScriptExecutionUntilFirstPaintOrFinishedParsingEnabled();
+  if (!document_->Parsing()) {
+    document_->Loader()->DidObserveLoadingBehavior(
+        kLoadingBehaviorAsyncScriptReadyBeforeDocumentFinishedParsing);
+  }
   return !delay_async_script_milestone_reached_ && flags_enabled;
 }
 
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
index 88ee4ae..d83992e 100644
--- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
+++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -1001,6 +1001,33 @@
       getter: "GetMathFractionBarThickness",
     },
     {
+      name: "MathPaddedLSpace",
+      field_template: "external",
+      default_value: "Length()",
+      include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
+      type_name: "Length",
+      field_group: "*",
+      getter: "GetMathPaddedLSpace",
+    },
+    {
+      name: "MathPaddedVOffset",
+      field_template: "external",
+      default_value: "Length()",
+      include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
+      type_name: "Length",
+      field_group: "*",
+      getter: "GetMathPaddedVOffset",
+    },
+    {
+      name: "MathPaddedDepth",
+      field_template: "external",
+      default_value: "Length()",
+      include_paths: ["third_party/blink/renderer/platform/geometry/length.h"],
+      type_name: "Length",
+      field_group: "*",
+      getter: "GetMathPaddedDepth",
+    },
+    {
       name: "MathScriptLevel",
       inherited: true,
       field_template: "primitive",
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 62c46ca6..1f795f4 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -500,7 +500,6 @@
     "//third_party/blink/public:blink_headers",
     "//third_party/blink/renderer/core",
     "//third_party/blink/renderer/core:unit_test_support",
-    "//third_party/blink/renderer/modules/font_access:unit_tests",
     "//third_party/blink/renderer/modules/gamepad:unit_tests",
     "//third_party/blink/renderer/modules/hid:unit_tests",
     "//third_party/blink/renderer/modules/native_file_system:unit_tests",
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
index 427fd79..8d251f0 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -523,6 +523,18 @@
                                         is_selected);
 }
 
+// Returns true if the object is marked user-select:none
+bool AXLayoutObject::IsNotUserSelectable() const {
+  if (!GetLayoutObject())
+    return false;
+
+  const ComputedStyle* style = GetLayoutObject()->Style();
+  if (!style)
+    return false;
+
+  return (style->UserSelect() == EUserSelect::kNone);
+}
+
 // Returns true if the node's aria-selected attribute should be set to true
 // when the node is focused. This is true for only a subset of roles.
 bool AXLayoutObject::SelectionShouldFollowFocus() const {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.h b/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
index d339eb3f..9757985 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
@@ -96,6 +96,7 @@
   AccessibilityGrabbedState IsGrabbed() const override;
   AccessibilitySelectedState IsSelected() const override;
   bool IsSelectedFromFocus() const override;
+  bool IsNotUserSelectable() const override;
 
   // Whether objects are ignored, i.e. not included in the tree.
   AXObjectInclusion DefaultObjectInclusion(
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index e9d4561..cd674590f 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -790,6 +790,11 @@
         IsSelectedFromFocus());
   }
 
+  if (IsNotUserSelectable()) {
+    node_data->AddBoolAttribute(
+        ax::mojom::blink::BoolAttribute::kNotUserSelectableStyle, true);
+  }
+
   if (IsRichlyEditable())
     node_data->AddState(ax::mojom::blink::State::kRichlyEditable);
 
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h
index bb76671..0ffcab8 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -501,6 +501,7 @@
   // Is the object selected because selection is following focus?
   virtual bool IsSelectedFromFocus() const { return false; }
   virtual bool IsSelectedOptionActive() const { return false; }
+  virtual bool IsNotUserSelectable() const { return false; }
   virtual bool IsVisible() const;
   virtual bool IsVisited() const { return false; }
 
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.idl b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.idl
index da8d2fa..edb467dc 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.idl
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.idl
@@ -11,7 +11,7 @@
     SecureContext
 ] interface BluetoothRemoteGATTCharacteristic : EventTarget {
     [SameObject] readonly attribute BluetoothRemoteGATTService service;
-    readonly attribute UUID uuid;
+    [HighEntropy=Direct, MeasureAs=BluetoothRemoteGATTCharacteristic_Uuid] readonly attribute UUID uuid;
     readonly attribute BluetoothCharacteristicProperties properties;
     readonly attribute DataView? value;
     [RaisesException, CallWith=ScriptState, MeasureAs=WebBluetoothRemoteCharacteristicGetDescriptor] Promise<BluetoothRemoteGATTDescriptor> getDescriptor(BluetoothDescriptorUUID descriptor);
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.idl b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.idl
index 8d5faa4..f6ad62c 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.idl
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.idl
@@ -12,7 +12,7 @@
     SecureContext
 ] interface BluetoothRemoteGATTDescriptor  {
     [SameObject] readonly attribute BluetoothRemoteGATTCharacteristic characteristic;
-    readonly attribute UUID uuid;
+    [HighEntropy=Direct, MeasureAs=BluetoothRemoteGATTDescriptor_Uuid] readonly attribute UUID uuid;
     readonly attribute DataView? value;
     [CallWith=ScriptState, RaisesException, MeasureAs=WebBluetoothRemoteDescriptorReadValue] Promise<DataView> readValue();
     [CallWith=ScriptState, RaisesException, MeasureAs=WebBluetoothRemoteDescriptorWriteValue] Promise<void> writeValue(BufferSource value);
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.idl b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.idl
index 62de0fa..1cddb9a 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.idl
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.idl
@@ -10,7 +10,7 @@
     SecureContext
 ] interface BluetoothRemoteGATTService {
     [SameObject] readonly attribute BluetoothDevice device;
-    readonly attribute UUID uuid;
+    [HighEntropy=Direct, MeasureAs=BluetoothRemoteGATTService_Uuid] readonly attribute UUID uuid;
     readonly attribute boolean isPrimary;
     [RaisesException, CallWith=ScriptState, MeasureAs=WebBluetoothRemoteServiceGetCharacteristic] Promise<BluetoothRemoteGATTCharacteristic> getCharacteristic(BluetoothCharacteristicUUID characteristic);
     [RaisesException, CallWith=ScriptState, MeasureAs=WebBluetoothRemoteServiceGetCharacteristics] Promise<sequence<BluetoothRemoteGATTCharacteristic>> getCharacteristics(optional BluetoothCharacteristicUUID characteristic);
diff --git a/third_party/blink/renderer/modules/font_access/BUILD.gn b/third_party/blink/renderer/modules/font_access/BUILD.gn
index a7a1aef9..73070d8e 100644
--- a/third_party/blink/renderer/modules/font_access/BUILD.gn
+++ b/third_party/blink/renderer/modules/font_access/BUILD.gn
@@ -20,21 +20,3 @@
 
   deps = [ "//third_party/blink/renderer/platform" ]
 }
-
-source_set("unit_tests") {
-  testonly = true
-  sources = [ "font_metadata_unittest.cc" ]
-
-  configs += [
-    "//third_party/blink/renderer:config",
-    "//third_party/blink/renderer:inside_blink",
-    "//third_party/blink/renderer/core:blink_core_pch",
-  ]
-
-  deps = [
-    "//testing/gtest",
-    "//third_party/blink/renderer/modules",
-    "//third_party/blink/renderer/platform",
-    "//third_party/blink/renderer/platform/wtf",
-  ]
-}
diff --git a/third_party/blink/renderer/modules/font_access/font_metadata.cc b/third_party/blink/renderer/modules/font_access/font_metadata.cc
index 56f00cf..5f1779e 100644
--- a/third_party/blink/renderer/modules/font_access/font_metadata.cc
+++ b/third_party/blink/renderer/modules/font_access/font_metadata.cc
@@ -17,99 +17,6 @@
 #include "third_party/skia/include/core/SkStream.h"
 #include "third_party/skia/include/core/SkTypes.h"
 
-namespace {
-
-enum FontAccessStatus {
-  kOk,
-  // An invalid argument was passed to a method.
-  kInvalidArgument,
-};
-
-struct FontAccessError {
-  FontAccessStatus status;
-  String message;
-
-  bool IsOk() { return status == FontAccessStatus::kOk; }
-
-  static FontAccessError CreateOk() {
-    return FontAccessError{FontAccessStatus::kOk, ""};
-  }
-
-  static FontAccessError CreateInvalidArgument(String message) {
-    return FontAccessError{FontAccessStatus::kInvalidArgument, message};
-  }
-};
-
-bool isValidTableNameCharacter(unsigned int name_char) {
-  // According to the OpenType specifications, each byte in a Tag has a value
-  // between 0x20 and 0x7E.
-  // https://docs.microsoft.com/en-us/typography/opentype/spec/otff#data-types
-  return (name_char >= 0x20 && name_char <= 0x7E);
-}
-
-bool isValidTableName(const String& table_name) {
-  // According to the OpenType specifications, a Tag may be interpreted as a
-  // an array with 4 elements. The String representation will be 4 characters,
-  // each character representing one byte of a Tag.
-  if (table_name.length() != 4) {
-    return false;
-  }
-
-  for (unsigned i = 0; i < 4; ++i) {
-    if (!isValidTableNameCharacter(table_name[i]))
-      return false;
-  }
-  return true;
-}
-
-String convertTagToString(uint32_t tag) {
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
-  // Tag assumed to be in Big Endian byte ordering.
-  // Swap byte ordering if on Little Endian architecture.
-  tag = base::ByteSwap(tag);
-#endif
-  char buf[5];
-  std::memcpy(&buf, &tag, 4);
-  buf[4] = '\0';
-  return String(&buf[0], size_t{4});
-}
-
-std::pair<FontAccessError, uint32_t> convertStringToTag(
-    const String& table_name) {
-  if (!isValidTableName(table_name)) {
-    return std::make_pair(
-        FontAccessError::CreateInvalidArgument(String::Format(
-            "Invalid table name: %s", table_name.Latin1().c_str())),
-        0u);
-  }
-
-  // Tags in OpenType are always in Big Endian order.
-  // https://docs.microsoft.com/en-us/typography/opentype/spec/otff#data-types
-  uint32_t tag;
-
-  // Since we know that table_name is "valid", i.e. all characters are within
-  // the ASCII range, we can safely assume the following works, whether or not
-  // each character is 8 or 16 bit encoded.
-  base::ReadBigEndian(table_name.Ascii().c_str(), &tag);
-
-  return std::make_pair(FontAccessError::CreateOk(), tag);
-}
-
-std::pair<FontAccessError, Vector<uint32_t>> convertTableNamesToTags(
-    const Vector<String>& table_names) {
-  Vector<uint32_t> output;
-  for (auto tname : table_names) {
-    auto tag_result = convertStringToTag(tname);
-    if (!tag_result.first.IsOk()) {
-      return std::make_pair(tag_result.first, Vector<uint32_t>());
-    }
-    output.push_back(tag_result.second);
-  }
-  return std::make_pair(FontAccessError::CreateOk(), std::move(output));
-}
-
-}  // namespace
-
 namespace blink {
 
 FontMetadata::FontMetadata(const FontEnumerationEntry& entry)
@@ -121,34 +28,6 @@
   return MakeGarbageCollected<FontMetadata>(entry);
 }
 
-ScriptPromise FontMetadata::getTables(ScriptState* script_state) {
-  ScriptPromiseResolver* resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-  ScriptPromise promise = resolver->Promise();
-
-  Vector<String> tables;
-
-  Thread::Current()->GetTaskRunner()->PostTask(
-      FROM_HERE,
-      WTF::Bind(&FontMetadata::getTablesImpl, WrapPersistent(resolver),
-                postscriptName_, std::move(tables)));
-
-  return promise;
-}
-
-ScriptPromise FontMetadata::getTables(ScriptState* script_state,
-                                      const Vector<String>& tables) {
-  ScriptPromiseResolver* resolver =
-      MakeGarbageCollected<ScriptPromiseResolver>(script_state);
-  ScriptPromise promise = resolver->Promise();
-
-  Thread::Current()->GetTaskRunner()->PostTask(
-      FROM_HERE, WTF::Bind(&FontMetadata::getTablesImpl,
-                           WrapPersistent(resolver), postscriptName_, tables));
-
-  return promise;
-}
-
 ScriptPromise FontMetadata::blob(ScriptState* script_state) {
   ScriptPromiseResolver* resolver =
       MakeGarbageCollected<ScriptPromiseResolver>(script_state);
@@ -165,96 +44,6 @@
   ScriptWrappable::Trace(visitor);
 }
 
-// static
-void FontMetadata::getTablesImpl(ScriptPromiseResolver* resolver,
-                                 const String& postscriptName,
-                                 const Vector<String>& tableNames) {
-  if (!resolver->GetScriptState()->ContextIsValid())
-    return;
-
-  FontDescription description;
-  scoped_refptr<SimpleFontData> font_data =
-      FontCache::GetFontCache()->GetFontData(description,
-                                             AtomicString(postscriptName));
-  if (!font_data) {
-    auto message = String::Format("The font %s could not be accessed.",
-                                  postscriptName.Latin1().c_str());
-    ScriptState::Scope scope(resolver->GetScriptState());
-    resolver->Reject(V8ThrowException::CreateTypeError(
-        resolver->GetScriptState()->GetIsolate(), message));
-    return;
-  }
-
-  const SkTypeface* typeface = font_data->PlatformData().Typeface();
-  Vector<SkFontTableTag> tags;
-  if (tableNames.IsEmpty()) {
-    // No tables supplied. Fetch all.
-    const int num_tables = typeface->countTables();
-
-    SkFontTableTag sk_tags[num_tables];
-    const unsigned int ret_val = typeface->getTableTags(sk_tags);
-    if (ret_val == 0) {
-      auto message = String::Format("Error enumerating tables for font %s.",
-                                    postscriptName.Latin1().c_str());
-      ScriptState::Scope scope(resolver->GetScriptState());
-      resolver->Reject(V8ThrowException::CreateTypeError(
-          resolver->GetScriptState()->GetIsolate(), message));
-      return;
-    }
-    tags.Append(sk_tags, num_tables);
-    DCHECK(ret_val == tags.size());
-  } else {
-    // Table names supplied. Validate and convert for retrieval.
-    auto result = convertTableNamesToTags(tableNames);
-    if (!result.first.IsOk()) {
-      ScriptState::Scope scope(resolver->GetScriptState());
-      resolver->Reject(V8ThrowException::CreateTypeError(
-          resolver->GetScriptState()->GetIsolate(), result.first.message));
-      return;
-    }
-    tags = result.second;
-  }
-
-  auto* output = MakeGarbageCollected<HeapHashMap<String, Member<Blob>>>();
-
-  for (auto tag : tags) {
-    wtf_size_t table_size = SafeCast<wtf_size_t>(typeface->getTableSize(tag));
-    String output_table_name = convertTagToString(tag);
-
-    if (!isValidTableName(output_table_name)) {
-      auto message = String::Format("The font %s could not be accessed.",
-                                    postscriptName.Latin1().c_str());
-      ScriptState::Scope scope(resolver->GetScriptState());
-      resolver->Reject(V8ThrowException::CreateTypeError(
-          resolver->GetScriptState()->GetIsolate(), message));
-      return;
-    };
-
-    if (!table_size) {
-      // If table is not found or has size zero, skip it.
-      continue;
-    }
-
-    // TODO(https://crbug.com/1069900): getTableData makes a copy of the bytes.
-    // Stream the font bytes instead.
-    Vector<char> bytes(table_size);
-    size_t returned_size =
-        typeface->getTableData(tag, 0ULL, table_size, bytes.data());
-    DCHECK_EQ(table_size, returned_size);
-
-    scoped_refptr<RawData> raw_data = RawData::Create();
-    bytes.swap(*raw_data->MutableData());
-    auto blob_data = std::make_unique<BlobData>();
-    blob_data->AppendData(std::move(raw_data));
-
-    auto* blob = MakeGarbageCollected<Blob>(
-        BlobDataHandle::Create(std::move(blob_data), table_size));
-    output->Set(output_table_name, blob);
-  }
-
-  auto* map = MakeGarbageCollected<FontTableMap>(*output);
-  resolver->Resolve(map);
-}
 
 // static
 void FontMetadata::blobImpl(ScriptPromiseResolver* resolver,
diff --git a/third_party/blink/renderer/modules/font_access/font_metadata.h b/third_party/blink/renderer/modules/font_access/font_metadata.h
index c8ba8ef..771e7b9 100644
--- a/third_party/blink/renderer/modules/font_access/font_metadata.h
+++ b/third_party/blink/renderer/modules/font_access/font_metadata.h
@@ -44,8 +44,6 @@
   String fullName() const { return fullName_; }
   String family() const { return family_; }
 
-  ScriptPromise getTables(ScriptState*);
-  ScriptPromise getTables(ScriptState*, const Vector<String>& tables);
   ScriptPromise blob(ScriptState*);
 
   void Trace(Visitor*) const override;
diff --git a/third_party/blink/renderer/modules/font_access/font_metadata.idl b/third_party/blink/renderer/modules/font_access/font_metadata.idl
index 2da9f62..14cde9c1 100644
--- a/third_party/blink/renderer/modules/font_access/font_metadata.idl
+++ b/third_party/blink/renderer/modules/font_access/font_metadata.idl
@@ -11,6 +11,5 @@
   readonly attribute USVString postscriptName;
   readonly attribute USVString fullName;
   readonly attribute USVString family;
-  [CallWith=ScriptState, Measure] Promise<FontTableMap> getTables(optional sequence<ByteString> tables);
   [CallWith=ScriptState, Measure] Promise<Blob> blob();
 };
diff --git a/third_party/blink/renderer/modules/font_access/font_metadata_unittest.cc b/third_party/blink/renderer/modules/font_access/font_metadata_unittest.cc
deleted file mode 100644
index 898e1a5..0000000
--- a/third_party/blink/renderer/modules/font_access/font_metadata_unittest.cc
+++ /dev/null
@@ -1,73 +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 "third_party/blink/renderer/modules/font_access/font_metadata.h"
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_font_table_map.h"
-#include "third_party/blink/renderer/modules/font_access/font_table_map.h"
-#include "third_party/blink/renderer/platform/fonts/font_cache.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-
-namespace blink {
-
-TEST(FontMetadata, TestStrings8And16Bits) {
-  std::vector<FontEnumerationEntry> expectations;
-#if defined(OS_MAC)
-  expectations.push_back(FontEnumerationEntry{"Monaco", "Monaco", "Monaco"});
-  expectations.push_back(
-      FontEnumerationEntry{"Menlo-Regular", "Menlo Regular", "Menlo"});
-  expectations.push_back(
-      FontEnumerationEntry{"Menlo-Bold", "Menlo Bold", "Menlo"});
-  expectations.push_back(
-      FontEnumerationEntry{"Menlo-BoldItalic", "Menlo Bold Italic", "Menlo"});
-#endif
-
-  for (auto f : expectations) {
-    // Set up 8 and 16 bit inputs.
-    const std::string tableNameStr = "name";
-
-    Vector<String> tableNames8;
-    const String tName8 = String(tableNameStr.c_str());
-    ASSERT_TRUE(tName8.Is8Bit());
-    tableNames8.push_back(tName8);
-
-    Vector<String> tableNames16;
-    String tName16 = String(tableNameStr.c_str());
-    tName16.Ensure16Bit();
-    ASSERT_FALSE(tName16.Is8Bit());
-    tableNames16.push_back(tName16);
-
-    Vector<Vector<String>> test_inputs;
-    test_inputs.push_back(tableNames8);
-    test_inputs.push_back(tableNames16);
-
-    V8TestingScope scope;
-    auto* script_state = scope.GetScriptState();
-    auto* metadata = FontMetadata::Create(f);
-    for (auto t : test_inputs) {
-      ScriptPromise promise = metadata->getTables(script_state, t);
-      ScriptPromiseTester tester(script_state, promise);
-      tester.WaitUntilSettled();
-      EXPECT_TRUE(tester.IsFulfilled());
-      ASSERT_TRUE(tester.Value().IsObject());
-
-      FontTableMap* tableMap =
-          V8FontTableMap::ToImpl(tester.Value()
-                                     .V8Value()
-                                     ->ToObject(script_state->GetContext())
-                                     .ToLocalChecked());
-      ASSERT_EQ(tableMap->size(), 1u);
-
-      const FontTableMap::MapType map = tableMap->GetHashMap();
-      EXPECT_TRUE(map.Contains("name"));
-    }
-  }
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_decoder_init.idl b/third_party/blink/renderer/modules/webcodecs/audio_decoder_init.idl
index c3cf975..4a55d99 100644
--- a/third_party/blink/renderer/modules/webcodecs/audio_decoder_init.idl
+++ b/third_party/blink/renderer/modules/webcodecs/audio_decoder_init.idl
@@ -5,6 +5,6 @@
 // https://github.com/WICG/web-codecs
 
 dictionary AudioDecoderInit {
-  AudioFrameOutputCallback output;
-  WebCodecsErrorCallback error;
+  required AudioFrameOutputCallback output;
+  required WebCodecsErrorCallback error;
 };
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_frame.cc b/third_party/blink/renderer/modules/webcodecs/audio_frame.cc
index e048804..d959b0a 100644
--- a/third_party/blink/renderer/modules/webcodecs/audio_frame.cc
+++ b/third_party/blink/renderer/modules/webcodecs/audio_frame.cc
@@ -3,7 +3,10 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/renderer/modules/webcodecs/audio_frame.h"
+#include "media/base/audio_buffer.h"
+#include "media/base/audio_bus.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_audio_frame_init.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
 
 namespace blink {
 
@@ -19,7 +22,26 @@
 
 AudioFrame::AudioFrame(scoped_refptr<media::AudioBuffer> buffer)
     : timestamp_(buffer->timestamp().InMicroseconds()) {
-  // FIXME - use the |buffer| to initialize AudioBuffer.
+  buffer_ = AudioBuffer::CreateUninitialized(
+      buffer->channel_count(), buffer->frame_count(), buffer->sample_rate());
+
+  // Wrap blink buffer a media::AudioBus so we can interface with
+  // media::AudioBuffer to copy the data out.
+  auto media_bus_wrapper =
+      media::AudioBus::CreateWrapper(buffer->channel_count());
+  for (int i = 0; i < media_bus_wrapper->channels(); ++i) {
+    DCHECK_EQ(buffer_->getChannelData(i)->byteLengthAsSizeT(),
+              buffer->frame_count() * sizeof(float));
+    float* channel_data = buffer_->getChannelData(i)->Data();
+    media_bus_wrapper->SetChannelData(i, channel_data);
+  }
+  media_bus_wrapper->set_frames(buffer->frame_count());
+
+  // Copy the frames.
+  // TODO(chcunningham): Avoid this copy by refactoring blink::AudioBuffer to
+  // ref a media::AudioBuffer and only copy for calls to copyToChannel().
+  buffer->ReadFrames(media_bus_wrapper->frames(), 0 /* source_frame_offset */,
+                     0 /* dest_frame_offset */, media_bus_wrapper.get());
 }
 
 void AudioFrame::close() {
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder_init.idl b/third_party/blink/renderer/modules/webcodecs/video_decoder_init.idl
index fb4a05f..983372d 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_decoder_init.idl
+++ b/third_party/blink/renderer/modules/webcodecs/video_decoder_init.idl
@@ -5,6 +5,6 @@
 // https://github.com/WICG/web-codecs
 
 dictionary VideoDecoderInit {
-  VideoFrameOutputCallback output;
-  WebCodecsErrorCallback error;
+  required VideoFrameOutputCallback output;
+  required WebCodecsErrorCallback error;
 };
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
index 919bbeb8..8d3bba71 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
@@ -83,6 +83,10 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
+int32_t VideoEncoder::encodeQueueSize() {
+  return requested_encodes_;
+}
+
 void VideoEncoder::configure(const VideoEncoderConfig* config,
                              ExceptionState& exception_state) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -126,6 +130,7 @@
   request->type = Request::Type::kEncode;
   request->frame = frame;
   request->encodeOpts = opts;
+  ++requested_encodes_;
   return EnqueueRequest(request);
 }
 
@@ -178,17 +183,25 @@
   output_callback_->InvokeAndReportException(nullptr, chunk);
 }
 
-void VideoEncoder::CallErrorCallback(DOMException* ex) {
-  if (!script_state_->ContextIsValid() || !error_callback_)
+void VideoEncoder::HandleError(DOMException* ex) {
+  // Save a temp before we clear the callback.
+  V8WebCodecsErrorCallback* error_callback = error_callback_.Get();
+
+  // Errors are permanent. Shut everything down.
+  error_callback_.Clear();
+  media_encoder_.reset();
+  output_callback_.Clear();
+
+  if (!script_state_->ContextIsValid() || !error_callback)
     return;
+
   ScriptState::Scope scope(script_state_);
-  error_callback_->InvokeAndReportException(nullptr, ex);
+  error_callback->InvokeAndReportException(nullptr, ex);
 }
 
-void VideoEncoder::CallErrorCallback(DOMExceptionCode code,
-                                     const String& message) {
+void VideoEncoder::HandleError(DOMExceptionCode code, const String& message) {
   auto* ex = MakeGarbageCollected<DOMException>(code, message);
-  CallErrorCallback(ex);
+  HandleError(ex);
 }
 
 void VideoEncoder::EnqueueRequest(Request* request) {
@@ -219,6 +232,7 @@
 void VideoEncoder::ProcessEncode(Request* request) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(request->type, Request::Type::kEncode);
+  DCHECK_GT(requested_encodes_, 0);
 
   auto done_callback = [](VideoEncoder* self, Request* req,
                           media::Status status) {
@@ -227,19 +241,19 @@
     DCHECK_CALLED_ON_VALID_SEQUENCE(self->sequence_checker_);
     if (!status.is_ok()) {
       std::string msg = "Encoding error: " + status.message();
-      self->CallErrorCallback(DOMExceptionCode::kOperationError, msg.c_str());
+      self->HandleError(DOMExceptionCode::kOperationError, msg.c_str());
     }
     self->ProcessRequests();
   };
 
   if (!media_encoder_) {
-    CallErrorCallback(DOMExceptionCode::kOperationError,
-                      "Encoder is not configured");
+    HandleError(DOMExceptionCode::kOperationError, "Encoder is not configured");
     return;
   }
 
   bool keyframe = request->encodeOpts->hasKeyFrameNonNull() &&
                   request->encodeOpts->keyFrameNonNull();
+  --requested_encodes_;
   media_encoder_->Encode(request->frame->frame(), keyframe,
                          WTF::Bind(done_callback, WrapWeakPersistent(this),
                                    WrapPersistentIfNeeded(request)));
@@ -252,9 +266,10 @@
   auto* config = request->config.Get();
   AccelerationPreference acc_pref = AccelerationPreference::kAllow;
 
+  // TODO(https://crbug.com/1116783): Delete this, allow reconfiguration.
   if (media_encoder_) {
-    CallErrorCallback(DOMExceptionCode::kOperationError,
-                      "Encoder has already been congfigured");
+    HandleError(DOMExceptionCode::kOperationError,
+                "Encoder has already been congfigured");
     return;
   }
 
@@ -267,8 +282,8 @@
     } else if (preference == "allow") {
       acc_pref = AccelerationPreference::kAllow;
     } else {
-      CallErrorCallback(DOMExceptionCode::kNotFoundError,
-                        "Unknown acceleration type");
+      HandleError(DOMExceptionCode::kNotFoundError,
+                  "Unknown acceleration type");
       return;
     }
   }
@@ -277,7 +292,7 @@
   std::string profile_str = config->profile().Utf8();
   auto codec_type = media::StringToVideoCodec(codec_str);
   if (codec_type == media::kUnknownVideoCodec) {
-    CallErrorCallback(DOMExceptionCode::kNotFoundError, "Unknown codec type");
+    HandleError(DOMExceptionCode::kNotFoundError, "Unknown codec type");
     return;
   }
 
@@ -286,8 +301,8 @@
   media::VideoCodecProfile profile = media::VIDEO_CODEC_PROFILE_UNKNOWN;
   if (codec_type == media::kCodecVP8) {
     if (acc_pref == AccelerationPreference::kRequire) {
-      CallErrorCallback(DOMExceptionCode::kNotFoundError,
-                        "Accelerated vp8 is not supported");
+      HandleError(DOMExceptionCode::kNotFoundError,
+                  "Accelerated vp8 is not supported");
       return;
     }
     media_encoder_ = CreateVpxVideoEncoder();
@@ -296,13 +311,12 @@
     uint8_t level = 0;
     media::VideoColorSpace color_space;
     if (!ParseNewStyleVp9CodecID(profile_str, &profile, &level, &color_space)) {
-      CallErrorCallback(DOMExceptionCode::kNotFoundError,
-                        "Invalid vp9 profile");
+      HandleError(DOMExceptionCode::kNotFoundError, "Invalid vp9 codec string");
       return;
     }
     if (acc_pref == AccelerationPreference::kRequire) {
-      CallErrorCallback(DOMExceptionCode::kNotFoundError,
-                        "Accelerated vp9 is not supported");
+      HandleError(DOMExceptionCode::kNotFoundError,
+                  "Accelerated vp9 is not supported");
       return;
     }
     media_encoder_ = CreateVpxVideoEncoder();
@@ -310,21 +324,19 @@
     codec_type = media::kCodecH264;
     uint8_t level = 0;
     if (!ParseAVCCodecId(profile_str, &profile, &level)) {
-      CallErrorCallback(DOMExceptionCode::kNotFoundError,
-                        "Invalid AVC profile");
+      HandleError(DOMExceptionCode::kNotFoundError, "Invalid AVC profile");
       return;
     }
     if (acc_pref == AccelerationPreference::kDeny) {
-      CallErrorCallback(DOMExceptionCode::kNotFoundError,
-                        "Software h264 is not supported yet");
+      HandleError(DOMExceptionCode::kNotFoundError,
+                  "Software h264 is not supported yet");
       return;
     }
     media_encoder_ = CreateAcceleratedVideoEncoder();
   }
 
   if (!media_encoder_) {
-    CallErrorCallback(DOMExceptionCode::kNotFoundError,
-                      "Unsupported codec type");
+    HandleError(DOMExceptionCode::kNotFoundError, "Unsupported codec type");
     return;
   }
 
@@ -339,22 +351,28 @@
       return;
     DCHECK_CALLED_ON_VALID_SEQUENCE(self->sequence_checker_);
     if (!status.is_ok()) {
-      self->media_encoder_.reset();
-      self->output_callback_.Clear();
-      self->error_callback_.Clear();
       std::string msg = "Encoder initialization error: " + status.message();
-      self->CallErrorCallback(DOMExceptionCode::kOperationError, msg.c_str());
+      self->HandleError(DOMExceptionCode::kOperationError, msg.c_str());
     }
     self->stall_request_processing_ = false;
     self->ProcessRequests();
   };
 
   media::VideoEncoder::Options options;
-  options.bitrate = config->bitrate();
+
+  // Required configuration.
   options.height = frame_size_.height();
   options.width = frame_size_.width();
   options.framerate = config->framerate();
+
+  // Optional configuration.
+  if (config->hasBitrate())
+    options.bitrate = config->bitrate();
+
+  // TODO(https://crbug.com/1116771): Let the encoder figure out its thread
+  // count (it knows better).
   options.threads = 1;
+
   stall_request_processing_ = true;
   media_encoder_->Initialize(profile, options, output_cb,
                              WTF::Bind(done_callback, WrapWeakPersistent(this),
@@ -377,7 +395,7 @@
       std::string msg = "Flushing error: " + status.message();
       auto* ex = MakeGarbageCollected<DOMException>(
           DOMExceptionCode::kOperationError, msg.c_str());
-      self->CallErrorCallback(ex);
+      self->HandleError(ex);
       req->resolver.Release()->Reject(ex);
     }
     self->stall_request_processing_ = false;
@@ -387,7 +405,7 @@
   if (!media_encoder_) {
     auto* ex = MakeGarbageCollected<DOMException>(
         DOMExceptionCode::kOperationError, "Encoder is not configured");
-    CallErrorCallback(ex);
+    HandleError(ex);
     request->resolver.Release()->Reject(ex);
     return;
   }
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.h b/third_party/blink/renderer/modules/webcodecs/video_encoder.h
index be357819..22affdb 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_encoder.h
+++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.h
@@ -41,6 +41,8 @@
   ~VideoEncoder() override;
 
   // video_encoder.idl implementation.
+  int32_t encodeQueueSize();
+
   void encode(VideoFrame* frame,
               const VideoEncoderEncodeOptions*,
               ExceptionState&);
@@ -76,8 +78,8 @@
   enum class AccelerationPreference { kAllow, kDeny, kRequire };
 
   void CallOutputCallback(EncodedVideoChunk* chunk);
-  void CallErrorCallback(DOMException* ex);
-  void CallErrorCallback(DOMExceptionCode code, const String& message);
+  void HandleError(DOMException* ex);
+  void HandleError(DOMExceptionCode code, const String& message);
   void EnqueueRequest(Request* request);
   void ProcessRequests();
   void ProcessEncode(Request* request);
@@ -93,6 +95,7 @@
   Member<V8VideoEncoderOutputCallback> output_callback_;
   Member<V8WebCodecsErrorCallback> error_callback_;
   HeapDeque<Member<Request>> requests_;
+  int32_t requested_encodes_ = 0;
 
   // Some kConfigure and kFlush requests can't be executed in parallel with
   // kEncode. This flag stops processing of new requests in the requests_ queue
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.idl b/third_party/blink/renderer/modules/webcodecs/video_encoder.idl
index a9b518b5..3ce6a0c1 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_encoder.idl
+++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.idl
@@ -11,6 +11,13 @@
     [CallWith=ScriptState, RaisesException]
     constructor(VideoEncoderInit init);
 
+    // The number of pending decode requests. This does not include requests that
+    // have been sent to the underlying codec.
+    //
+    // Applications can minimize underflow by enqueueing encode requests until
+    // |encodeQueueSize| is greater than a constant.
+    readonly attribute long encodeQueueSize;
+
     // Performs original configuration of the encoder.
     // Resolved after configuration is done. It should be called only
     // once per encoder instance, before calling any other methods.
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl b/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl
index d20d55d..0f6085a1 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl
+++ b/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl
@@ -14,11 +14,11 @@
 dictionary VideoEncoderConfig {
   required DOMString codec;
   DOMString profile;
-  VideoEncoderAccelerationPreference acceleration;
+  VideoEncoderAccelerationPreference acceleration = "allow";
 
   unsigned long long bitrate;
 
-  double framerate;
+  required double framerate;
 
   required unsigned long width;
   required unsigned long height;
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder_init.idl b/third_party/blink/renderer/modules/webcodecs/video_encoder_init.idl
index 1e4e69c..4155ad6 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_encoder_init.idl
+++ b/third_party/blink/renderer/modules/webcodecs/video_encoder_init.idl
@@ -9,5 +9,5 @@
   required VideoEncoderOutputCallback output;
 
   // Called when there is a decoding error.
-  WebCodecsErrorCallback error;
+  required WebCodecsErrorCallback error;
 };
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.cc b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
index 09986840..1789197 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_frame.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
@@ -97,17 +97,18 @@
                                       "No source was provided");
     return nullptr;
   }
-  gfx::Size size(source->width(), source->height());
-  gfx::Rect rect(size);
-  base::TimeDelta timestamp =
-      base::TimeDelta::FromMicroseconds(init->timestamp());
 
-  if (!source) {
+  if (!source->BitmapImage()) {
     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                       "Invalid source state");
     return nullptr;
   }
 
+  gfx::Size size(source->width(), source->height());
+  gfx::Rect rect(size);
+  base::TimeDelta timestamp =
+      base::TimeDelta::FromMicroseconds(init->timestamp());
+
   auto sk_image =
       source->BitmapImage()->PaintImageForCurrentFrame().GetSkImage();
   auto sk_color_space = sk_image->refColorSpace();
@@ -265,9 +266,22 @@
 }
 
 void VideoFrame::destroy() {
+  // TODO(tguilbert): Add a warning when destroying already destroyed frames?
   handle_->Invalidate();
 }
 
+VideoFrame* VideoFrame::clone(ExceptionState& exception_state) {
+  auto frame = handle_->frame();
+
+  if (!frame) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+                                      "Cannot clone destroyed VideoFrame.");
+    return nullptr;
+  }
+
+  return MakeGarbageCollected<VideoFrame>(std::move(frame));
+}
+
 scoped_refptr<VideoFrame::Handle> VideoFrame::handle() {
   return handle_;
 }
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.h b/third_party/blink/renderer/modules/webcodecs/video_frame.h
index b2afa96d..53c528f 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_frame.h
+++ b/third_party/blink/renderer/modules/webcodecs/video_frame.h
@@ -86,6 +86,11 @@
   // This effectively "destroys" all frames sharing the same Handle.
   void destroy();
 
+  // Creates a copy of |this|, with a new Handle, referencing the same
+  // media::VideoFrame. The cloned frame will not be destroyed when |this| is,
+  // and its lifetime should be independently managed.
+  VideoFrame* clone(ExceptionState&);
+
   ScriptPromise createImageBitmap(ScriptState*,
                                   const ImageBitmapOptions*,
                                   ExceptionState&);
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.idl b/third_party/blink/renderer/modules/webcodecs/video_frame.idl
index ce67db7..66dc371 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_frame.idl
+++ b/third_party/blink/renderer/modules/webcodecs/video_frame.idl
@@ -54,6 +54,11 @@
   // TODO(sandersd): Describe how a destroyed VideoFrame acts.
   void destroy();
 
+  // Creates of the copy of this VideoFrame, which needs to be independently
+  // destroyed.
+  [RaisesException]
+  VideoFrame clone();
+
   // Create an ImageBitmap from the crop region, scaled to the display size.
   // TODO(sandersd): Should use the global createImageBitmap() instead.
   [CallWith=ScriptState, RaisesException] Promise<ImageBitmap> createImageBitmap(
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame_init.idl b/third_party/blink/renderer/modules/webcodecs/video_frame_init.idl
index 2ddeb46..b1c7c21a 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_frame_init.idl
+++ b/third_party/blink/renderer/modules/webcodecs/video_frame_init.idl
@@ -5,6 +5,6 @@
 // https://github.com/WICG/web-codecs
 
 dictionary VideoFrameInit {
-  unsigned long long timestamp;  // microseconds
-  unsigned long long? duration;  // microseconds
+  required unsigned long long timestamp;  // microseconds
+  unsigned long long duration;  // microseconds
 };
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame_test.cc b/third_party/blink/renderer/modules/webcodecs/video_frame_test.cc
index b540a10..4d4041b 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_frame_test.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_frame_test.cc
@@ -4,6 +4,7 @@
 
 #include "media/base/video_frame.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/modules/webcodecs/video_frame.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
@@ -104,6 +105,42 @@
   EXPECT_EQ(media_frame, frame_with_new_handle->frame());
 }
 
+TEST_F(VideoFrameTest, ClonedFrame) {
+  V8TestingScope scope;
+
+  scoped_refptr<media::VideoFrame> media_frame =
+      CreateDefaultBlackMediaVideoFrame();
+  VideoFrame* blink_frame = CreateBlinkVideoFrame(media_frame);
+
+  VideoFrame* cloned_frame = blink_frame->clone(scope.GetExceptionState());
+
+  // The cloned frame should be referencing the same media::VideoFrame.
+  EXPECT_EQ(blink_frame->frame(), cloned_frame->frame());
+  EXPECT_EQ(media_frame, cloned_frame->frame());
+  EXPECT_FALSE(scope.GetExceptionState().HadException());
+
+  blink_frame->destroy();
+
+  // Destroying the original frame should not affect the cloned frame.
+  EXPECT_EQ(media_frame, cloned_frame->frame());
+}
+
+TEST_F(VideoFrameTest, CloningDestroyedFrame) {
+  V8TestingScope scope;
+
+  scoped_refptr<media::VideoFrame> media_frame =
+      CreateDefaultBlackMediaVideoFrame();
+  VideoFrame* blink_frame = CreateBlinkVideoFrame(media_frame);
+
+  blink_frame->destroy();
+
+  VideoFrame* cloned_frame = blink_frame->clone(scope.GetExceptionState());
+
+  // No frame should have been created, and there should be an exception.
+  EXPECT_EQ(nullptr, cloned_frame);
+  EXPECT_TRUE(scope.GetExceptionState().HadException());
+}
+
 }  // namespace
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl b/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
index dbce239..40e4002bb 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
@@ -13,7 +13,7 @@
 [
     Exposed(Window WebGPU, Worker WebGPU)
 ] interface GPUAdapter {
-    readonly attribute DOMString name;
+    [HighEntropy=Direct, MeasureAs=GPUAdapter_Name] readonly attribute DOMString name;
     [CallWith=ScriptState, SameObject] readonly attribute FrozenArray<GPUExtensionName> extensions;
 
     [CallWith=ScriptState] Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
diff --git a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
index 53a05526..1c824e1 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
@@ -120,14 +120,8 @@
       layer_state.Effect().HasBackdropEffect() ||
       !layer_state.Effect().Filter().IsEmpty());
 
-  auto safe_opaque_background_color =
-      paint_artifact->SafeOpaqueBackgroundColor(paint_chunks);
-  cc_picture_layer_->SetSafeOpaqueBackgroundColor(safe_opaque_background_color);
-  // TODO(masonfreed): We don't need to set the background color here; only the
-  // safe opaque background color matters. But making that change would require
-  // rebaselining 787 tests to remove the "background_color" property from the
-  // layer dumps.
-  cc_picture_layer_->SetBackgroundColor(safe_opaque_background_color);
+  paint_artifact->UpdateBackgroundColor(cc_picture_layer_.get(), paint_chunks);
+
   return cc_picture_layer_;
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index 562a1c8d..5865f8a 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -146,10 +146,18 @@
   return layers_as_json.Finalize();
 }
 
+static void UpdateLayerProperties(const GraphicsLayer& graphics_layer) {
+  cc::PictureLayer& cc_layer = graphics_layer.CcLayer();
+  const PaintArtifact& paint_artifact =
+      graphics_layer.GetPaintController().GetPaintArtifact();
+  paint_artifact.UpdateBackgroundColor(&cc_layer, paint_artifact.PaintChunks());
+}
+
 static scoped_refptr<cc::Layer> CcLayerForPaintChunk(
     const PaintArtifact& paint_artifact,
     const PaintChunk& paint_chunk,
-    const FloatPoint& pending_layer_offset) {
+    const FloatPoint& pending_layer_offset,
+    const HashSet<const GraphicsLayer*>& repainted_layers) {
   if (paint_chunk.size() != 1)
     return nullptr;
 
@@ -169,16 +177,17 @@
   cc::Layer* layer = nullptr;
   FloatPoint layer_offset;
   if (display_item.IsGraphicsLayerWrapper()) {
-    const auto& graphics_layer_display_item =
-        static_cast<const GraphicsLayerDisplayItem&>(display_item);
-    const auto& graphics_layer = graphics_layer_display_item.GetGraphicsLayer();
+    const GraphicsLayer& graphics_layer =
+        static_cast<const GraphicsLayerDisplayItem&>(display_item)
+            .GetGraphicsLayer();
     if (graphics_layer.ShouldCreateLayersAfterPaint()) {
       DCHECK(RuntimeEnabledFeatures::CompositeSVGEnabled());
       return nullptr;
     }
     layer = &graphics_layer.CcLayer();
-    layer_offset = FloatPoint(graphics_layer_display_item.GetGraphicsLayer()
-                                  .GetOffsetFromTransformNode());
+    layer_offset = FloatPoint(graphics_layer.GetOffsetFromTransformNode());
+    if (repainted_layers.Contains(&graphics_layer))
+      UpdateLayerProperties(graphics_layer);
   } else {
     const auto& foreign_layer_display_item =
         static_cast<const ForeignLayerDisplayItem&>(display_item);
@@ -313,7 +322,8 @@
     const PendingLayer& pending_layer,
     Vector<std::unique_ptr<ContentLayerClientImpl>>& new_content_layer_clients,
     Vector<scoped_refptr<cc::Layer>>& new_scroll_hit_test_layers,
-    Vector<scoped_refptr<cc::ScrollbarLayerBase>>& new_scrollbar_layers) {
+    Vector<scoped_refptr<cc::ScrollbarLayerBase>>& new_scrollbar_layers,
+    const HashSet<const GraphicsLayer*>& repainted_layers) {
   auto paint_chunks = pending_layer.paint_artifact->GetPaintChunkSubset(
       pending_layer.paint_chunk_indices);
   DCHECK(paint_chunks.size());
@@ -324,7 +334,8 @@
   // just return its cc::Layer.
   if ((cc_layer = CcLayerForPaintChunk(
            *pending_layer.paint_artifact, first_paint_chunk,
-           pending_layer.offset_of_decomposited_transforms))) {
+           pending_layer.offset_of_decomposited_transforms,
+           repainted_layers))) {
     DCHECK_EQ(paint_chunks.size(), 1u);
     return cc_layer;
   }
@@ -1237,11 +1248,22 @@
 void PaintArtifactCompositor::Update(
     scoped_refptr<const PaintArtifact> paint_artifact,
     const ViewportProperties& viewport_properties,
-    const Vector<const TransformPaintPropertyNode*>& scroll_translation_nodes) {
+    const Vector<const TransformPaintPropertyNode*>& scroll_translation_nodes,
+    const HashSet<const GraphicsLayer*>& repainted_layers) {
+  DCHECK(NeedsUpdate() || repainted_layers.size());
   DCHECK(scroll_translation_nodes.IsEmpty() ||
          RuntimeEnabledFeatures::ScrollUnificationEnabled());
-  DCHECK(NeedsUpdate());
   DCHECK(root_layer_);
+
+  if (!NeedsUpdate()) {
+    // It's possible to get here when there are no paint property updates that
+    // necessitate a compositing update (e.g., a background color changes). In
+    // that case, we just update non-compositing-related cc::Layer properties
+    // for layers that have been repainted, and do nothing else.
+    UpdateRepaintedLayerProperties(paint_artifact, repainted_layers);
+    return;
+  }
+
   // The tree will be null after detaching and this update can be ignored.
   // See: WebViewImpl::detachPaintArtifactCompositor().
   cc::LayerTreeHost* host = root_layer_->layer_tree_host();
@@ -1303,7 +1325,7 @@
 
     scoped_refptr<cc::Layer> layer = CompositedLayerForPendingLayer(
         pending_layer, new_content_layer_clients, new_scroll_hit_test_layers,
-        new_scrollbar_layers);
+        new_scrollbar_layers, repainted_layers);
 
     // In Pre-CompositeAfterPaint, touch action rects and non-fast scrollable
     // regions are updated through ScrollingCoordinator.
@@ -1428,6 +1450,29 @@
 #endif
 }
 
+void PaintArtifactCompositor::UpdateRepaintedLayerProperties(
+    scoped_refptr<const PaintArtifact> paint_artifact,
+    const HashSet<const GraphicsLayer*>& repainted_layers) const {
+  for (const auto& pending_layer : pending_layers_) {
+    auto paint_chunks =
+        paint_artifact->GetPaintChunkSubset(pending_layer.paint_chunk_indices);
+    DCHECK(paint_chunks.size());
+    const PaintChunk& paint_chunk = paint_chunks[0];
+    if (paint_chunk.size() != 1)
+      continue;
+    const auto& display_item =
+        paint_artifact->GetDisplayItemList()[paint_chunk.begin_index];
+    if (!display_item.IsGraphicsLayerWrapper())
+      continue;
+    const GraphicsLayer& graphics_layer =
+        static_cast<const GraphicsLayerDisplayItem&>(display_item)
+            .GetGraphicsLayer();
+    if (repainted_layers.Contains(&graphics_layer)) {
+      UpdateLayerProperties(graphics_layer);
+    }
+  }
+}
+
 bool PaintArtifactCompositor::CanDirectlyUpdateProperties() const {
   // Don't try to retrieve property trees if we need an update. The full
   // update will update all of the nodes, so a direct update doesn't need to
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
index cd528b3..c37f319 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
@@ -142,10 +142,11 @@
   // noncomposited nodes, and is used for Scroll Unification to generate scroll
   // nodes for noncomposited scrollers to complete the compositor's scroll
   // property tree.
-  void Update(scoped_refptr<const PaintArtifact>,
-              const ViewportProperties& viewport_properties,
-              const Vector<const TransformPaintPropertyNode*>&
-                  scroll_translation_nodes);
+  void Update(
+      scoped_refptr<const PaintArtifact>,
+      const ViewportProperties& viewport_properties,
+      const Vector<const TransformPaintPropertyNode*>& scroll_translation_nodes,
+      const HashSet<const GraphicsLayer*>& repainted_layers);
 
   bool DirectlyUpdateCompositedOpacityValue(const EffectPaintPropertyNode&);
   bool DirectlyUpdateScrollOffsetTransform(const TransformPaintPropertyNode&);
@@ -278,6 +279,10 @@
     } compositing_type;
   };
 
+  void UpdateRepaintedLayerProperties(
+      scoped_refptr<const PaintArtifact> paint_artifact,
+      const HashSet<const GraphicsLayer*>& repainted_layers) const;
+
   void DecompositeTransforms(const PaintArtifact&);
 
   // Collects the PaintChunks into groups which will end up in the same
@@ -316,7 +321,8 @@
       Vector<std::unique_ptr<ContentLayerClientImpl>>&
           new_content_layer_clients,
       Vector<scoped_refptr<cc::Layer>>& new_scroll_hit_test_layers,
-      Vector<scoped_refptr<cc::ScrollbarLayerBase>>& new_scrollbar_layers);
+      Vector<scoped_refptr<cc::ScrollbarLayerBase>>& new_scrollbar_layers,
+      const HashSet<const GraphicsLayer*>& repainted_layers);
 
   bool PropertyTreeStateChanged(const PropertyTreeState&) const;
 
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
index 50cd92d..a940869 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -25,6 +25,7 @@
 #include "cc/trees/transform_node.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
 #include "third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h"
 #include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
@@ -148,9 +149,11 @@
       const ViewportProperties& viewport_properties = ViewportProperties(),
       const WTF::Vector<const TransformPaintPropertyNode*>&
           scroll_translation_nodes = {}) {
+    HashSet<const GraphicsLayer*> repainted_layers;
     paint_artifact_compositor_->SetNeedsUpdate();
     paint_artifact_compositor_->Update(artifact, viewport_properties,
-                                       scroll_translation_nodes);
+                                       scroll_translation_nodes,
+                                       repainted_layers);
     layer_tree_->layer_tree_host()->LayoutAndUpdateLayers();
   }
 
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index 38e5344..3afa9131 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -260,11 +260,13 @@
   return previous_interest_rect_;
 }
 
-bool GraphicsLayer::PaintRecursively() {
-  bool painted = false;
-  ForAllPaintingGraphicsLayers(
-      *this, [&painted](GraphicsLayer& layer) { painted |= layer.Paint(); });
-  return painted;
+void GraphicsLayer::PaintRecursively(
+    HashSet<const GraphicsLayer*>& repainted_layers) {
+  ForAllPaintingGraphicsLayers(*this,
+                               [&repainted_layers](GraphicsLayer& layer) {
+                                 if (layer.Paint())
+                                   repainted_layers.insert(&layer);
+                               });
 }
 
 bool GraphicsLayer::Paint() {
@@ -282,7 +284,6 @@
   if (PaintWithoutCommit()) {
     GetPaintController().CommitNewDisplayItems();
     UpdateShouldCreateLayersAfterPaint();
-    UpdateSafeOpaqueBackgroundColor();
   } else if (!needs_check_raster_invalidation_) {
     return false;
   }
@@ -322,14 +323,6 @@
   return true;
 }
 
-void GraphicsLayer::UpdateSafeOpaqueBackgroundColor() {
-  if (!DrawsContent())
-    return;
-  CcLayer().SetSafeOpaqueBackgroundColor(
-      GetPaintController().GetPaintArtifact().SafeOpaqueBackgroundColor(
-          GetPaintController().GetPaintArtifact().PaintChunks()));
-}
-
 void GraphicsLayer::UpdateShouldCreateLayersAfterPaint() {
   should_create_layers_after_paint_ = false;
   if (!RuntimeEnabledFeatures::CompositeSVGEnabled())
@@ -546,12 +539,9 @@
   UpdateLayerIsDrawable();
 }
 
-RGBA32 GraphicsLayer::BackgroundColor() const {
-  return CcLayer().background_color();
-}
-
-void GraphicsLayer::SetBackgroundColor(RGBA32 color) {
-  CcLayer().SetBackgroundColor(color);
+void GraphicsLayer::SetContentsLayerBackgroundColor(Color color) {
+  if (contents_layer_)
+    contents_layer_->SetBackgroundColor(color.Rgb());
 }
 
 bool GraphicsLayer::ContentsOpaque() const {
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h
index 6725517..d4b3630c1 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -137,11 +137,7 @@
   bool ContentsAreVisible() const { return contents_visible_; }
   void SetContentsVisible(bool);
 
-  // For special cases, e.g. drawing missing tiles on Android.
-  // The compositor should never paint this color in normal cases because the
-  // Layer will paint the background by itself.
-  RGBA32 BackgroundColor() const;
-  void SetBackgroundColor(RGBA32);
+  void SetContentsLayerBackgroundColor(Color color);
 
   // Opaque means that we know the layer contents have no alpha.
   bool ContentsOpaque() const;
@@ -184,8 +180,7 @@
                                PaintInvalidationReason);
 
   IntRect InterestRect();
-  // Returns true if this or any descendant is repainted.
-  bool PaintRecursively();
+  void PaintRecursively(HashSet<const GraphicsLayer*>& repainted_layers);
   // Returns true if this layer is repainted.
   bool Paint();
 
@@ -251,7 +246,6 @@
   size_t GetApproximateUnsharedMemoryUsage() const final;
 
   void UpdateShouldCreateLayersAfterPaint();
-  void UpdateSafeOpaqueBackgroundColor();
 
   // Returns true if PaintController::PaintArtifact() changed and needs commit.
   bool PaintWithoutCommit(const IntRect* interest_rect = nullptr);
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc b/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
index 387e11f..31eab3d 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
@@ -131,7 +131,8 @@
   EXPECT_TRUE(transform2->Changed(PaintPropertyChangeType::kChangedOnlyValues,
                                   transform_root));
   layers_.graphics_layer_client().SetNeedsRepaint(true);
-  layers_.graphics_layer().PaintRecursively();
+  HashSet<const GraphicsLayer*> repainted_layers;
+  layers_.graphics_layer().PaintRecursively(repainted_layers);
   layers_.graphics_layer().GetPaintController().FinishCycle();
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
index 035cb7d2..0fb75f0 100644
--- a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
@@ -78,7 +78,7 @@
   return BitmapsEqual(std::move(record), std::move(other_record), bounds);
 }
 
-SkColor DrawingDisplayItem::BackgroundColor() const {
+SkColor DrawingDisplayItem::BackgroundColor(uint64_t& area) const {
   if (GetType() != DisplayItem::kBoxDecorationBackground &&
       GetType() != DisplayItem::kDocumentBackground &&
       GetType() != DisplayItem::kDocumentRootBackdrop)
@@ -89,14 +89,30 @@
 
   for (cc::PaintOpBuffer::Iterator it(record_.get()); it; ++it) {
     const auto* op = *it;
-    if (op->GetType() == cc::PaintOpType::DrawRect ||
-        op->GetType() == cc::PaintOpType::DrawRRect) {
-      const auto& flags = static_cast<const cc::PaintOpWithFlags*>(op)->flags;
-      // Skip op with looper or shader which may modify the color.
-      if (!flags.getLooper() && !flags.getShader() &&
-          flags.getStyle() == cc::PaintFlags::kFill_Style)
-        return flags.getColor();
+    if (!op->IsPaintOpWithFlags())
+      continue;
+    const auto& flags = static_cast<const cc::PaintOpWithFlags*>(op)->flags;
+    // Skip op with looper or shader which may modify the color.
+    if (flags.getLooper() || flags.getShader() ||
+        flags.getStyle() != cc::PaintFlags::kFill_Style) {
+      continue;
     }
+    SkRect item_rect;
+    switch (op->GetType()) {
+      case cc::PaintOpType::DrawRect:
+        item_rect = static_cast<const cc::DrawRectOp*>(op)->rect;
+        break;
+      case cc::PaintOpType::DrawIRect:
+        item_rect = SkRect::Make(static_cast<const cc::DrawIRectOp*>(op)->rect);
+        break;
+      case cc::PaintOpType::DrawRRect:
+        item_rect = static_cast<const cc::DrawRRectOp*>(op)->rrect.rect();
+        break;
+      default:
+        continue;
+    }
+    area = static_cast<uint64_t>(item_rect.width() * item_rect.height());
+    return flags.getColor();
   }
   return SK_ColorTRANSPARENT;
 }
diff --git a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
index 2c8cb92..1513a409 100644
--- a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
@@ -51,7 +51,7 @@
     known_to_be_opaque_ = true;
   }
 
-  SkColor BackgroundColor() const;
+  SkColor BackgroundColor(uint64_t& area) const;
 
  private:
   bool CalculateKnownToBeOpaque(const PaintRecord*) const;
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
index 82c60942..69d2b62 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
 
+#include "cc/layers/layer.h"
 #include "cc/paint/display_item_list.h"
 #include "third_party/blink/renderer/platform/geometry/int_rect.h"
 #include "third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h"
@@ -94,16 +95,38 @@
       ->ReleaseAsRecord();
 }
 
-SkColor PaintArtifact::SafeOpaqueBackgroundColor(
-    const PaintChunkSubset& chunks) const {
-  // Find the background color from the first drawing display item.
-  for (const auto& chunk : chunks) {
-    for (const auto& item : display_item_list_.ItemsInPaintChunk(chunk)) {
-      if (item.IsDrawing() && item.DrawsContent())
-        return static_cast<const DrawingDisplayItem&>(item).BackgroundColor();
+// The heuristic for picking a checkerboarding color works as follows:
+//   - During paint, PaintChunker will look for background color display items,
+//     and annotates the chunk with the index of the display item that paints
+//     the largest area background color (ties are broken by selecting the
+//     display item that paints last).
+//   - After layer allocation, the paint chunks assigned to a layer are
+//     examined for a background color annotation. The chunk with the largest
+//     background color annotation is selected.
+//   - If the area of the selected background color is at least half the size
+//     of the layer, then it is set as the layer's background color.
+//   - The same color is used for the layer's safe opaque background color, but
+//     without the size requirement, as safe opaque background color should
+//     always get a value if possible.
+void PaintArtifact::UpdateBackgroundColor(
+    cc::Layer* layer,
+    const PaintChunkSubset& paint_chunks) const {
+  SkColor color = SK_ColorTRANSPARENT;
+  uint64_t area = 0;
+  for (const auto& chunk : paint_chunks) {
+    if (chunk.background_color != Color::kTransparent &&
+        chunk.background_color_area >= area) {
+      color = chunk.background_color.Rgb();
+      area = chunk.background_color_area;
     }
   }
-  return SK_ColorTRANSPARENT;
+
+  layer->SetSafeOpaqueBackgroundColor(color);
+
+  uint64_t layer_area = layer->bounds().width() * layer->bounds().height();
+  if (area < layer_area / 2)
+    color = SK_ColorTRANSPARENT;
+  layer->SetBackgroundColor(color);
 }
 
 void PaintArtifact::FinishCycle() {
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
index 361b5197..64aa128c 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
@@ -15,6 +15,7 @@
 #include "third_party/skia/include/core/SkColor.h"
 
 namespace cc {
+class Layer;
 class PaintCanvas;
 }
 
@@ -83,13 +84,14 @@
   sk_sp<PaintRecord> GetPaintRecord(const PropertyTreeState& replay_state,
                                     const IntPoint& offset = IntPoint()) const;
 
-  SkColor SafeOpaqueBackgroundColor(const PaintChunkSubset&) const;
-
   // Called when the caller finishes updating a full document life cycle.
   // Will cleanup data (e.g. raster invalidations) that will no longer be used
   // for the next cycle, and update status to be ready for the next cycle.
   void FinishCycle();
 
+  void UpdateBackgroundColor(cc::Layer* layer,
+                             const PaintChunkSubset& paint_chunks) const;
+
  private:
   PaintArtifact();
   PaintArtifact(DisplayItemList, Vector<PaintChunk>);
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc b/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
index dbd2fb2d..8a2734c 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
@@ -13,6 +13,8 @@
 struct SameSizeAsPaintChunk {
   wtf_size_t begin_index;
   wtf_size_t end_index;
+  Color background_color;
+  uint64_t background_color_area;
   PaintChunk::Id id;
   PropertyTreeState properties;
   IntRect bounds;
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h b/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
index 9aa3793..8559f92 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
@@ -34,6 +34,8 @@
              const PropertyTreeStateOrAlias& props)
       : begin_index(begin),
         end_index(end),
+        background_color(Color::kTransparent),
+        background_color_area(0u),
         id(id),
         properties(props),
         known_to_be_opaque(false),
@@ -45,6 +47,8 @@
   PaintChunk(wtf_size_t begin, PaintChunk&& other)
       : begin_index(begin),
         end_index(begin + other.size()),
+        background_color(other.background_color),
+        background_color_area(other.background_color_area),
         id(other.id),
         properties(other.properties),
         hit_test_data(std::move(other.hit_test_data)),
@@ -104,6 +108,13 @@
   // |endIndex - beginIndex| drawings in the chunk.
   wtf_size_t end_index;
 
+  // Color to use for checkerboarding, derived from display item's in this
+  // chunk; or Color::kTransparent if no such display item exists.
+  Color background_color;
+
+  // The area that is painted by the paint op that defines background_color.
+  uint64_t background_color_area;
+
   // Identifier of this chunk. It should be unique if |is_cacheable| is true.
   // This is used to match a new chunk to a cached old chunk to track changes
   // of chunk contents, so the id should be stable across document cycles.
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc b/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc
index 51ef1ea0..f9bff6a4 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc
@@ -18,7 +18,8 @@
 bool PaintChunker::IsInInitialState() const {
   if (current_properties_ != PropertyTreeState::Uninitialized())
     return false;
-
+  DCHECK_EQ(candidate_background_color_.Rgb(), Color::kTransparent);
+  DCHECK_EQ(candidate_background_area_, 0u);
   DCHECK(chunks_.IsEmpty());
   return true;
 }
@@ -40,7 +41,7 @@
 }
 
 void PaintChunker::AppendByMoving(PaintChunk&& chunk) {
-  UpdateLastChunkKnownToBeOpaque();
+  FinalizeLastChunkProperties();
   wtf_size_t next_chunk_begin_index =
       chunks_.IsEmpty() ? 0 : LastChunk().end_index;
   chunks_.emplace_back(next_chunk_begin_index, std::move(chunk));
@@ -58,7 +59,7 @@
   if (WillForceNewChunk() || current_properties_ != LastChunk().properties) {
     if (!next_chunk_id_)
       next_chunk_id_.emplace(id);
-    UpdateLastChunkKnownToBeOpaque();
+    FinalizeLastChunkProperties();
     wtf_size_t begin = chunks_.IsEmpty() ? 0 : LastChunk().end_index;
     chunks_.emplace_back(begin, begin, *next_chunk_id_, current_properties_);
     next_chunk_id_ = base::nullopt;
@@ -82,6 +83,15 @@
   if (item.DrawsContent())
     chunk.drawable_bounds.Unite(item.VisualRect());
 
+  // If this paints the background and it's larger than our current candidate,
+  // set the candidate to be this item.
+  if (item.IsDrawing() && item.DrawsContent()) {
+    uint64_t item_area;
+    Color item_color =
+        static_cast<const DrawingDisplayItem&>(item).BackgroundColor(item_area);
+    ProcessBackgroundColorCandidate(chunk.id, item_color, item_area);
+  }
+
   constexpr wtf_size_t kMaxRegionComplexity = 10;
   if (item.IsDrawing() &&
       static_cast<const DrawingDisplayItem&>(item).KnownToBeOpaque() &&
@@ -153,17 +163,36 @@
   SetForceNewChunk(true);
 }
 
-void PaintChunker::UpdateLastChunkKnownToBeOpaque() {
+void PaintChunker::ProcessBackgroundColorCandidate(const PaintChunk::Id& id,
+                                                   Color color,
+                                                   uint64_t area) {
+  EnsureCurrentChunk(id);
+  if (color != Color::kTransparent &&
+      (candidate_background_color_ == Color::kTransparent ||
+       (area >= candidate_background_area_))) {
+    candidate_background_color_ = color;
+    candidate_background_area_ = area;
+  }
+}
+
+void PaintChunker::FinalizeLastChunkProperties() {
   if (chunks_.IsEmpty() || LastChunk().is_moved_from_cached_subsequence)
     return;
 
   LastChunk().known_to_be_opaque =
       last_chunk_known_to_be_opaque_region_.Contains(LastChunk().bounds);
   last_chunk_known_to_be_opaque_region_ = Region();
+
+  if (candidate_background_color_ != Color::kTransparent) {
+    LastChunk().background_color = candidate_background_color_;
+    LastChunk().background_color_area = candidate_background_area_;
+  }
+  candidate_background_color_ = Color::kTransparent;
+  candidate_background_area_ = 0u;
 }
 
 Vector<PaintChunk> PaintChunker::ReleasePaintChunks() {
-  UpdateLastChunkKnownToBeOpaque();
+  FinalizeLastChunkProperties();
   next_chunk_id_ = base::nullopt;
   current_properties_ = PropertyTreeState::Uninitialized();
   chunks_.ShrinkToFit();
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h b/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h
index 4cbab899..297a979 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h
@@ -72,13 +72,17 @@
       const TransformPaintPropertyNode* scroll_translation,
       const IntRect&);
 
+  void ProcessBackgroundColorCandidate(const PaintChunk::Id& id,
+                                       Color color,
+                                       uint64_t area);
+
   // Releases the generated paint chunk list and raster invalidations and
   // resets the state of this object.
   Vector<PaintChunk> ReleasePaintChunks();
 
  private:
   PaintChunk& EnsureCurrentChunk(const PaintChunk::Id&);
-  void UpdateLastChunkKnownToBeOpaque();
+  void FinalizeLastChunkProperties();
 
   Vector<PaintChunk> chunks_;
 
@@ -99,6 +103,9 @@
   // before and after subsequences by calling ForceNewChunk().
   bool force_new_chunk_;
 
+  Color candidate_background_color_ = Color::kTransparent;
+  uint64_t candidate_background_area_ = 0;
+
   DISALLOW_COPY_AND_ASSIGN(PaintChunker);
 };
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
index 28a0ba5..aac557b 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
@@ -116,6 +116,14 @@
     new_paint_chunks_.CreateScrollHitTestChunk(id, scroll_translation, rect);
   }
 
+  void SetPossibleBackgroundColor(const DisplayItemClient& client,
+                                  Color color,
+                                  uint64_t area) {
+    PaintChunk::Id id = {client, DisplayItem::kBoxDecorationBackground,
+                         current_fragment_};
+    new_paint_chunks_.ProcessBackgroundColorCandidate(id, color, area);
+  }
+
   template <typename DisplayItemClass, typename... Args>
   void CreateAndAppend(Args&&... args) {
     static_assert(WTF::IsSubclass<DisplayItemClass, DisplayItem>::value,
diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc
index bf1f48be..26868d53 100644
--- a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc
+++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc
@@ -61,10 +61,8 @@
   if (image_extension == "bmp")
     return cc::ImageType::kBMP;
 #if BUILDFLAG(ENABLE_AV1_DECODER)
-  if (base::FeatureList::IsEnabled(features::kAVIF) &&
-      image_extension == "avif") {
+  if (image_extension == "avif")
     return cc::ImageType::kAVIF;
-  }
 #endif
   return cc::ImageType::kInvalid;
 }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 96c6adf..0df20be 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1396,10 +1396,7 @@
 crbug.com/626703 external/wpt/css/css-text/text-transform/math/text-transform-math-sans-serif-bold-italic-001.tentative.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/text-transform/math/text-transform-math-sans-serif-001.tentative.html [ Failure ]
 crbug.com/1043295 [ Fuchsia ] virtual/font-access/http/tests/font-access/font-access-window-enumeration.html [ Skip ]
-crbug.com/1043295 [ Fuchsia ] virtual/font-access/http/tests/font-access/font-access-window-getTables.html [ Skip ]
-crbug.com/1043295 [ Fuchsia ] virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html [ Skip ]
 crbug.com/1043295 [ Fuchsia ] virtual/font-access/http/tests/font-access/font-access-window-blob.html [ Skip ]
-crbug.com/1087671 [ Mac ] virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html [ Skip ]
 
 # ====== Style team owned tests from here ======
 
@@ -2725,15 +2722,9 @@
 crbug.com/626703 [ Linux ] external/wpt/css/css-ui/appearance-button-002.tentative.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/css/css-ui/appearance-button-002.tentative.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/css/css-ui/appearance-button-002.tentative.html [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/css/css-sizing/range-percent-intrinsic-size-2a.html [ Failure ]
-crbug.com/626703 [ Mac ] external/wpt/css/css-sizing/range-percent-intrinsic-size-2a.html [ Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-sizing/range-percent-intrinsic-size-2a.html [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/css/css-ui/webkit-appearance-button-002.tentative.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/css/css-ui/webkit-appearance-button-002.tentative.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/css/css-ui/webkit-appearance-button-002.tentative.html [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/css/css-sizing/range-percent-intrinsic-size-2.html [ Failure ]
-crbug.com/626703 [ Mac ] external/wpt/css/css-sizing/range-percent-intrinsic-size-2.html [ Failure ]
-crbug.com/626703 [ Win ] external/wpt/css/css-sizing/range-percent-intrinsic-size-2.html [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/css/css-color/t422-rgba-a0.6-a.xht [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/css/css-color/t32-opacity-basic-0.6-a.xht [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/css/css-color/t32-opacity-basic-0.6-a.xht [ Failure ]
@@ -6756,3 +6747,6 @@
 crbug.com/1095540 virtual/threaded-prefer-compositing/fast/scrolling/resize-corner-tracking-touch.html [ Pass Failure ]
 crbug.com/1113521 [ Mac ] fast/events/mouse-cursor-image-set.html [ Pass Crash ]
 crbug.com/1046784 http/tests/devtools/network/network-content-replacement-xhr.js [ Pass Failure ]
+
+# Sheriff 2020-08-14
+crbug.com/1116681 [ Mac ] fast/frames/iframe-scaling-with-scroll.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/compositing/absolute-inside-out-of-view-fixed-expected.txt b/third_party/blink/web_tests/compositing/absolute-inside-out-of-view-fixed-expected.txt
index 2c479bb..f353a5d 100644
--- a/third_party/blink/web_tests/compositing/absolute-inside-out-of-view-fixed-expected.txt
+++ b/third_party/blink/web_tests/compositing/absolute-inside-out-of-view-fixed-expected.txt
@@ -10,7 +10,8 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='fixed'",
       "bounds": [100, 100],
-      "contentsOpaque": true
+      "contentsOpaque": true,
+      "backgroundColor": "#008000"
     },
     {
       "name": "ContentsLayer for Vertical Scrollbar Layer",
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/body-background-painted-expected.txt b/third_party/blink/web_tests/compositing/contents-opaque/body-background-painted-expected.txt
index 89433a4..24f2823 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/body-background-painted-expected.txt
+++ b/third_party/blink/web_tests/compositing/contents-opaque/body-background-painted-expected.txt
@@ -8,8 +8,7 @@
     },
     {
       "name": "LayoutNGBlockFlow HTML",
-      "bounds": [800, 600],
-      "backgroundColor": "#D3D3D3"
+      "bounds": [800, 600]
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='underbody'",
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/filter-expected.txt b/third_party/blink/web_tests/compositing/contents-opaque/filter-expected.txt
index 16b5c3b..75ad3745 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/filter-expected.txt
+++ b/third_party/blink/web_tests/compositing/contents-opaque/filter-expected.txt
@@ -15,6 +15,7 @@
     {
       "name": "LayoutNGBlockFlow DIV class='composited container-box'",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "transform": 2
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-child-expected.txt b/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-child-expected.txt
index 48287d7..e5cee28d 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-child-expected.txt
+++ b/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-child-expected.txt
@@ -9,7 +9,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='caption'",
       "bounds": [200, 100],
-      "backgroundColor": "#008000",
+      "backgroundColor": "#0000FF",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-text-expected.txt b/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-text-expected.txt
index 64989bc..83dc3ef8 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-text-expected.txt
+++ b/third_party/blink/web_tests/compositing/contents-opaque/hidden-with-visible-text-expected.txt
@@ -10,7 +10,6 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='caption'",
       "bounds": [200, 100],
-      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt b/third_party/blink/web_tests/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
index 7fcfc716..7d2f2bf3 100644
--- a/third_party/blink/web_tests/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
+++ b/third_party/blink/web_tests/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
@@ -11,7 +11,7 @@
       "position": [-30, -30],
       "bounds": [160, 160],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#0000FF",
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/draws-content/canvas-background-layer-expected.txt b/third_party/blink/web_tests/compositing/draws-content/canvas-background-layer-expected.txt
index a4edba5..6bea71e66 100644
--- a/third_party/blink/web_tests/compositing/draws-content/canvas-background-layer-expected.txt
+++ b/third_party/blink/web_tests/compositing/draws-content/canvas-background-layer-expected.txt
@@ -10,7 +10,6 @@
       "name": "LayoutHTMLCanvas CANVAS id='canvas-simple'",
       "bounds": [50, 50],
       "contentsOpaque": true,
-      "backgroundColor": "#008000",
       "transform": 1
     },
     {
@@ -23,7 +22,6 @@
     {
       "name": "LayoutHTMLCanvas CANVAS id='canvas-transparent-background'",
       "bounds": [50, 50],
-      "backgroundColor": "#00FF0080",
       "transform": 2
     },
     {
@@ -71,7 +69,6 @@
       "name": "LayoutHTMLCanvas CANVAS id='canvas-opaque'",
       "bounds": [50, 50],
       "contentsOpaque": true,
-      "backgroundColor": "#008000",
       "transform": 6
     },
     {
diff --git a/third_party/blink/web_tests/compositing/draws-content/webgl-background-layer-expected.txt b/third_party/blink/web_tests/compositing/draws-content/webgl-background-layer-expected.txt
index 621cdb15..a9c1e652 100644
--- a/third_party/blink/web_tests/compositing/draws-content/webgl-background-layer-expected.txt
+++ b/third_party/blink/web_tests/compositing/draws-content/webgl-background-layer-expected.txt
@@ -10,7 +10,6 @@
       "name": "LayoutHTMLCanvas CANVAS id='canvas-simple'",
       "bounds": [50, 50],
       "contentsOpaque": true,
-      "backgroundColor": "#008000",
       "transform": 1
     },
     {
@@ -58,7 +57,6 @@
     {
       "name": "LayoutHTMLCanvas CANVAS id='canvas-transparent-background'",
       "bounds": [50, 50],
-      "backgroundColor": "#00FF0080",
       "transform": 5
     },
     {
diff --git a/third_party/blink/web_tests/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt b/third_party/blink/web_tests/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt
index cdec5f9..77acef1 100644
--- a/third_party/blink/web_tests/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt
+++ b/third_party/blink/web_tests/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='software')",
       "position": [-105, -105],
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt b/third_party/blink/web_tests/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
index 6c8343cf..ce951477 100644
--- a/third_party/blink/web_tests/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
+++ b/third_party/blink/web_tests/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
@@ -10,7 +10,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-parent'",
       "position": [-100, -100],
       "bounds": [200, 200],
-      "backgroundColor": "#000000",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt b/third_party/blink/web_tests/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt
index f9898ed..97f9f2cf 100644
--- a/third_party/blink/web_tests/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt
+++ b/third_party/blink/web_tests/compositing/force-compositing-mode/overflow-iframe-enter-compositing-expected.txt
@@ -9,6 +9,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [508, 516],
+      "backgroundColor": "#0000FF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt b/third_party/blink/web_tests/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt
index f9898ed..97f9f2cf 100644
--- a/third_party/blink/web_tests/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt
+++ b/third_party/blink/web_tests/compositing/force-compositing-mode/overflow-iframe-layer-expected.txt
@@ -9,6 +9,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [508, 516],
+      "backgroundColor": "#0000FF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/geometry/bounds-clipped-composited-child-expected.txt b/third_party/blink/web_tests/compositing/geometry/bounds-clipped-composited-child-expected.txt
index 2b1f0f9..e5f427a 100644
--- a/third_party/blink/web_tests/compositing/geometry/bounds-clipped-composited-child-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/bounds-clipped-composited-child-expected.txt
@@ -9,6 +9,7 @@
     {
       "name": "LayoutNGBlockFlow DIV class='container'",
       "bounds": [200, 100],
+      "backgroundColor": "#008000",
       "transform": 2
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt
index 82e2ff1..b70e105 100644
--- a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt
@@ -16,6 +16,7 @@
       "position": [10, 10],
       "bounds": [50, 50],
       "contentsOpaque": true,
+      "backgroundColor": "#000000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-expected.txt b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-expected.txt
index ce4fafe..d102e41 100644
--- a/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/bounds-ignores-hidden-expected.txt
@@ -10,7 +10,8 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited'",
       "position": [10, 10],
       "bounds": [50, 50],
-      "contentsOpaque": true
+      "contentsOpaque": true,
+      "backgroundColor": "#000000"
     },
     {
       "name": "ContentsLayer for Horizontal Scrollbar Layer",
diff --git a/third_party/blink/web_tests/compositing/geometry/clip-expected.txt b/third_party/blink/web_tests/compositing/geometry/clip-expected.txt
index 985efdd..5e388dd 100644
--- a/third_party/blink/web_tests/compositing/geometry/clip-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/clip-expected.txt
@@ -12,7 +12,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box'",
       "position": [-5, -5],
       "bounds": [110, 110],
-      "backgroundColor": "#808080",
+      "backgroundColor": "#00000033",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt b/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt
index 4ecd57ef..5784f97 100644
--- a/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt
@@ -13,7 +13,7 @@
       "position": [5, 15],
       "bounds": [90, 80],
       "contentsOpaque": true,
-      "backgroundColor": "#808080",
+      "backgroundColor": "#00000033",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt b/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt
index 1e39f033..a511c212 100644
--- a/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box'",
       "position": [-5, -5],
       "bounds": [110, 110],
-      "backgroundColor": "#808080",
+      "backgroundColor": "#00000033",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt
index 6478d4d..617a475 100644
--- a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='indicator')",
       "position": [-800, -21],
       "bounds": [1200, 142],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-transformed-expected.txt b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-transformed-expected.txt
index 05447e2c..cc820fa8 100644
--- a/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-transformed-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/limit-layer-bounds-transformed-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='indicator')",
       "position": [-1000, -21],
       "bounds": [1221, 142],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/layer-creation/animation-overlap-with-children-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/animation-overlap-with-children-expected.txt
index 55b0b64..6dd57ee 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/animation-overlap-with-children-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/animation-overlap-with-children-expected.txt
@@ -25,6 +25,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='test1 box')",
       "position": [5, 15],
       "bounds": [100, 100],
+      "backgroundColor": "#FFA500",
       "transform": 3
     },
     {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-change-out-of-view-in-view-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-change-out-of-view-in-view-expected.txt
index 18480930..4b6aca6d 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-change-out-of-view-in-view-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-change-out-of-view-in-view-expected.txt
@@ -18,7 +18,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='fixed2'",
       "contentsOpaque": true,
       "drawsContent": false,
-      "backgroundColor": "#C0C0C0",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-under-transform-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-under-transform-expected.txt
index e234fb0d..604a2a6 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/fixed-position-under-transform-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/fixed-position-under-transform-expected.txt
@@ -11,6 +11,7 @@
       "name": "LayoutNGBlockFlow DIV id='transform'",
       "position": [100, 100],
       "bounds": [256, 256],
+      "backgroundColor": "#FF0000",
       "transform": 3
     },
     {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap-expected.txt
index fe614ef..d666557d 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap-expected.txt
@@ -31,6 +31,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV class='box')",
       "position": [23, 213],
       "bounds": [210, 100],
+      "backgroundColor": "#0000FF",
       "transform": 3
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-container-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-container-expected.txt
index a4e0cc2..4440e231 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-container-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-container-expected.txt
@@ -31,6 +31,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV class='box yellow')",
       "position": [-51, 451],
       "bounds": [100, 100],
+      "backgroundColor": "#FFFF00",
       "transform": 3
     },
     {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-child-layer-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overlap-child-layer-expected.txt
index 58cb176..daa25c0 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overlap-child-layer-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-child-layer-expected.txt
@@ -11,12 +11,14 @@
       "position": [-400, 0],
       "bounds": [256, 256],
       "contentsOpaque": true,
+      "backgroundColor": "#FF0000",
       "transform": 1
     },
     {
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='green')",
       "position": [-400, 0],
       "bounds": [300, 300],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping-expected.txt
index e8bd8b6..6712c38 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping-expected.txt
@@ -24,6 +24,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='overlap')",
       "position": [400, 0],
       "bounds": [100, 100],
+      "backgroundColor": "#0000FF",
       "transform": 2
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt
index 2cbe378..4b6369b 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt
@@ -16,6 +16,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='over')",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/layer-creation/rotate3d-overlap-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/rotate3d-overlap-expected.txt
index f2d6c9f..7552f57a 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/rotate3d-overlap-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/rotate3d-overlap-expected.txt
@@ -26,6 +26,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV class='box')",
       "position": [-5, 115],
       "bounds": [110, 110],
+      "backgroundColor": "#0000FF",
       "transform": 2
     },
     {
@@ -39,6 +40,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV class='box')",
       "position": [-5, 115],
       "bounds": [110, 110],
+      "backgroundColor": "#0000FF",
       "transform": 4
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/layer-creation/spanOverlapsCanvas-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/spanOverlapsCanvas-expected.txt
index cf64eced..6fdb1f8 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/spanOverlapsCanvas-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/spanOverlapsCanvas-expected.txt
@@ -19,6 +19,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='output')",
       "bounds": [100, 50],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
index e1be4b3..ddec749e 100644
--- a/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
+++ b/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
@@ -16,6 +16,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV id='squashed')",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-hidden-with-touch-expected.txt b/third_party/blink/web_tests/compositing/overflow/overflow-hidden-with-touch-expected.txt
index c543542..9e8531ab 100644
--- a/third_party/blink/web_tests/compositing/overflow/overflow-hidden-with-touch-expected.txt
+++ b/third_party/blink/web_tests/compositing/overflow/overflow-hidden-with-touch-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-overlay-with-touch-expected.txt b/third_party/blink/web_tests/compositing/overflow/overflow-overlay-with-touch-expected.txt
deleted file mode 100644
index c543542..0000000
--- a/third_party/blink/web_tests/compositing/overflow/overflow-overlay-with-touch-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt b/third_party/blink/web_tests/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
index 6e4f9d4d..b977ffbb 100644
--- a/third_party/blink/web_tests/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
+++ b/third_party/blink/web_tests/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1200, 10000],
+      "backgroundColor": "#008000",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt b/third_party/blink/web_tests/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt
index df05a3f..54e64e9 100644
--- a/third_party/blink/web_tests/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt
+++ b/third_party/blink/web_tests/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt
@@ -12,7 +12,8 @@
     },
     {
       "name": "Scrolling Contents Layer",
-      "bounds": [305, 1224]
+      "bounds": [305, 1224],
+      "backgroundColor": "#C0C0C0"
     },
     {
       "name": "ContentsLayer for Horizontal Scrollbar Layer",
diff --git a/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt b/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
index 3da86bb..23a33a0 100644
--- a/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
@@ -39,6 +39,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-grandchildren-not-contained' class='positionAbsolute positioned')",
       "position": [25, 65],
       "bounds": [80, 40],
+      "backgroundColor": "#800080",
       "transform": 1
     },
     {
@@ -53,6 +54,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-grandchildren-not-contained' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 2
     },
     {
@@ -111,6 +113,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-not-contained' class='positionAbsolute positioned')",
       "position": [25, 65],
       "bounds": [80, 40],
+      "backgroundColor": "#800080",
       "transform": 5
     },
     {
@@ -125,6 +128,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-not-contained' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 6
     },
     {
@@ -160,6 +164,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-sibling-grandchildren-not-contained' class='positionAbsolute positioned')",
       "position": [25, 65],
       "bounds": [80, 40],
+      "backgroundColor": "#800080",
       "transform": 7
     },
     {
@@ -174,6 +179,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren-not-contained' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 8
     },
     {
@@ -232,6 +238,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-sibling-not-contained' class='positionAbsolute positioned')",
       "position": [25, 65],
       "bounds": [80, 40],
+      "backgroundColor": "#800080",
       "transform": 11
     },
     {
@@ -246,6 +253,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 12
     },
     {
@@ -354,6 +362,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling-grandchildren' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 18
     },
     {
@@ -398,6 +407,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 22
     },
     {
@@ -448,6 +458,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-grandchildren' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 24
     },
     {
@@ -492,6 +503,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 28
     },
     {
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-absolute-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-absolute-expected.txt
index 66561f8..1f6f401 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-absolute-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-absolute-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FFFFFF"
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='positioned layer'",
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-expected.txt
index b29b1a0d..3ae8ab37 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt
index ecc12fa..10d0133 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-fixed-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-fixed-expected.txt
index 66561f8..1f6f401 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-fixed-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-fixed-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FFFFFF"
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='positioned layer'",
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-fixed-overflow-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-fixed-overflow-expected.txt
index b72861de..8abd3d6 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-fixed-overflow-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-fixed-overflow-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt
index 795d8a8..cbd72c9 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-expected.txt
index 0557b9d..70ecb37 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutView #document",
       "bounds": [400, 400],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FFFFFF"
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='positioned layer'",
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt
index 19c34174..cb7d1a70 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt
@@ -11,7 +11,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt
index ffe54b6..ec09ede 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt
@@ -15,7 +15,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-expected.txt
index 0557b9d..70ecb37 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutView #document",
       "bounds": [400, 400],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FFFFFF"
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='positioned layer'",
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt
index f9a60ea7..6cb4425 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt
@@ -11,7 +11,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt
index 4756200..765c1c0 100644
--- a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt
@@ -15,7 +15,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/squashing/add-remove-squashed-layers-expected.txt b/third_party/blink/web_tests/compositing/squashing/add-remove-squashed-layers-expected.txt
index 958018c..e89de89d 100644
--- a/third_party/blink/web_tests/compositing/squashing/add-remove-squashed-layers-expected.txt
+++ b/third_party/blink/web_tests/compositing/squashing/add-remove-squashed-layers-expected.txt
@@ -134,6 +134,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='C' class='overlap3')",
       "position": [240, 240],
       "bounds": [100, 100],
+      "backgroundColor": "#FF00FF",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z-expected.txt b/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z-expected.txt
index c37d5a3d..6150c1dd 100644
--- a/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z-expected.txt
+++ b/third_party/blink/web_tests/compositing/squashing/composited-bounds-for-negative-z-expected.txt
@@ -23,6 +23,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [285, 1000],
+      "backgroundColor": "#ADD8E6",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt b/third_party/blink/web_tests/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt
index 3243f60..a951442 100644
--- a/third_party/blink/web_tests/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt
+++ b/third_party/blink/web_tests/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt
@@ -16,6 +16,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='box')",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/squashing/move-squashing-layer-expected.txt b/third_party/blink/web_tests/compositing/squashing/move-squashing-layer-expected.txt
index d5d97db..7c2d2c40 100644
--- a/third_party/blink/web_tests/compositing/squashing/move-squashing-layer-expected.txt
+++ b/third_party/blink/web_tests/compositing/squashing/move-squashing-layer-expected.txt
@@ -26,6 +26,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV id='squashed')",
       "position": [-92, -92],
       "bounds": [100, 100],
+      "backgroundColor": "#0000FF",
       "transform": 2
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/squashing/no-squashing-for-filters-expected.txt b/third_party/blink/web_tests/compositing/squashing/no-squashing-for-filters-expected.txt
index 3b8eccd..7b951d0e 100644
--- a/third_party/blink/web_tests/compositing/squashing/no-squashing-for-filters-expected.txt
+++ b/third_party/blink/web_tests/compositing/squashing/no-squashing-for-filters-expected.txt
@@ -22,7 +22,8 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='trysquashed')",
       "position": [50, 50],
-      "bounds": [50, 50]
+      "bounds": [50, 50],
+      "backgroundColor": "#D3D3D3"
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/compositing/squashing/repaint-child-of-squashed-expected.txt b/third_party/blink/web_tests/compositing/squashing/repaint-child-of-squashed-expected.txt
index 6a3a279..573353b 100644
--- a/third_party/blink/web_tests/compositing/squashing/repaint-child-of-squashed-expected.txt
+++ b/third_party/blink/web_tests/compositing/squashing/repaint-child-of-squashed-expected.txt
@@ -18,6 +18,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='box top')",
       "position": [80, 80],
       "bounds": [100, 100],
+      "backgroundColor": "#00FFFF",
       "transform": 1
     }
   ],
@@ -54,6 +55,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='box top')",
       "position": [80, 80],
       "bounds": [100, 100],
+      "backgroundColor": "#00FFFF",
       "invalidations": [
         [10, 10, 50, 50]
       ],
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-compositing-hover-expected.txt b/third_party/blink/web_tests/compositing/squashing/squash-compositing-hover-expected.txt
index b697378..2362d56d 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-compositing-hover-expected.txt
+++ b/third_party/blink/web_tests/compositing/squashing/squash-compositing-hover-expected.txt
@@ -144,6 +144,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='box middle')",
       "position": [80, 80],
       "bounds": [100, 100],
+      "backgroundColor": "#00FF00",
       "transform": 2
     },
     {
@@ -157,6 +158,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='box top')",
       "position": [80, 80],
       "bounds": [100, 100],
+      "backgroundColor": "#00FFFF",
       "transform": 3
     }
   ],
diff --git a/third_party/blink/web_tests/compositing/squashing/squashing-sparsity-heuristic-expected.txt b/third_party/blink/web_tests/compositing/squashing/squashing-sparsity-heuristic-expected.txt
index fe1693d8..c0a1ad7 100644
--- a/third_party/blink/web_tests/compositing/squashing/squashing-sparsity-heuristic-expected.txt
+++ b/third_party/blink/web_tests/compositing/squashing/squashing-sparsity-heuristic-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1')",
       "position": [80, 80],
       "bounds": [10, 10],
+      "backgroundColor": "#0000FF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/css3/blending/mix-blend-mode-2nd-stacking-context-composited-expected.txt b/third_party/blink/web_tests/css3/blending/mix-blend-mode-2nd-stacking-context-composited-expected.txt
index 827d3657..9f0e3fa 100644
--- a/third_party/blink/web_tests/css3/blending/mix-blend-mode-2nd-stacking-context-composited-expected.txt
+++ b/third_party/blink/web_tests/css3/blending/mix-blend-mode-2nd-stacking-context-composited-expected.txt
@@ -8,7 +8,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='accelerated stacking-context'",
       "bounds": [160, 90],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#008000",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-reason-children-expected.txt b/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-reason-children-expected.txt
index cf69a743..cde94cd 100644
--- a/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-reason-children-expected.txt
+++ b/third_party/blink/web_tests/css3/blending/mix-blend-mode-composited-reason-children-expected.txt
@@ -8,8 +8,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='stacking-context'",
       "position": [8, 8],
       "contentsOpaque": true,
-      "drawsContent": false,
-      "backgroundColor": "#FF0000"
+      "drawsContent": false
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='stacking-context'",
diff --git a/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-2-stacking-contexts-expected.txt b/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-2-stacking-contexts-expected.txt
index 426f4d3..13972b5 100644
--- a/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-2-stacking-contexts-expected.txt
+++ b/third_party/blink/web_tests/css3/blending/mix-blend-mode-isolation-2-stacking-contexts-expected.txt
@@ -8,8 +8,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='stacking-context'",
       "position": [8, 8],
       "contentsOpaque": true,
-      "drawsContent": false,
-      "backgroundColor": "#FF0000"
+      "drawsContent": false
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='stacking-context'",
@@ -32,7 +31,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='accelerated stacking-context'",
       "contentsOpaque": true,
       "drawsContent": false,
-      "backgroundColor": "#FF0000",
       "transform": 2
     },
     {
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 6ed2308d..94870592 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
@@ -153482,7 +153482,7 @@
        ]
       ],
       "sync-start-times.html": [
-       "06dcf0305639f21fbeea35039023fe2102c38451",
+       "e9ef6762ea74689c617552ce3122e5ea734cdf20",
        [
         null,
         [
@@ -157449,7 +157449,7 @@
       []
      ],
      "constructors-expected.txt": [
-      "ebb7dde64bb751128721d31934acf23148a28cbf",
+      "bf840dabe0af5579a2cd27278d0371b83a5462fc",
       []
      ],
      "default-iterator-object-expected.txt": [
@@ -166839,7 +166839,7 @@
       []
      ],
      "event-dispatch.tentative-expected.txt": [
-      "a4512f67d28b1cdd814fa152b6d8fef4fe153e82",
+      "0feefd2eedc72d4c5724d016e9ba3de6d51a4bb1",
       []
      ],
      "event-order.tentative-expected.txt": [
@@ -189385,7 +189385,7 @@
       ]
      },
      "event-dispatch.tentative-expected.txt": [
-      "6c2a306154da5228dee5771f2b7ecaf953683af4",
+      "294ff2555a187ba81afc27ffa35ca46c9e9050ea",
       []
      ],
      "idlharness-expected.txt": [
@@ -198655,22 +198655,6 @@
      "HTMLCollection-as-prototype-expected.txt": [
       "f36f3bf1426c59572dc577805db9d9a3503ffd29",
       []
-     ],
-     "HTMLCollection-delete-expected.txt": [
-      "4e83310253ec2afe853ba52b5dc12ea498f1fbcd",
-      []
-     ],
-     "HTMLCollection-own-props-expected.txt": [
-      "4d2dd7fc4d6f07aa855ea46158784cc4c4977170",
-      []
-     ],
-     "HTMLCollection-supported-property-indices-expected.txt": [
-      "be034fafcfe7066e657a1071d00d39fd7321d67c",
-      []
-     ],
-     "HTMLCollection-supported-property-names-expected.txt": [
-      "30d2dd44e943d0b8f796fc76dde01286ee3fbe89",
-      []
      ]
     },
     "common.js": [
@@ -198748,7 +198732,7 @@
      []
     ],
     "idlharness.window_exclude=Node-expected.txt": [
-     "0aa1687706a2b60295c26653b16a6f059370c1cb",
+     "58f17fc27836870051e6f09c1cacffb193f7f3d0",
      []
     ],
     "lists": {
@@ -204080,10 +204064,6 @@
         "6387bc89c8f39f43a49079a45be7e3d1910569a1",
         []
        ],
-       "api-availability-expected.txt": [
-        "8676e6ed8abab677631fa87c21b6ac770422d669",
-        []
-       ],
        "browsing_context_name-0.html": [
         "5cbab71a5eaac4fd789a470cca2538225589a497",
         []
@@ -204851,7 +204831,7 @@
         []
        ],
        "location-protocol-setter-non-broken-expected.txt": [
-        "73507dc26a7a6935592a606ac49ce62bbaf4ff8c",
+        "4d1f8a9abd4d46f445ceb66ec1f65fe65425aabd",
         []
        ],
        "location-protocol-setter-non-broken-weird-expected.txt": [
@@ -204874,18 +204854,6 @@
         "dfeea3d36e6e594b7d90a5c5eb6063943eb7f2a7",
         []
        ],
-       "location-prototype-setting-same-origin-expected.txt": [
-        "f1e424f8fcf3924342e1077d82a8986939687f9c",
-        []
-       ],
-       "location-stringifier-expected.txt": [
-        "59612a1b796be218c107943580d9c408601ff665",
-        []
-       ],
-       "location-valueof-expected.txt": [
-        "1086fb9fd54aca0cc6675f7cf9b4408ae8bb4da5",
-        []
-       ],
        "location_assign_about_blank-1.html": [
         "b43598f2cd8f47bcd23373075773ef245c95c21a",
         []
@@ -205384,10 +205352,6 @@
         "e08395a89affb9f921c9cae368f32c7c5444970b",
         []
        ],
-       "prototype-expected.txt": [
-        "312d0a1aa5fc22cd30618476df4a5538d1b4af50",
-        []
-       ],
        "test.html": [
         "c3b3cc185255d159b0f9ff9fd97aae71170d0af6",
         []
@@ -205429,16 +205393,8 @@
         []
        ]
       },
-      "window-indexed-properties-expected.txt": [
-       "f958b38c919a376fb363f746b023eeab44d4b4ff",
-       []
-      ],
-      "window-indexed-properties-strict-expected.txt": [
-       "24149dd095eaed7a4b925498c90bbf80cff7df65",
-       []
-      ],
       "window-properties.https-expected.txt": [
-       "76418e85aa664da7e4e6a7f5219fb5dde1d3e46a",
+       "90301e06ddd143e349dbe6e12ced7dc0dad8fde9",
        []
       ],
       "window-reuse-in-nested-browsing-contexts.tentative-expected.txt": [
@@ -205462,10 +205418,6 @@
      },
      "windows": {
       "auxiliary-browsing-contexts": {
-       "opener-setter.window-expected.txt": [
-        "8dfee380a4f83d006027c76b643ffa4bb8a11ddd",
-        []
-       ],
        "resources": {
         "close-opener.html": [
          "f41773ed2cd00945e844e6ec3abb3c0e49b00854",
@@ -205601,12 +205553,8 @@
        "5ae578d930f8a9e29d4f6396299d09efe167e728",
        []
       ],
-      "embedded-opener-expected.txt": [
-       "16481744cb91f79d4589e364e539ef8d4128bc90",
-       []
-      ],
       "embedded-opener-remove-frame-expected.txt": [
-       "1d304732ae89dc1d919737f00e0d29eaec6d5e91",
+       "36c9182acf3571c65b546a886539972edad4e5ac",
        []
       ],
       "nested-browsing-contexts": {
@@ -206956,10 +206904,6 @@
        ]
       },
       "the-offscreen-canvas": {
-       "2d.getcontext.extraargs-expected.txt": [
-        "7212cb86263531b14d5a476773e1b53681644610",
-        []
-       ],
        "size.attributes.idl-expected.txt": [
         "6046e3bd01e110f56729b99516515b109d8a426c",
         []
@@ -207748,10 +207692,6 @@
         "a134f46ae4f026f047d3d2556bd665b1403d85f5",
         []
        ],
-       "dataset-binding.window-expected.txt": [
-        "0f3419e7fc36e3093a7e183bf3d14f8e08c830ff",
-        []
-       ],
        "dir_auto-EN-L-ref.html": [
         "de6e13b3a3221f6054e387eb76525673bc1201f9",
         []
@@ -208099,11 +208039,11 @@
       []
      ],
      "idlharness.https_exclude=(Document_Window_HTML._)-expected.txt": [
-      "9f3049c1e0d0daa483bbb0e332d96478cedd6985",
+      "7968f85556da5f0881b2ca3a60c1d32fd4522b1c",
       []
      ],
      "idlharness.https_include=(Document_Window)-expected.txt": [
-      "2a60f996ab87e61e651effd9c958610bd7d1cf54",
+      "ecc0d9891941d601d6ef705c6759553b867c479d",
       []
      ],
      "idlharness.https_include=HTML._-expected.txt": [
@@ -214598,12 +214538,8 @@
         "25900f613e24a8146e00cfe68f4fd11d481ca2a9",
         []
        ],
-       "form-indexed-element-expected.txt": [
-        "c25ec2fe6ce147656cfefe0633efd106936f39fc",
-        []
-       ],
        "form-nameditem-expected.txt": [
-        "86a0d6792487d76ddba8748af29f09ce4121beb4",
+        "90758955cb9790fb082a2de0097eee0315c48a95",
         []
        ],
        "resources": {
@@ -218916,7 +218852,7 @@
      []
     ],
     "wasm-web-api.idl": [
-     "1cc2f17679b2e89604e0d4a901f0dabbaa6917e5",
+     "23856007a6d8749004122c7f0c10acb879c2f24a",
      []
     ],
     "web-animations.idl": [
@@ -221207,14 +221143,6 @@
      "6905a68e7901ce26bc1a363062304e1536604400",
      []
     ],
-    "idlharness.https.any-expected.txt": [
-     "fd08a2bb73c2a94f8c4c36393a195471450e84d4",
-     []
-    ],
-    "idlharness.https.any.worker-expected.txt": [
-     "0b3ae0d7ccbcfee19de1287167959f61a433af58",
-     []
-    ],
     "native_FileSystemWritableFileStream-write-manual.https-expected.txt": [
      "53bf72d0a209fb6a85c7ebc48adb92dfdd4bb1de",
      []
@@ -224973,7 +224901,7 @@
       []
      ],
      "webxr-test.js": [
-      "51b2b132276465645031de151f7f569b4dd6d63f",
+      "a1f57ac036b04a2b804d83acb594507aa9d1f31c",
       []
      ],
      "webxr-test.js.headers": [
@@ -226450,10 +226378,6 @@
       "e6e6986dc00a2077b683c28c4b9d639ef0f2d949",
       []
      ],
-     "detached-context.https-expected.txt": [
-      "904eaa7c97d76506033b177eac0a76ac8a076e60",
-      []
-     ],
      "fetch-canvas-tainting-video-with-range-request.https-expected.txt": [
       "eb2733136fe9f8fbdb385fff6da47c50a73f9148",
       []
@@ -236147,7 +236071,7 @@
       []
      ],
      "browser.py": [
-      "6abe151948438beaf4cd252b44d63d751587b1ec",
+      "6c1c445de23557953210be0b4595dec7fc6bf26a",
       []
      ],
      "commands.json": [
@@ -236183,7 +236107,7 @@
       []
      ],
      "run.py": [
-      "aec874fa1969cd86a875cc445067073b8a7c8944",
+      "18f1c55145e819dbf16aeb35cfcbf3dedcaf5d7d",
       []
      ],
      "testfiles.py": [
@@ -237729,7 +237653,7 @@
       []
      ],
      "setters_tests.json": [
-      "6c011e2f9acae432b62d04630f65782493565f9c",
+      "db217da23d559bc7983471cda5547a6551b84945",
       []
      ],
      "toascii.json": [
@@ -238150,7 +238074,7 @@
        []
       ],
       "animate-no-browsing-context-expected.txt": [
-       "de9770be913bd9a3c3b8706887b573af02509501",
+       "91238a475503e550d5c625007db878116069158a",
        []
       ]
      },
@@ -238160,7 +238084,7 @@
        []
       ],
       "style-change-events-expected.txt": [
-       "ae99c09d35c85b72a189ce367be2ad2f5acfd60a",
+       "a618fd79eb71323d65202f9ecc6fca7c4614ff40",
        []
       ]
      },
@@ -238174,7 +238098,7 @@
        []
       ],
       "style-change-events-expected.txt": [
-       "ea372480457f4bb391aec9beb1e16992a7465aef",
+       "a3ce4529056ab9b227ebc34f2384deca356eaf93",
        []
       ],
       "target-expected.txt": [
@@ -238232,7 +238156,7 @@
        []
       ],
       "setting-the-timeline-of-an-animation-expected.txt": [
-       "1b685b0566ee9e911c2ff10658344aa0d25c7ea4",
+       "305bfa278215a6e0aafa5062ebac6cb03f6913ca",
        []
       ],
       "sync-start-times-ref.html": [
@@ -238250,7 +238174,7 @@
      },
      "timelines": {
       "update-and-send-events-replacement-expected.txt": [
-       "d583a4f0555923321aec16d04de0644ad2a472a1",
+       "56358f91b29c41d38fb01bb9d1d130e67d1b66fa",
        []
       ]
      }
@@ -239482,7 +239406,7 @@
      []
     ],
     "RTCPeerConnection-iceGatheringState-expected.txt": [
-     "db32c8e1339f96d1b5c5fe2bd26d88d0d6bc1ed2",
+     "b8da17006905b4af212310d30d2cabfd3113f8bf",
      []
     ],
     "RTCPeerConnection-mandatory-getStats.https-expected.txt": [
@@ -240318,7 +240242,7 @@
        []
       ],
       "region-expected.txt": [
-       "bbc8739b6edda3d9cc3db75af10236876204d83f",
+       "305af887cbb64413add0152ae0b7bb0d83120d97",
        []
       ]
      },
@@ -345364,6 +345288,15 @@
         {}
        ]
       ],
+      "input-change-event-properties.html": [
+       "f3c6f7d4625e2bc6c9098322476b3d2f73fa8dd7",
+       [
+        null,
+        {
+         "testdriver": true
+        }
+       ]
+      ],
       "resetting-a-form": {
        "reset-event.html": [
         "f7d98f721653cd5ed98aa602e367cea635cd5820",
@@ -355406,6 +355339,15 @@
        "testdriver": true
       }
      ]
+    ],
+    "select-event-drag-remove.html": [
+     "f5c2e702e5783e3f9067c7735ab02f905d3de69b",
+     [
+      null,
+      {
+       "testdriver": true
+      }
+     ]
     ]
    },
    "installedapp": {
@@ -379763,7 +379705,7 @@
      ]
     ],
     "scroll-animation.html": [
-     "60fc4c500cd3e06bf67f511687dd9c7161fa6a0f",
+     "ef36236d2191a62c4384d146aecbe36025e007fd",
      [
       null,
       {}
@@ -399454,7 +399396,7 @@
        ]
       ],
       "timelines.html": [
-       "50bb3ac5877ff6c676c8781113fe3b9da4104fdd",
+       "d570eed5c28637c001b1d1c178630bdb424afd31",
        [
         null,
         {}
@@ -410392,7 +410334,7 @@
     },
     "dom-overlay": {
      "ar_dom_overlay.https.html": [
-      "de0cb68744956558541b574fd88800d262d23e97",
+      "27837e12681f9c747dc8f13194ffa89e016f520e",
       [
        null,
        {}
@@ -410422,6 +410364,15 @@
         ]
        }
       ]
+     ],
+     "nested_fullscreen.https.html": [
+      "a8fc70fca6a7c33af4287d92a4318cca621ca0bd",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
      ]
     },
     "events_input_source_recreation.https.html": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2-ref.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2-ref.html
index 9a6e928..d98c822 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2-ref.html
@@ -56,7 +56,7 @@
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
 
-<div class="grid" style="grid: min-content / auto">
+<div class="grid" style="grid: minmax(min-content,30px) / auto">
   <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1">
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
@@ -78,7 +78,7 @@
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
 
-<div class="grid" style="grid: min-content / auto">
+<div class="grid" style="grid: minmax(min-content,30px) / auto">
   <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1">
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
@@ -103,7 +103,7 @@
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
 
-<div class="grid" style="grid: min-content / auto">
+<div class="grid" style="grid: minmax(min-content,30px) / auto">
   <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1">
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
@@ -125,7 +125,7 @@
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
 
-<div class="grid" style="grid: min-content / auto">
+<div class="grid" style="grid: minmax(min-content,30px) / auto">
   <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1">
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2a-ref.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2a-ref.html
index 9aab2aed..11afa34 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2a-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/range-percent-intrinsic-size-2a-ref.html
@@ -47,7 +47,7 @@
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
 
-<div class="grid" style="grid: min-content / auto">
+<div class="grid" style="grid: minmax(min-content,30px) / auto">
   <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1">
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
@@ -67,7 +67,7 @@
   <input type="range" class="mb" orient="vertical">
 </div></div>
 
-<div class="grid" style="grid: min-content / auto">
+<div class="grid" style="grid: minmax(min-content,30px) / auto">
   <input type="range" class="b" orient="vertical" style="height:50%; grid-area:1/1">
   <input type="range" class="b" orient="vertical" style="visibility:hidden; grid-area:1/1">
 </div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/input-change-event-properties.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/input-change-event-properties.html
new file mode 100644
index 0000000..f3c6f7d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/input-change-event-properties.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test the properties of input and change events</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<fieldset id="clickable">
+  <input type="checkbox">
+  <input type="radio">
+</fieldset>
+
+<fieldset id="typeable">
+  <input type="text">
+  <input type="search">
+  <input type="tel">
+  <input type="url">
+  <input type="email">
+  <input type="password">
+  <input type="number">
+  <textarea></textarea>
+</fieldset>
+
+<select>
+  <option>1</option>
+  <option>2</option>
+</select>
+
+<!-- Not going to test the more complicated input types like date or color for now... -->
+
+<button id="click-me-to-unfocus-other-things">Clickable</button>
+
+<script>
+"use strict";
+const clickMeToUnfocusOtherThings = document.querySelector("#click-me-to-unfocus-other-things");
+
+for (const el of document.querySelector("#clickable").children) {
+  test(() => {
+    let inputEvent, changeEvent;
+    el.oninput = e => inputEvent = e;
+    el.onchange = e => changeEvent = e;
+
+    el.click();
+
+    assert_event(inputEvent, { bubbles: true, cancelable: false, composed: true });
+    assert_event(changeEvent, { bubbles: true, cancelable: false, composed: false });
+  }, `${el.outerHTML} click()`);
+}
+
+for (const el of document.querySelector("#typeable").children) {
+  promise_test(async () => {
+    let inputEvent, changeEvent;
+    el.oninput = e => inputEvent = e;
+    el.onchange = e => changeEvent = e;
+
+    await test_driver.send_keys(el, "1"); // has to be a number so <input type=number> works
+    await test_driver.click(clickMeToUnfocusOtherThings);
+
+    assert_event(inputEvent, { bubbles: true, cancelable: false, composed: true });
+    assert_event(changeEvent, { bubbles: true, cancelable: false, composed: false });
+  }, `${el.outerHTML} typing`);
+}
+
+promise_test(async () => {
+  const el = document.querySelector("select");
+
+  let inputEvent, changeEvent;
+  el.oninput = e => inputEvent = e;
+  el.onchange = e => changeEvent = e;
+
+  // TODO: this doesn't seem to work in Safari/on Macs. Or maybe Safari is legitimately failing.
+  // Someone with a Mac should investigate.
+  await test_driver.send_keys(el, "\uE015"); // down arrow key
+  await test_driver.click(clickMeToUnfocusOtherThings);
+
+  assert_event(inputEvent, { bubbles: true, cancelable: false, composed: true });
+  assert_event(changeEvent, { bubbles: true, cancelable: false, composed: false });
+}, `<select> pressing down arrow`);
+
+function assert_event(e, { bubbles, cancelable, composed }) {
+  assert_equals(e.bubbles, bubbles, `${e.type} bubbles`);
+  assert_equals(e.cancelable, cancelable, `${e.type} cancelable`);
+  assert_equals(e.composed, composed, `${e.type} composed`);
+}
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/input-events/select-event-drag-remove.html b/third_party/blink/web_tests/external/wpt/input-events/select-event-drag-remove.html
new file mode 100644
index 0000000..f5c2e70
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/input-events/select-event-drag-remove.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Drag select triggers the right event, and doesn't crash if it removes the target while at it</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1386418">
+<style>
+  input {
+    border: 0;
+    padding: 0;
+    font: 16px/1 monospace;
+  }
+</style>
+<input type="text" value="Drag select to crash">
+<script>
+async_test(t => {
+  let input = document.querySelector("input");
+  input.addEventListener("select", t.step_func(function() {
+    input.remove();
+    requestAnimationFrame(() => requestAnimationFrame(() => t.done()));
+  }));
+  new test_driver.Actions()
+      .pointerMove(0, 0, { origin: input })
+      .pointerDown()
+      .pointerMove(40, 0, { origin: input })
+      .pointerUp()
+      .send();
+}, "Drag and remove from the select event doesn't crash");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/wasm-web-api.idl b/third_party/blink/web_tests/external/wpt/interfaces/wasm-web-api.idl
index 1cc2f17..2385600 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/wasm-web-api.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/wasm-web-api.idl
@@ -3,6 +3,7 @@
 // (https://github.com/tidoust/reffy-reports)
 // Source: WebAssembly Web API (https://webassembly.github.io/spec/web-api/)
 
+[Exposed=(Window,Worker)]
 partial namespace WebAssembly {
   Promise<Module> compileStreaming(Promise<Response> source);
   Promise<WebAssemblyInstantiatedSource> instantiateStreaming(
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/mpadded/mpadded-001-expected.txt b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/mpadded/mpadded-001-expected.txt
deleted file mode 100644
index f6520243..0000000
--- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/mpadded/mpadded-001-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS mpadded (no attributes)
-FAIL Different widths assert_approx_equals: width 0 expected 25 +/- 1 but got 0
-FAIL Different heights assert_approx_equals: height0 expected 25 +/- 1 but got 0
-FAIL Different depths assert_approx_equals: depth0 expected 25 +/- 1 but got 0
-FAIL Various combinations of height, depth and width. assert_approx_equals: width0 expected 25 +/- 1 but got 0
-PASS Preferred width
-PASS dynamic attributes (remove)
-FAIL dynamic attributes (attach) assert_approx_equals: expected 50 +/- 1 but got 0
-FAIL dynamic attributes (modify) assert_approx_equals: expected 50 +/- 1 but got 0
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/mpadded/mpadded-002.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/mpadded/mpadded-002.html
index d376bd3d..a5f7752 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/mpadded/mpadded-002.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/mpadded/mpadded-002.html
@@ -48,8 +48,8 @@
 
     test(function() {
       var mpadded = getBox("percentages");
-      assert_equals(mpadded.width, contentWidth / 2, "width");
-      assert_approx_equals(getBox("baseline").bottom - mpadded.top, contentHeight / 3, epsilon, "height");
+      assert_equals(mpadded.width, contentWidth, "width");
+      assert_approx_equals(getBox("baseline").bottom - mpadded.top, contentHeight, epsilon, "height");
       assert_approx_equals(mpadded.bottom - getBox("baseline").bottom, contentDepth, epsilon, "depth");
     }, "Percentage calculation for width, height and depth");
 
@@ -133,7 +133,7 @@
       <mpadded id="height0" height="25px"><mspace width="100px" depth="125px" height="150px" style="background: black; opacity: .5"/></mpadded>
       <mpadded id="height1" height="50px"><mspace width="100px" depth="125px" height="150px" style="background: black; opacity: .5"/></mpadded>
       <mpadded id="height2" height="75px"><mspace width="100px" depth="125px" height="150px" style="background: black; opacity: .5"/></mpadded>
-      <mpadded id="percentages" width="50%" height="33%" depth="100%"><mspace width="100px" depth="125px" height="150px" style="background: black; opacity: .5"/></mpadded>
+      <mpadded id="percentages" width="50%" height="33%" depth="10%"><mspace width="100px" depth="125px" height="150px" style="background: black; opacity: .5"/></mpadded>
     </math>
   </p>
   <p>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/mpadded/mpadded-003-expected.txt b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/mpadded/mpadded-003-expected.txt
deleted file mode 100644
index 2b658e23..0000000
--- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/mpadded/mpadded-003-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-PASS lspace/voffset shifts don't affect mpadded preferred width
-PASS lspace/voffset shifts don't affect mpadded size
-FAIL content is shifted by the specified lspace/voffset assert_approx_equals: positive lspace expected 5 +/- 1 but got 0
-FAIL content is shifted by the specified lspace/voffset (RTL) assert_approx_equals: positive lspace expected -5 +/- 1 but got 0
-FAIL dynamic changes of lspace/voffset assert_approx_equals: attach lspace expected 5 +/- 1 but got 0
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js b/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js
index 51b2b13..a1f57ac0 100644
--- a/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js
+++ b/third_party/blink/web_tests/external/wpt/resources/chromium/webxr-test.js
@@ -63,6 +63,21 @@
   }
 
   simulateUserActivation(callback) {
+    if (window.top !== window) {
+      // test_driver.click only works for the toplevel frame. This alternate
+      // Chrome-specific method is sufficient for starting an XR session in an
+      // iframe, and is used in platform-specific tests.
+      //
+      // TODO(https://github.com/web-platform-tests/wpt/issues/20282): use
+      // a cross-platform method if available.
+      xr_debug('simulateUserActivation', 'use eventSender');
+      document.addEventListener('click', callback);
+      eventSender.mouseMoveTo(0, 0);
+      eventSender.mouseDown();
+      eventSender.mouseUp();
+      document.removeEventListener('click', callback);
+      return;
+    }
     const button = document.createElement('button');
     button.textContent = 'click to continue test';
     button.style.display = 'block';
diff --git a/third_party/blink/web_tests/external/wpt/tools/wpt/browser.py b/third_party/blink/web_tests/external/wpt/tools/wpt/browser.py
index 6abe151..6c1c445 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wpt/browser.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wpt/browser.py
@@ -560,10 +560,29 @@
         os.remove(installer_path)
         return self.find_nightly_binary(dest)
 
-    def install_mojojs(self, dest):
-        url = self._latest_chromium_snapshot_url() + "mojojs.zip"
+    def install_mojojs(self, dest, channel, browser_binary):
+        if channel == "nightly":
+            url = self._latest_chromium_snapshot_url() + "mojojs.zip"
+        else:
+            chrome_version = self.version(binary=browser_binary)
+            assert chrome_version, "Cannot determine the version of Chrome"
+            # Remove channel suffixes (e.g. " dev").
+            chrome_version = chrome_version.split(' ')[0]
+            url = "https://storage.googleapis.com/chrome-wpt-mojom/%s/linux64/mojojs.zip" % chrome_version
+
+        last_url_file = os.path.join(dest, "mojojs", "gen", "DOWNLOADED_FROM")
+        if os.path.exists(last_url_file):
+            with open(last_url_file, "rt") as f:
+                last_url = f.read().strip()
+            if last_url == url:
+                self.logger.info("Mojo bindings already up to date")
+                return
+            rmtree(os.path.join(dest, "mojojs", "gen"))
+
         self.logger.info("Downloading Mojo bindings from %s" % url)
         unzip(get(url).raw, dest)
+        with open(last_url_file, "wt") as f:
+            f.write(url)
 
     def _chromedriver_platform_string(self):
         platform = self.platforms.get(uname[0])
diff --git a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
index aec874f..18f1c551 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wpt/run.py
@@ -312,6 +312,7 @@
 class Chrome(BrowserSetup):
     name = "chrome"
     browser_cls = browser.Chrome
+    experimental_channels = ("dev", "canary", "nightly")
 
     def setup_kwargs(self, kwargs):
         browser_channel = kwargs["browser_channel"]
@@ -321,9 +322,14 @@
                 kwargs["binary"] = binary
             else:
                 raise WptrunError("Unable to locate Chrome binary")
-        if browser_channel == "nightly":
+        # TODO(Hexcles): Enable this everywhere when Chrome 86 becomes stable.
+        if browser_channel in self.experimental_channels:
             try:
-                self.browser.install_mojojs(self.venv.path)
+                self.browser.install_mojojs(
+                    dest=self.venv.path,
+                    channel=browser_channel,
+                    browser_binary=kwargs["binary"],
+                )
                 kwargs["enable_mojojs"] = True
                 logger.info("MojoJS enabled")
             except Exception as e:
@@ -350,7 +356,7 @@
                 kwargs["webdriver_binary"] = webdriver_binary
             else:
                 raise WptrunError("Unable to locate or install chromedriver binary")
-        if browser_channel in ("dev", "canary", "nightly"):
+        if browser_channel in self.experimental_channels:
             logger.info("Automatically turning on experimental features for Chrome Dev/Canary or Chromium trunk")
             kwargs["binary_args"].append("--enable-experimental-web-platform-features")
             # HACK(Hexcles): work around https://github.com/web-platform-tests/wpt/issues/16448
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json b/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json
index 6c011e2..db217da 100644
--- a/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json
+++ b/third_party/blink/web_tests/external/wpt/url/resources/setters_tests.json
@@ -119,11 +119,11 @@
             }
         },
         {
-            "href": "gopher://example.net:1234",
+            "href": "https://example.net:1234",
             "new_value": "file",
             "expected": {
-                "href": "gopher://example.net:1234",
-                "protocol": "gopher:"
+                "href": "https://example.net:1234/",
+                "protocol": "https:"
             }
         },
         {
@@ -145,7 +145,7 @@
         },
         {
             "href": "file:///test",
-            "new_value": "gopher",
+            "new_value": "https",
             "expected": {
                 "href": "file:///test",
                 "protocol": "file:"
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/pattern.png b/third_party/blink/web_tests/external/wpt/webcodecs/pattern.png
new file mode 100644
index 0000000..85676f2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webcodecs/pattern.png
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/video-encoder.html b/third_party/blink/web_tests/external/wpt/webcodecs/video-encoder.html
new file mode 100644
index 0000000..ce03f05
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webcodecs/video-encoder.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<html>
+<title>Test the VideoTrackReader API.</title>
+<body>
+  <img id='frame_image' src="pattern.png">
+</body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<script>
+
+async function generateBitmap(width, height) {
+  return createImageBitmap(document.getElementById('frame_image'),
+                                  { resizeWidth: width,
+                                    resizeHeight: height });
+}
+
+async function createVideoFrame(width, height, timestamp) {
+  let bitmap = await generateBitmap(width, height);
+  return new VideoFrame(bitmap, { timestamp: timestamp });
+}
+
+// Calls done after giving async output/error callbacks a final chance to run.
+async function asyncDone(test) {
+  test.step_timeout(test.done.bind(test), 0);
+}
+
+async_test(async (t) => {
+  // VideoEncoderInit lacks required fields.
+  assert_throws_js(TypeError, () => { new VideoEncoder({}); });
+
+  // VideoEncoderInit has required fields.
+  let encoder = new VideoEncoder({
+    output(chunk) { assert_unreached("Unexpected output");  },
+    error(error) { assert_unreached("Unexpected error:" + error); },
+  });
+  encoder.close();
+
+  asyncDone(t);
+}, 'Test VideoEncoder construction');
+
+async_test(async (t) => {
+  let encoder = new VideoEncoder({
+    output(chunk) { assert_unreached("Unexpected output");  },
+    error(error) { assert_unreached("Unexpected error:" + error); },
+  });
+
+  const requiredConfigPairs = {
+    codec: 'vp8',
+    framerate: 25,
+    width: 640,
+    height: 480
+  };
+  let incrementalConfig = {};
+
+  for (let key in requiredConfigPairs) {
+    // Configure  should fail while required keys are missing.
+    assert_throws_js(TypeError, () => { encoder.configure(incrementalConfig); });
+    incrementalConfig[key] = requiredConfigPairs[key];
+  }
+
+  // Configure should pass once incrementalConfig meets all requirements.
+  encoder.configure(incrementalConfig);
+
+  encoder.configure(incrementalConfig);
+
+  encoder.close();
+
+  asyncDone(t);
+}, 'Test VideoEncoder.configure()');
+
+async_test(async (t) => {
+  let encoder = new VideoEncoder({
+    output(chunk) { assert_unreached("Unexpected output"); },
+    error(error) { assert_unreached("Unexpected error:" + error); },
+  });
+
+  let videoFrame = await createVideoFrame(640, 480, 0);
+
+  assert_throws_dom('InvalidStateError',
+                    () => { encoder.encode(videoFrame); },
+                    'first encode');
+
+  // Once more for good measure.
+  assert_throws_dom('InvalidStateError',
+                    () => { encoder.encode(videoFrame); },
+                    'second encode');
+
+  encoder.close();
+
+  asyncDone(t);
+}, 'Test encode() before configure() throws InvalidStateError.');
+
+async_test(async (t) => {
+  let output_chunks = [];
+  let encoder = new VideoEncoder({
+    output(chunk) { output_chunks.push(chunk); },
+    error(error) { assert_unreached("Unexpected error:" + error); },
+  });
+
+  // No encodes yet.
+  assert_equals(encoder.encodeQueueSize, 0);
+
+  const config = {
+    codec: 'vp8',
+    framerate: 25,
+    width: 640,
+    height: 480
+  };
+  encoder.configure(config);
+
+  // Still no encodes.
+  assert_equals(encoder.encodeQueueSize, 0);
+
+  let frame1 = await createVideoFrame(640, 480, 0);
+  let frame2 = await createVideoFrame(640, 480, 33333);
+
+  encoder.encode(frame1);
+  encoder.encode(frame2);
+
+  // Could be 0, 1, or 2. We can't guarantee this check runs before the UA has
+  // processed the encodes.
+  assert_true(encoder.encodeQueueSize >= 0 && encoder.encodeQueueSize <= 2)
+
+  await encoder.flush();
+
+  // We can guarantee that all encodes are processed after a flush.
+  assert_equals(encoder.encodeQueueSize, 0);
+
+  assert_equals(output_chunks.length, 2);
+  assert_equals(output_chunks[0].timestamp, frame1.timestamp);
+  assert_equals(output_chunks[1].timestamp, frame2.timestamp);
+
+  encoder.close();
+
+  asyncDone(t);
+}, 'Test successful configure(), encode(), and flush()');
+</script>
+</html>
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
index f4af425..e788d0e7 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutNGBlockFlow DIV class='box'",
       "position": [-30, -30],
       "bounds": [160, 160],
-      "backgroundColor": "#0000FF",
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
index afd2a61..4631b77 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
@@ -10,13 +10,11 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='composited-parent'",
       "position": [-100, -100],
       "bounds": [200, 200],
-      "backgroundColor": "#000000",
       "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software-parent'",
-      "bounds": [225, 225],
-      "backgroundColor": "#008000"
+      "bounds": [225, 225]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/fixed-body-background-positioned-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/fixed-body-background-positioned-expected.txt
index 7e3fefc..537b4f00 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/fixed-body-background-positioned-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/fixed-body-background-positioned-expected.txt
@@ -14,7 +14,6 @@
     {
       "name": "LayoutNGBlockFlow HTML",
       "bounds": [785, 3700],
-      "backgroundColor": "#00000080",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/fixed-position-changed-to-absolute-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/fixed-position-changed-to-absolute-expected.txt
index 32fc382..e26108c2 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/fixed-position-changed-to-absolute-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/fixed-position-changed-to-absolute-expected.txt
@@ -16,8 +16,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='layer-A'",
       "position": [20, 20],
-      "bounds": [226, 180],
-      "backgroundColor": "#6AA6A6"
+      "bounds": [226, 180]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex-expected.txt
index 420479c..418630e 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex-expected.txt
@@ -8,19 +8,16 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited'",
-      "bounds": [500, 250],
-      "backgroundColor": "#000000"
+      "bounds": [500, 250]
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited'",
       "bounds": [150, 150],
-      "backgroundColor": "#000000",
       "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='indicator box'",
-      "bounds": [100, 350],
-      "backgroundColor": "#008000"
+      "bounds": [100, 350]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-expected.txt
index c491649..c43446f 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-expected.txt
@@ -12,7 +12,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box'",
       "position": [-5, -5],
       "bounds": [110, 110],
-      "backgroundColor": "#808080",
+      "backgroundColor": "#00000033",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-inside-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-inside-expected.txt
index de69cb2..b6cb945d 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-inside-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-inside-expected.txt
@@ -13,7 +13,7 @@
       "position": [5, 15],
       "bounds": [90, 80],
       "contentsOpaque": true,
-      "backgroundColor": "#808080",
+      "backgroundColor": "#00000033",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-with-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-with-shadow-expected.txt
index 6096439..1d8a941 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-with-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/clip-with-shadow-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited box'",
       "position": [-5, -5],
       "bounds": [110, 110],
-      "backgroundColor": "#808080",
+      "backgroundColor": "#00000033",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-overflow-root-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-overflow-root-expected.txt
index aa13619..0bfaf570 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-overflow-root-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-overflow-root-expected.txt
@@ -14,8 +14,7 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='indicator'",
-      "bounds": [216, 142],
-      "backgroundColor": "#FF0000"
+      "bounds": [216, 142]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-positioned-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-positioned-expected.txt
index aeb3e36b6..5dfffd3 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-positioned-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-positioned-expected.txt
@@ -16,8 +16,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='indicator'",
       "position": [0, 8],
-      "bounds": [150, 142],
-      "backgroundColor": "#FF0000"
+      "bounds": [150, 142]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt
index 4372839..356cebe 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt
@@ -17,7 +17,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='indicator'",
       "position": [0, 8],
       "bounds": [429, 142],
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#008000"
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-transformed-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-transformed-expected.txt
index 8e44ebab..6374f6c4 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-transformed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/geometry/limit-layer-bounds-transformed-expected.txt
@@ -17,7 +17,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='indicator'",
       "position": [0, 8],
       "bounds": [350, 142],
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#008000"
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/iframes/resizer-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/iframes/resizer-expected.txt
index 4bbfef3..90ce25f 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/iframes/resizer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/iframes/resizer-expected.txt
@@ -9,7 +9,6 @@
     {
       "name": "LayoutIFrame IFRAME class='container'",
       "bounds": [304, 154],
-      "backgroundColor": "#9A9A9A",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/animation-overlap-with-children-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/animation-overlap-with-children-expected.txt
index 978b0345..2714445 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/animation-overlap-with-children-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/animation-overlap-with-children-expected.txt
@@ -25,7 +25,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='test1 box'",
       "position": [11, 21],
       "bounds": [220, 150],
-      "backgroundColor": "#FFA500",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page-expected.txt
index f67e188..f03f96d5 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page-expected.txt
@@ -22,14 +22,12 @@
     {
       "name": "LayoutIFrame (positioned) IFRAME id='iframe2' class='composited'",
       "bounds": [154, 154],
-      "backgroundColor": "#9A9A9A",
       "transform": 2
     },
     {
       "name": "LayoutIFrame (positioned) IFRAME id='iframe3'",
       "position": [10, 380],
-      "bounds": [154, 154],
-      "backgroundColor": "#9A9A9A"
+      "bounds": [154, 154]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-clipping-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-clipping-expected.txt
index ddfdc4e..cb2c355 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-clipping-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-clipping-expected.txt
@@ -42,8 +42,7 @@
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='box yellow'",
       "position": [18, 571],
-      "bounds": [151, 231],
-      "backgroundColor": "#FFFF00"
+      "bounds": [151, 231]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-container-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-container-expected.txt
index 40079d0..4d1d035 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-container-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-container-expected.txt
@@ -113,8 +113,7 @@
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='first-green-box' class='box green rotate-45deg'",
       "position": [18, 328],
-      "bounds": [174, 464],
-      "backgroundColor": "#008000"
+      "bounds": [174, 464]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-expected.txt
index aa4b51f..15cd4b3 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-animation-expected.txt
@@ -16,8 +16,7 @@
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='box'",
       "position": [18, 129],
-      "bounds": [101, 231],
-      "backgroundColor": "#0000FF"
+      "bounds": [101, 231]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-3d-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-3d-expected.txt
index 00d2a4a4..fb61aaf 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-3d-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-3d-expected.txt
@@ -57,8 +57,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box top left'",
       "position": [8, 8],
-      "bounds": [300, 371],
-      "backgroundColor": "#808080"
+      "bounds": [300, 371]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-layer-with-transform-body-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-layer-with-transform-body-expected.txt
index 3e5aea187..9b1bed7 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-layer-with-transform-body-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-layer-with-transform-body-expected.txt
@@ -9,7 +9,6 @@
     {
       "name": "LayoutNGBlockFlow BODY",
       "bounds": [784, 584],
-      "backgroundColor": "#FF0000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-preserved-3d-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-preserved-3d-expected.txt
index 2d7ab714..5a78be0 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-preserved-3d-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/overlap-transformed-preserved-3d-expected.txt
@@ -248,8 +248,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box top left'",
       "position": [8, 8],
-      "bounds": [300, 371],
-      "backgroundColor": "#808080"
+      "bounds": [300, 371]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/scroll-partial-update-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/scroll-partial-update-expected.txt
index 94a846b..867b1baf 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/scroll-partial-update-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/layer-creation/scroll-partial-update-expected.txt
@@ -16,8 +16,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='overlay'",
       "position": [10, 8],
-      "bounds": [400, 204],
-      "backgroundColor": "#00000080"
+      "bounds": [400, 204]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-auto-with-touch-expected.txt
index 82c7392..9bd3baf 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-auto-with-touch-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
index 82c7392..9bd3baf 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-hidden-with-touch-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-hidden-with-touch-expected.txt
index 82c7392..9bd3baf 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-hidden-with-touch-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-hidden-with-touch-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-overlay-with-touch-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-overlay-with-touch-expected.txt
index 82c7392..9bd3baf 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-overlay-with-touch-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/overflow-overlay-with-touch-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt
index 17f8b82..4a640d15 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt
@@ -34,7 +34,6 @@
       "position": [5, 5],
       "bounds": [60, 172],
       "backfaceVisibility": "hidden",
-      "backgroundColor": "#0000FF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
index 0363be8e..c416df8e 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
@@ -34,14 +34,12 @@
       "name": "LayoutNGBlockFlow DIV id='container-absolute-grandchildren-not-contained' class='overflow'",
       "position": [2, 6],
       "bounds": [85, 136],
-      "backgroundColor": "#0000FF",
       "transform": 2
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-grandchildren-not-contained' class='positionAbsolute positioned'",
       "position": [35, 10],
-      "bounds": [199, 105],
-      "backgroundColor": "#800080"
+      "bounds": [199, 105]
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='container-absolute-grandchildren' class='positionAbsolute overflow'",
@@ -71,7 +69,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='container-absolute-grandchildren' class='positionAbsolute overflow'",
       "position": [2, 6],
       "bounds": [105, 136],
-      "backgroundColor": "#800080",
       "transform": 4
     },
     {
@@ -96,14 +93,12 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-not-contained' class='positionAbsolute positioned'",
       "position": [275, 10],
-      "bounds": [199, 105],
-      "backgroundColor": "#800080"
+      "bounds": [199, 105]
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-not-contained' class='scrolled'",
       "position": [6, 6],
       "bounds": [75, 108],
-      "backgroundColor": "#0000FF",
       "transform": 6
     },
     {
@@ -129,14 +124,12 @@
       "name": "LayoutNGBlockFlow DIV id='container-absolute-sibling-grandchildren-not-contained' class='overflow'",
       "position": [2, 6],
       "bounds": [85, 136],
-      "backgroundColor": "#0000FF",
       "transform": 8
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-sibling-grandchildren-not-contained' class='positionAbsolute positioned'",
       "position": [10, 75],
-      "bounds": [465, 159],
-      "backgroundColor": "#800080"
+      "bounds": [465, 159]
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='container-absolute-sibling-grandchildren' class='positionAbsolute overflow'",
@@ -166,7 +159,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='container-absolute-sibling-grandchildren' class='positionAbsolute overflow'",
       "position": [2, 6],
       "bounds": [105, 136],
-      "backgroundColor": "#800080",
       "transform": 10
     },
     {
@@ -191,14 +183,12 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-sibling-not-contained' class='positionAbsolute positioned'",
       "position": [155, 130],
-      "bounds": [199, 105],
-      "backgroundColor": "#800080"
+      "bounds": [199, 105]
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled'",
       "position": [6, 6],
       "bounds": [75, 108],
-      "backgroundColor": "#0000FF",
       "transform": 12
     },
     {
@@ -229,7 +219,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-sibling' class='positionAbsolute positioned'",
       "position": [6, 6],
       "bounds": [101, 108],
-      "backgroundColor": "#800080",
       "transform": 14
     },
     {
@@ -260,7 +249,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute' class='positionAbsolute positioned'",
       "position": [6, 6],
       "bounds": [101, 136],
-      "backgroundColor": "#800080",
       "transform": 16
     },
     {
@@ -285,7 +273,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='container-fixed-sibling-grandchildren' class='positionAbsolute overflow'",
       "position": [2, 6],
       "bounds": [85, 136],
-      "backgroundColor": "#0000FF",
       "transform": 18
     },
     {
@@ -324,7 +311,6 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled'",
       "position": [6, 6],
       "bounds": [75, 108],
-      "backgroundColor": "#0000FF",
       "transform": 22
     },
     {
@@ -349,7 +335,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='container-fixed-grandchildren' class='positionAbsolute overflow'",
       "position": [2, 6],
       "bounds": [85, 136],
-      "backgroundColor": "#0000FF",
       "transform": 24
     },
     {
@@ -389,7 +374,6 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled'",
       "position": [6, 6],
       "bounds": [75, 136],
-      "backgroundColor": "#0000FF",
       "transform": 28
     },
     {
@@ -438,7 +422,6 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-grandchildren-not-contained' class='scrolled onTop'",
       "position": [6, 62],
       "bounds": [75, 80],
-      "backgroundColor": "#0000FF",
       "transform": 2
     },
     {
@@ -461,42 +444,36 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren-not-contained' class='scrolled onTop'",
       "position": [6, 62],
       "bounds": [75, 80],
-      "backgroundColor": "#0000FF",
       "transform": 8
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren' class='scrolled onTop'",
       "position": [6, 62],
       "bounds": [75, 80],
-      "backgroundColor": "#0000FF",
       "transform": 10
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled onTop'",
       "position": [6, 62],
       "bounds": [75, 80],
-      "backgroundColor": "#0000FF",
       "transform": 12
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling' class='scrolled onTop'",
       "position": [6, 62],
       "bounds": [75, 80],
-      "backgroundColor": "#0000FF",
       "transform": 14
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling-grandchildren' class='scrolled onTop'",
       "position": [6, 62],
       "bounds": [75, 80],
-      "backgroundColor": "#0000FF",
       "transform": 18
     },
     {
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled onTop'",
       "position": [6, 62],
       "bounds": [75, 80],
-      "backgroundColor": "#0000FF",
       "transform": 22
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-expected.txt
index 884e112e..0d4c363 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FFFFFF"
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='positioned layer'",
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-overflow-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-overflow-expected.txt
index 3966ac7..57e03af 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-overflow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-overflow-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt
index 0a4cf5d1..e8ffb06 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-expected.txt
index 11c427ac..8e14921 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FFFFFF"
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='positioned indicator'",
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-overflow-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-overflow-expected.txt
index d0fd140..2869b08 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-overflow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-overflow-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt
index 514a26d..b9f475dd 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt
index 7d4e9b0..936b8e5 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt
@@ -11,7 +11,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt
index 38c791e..3b967187 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt
@@ -11,7 +11,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt
index b63fedb..39fe5044 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt
@@ -11,7 +11,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt
index b63fedb..39fe5044 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt
@@ -11,7 +11,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/scrollbars/nested-overlay-scrollbars-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/scrollbars/nested-overlay-scrollbars-expected.txt
index b45b4b8..6cf5e5b 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/scrollbars/nested-overlay-scrollbars-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/scrollbars/nested-overlay-scrollbars-expected.txt
@@ -29,7 +29,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='inner'",
       "position": [2, 2],
       "bounds": [5000, 9000],
-      "backgroundColor": "#808080",
       "transform": 3
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/add-remove-squashed-layers-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/add-remove-squashed-layers-expected.txt
index 4d8c58a..4d65fe3 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/add-remove-squashed-layers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/add-remove-squashed-layers-expected.txt
@@ -19,8 +19,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1'",
       "position": [140, 140],
-      "bounds": [180, 180],
-      "backgroundColor": "#0000FF"
+      "bounds": [180, 180]
     }
   ],
   "transforms": [
@@ -56,7 +55,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1'",
       "position": [140, 140],
       "bounds": [260, 260],
-      "backgroundColor": "#0000FF",
       "invalidations": [
         [160, 160, 100, 100]
       ]
@@ -95,7 +93,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1'",
       "position": [140, 140],
       "bounds": [260, 260],
-      "backgroundColor": "#0000FF",
       "invalidations": [
         [80, 80, 100, 100]
       ]
@@ -174,7 +171,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='B' class='overlap2'",
       "position": [220, 220],
       "bounds": [180, 180],
-      "backgroundColor": "#00FF00",
       "invalidations": [
         [0, 0, 180, 180]
       ]
@@ -213,7 +209,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1'",
       "position": [140, 140],
       "bounds": [180, 180],
-      "backgroundColor": "#0000FF",
       "invalidations": [
         [0, 0, 180, 180]
       ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/no-squashing-for-filters-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/no-squashing-for-filters-expected.txt
index 10a1043..b57d51af 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/no-squashing-for-filters-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/no-squashing-for-filters-expected.txt
@@ -15,8 +15,7 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='trysquashed'",
-      "bounds": [100, 100],
-      "backgroundColor": "#D3D3D3"
+      "bounds": [100, 100]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/opacity-squashed-owner-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/opacity-squashed-owner-expected.txt
index eb2346d..2c163f8 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/opacity-squashed-owner-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/opacity-squashed-owner-expected.txt
@@ -16,8 +16,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='squashed'",
       "position": [16, 4],
-      "bounds": [40, 90],
-      "backgroundColor": "#90EE90"
+      "bounds": [40, 90]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/selection-repaint-with-gaps-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/selection-repaint-with-gaps-expected.txt
index 414a828..3adbc91a 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/selection-repaint-with-gaps-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/selection-repaint-with-gaps-expected.txt
@@ -16,7 +16,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='item'",
       "position": [15, 35],
       "bounds": [100, 210],
-      "backgroundColor": "#D3D3D3",
       "invalidations": [
         [0, 80, 40, 40]
       ]
@@ -52,7 +51,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='item'",
       "position": [15, 35],
       "bounds": [100, 210],
-      "backgroundColor": "#D3D3D3",
       "invalidations": [
         [0, 160, 40, 40],
         [0, 80, 40, 40]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-above-fixed-1-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-above-fixed-1-expected.txt
index d9b0c61..0f9edd2 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-above-fixed-1-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-above-fixed-1-expected.txt
@@ -27,8 +27,7 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV id='paragraph-b' class='overlapping lime'",
       "position": [0, 100],
       "bounds": [200, 1300],
-      "contentsOpaque": true,
-      "backgroundColor": "#00FF00"
+      "contentsOpaque": true
     }
   ],
   "transforms": [
@@ -74,7 +73,6 @@
       "position": [0, 200],
       "bounds": [200, 1200],
       "contentsOpaque": true,
-      "backgroundColor": "#00FFFF",
       "invalidations": [
         [0, 0, 200, 1200]
       ],
@@ -130,7 +128,6 @@
       "position": [0, 200],
       "bounds": [200, 1200],
       "contentsOpaque": true,
-      "backgroundColor": "#00FFFF",
       "transform": 1
     }
   ],
@@ -186,7 +183,6 @@
       "position": [0, 300],
       "bounds": [200, 1100],
       "contentsOpaque": true,
-      "backgroundColor": "#00FF00",
       "invalidations": [
         [0, 0, 200, 1100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-compositing-hover-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-compositing-hover-expected.txt
index b17b9f3..d010dcf 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-compositing-hover-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-compositing-hover-expected.txt
@@ -19,8 +19,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [180, 180],
-      "bounds": [260, 260],
-      "backgroundColor": "#00FF00"
+      "bounds": [260, 260]
     }
   ],
   "transforms": [
@@ -62,8 +61,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle2'",
       "position": [260, 260],
-      "bounds": [180, 180],
-      "backgroundColor": "#FF00FF"
+      "bounds": [180, 180]
     }
   ],
   "transforms": [
@@ -167,8 +165,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [180, 180],
-      "bounds": [180, 180],
-      "backgroundColor": "#00FF00"
+      "bounds": [180, 180]
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box top'",
@@ -219,8 +216,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [180, 180],
-      "bounds": [260, 260],
-      "backgroundColor": "#00FF00"
+      "bounds": [260, 260]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-onto-nephew-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-onto-nephew-expected.txt
index 2288050..9f60b07 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-onto-nephew-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-onto-nephew-expected.txt
@@ -16,8 +16,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [40, 40],
-      "bounds": [180, 190],
-      "backgroundColor": "#00FF00"
+      "bounds": [180, 190]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-onto-transform-backing-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-onto-transform-backing-expected.txt
index 93ab011b..a9cf5499 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-onto-transform-backing-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-onto-transform-backing-expected.txt
@@ -16,8 +16,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [20, 20],
-      "bounds": [260, 260],
-      "backgroundColor": "#00FF00"
+      "bounds": [260, 260]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-paint-invalidation-fixed-position-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-paint-invalidation-fixed-position-expected.txt
index 2f2fee6..d548346 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-paint-invalidation-fixed-position-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-paint-invalidation-fixed-position-expected.txt
@@ -18,7 +18,7 @@
       "position": [8, 25],
       "bounds": [100, 125],
       "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3",
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 25, 100, 100]
       ]
@@ -56,7 +56,7 @@
       "position": [8, 25],
       "bounds": [100, 125],
       "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3",
+      "backgroundColor": "#0000FF",
       "invalidations": [
         [0, 25, 100, 100]
       ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-simple-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-simple-expected.txt
index 16a3b8b..97ab1e5 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-simple-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-simple-expected.txt
@@ -16,8 +16,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [20, 20],
-      "bounds": [260, 260],
-      "backgroundColor": "#00FF00"
+      "bounds": [260, 260]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-three-layers-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-three-layers-expected.txt
index cb53fdb..9f66394 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-three-layers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-three-layers-expected.txt
@@ -16,8 +16,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [40, 40],
-      "bounds": [180, 190],
-      "backgroundColor": "#00FF00"
+      "bounds": [180, 190]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-expected.txt
index dc18a75..f43d660 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-expected.txt
@@ -15,8 +15,7 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
-      "bounds": [280, 280],
-      "backgroundColor": "#00FF00"
+      "bounds": [280, 280]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-repainting-child-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-repainting-child-expected.txt
index 254675f..e340e40 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-repainting-child-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-repainting-child-expected.txt
@@ -16,8 +16,7 @@
     },
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
-      "bounds": [280, 280],
-      "backgroundColor": "#00FF00"
+      "bounds": [280, 280]
     }
   ],
   "transforms": [
@@ -52,7 +51,6 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "bounds": [280, 280],
-      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 141, 141]
       ]
@@ -90,7 +88,6 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "bounds": [280, 280],
-      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 141, 141]
       ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt
index 3bf57fa..fe6389ba 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt
@@ -17,8 +17,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [4, 4],
-      "bounds": [276, 276],
-      "backgroundColor": "#00FF00"
+      "bounds": [276, 276]
     }
   ],
   "transforms": [
@@ -54,7 +53,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [4, 4],
       "bounds": [276, 276],
-      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 132, 132]
       ]
@@ -93,7 +91,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [4, 4],
       "bounds": [276, 276],
-      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 132, 132]
       ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashed-layer-loses-graphicslayer-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashed-layer-loses-graphicslayer-expected.txt
index 96b12ae..e1cd79d 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashed-layer-loses-graphicslayer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashed-layer-loses-graphicslayer-expected.txt
@@ -19,8 +19,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1'",
       "position": [140, 140],
-      "bounds": [260, 260],
-      "backgroundColor": "#0000FF"
+      "bounds": [260, 260]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashed-repaints-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashed-repaints-expected.txt
index d4ccf95..d18f7fcf0 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashed-repaints-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashed-repaints-expected.txt
@@ -19,8 +19,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1'",
       "position": [140, 140],
-      "bounds": [260, 260],
-      "backgroundColor": "#0000FF"
+      "bounds": [260, 260]
     }
   ],
   "transforms": [
@@ -56,7 +55,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1'",
       "position": [140, 140],
       "bounds": [260, 260],
-      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 100, 100]
       ]
@@ -95,7 +93,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1'",
       "position": [140, 140],
       "bounds": [260, 260],
-      "backgroundColor": "#0000FF",
       "invalidations": [
         [80, 80, 100, 100],
         [0, 0, 100, 100]
@@ -135,7 +132,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1'",
       "position": [140, 140],
       "bounds": [260, 260],
-      "backgroundColor": "#0000FF",
       "invalidations": [
         [160, 160, 100, 100],
         [80, 80, 100, 100]
@@ -175,7 +171,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='A' class='overlap1'",
       "position": [140, 140],
       "bounds": [260, 260],
-      "backgroundColor": "#008000",
       "invalidations": [
         [160, 160, 100, 100],
         [0, 0, 100, 100]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashing-sparsity-heuristic-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashing-sparsity-heuristic-expected.txt
index 3a115aac..6e9c441c 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashing-sparsity-heuristic-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/squashing/squashing-sparsity-heuristic-expected.txt
@@ -23,8 +23,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='B' class='overlap2'",
       "position": [220, 220],
-      "bounds": [25, 90],
-      "backgroundColor": "#00FF00"
+      "bounds": [25, 90]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/blending/mix-blend-mode-composited-layers-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/blending/mix-blend-mode-composited-layers-expected.txt
index d17c38415..de925fd 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/blending/mix-blend-mode-composited-layers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/blending/mix-blend-mode-composited-layers-expected.txt
@@ -8,8 +8,7 @@
     },
     {
       "name": "Scrolling background of LayoutView #document",
-      "bounds": [800, 600],
-      "backgroundColor": "#008000"
+      "bounds": [800, 600]
     },
     {
       "name": "LayoutNGBlockFlow DIV",
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
index 432c9ed..238aeacc 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
@@ -44,8 +44,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
       "position": [100, 100],
-      "bounds": [200, 200],
-      "backgroundColor": "#000000"
+      "bounds": [200, 200]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
index 432c9ed..238aeacc 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
@@ -44,8 +44,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
       "position": [100, 100],
-      "bounds": [200, 200],
-      "backgroundColor": "#000000"
+      "bounds": [200, 200]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/chunk-reorder-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/chunk-reorder-expected.txt
index 44f004e..5f32a08b 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/chunk-reorder-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/chunk-reorder-expected.txt
@@ -9,7 +9,6 @@
     {
       "name": "LayoutNGBlockFlow DIV",
       "bounds": [784, 1],
-      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 1, 1]
       ],
@@ -19,7 +18,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='chunk5'",
       "position": [400, 400],
       "bounds": [150, 150],
-      "backgroundColor": "#0000FF",
       "invalidations": [
         [0, 0, 150, 150]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer-expected.txt
index 83ae0ac1..83e0ecc 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer-expected.txt
@@ -14,7 +14,6 @@
     {
       "name": "LayoutNGBlockFlow DIV",
       "bounds": [304, 200],
-      "backgroundColor": "#9A9A9A",
       "invalidations": [
         [10, 10, 50, 50]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt
index 2f3cbf9..6288496 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt
@@ -17,7 +17,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV",
       "position": [50, 50],
       "bounds": [251, 251],
-      "backgroundColor": "#ADD8E6",
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [50, 50, 201, 201]
       ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/pointer-events-composited-scrolling-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/pointer-events-composited-scrolling-expected.txt
index 778a8d4..f558b58e 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/pointer-events-composited-scrolling-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/pointer-events-composited-scrolling-expected.txt
@@ -9,7 +9,6 @@
     {
       "name": "LayoutNGBlockFlow DIV id='target'",
       "bounds": [100, 100],
-      "backgroundColor": "#0000FF",
       "invalidations": [
         [0, 30, 50, 50]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/remove-squashed-layer-plus-move-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/remove-squashed-layer-plus-move-expected.txt
index 7781432..ddba635 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/remove-squashed-layer-plus-move-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/remove-squashed-layer-plus-move-expected.txt
@@ -32,7 +32,6 @@
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='mv-tile'",
       "position": [8, 8],
       "bounds": [1000, 105],
-      "backgroundColor": "#ADD8E6",
       "invalidations": [
         [0, 0, 1000, 105]
       ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.txt
index da31a82..ddcd713 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/repaint-squashed-layer-in-rect-expected.txt
@@ -33,7 +33,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV",
       "position": [8, 0],
       "bounds": [592, 600],
-      "backgroundColor": "#ADD8E6",
       "invalidations": [
         [392, 400, 200, 200]
       ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
index e106bf4..3919a43 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
@@ -18,7 +18,7 @@
       "position": [50, 50],
       "bounds": [50, 50],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 50, 50]
       ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt
index c05afda4..431919c7 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt
@@ -11,7 +11,6 @@
       "position": [1, 11],
       "bounds": [100, 410],
       "backfaceVisibility": "hidden",
-      "backgroundColor": "#008000",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.txt
index beae226..ead8a30f 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer-expected.txt
@@ -17,7 +17,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
       "position": [180, 180],
       "bounds": [262, 200],
-      "backgroundColor": "#00FF00",
       "invalidations": [
         [80, 80, 182, 29]
       ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/updating-scrolling-content-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/updating-scrolling-content-expected.txt
index b48ae68..5248e31 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/updating-scrolling-content-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/compositing/updating-scrolling-content-expected.txt
@@ -27,7 +27,6 @@
     {
       "name": "LayoutNGBlockFlow DIV id='scroller'",
       "bounds": [185, 1200],
-      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 185, 200]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt
index 9118e28..1d112b5 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child-expected.txt
@@ -15,7 +15,6 @@
     {
       "name": "LayoutNGBlockFlow HTML",
       "bounds": [785, 10016],
-      "backgroundColor": "#ADD8E6",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.txt
index 121d5bd..ae6f2e9 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child-expected.txt
@@ -15,7 +15,6 @@
       "name": "LayoutNGBlockFlow DIV class='accelerated'",
       "position": [-14, -14],
       "bounds": [214, 260],
-      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 214, 260]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/position/fixed-element-repaint-after-compositing-update-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/position/fixed-element-repaint-after-compositing-update-expected.txt
index 8f23e75..9d92427 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/position/fixed-element-repaint-after-compositing-update-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/position/fixed-element-repaint-after-compositing-update-expected.txt
@@ -10,7 +10,6 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='fixedOverlapping'",
       "position": [8, 88],
       "bounds": [792, 512],
-      "backgroundColor": "#008000",
       "invalidations": [
         [142, 62, 100, 100],
         [0, 0, 100, 100]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
index 1ca3e97..c699cac21 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
@@ -15,7 +15,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
       "bounds": [100, 100],
-      "backgroundColor": "#008000",
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/caret-with-composited-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/caret-with-composited-scroll-expected.txt
index fc96184..5295306 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/caret-with-composited-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/caret-with-composited-scroll-expected.txt
@@ -21,7 +21,6 @@
     {
       "name": "LayoutNGBlockFlow DIV id='scroller'",
       "bounds": [205, 1022],
-      "backgroundColor": "#D3D3D3",
       "invalidations": [
         [0, 998, 205, 24]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/invalidate-after-composited-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/invalidate-after-composited-scroll-expected.txt
index 5b426be..b1a1028 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/invalidate-after-composited-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/invalidate-after-composited-scroll-expected.txt
@@ -27,7 +27,6 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='scroller'",
       "bounds": [185, 4900],
-      "backgroundColor": "#FFEFD5",
       "invalidations": [
         [0, 2400, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/overflow-move-after-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/overflow-move-after-scroll-expected.txt
index e235fd18..98e3570c2a 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/overflow-move-after-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/overflow-move-after-scroll-expected.txt
@@ -33,7 +33,6 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='scroller' class='scroller'",
       "bounds": [685, 600],
-      "backgroundColor": "#CCEEFF",
       "invalidations": [
         [300, 200, 120, 50],
         [50, 200, 120, 50]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/overflow-scroll-after-move-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/overflow-scroll-after-move-expected.txt
index 360e821c..d898478 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/overflow-scroll-after-move-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/overflow-scroll-after-move-expected.txt
@@ -33,7 +33,6 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='scroller'",
       "bounds": [285, 900],
-      "backgroundColor": "#CCEEFF",
       "invalidations": [
         [50, 310, 200, 50],
         [50, 200, 200, 50]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
index 2eaed165..c1e928c 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
@@ -16,7 +16,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
       "bounds": [100, 100],
       "contentsOpaque": true,
-      "backgroundColor": "#008000",
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt
index 9fdccdb..93fc8d6 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling background of LayoutView #document",
       "bounds": [804, 604],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [2, 2, 800, 600]
       ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
index ef02d97..6e2f354 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
@@ -11,7 +11,6 @@
       "position": [-2, -2],
       "bounds": [404, 544],
       "backfaceVisibility": "hidden",
-      "backgroundColor": "#FFFF00",
       "invalidations": [
         [0, 0, 404, 544]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
index ffcc372..976fde4 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow-expected.txt
@@ -44,8 +44,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
       "position": [200, 200],
-      "bounds": [400, 400],
-      "backgroundColor": "#000000"
+      "bounds": [400, 400]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
index ffcc372..976fde4 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200/css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow-expected.txt
@@ -44,8 +44,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='software-layer-to-promote' class='final-drop-shadow'",
       "position": [200, 200],
-      "bounds": [400, 400],
-      "backgroundColor": "#000000"
+      "bounds": [400, 400]
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/absolute-inside-out-of-view-fixed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/absolute-inside-out-of-view-fixed-expected.txt
index 3732492..2b17338 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/absolute-inside-out-of-view-fixed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/absolute-inside-out-of-view-fixed-expected.txt
@@ -10,7 +10,8 @@
     {
       "name": "LayoutBlockFlow (positioned) DIV class='fixed'",
       "bounds": [100, 100],
-      "contentsOpaque": true
+      "contentsOpaque": true,
+      "backgroundColor": "#008000"
     },
     {
       "name": "ContentsLayer for Vertical Scrollbar Layer",
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/body-background-painted-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/body-background-painted-expected.txt
index 1a1f90b7..5cf3c3b 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/body-background-painted-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/body-background-painted-expected.txt
@@ -8,8 +8,7 @@
     },
     {
       "name": "LayoutBlockFlow HTML",
-      "bounds": [800, 600],
-      "backgroundColor": "#D3D3D3"
+      "bounds": [800, 600]
     },
     {
       "name": "LayoutBlockFlow (positioned) DIV id='underbody'",
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/filter-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/filter-expected.txt
index 0b480a6..d82fdbe 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/filter-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/filter-expected.txt
@@ -15,6 +15,7 @@
     {
       "name": "LayoutBlockFlow DIV class='composited container-box'",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "transform": 2
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/hidden-with-visible-child-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/hidden-with-visible-child-expected.txt
index db5de1d1..fee3ada 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/hidden-with-visible-child-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/hidden-with-visible-child-expected.txt
@@ -9,7 +9,7 @@
     {
       "name": "LayoutBlockFlow (positioned) DIV id='caption'",
       "bounds": [200, 100],
-      "backgroundColor": "#008000",
+      "backgroundColor": "#0000FF",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/hidden-with-visible-text-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/hidden-with-visible-text-expected.txt
index 81b2ae5..a465eca 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/hidden-with-visible-text-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/hidden-with-visible-text-expected.txt
@@ -10,7 +10,6 @@
     {
       "name": "LayoutBlockFlow (positioned) DIV id='caption'",
       "bounds": [200, 100],
-      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
index b305113..1432f73b8 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/contents-opaque/overflow-hidden-child-layers-expected.txt
@@ -11,7 +11,7 @@
       "position": [-30, -30],
       "bounds": [160, 160],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#0000FF",
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt
index 1f45360..1e3ea9928 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/filters/sw-layer-overlaps-hw-shadow-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='software')",
       "position": [-105, -105],
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
index ae2b8514..30f83d1 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow-expected.txt
@@ -10,7 +10,6 @@
       "name": "LayoutBlockFlow (positioned) DIV id='composited-parent'",
       "position": [-100, -100],
       "bounds": [200, 200],
-      "backgroundColor": "#000000",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-clipped-composited-child-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-clipped-composited-child-expected.txt
index e003bb6..8d969ee 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-clipped-composited-child-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-clipped-composited-child-expected.txt
@@ -9,6 +9,7 @@
     {
       "name": "LayoutBlockFlow DIV class='container'",
       "bounds": [200, 100],
+      "backgroundColor": "#008000",
       "transform": 2
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt
index f9beb847..4703404 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-ignores-hidden-dynamic-expected.txt
@@ -16,6 +16,7 @@
       "position": [10, 10],
       "bounds": [50, 50],
       "contentsOpaque": true,
+      "backgroundColor": "#000000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-ignores-hidden-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-ignores-hidden-expected.txt
index c0ef39c..49913de 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-ignores-hidden-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/bounds-ignores-hidden-expected.txt
@@ -10,7 +10,8 @@
       "name": "LayoutBlockFlow (positioned) DIV class='composited'",
       "position": [10, 10],
       "bounds": [50, 50],
-      "contentsOpaque": true
+      "contentsOpaque": true,
+      "backgroundColor": "#000000"
     },
     {
       "name": "ContentsLayer for Horizontal Scrollbar Layer",
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-expected.txt
index e1486a7..bb01f9d 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-expected.txt
@@ -12,7 +12,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='composited box'",
       "position": [-5, -5],
       "bounds": [110, 110],
-      "backgroundColor": "#808080",
+      "backgroundColor": "#00000033",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-inside-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-inside-expected.txt
index 6e4e9471..3563c143 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-inside-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-inside-expected.txt
@@ -13,7 +13,7 @@
       "position": [5, 15],
       "bounds": [90, 80],
       "contentsOpaque": true,
-      "backgroundColor": "#808080",
+      "backgroundColor": "#00000033",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-with-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-with-shadow-expected.txt
index 3267a22..269c326 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-with-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-with-shadow-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='composited box'",
       "position": [-5, -5],
       "bounds": [110, 110],
-      "backgroundColor": "#808080",
+      "backgroundColor": "#00000033",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt
index dd5d56e..33baab3 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/limit-layer-bounds-positioned-transition-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='indicator')",
       "position": [-800, -21],
       "bounds": [1200, 142],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/limit-layer-bounds-transformed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/limit-layer-bounds-transformed-expected.txt
index 03d83b3..08955fc 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/limit-layer-bounds-transformed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/limit-layer-bounds-transformed-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='indicator')",
       "position": [-1000, -21],
       "bounds": [1221, 142],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/animation-overlap-with-children-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/animation-overlap-with-children-expected.txt
index 2b4239b5..7305ad2 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/animation-overlap-with-children-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/animation-overlap-with-children-expected.txt
@@ -25,6 +25,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='test1 box')",
       "position": [5, 15],
       "bounds": [100, 100],
+      "backgroundColor": "#FFA500",
       "transform": 3
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-change-out-of-view-in-view-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-change-out-of-view-in-view-expected.txt
index 8f15e85..4b97748 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-change-out-of-view-in-view-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-change-out-of-view-in-view-expected.txt
@@ -18,7 +18,6 @@
       "name": "LayoutBlockFlow (positioned) DIV id='fixed2'",
       "contentsOpaque": true,
       "drawsContent": false,
-      "backgroundColor": "#C0C0C0",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-under-transform-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-under-transform-expected.txt
index 2577e49..d9d872a 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-under-transform-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-under-transform-expected.txt
@@ -11,6 +11,7 @@
       "name": "LayoutBlockFlow DIV id='transform'",
       "position": [100, 100],
       "bounds": [256, 256],
+      "backgroundColor": "#FF0000",
       "transform": 3
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overflow-scroll-overlap-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overflow-scroll-overlap-expected.txt
index da3a57c..b9e2263f 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overflow-scroll-overlap-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overflow-scroll-overlap-expected.txt
@@ -31,6 +31,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='box')",
       "position": [23, 213],
       "bounds": [210, 100],
+      "backgroundColor": "#0000FF",
       "transform": 3
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-animation-container-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-animation-container-expected.txt
index 3d103f8..76e8c4f 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-animation-container-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-animation-container-expected.txt
@@ -31,6 +31,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='box yellow')",
       "position": [-51, 451],
       "bounds": [100, 100],
+      "backgroundColor": "#FFFF00",
       "transform": 3
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-child-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-child-layer-expected.txt
index 69f7a6fb..79733be 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-child-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-child-layer-expected.txt
@@ -11,12 +11,14 @@
       "position": [-400, 0],
       "bounds": [256, 256],
       "contentsOpaque": true,
+      "backgroundColor": "#FF0000",
       "transform": 1
     },
     {
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='green')",
       "position": [-400, 0],
       "bounds": [300, 300],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-clipping-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-clipping-expected.txt
index 9b99b9c..970e85e 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-clipping-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-clipping-expected.txt
@@ -24,6 +24,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='overlap')",
       "position": [400, 0],
       "bounds": [100, 100],
+      "backgroundColor": "#0000FF",
       "transform": 2
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt
index 1f30d334..97a28ec 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt
@@ -16,6 +16,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='over')",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/rotate3d-overlap-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/rotate3d-overlap-expected.txt
index bf7309d..0818c5b 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/rotate3d-overlap-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/rotate3d-overlap-expected.txt
@@ -26,6 +26,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='box')",
       "position": [-5, 115],
       "bounds": [110, 110],
+      "backgroundColor": "#0000FF",
       "transform": 2
     },
     {
@@ -39,6 +40,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='box')",
       "position": [-5, 115],
       "bounds": [110, 110],
+      "backgroundColor": "#0000FF",
       "transform": 4
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/spanOverlapsCanvas-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/spanOverlapsCanvas-expected.txt
index 51451f2..e3ae7335 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/spanOverlapsCanvas-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/spanOverlapsCanvas-expected.txt
@@ -19,6 +19,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='output')",
       "bounds": [100, 50],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
index d13b85f1..1290e2a 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
@@ -16,6 +16,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='squashed')",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
index d472fbf0..7143daf2 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1200, 10000],
+      "backgroundColor": "#008000",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt
index d455bab..7f967ad 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/scrolling-content-clip-to-viewport-expected.txt
@@ -12,7 +12,8 @@
     },
     {
       "name": "Scrolling Contents Layer",
-      "bounds": [305, 1224]
+      "bounds": [305, 1224],
+      "backgroundColor": "#C0C0C0"
     },
     {
       "name": "ContentsLayer for Horizontal Scrollbar Layer",
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
index 21d459f..5b30dfe 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
@@ -39,6 +39,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='positioned-absolute-grandchildren-not-contained' class='positionAbsolute positioned')",
       "position": [25, 65],
       "bounds": [80, 40],
+      "backgroundColor": "#800080",
       "transform": 1
     },
     {
@@ -53,6 +54,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-grandchildren-not-contained' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 2
     },
     {
@@ -111,6 +113,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='positioned-absolute-not-contained' class='positionAbsolute positioned')",
       "position": [25, 65],
       "bounds": [80, 40],
+      "backgroundColor": "#800080",
       "transform": 5
     },
     {
@@ -125,6 +128,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-not-contained' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 6
     },
     {
@@ -160,6 +164,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='positioned-absolute-sibling-grandchildren-not-contained' class='positionAbsolute positioned')",
       "position": [25, 65],
       "bounds": [80, 40],
+      "backgroundColor": "#800080",
       "transform": 7
     },
     {
@@ -174,6 +179,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren-not-contained' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 8
     },
     {
@@ -232,6 +238,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='positioned-absolute-sibling-not-contained' class='positionAbsolute positioned')",
       "position": [25, 65],
       "bounds": [80, 40],
+      "backgroundColor": "#800080",
       "transform": 11
     },
     {
@@ -246,6 +253,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 12
     },
     {
@@ -354,6 +362,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling-grandchildren' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 18
     },
     {
@@ -398,6 +407,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 22
     },
     {
@@ -448,6 +458,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-grandchildren' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 24
     },
     {
@@ -492,6 +503,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled')",
       "position": [6, 90],
       "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
       "transform": 28
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-expected.txt
index ea33eae..0c9be332 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FFFFFF"
     },
     {
       "name": "LayoutBlockFlow (positioned) DIV class='positioned layer'",
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-overflow-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-overflow-expected.txt
index 87e9ad5..90212c0 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-overflow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-overflow-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt
index 9e2b03b..3213e0d 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-absolute-overflow-scrolled-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-expected.txt
index ea33eae..0c9be332 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FFFFFF"
     },
     {
       "name": "LayoutBlockFlow (positioned) DIV class='positioned layer'",
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-overflow-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-overflow-expected.txt
index 2f03e9a..f8330122 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-overflow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-overflow-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt
index a5b79fc..3737491 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-fixed-overflow-scrolled-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-expected.txt
index 828a99f..5a262be 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutView #document",
       "bounds": [400, 400],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FFFFFF"
     },
     {
       "name": "LayoutBlockFlow (positioned) DIV class='positioned layer'",
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt
index 71ef226..cf66534 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-overflow-expected.txt
@@ -11,7 +11,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt
index 6c01cc9f..8babb1e 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-absolute-overflow-scrolled-expected.txt
@@ -15,7 +15,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-expected.txt
index 828a99f..5a262be 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-expected.txt
@@ -10,7 +10,7 @@
       "name": "LayoutView #document",
       "bounds": [400, 400],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000"
+      "backgroundColor": "#FFFFFF"
     },
     {
       "name": "LayoutBlockFlow (positioned) DIV class='positioned layer'",
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt
index f79a873..f284580 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-overflow-expected.txt
@@ -11,7 +11,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt
index 394e57a..d8c1637b 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/rtl/rtl-iframe-fixed-overflow-scrolled-expected.txt
@@ -15,7 +15,7 @@
       "position": [15, 0],
       "bounds": [1000, 1000],
       "contentsOpaqueForText": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#FFFFFF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/add-remove-squashed-layers-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/add-remove-squashed-layers-expected.txt
index 982d1f2..2e258a4 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/add-remove-squashed-layers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/add-remove-squashed-layers-expected.txt
@@ -134,6 +134,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='C' class='overlap3')",
       "position": [240, 240],
       "bounds": [100, 100],
+      "backgroundColor": "#FF00FF",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/composited-bounds-for-negative-z-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/composited-bounds-for-negative-z-expected.txt
index 893cf2aa..d04d66f 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/composited-bounds-for-negative-z-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/composited-bounds-for-negative-z-expected.txt
@@ -23,6 +23,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [285, 1000],
+      "backgroundColor": "#ADD8E6",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt
index 0a94427..213f223 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/invisible-layers-should-not-affect-geometry-expected.txt
@@ -16,6 +16,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='box')",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/move-squashing-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/move-squashing-layer-expected.txt
index 5c610a81..bc43bba 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/move-squashing-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/move-squashing-layer-expected.txt
@@ -26,6 +26,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='squashed')",
       "position": [-92, -92],
       "bounds": [100, 100],
+      "backgroundColor": "#0000FF",
       "transform": 2
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/no-squashing-for-filters-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/no-squashing-for-filters-expected.txt
index 1676f50..8ddd6843 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/no-squashing-for-filters-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/no-squashing-for-filters-expected.txt
@@ -22,7 +22,8 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='trysquashed')",
       "position": [50, 50],
-      "bounds": [50, 50]
+      "bounds": [50, 50],
+      "backgroundColor": "#D3D3D3"
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/repaint-child-of-squashed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/repaint-child-of-squashed-expected.txt
index ec70799..8ab125a 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/repaint-child-of-squashed-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/repaint-child-of-squashed-expected.txt
@@ -18,6 +18,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='box top')",
       "position": [80, 80],
       "bounds": [100, 100],
+      "backgroundColor": "#00FFFF",
       "transform": 1
     }
   ],
@@ -54,6 +55,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='box top')",
       "position": [80, 80],
       "bounds": [100, 100],
+      "backgroundColor": "#00FFFF",
       "invalidations": [
         [10, 10, 50, 50]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squash-compositing-hover-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squash-compositing-hover-expected.txt
index 7eb47f1..3577510 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squash-compositing-hover-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squash-compositing-hover-expected.txt
@@ -144,6 +144,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='box middle')",
       "position": [80, 80],
       "bounds": [100, 100],
+      "backgroundColor": "#00FF00",
       "transform": 2
     },
     {
@@ -157,6 +158,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='box top')",
       "position": [80, 80],
       "bounds": [100, 100],
+      "backgroundColor": "#00FFFF",
       "transform": 3
     }
   ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squashing-sparsity-heuristic-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squashing-sparsity-heuristic-expected.txt
index 36e80cb..7cca796 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squashing-sparsity-heuristic-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/squashing/squashing-sparsity-heuristic-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='A' class='overlap1')",
       "position": [80, 80],
       "bounds": [10, 10],
+      "backgroundColor": "#0000FF",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-2nd-stacking-context-composited-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-2nd-stacking-context-composited-expected.txt
index 0e809f8f..c9928f1e 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-2nd-stacking-context-composited-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-2nd-stacking-context-composited-expected.txt
@@ -8,7 +8,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='accelerated stacking-context'",
       "bounds": [160, 90],
       "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
+      "backgroundColor": "#008000",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-composited-reason-children-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-composited-reason-children-expected.txt
index 1bbed86..50aefa8 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-composited-reason-children-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-composited-reason-children-expected.txt
@@ -8,8 +8,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='stacking-context'",
       "position": [8, 8],
       "contentsOpaque": true,
-      "drawsContent": false,
-      "backgroundColor": "#FF0000"
+      "drawsContent": false
     },
     {
       "name": "LayoutBlockFlow (positioned) DIV class='stacking-context'",
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-isolation-2-stacking-contexts-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-isolation-2-stacking-contexts-expected.txt
index f2141550..b3102c7 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-isolation-2-stacking-contexts-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/css3/blending/mix-blend-mode-isolation-2-stacking-contexts-expected.txt
@@ -8,8 +8,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='stacking-context'",
       "position": [8, 8],
       "contentsOpaque": true,
-      "drawsContent": false,
-      "backgroundColor": "#FF0000"
+      "drawsContent": false
     },
     {
       "name": "LayoutBlockFlow (positioned) DIV class='stacking-context'",
@@ -32,7 +31,6 @@
       "name": "LayoutBlockFlow (positioned) DIV class='accelerated stacking-context'",
       "contentsOpaque": true,
       "drawsContent": false,
-      "backgroundColor": "#FF0000",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt
index 559f356..3611cb0 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt
@@ -9,7 +9,6 @@
     {
       "name": "LayoutBlockFlow (positioned) DIV class='container'",
       "bounds": [14, 14],
-      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 14, 14]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
index d8dd844..02ee6bb6 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
@@ -18,6 +18,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='containerOverlapsComposited')",
       "position": [12, 12],
       "bounds": [100, 30000],
+      "backgroundColor": "#008000",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
index d6e72fb..ad72789 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
@@ -12,6 +12,7 @@
       "position": [-360, -90],
       "bounds": [360, 90],
       "contentsOpaque": true,
+      "backgroundColor": "#FFFF00",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt
index 0151590..41927735d9 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)",
       "position": [42, 42],
       "bounds": [200, 200],
+      "backgroundColor": "#ADD8E6",
       "invalidations": [
         [0, 0, 200, 200]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt
index 2811bba..1fdd398 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)",
       "position": [42, 42],
       "bounds": [251, 251],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [50, 50, 201, 201]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/new-stacking-context-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/new-stacking-context-expected.txt
index 6a569a6..fd39d4e6 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/new-stacking-context-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/new-stacking-context-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [200, 200],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 200, 200]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/overlap-test-with-filter-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/overlap-test-with-filter-expected.txt
index 2984294..a7d5e28 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/overlap-test-with-filter-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/overlap-test-with-filter-expected.txt
@@ -15,7 +15,6 @@
     {
       "name": "LayoutBlockFlow BODY",
       "bounds": [284, 84],
-      "backgroundColor": "#FFFF00",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
index 011ff15..09010a5 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
@@ -16,6 +16,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='foo')",
       "bounds": [100, 1000],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 1000]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
index b2931b4..97d1860 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) SPAN class='child')",
       "position": [42, 42],
       "bounds": [50, 50],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 50, 50]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt
index e4f856f..80dc382 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt
@@ -16,6 +16,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV)",
       "position": [47, 47],
       "bounds": [500, 500],
+      "backgroundColor": "#ADD8E6",
       "invalidations": [
         [0, 0, 500, 500]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
index 2469530..77693b4 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 1000, 1000]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt
index bd2eda0e..9606275 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='target')",
       "position": [20, 20],
       "bounds": [100, 100],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
index 4a94833..25f804582 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
@@ -10,6 +10,7 @@
     {
       "name": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt
index 946a582..8b8a853 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt
@@ -11,6 +11,7 @@
       "name": "LayoutBlockFlow (positioned) DIV class='reflected fixed'",
       "bounds": [100, 100],
       "contentsOpaque": true,
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt
index 8a050d6..8bdfade2e 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [10000, 385],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 10000, 200]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
index 1d99e2b..f336c5da 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
@@ -13,6 +13,7 @@
     {
       "name": "LayoutBlockFlow (positioned) DIV id='scrollpanel'",
       "bounds": [100, 100],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
index b27b721e..14ce229a 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
@@ -10,6 +10,7 @@
     {
       "name": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
index b27b721e..14ce229a 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
@@ -10,6 +10,7 @@
     {
       "name": "LayoutBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
index 4aef8da..20dfb2a5 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
@@ -17,6 +17,7 @@
     {
       "name": "LayoutBlockFlow (positioned) DIV id='searchbar'",
       "bounds": [150, 150],
+      "backgroundColor": "#800080",
       "transform": 3
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/dark-color-scheme/select/select-dark-mode-basic-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/dark-color-scheme/select/select-dark-mode-basic-expected.png
index 6d6340f..37d6d10 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/dark-color-scheme/select/select-dark-mode-basic-expected.png
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/dark-color-scheme/select/select-dark-mode-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
index 8d59128..610f7cd 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
index 8d59128..610f7cd 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt
index 8d59128..610f7cd 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
deleted file mode 100644
index d472fbf0..0000000
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [1208, 821],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='scroller'",
-      "bounds": [1200, 1000],
-      "transform": 1
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [1200, 10000],
-      "transform": 1
-    },
-    {
-      "name": "ContentsLayer for Vertical Scrollbar Layer",
-      "position": [1193, 0],
-      "bounds": [7, 1000],
-      "transform": 1
-    },
-    {
-      "name": "ContentsLayer for Horizontal Scrollbar Layer",
-      "position": [0, 593],
-      "bounds": [793, 7]
-    },
-    {
-      "name": "ContentsLayer for Vertical Scrollbar Layer",
-      "position": [793, 0],
-      "bounds": [7, 593]
-    },
-    {
-      "name": "Scroll Corner Layer",
-      "position": [793, 593],
-      "bounds": [7, 7]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
new file mode 100644
index 0000000..5b30dfe
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
@@ -0,0 +1,1047 @@
+{
+  "layers": [
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [785, 2016],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='container-absolute-grandchildren-not-contained' class='overflow'",
+      "bounds": [104, 104],
+      "transform": 1
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [2, 2],
+      "bounds": [85, 144],
+      "transform": 2
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 1
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 1
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 1
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='positioned-absolute-grandchildren-not-contained' class='positionAbsolute positioned')",
+      "position": [25, 65],
+      "bounds": [80, 40],
+      "backgroundColor": "#800080",
+      "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-grandchildren-not-contained' class='scrolled'",
+      "position": [6, 34],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-grandchildren-not-contained' class='scrolled')",
+      "position": [6, 90],
+      "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container-absolute-grandchildren' class='positionAbsolute overflow'",
+      "bounds": [104, 104],
+      "transform": 3
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [2, 2],
+      "bounds": [105, 144],
+      "transform": 4
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 3
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 3
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 3
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='container-absolute-not-contained' class='overflow'",
+      "bounds": [104, 104],
+      "transform": 5
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 5
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 5
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 5
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='positioned-absolute-not-contained' class='positionAbsolute positioned')",
+      "position": [25, 65],
+      "bounds": [80, 40],
+      "backgroundColor": "#800080",
+      "transform": 5
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-not-contained' class='scrolled'",
+      "position": [6, 34],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 6
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-not-contained' class='scrolled')",
+      "position": [6, 90],
+      "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
+      "transform": 6
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='container-absolute-sibling-grandchildren-not-contained' class='overflow'",
+      "bounds": [104, 104],
+      "transform": 7
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [2, 2],
+      "bounds": [85, 144],
+      "transform": 8
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 7
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 7
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 7
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='positioned-absolute-sibling-grandchildren-not-contained' class='positionAbsolute positioned')",
+      "position": [25, 65],
+      "bounds": [80, 40],
+      "backgroundColor": "#800080",
+      "transform": 7
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren-not-contained' class='scrolled'",
+      "position": [6, 34],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 8
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren-not-contained' class='scrolled')",
+      "position": [6, 90],
+      "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
+      "transform": 8
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container-absolute-sibling-grandchildren' class='positionAbsolute overflow'",
+      "bounds": [104, 104],
+      "transform": 9
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [2, 2],
+      "bounds": [105, 144],
+      "transform": 10
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 9
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 9
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 9
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='container-absolute-sibling-not-contained' class='overflow'",
+      "bounds": [104, 104],
+      "transform": 11
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 11
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 11
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 11
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='positioned-absolute-sibling-not-contained' class='positionAbsolute positioned')",
+      "position": [25, 65],
+      "bounds": [80, 40],
+      "backgroundColor": "#800080",
+      "transform": 11
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled'",
+      "position": [6, 34],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 12
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled')",
+      "position": [6, 90],
+      "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
+      "transform": 12
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container-absolute-sibling' class='positionAbsolute overflow'",
+      "bounds": [104, 104],
+      "transform": 13
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [2, 2],
+      "bounds": [105, 144],
+      "transform": 14
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 13
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 13
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 13
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container-absolute' class='positionAbsolute overflow'",
+      "bounds": [104, 104],
+      "transform": 15
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [2, 2],
+      "bounds": [105, 144],
+      "transform": 16
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 15
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 15
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 15
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container-fixed-sibling-grandchildren' class='positionAbsolute overflow'",
+      "bounds": [104, 104],
+      "transform": 17
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [2, 2],
+      "bounds": [85, 144],
+      "transform": 18
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 17
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 17
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 17
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='positioned-fixed-sibling-grandchildren' class='positionFixed positioned'",
+      "bounds": [80, 40],
+      "contentsOpaque": true,
+      "backgroundColor": "#800080",
+      "transform": 19
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling-grandchildren' class='scrolled'",
+      "position": [6, 34],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 18
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling-grandchildren' class='scrolled')",
+      "position": [6, 90],
+      "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
+      "transform": 18
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container-fixed-sibling' class='positionAbsolute overflow'",
+      "bounds": [104, 104],
+      "transform": 20
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 20
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 20
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 20
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='positioned-fixed-sibling' class='positionFixed positioned'",
+      "bounds": [80, 40],
+      "contentsOpaque": true,
+      "backgroundColor": "#800080",
+      "transform": 21
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled'",
+      "position": [6, 34],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 22
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled')",
+      "position": [6, 90],
+      "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
+      "transform": 22
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container-fixed-grandchildren' class='positionAbsolute overflow'",
+      "bounds": [104, 104],
+      "transform": 23
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "position": [2, 2],
+      "bounds": [85, 144],
+      "transform": 24
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 23
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 23
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 23
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='positioned-fixed-grandchildren' class='positionFixed positioned'",
+      "bounds": [80, 40],
+      "contentsOpaque": true,
+      "backgroundColor": "#800080",
+      "transform": 25
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-grandchildren' class='scrolled'",
+      "position": [6, 34],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 24
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-grandchildren' class='scrolled')",
+      "position": [6, 90],
+      "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
+      "transform": 24
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='container-fixed' class='positionAbsolute overflow'",
+      "bounds": [104, 104],
+      "transform": 26
+    },
+    {
+      "name": "ContentsLayer for Horizontal Scrollbar Layer",
+      "position": [2, 87],
+      "bounds": [85, 15],
+      "transform": 26
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [87, 2],
+      "bounds": [15, 85],
+      "transform": 26
+    },
+    {
+      "name": "Scroll Corner Layer",
+      "position": [87, 87],
+      "bounds": [15, 15],
+      "transform": 26
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='positioned-fixed' class='positionFixed positioned'",
+      "bounds": [80, 40],
+      "contentsOpaque": true,
+      "backgroundColor": "#800080",
+      "transform": 27
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled'",
+      "position": [6, 34],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 28
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled')",
+      "position": [6, 90],
+      "bounds": [75, 24],
+      "backgroundColor": "#0000FF",
+      "transform": 28
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='sibling-absolute-sibling-grandchildren-not-contained' class='positionFixed sibling'",
+      "bounds": [50, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 29
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='sibling-absolute-sibling-grandchildren' class='positionFixed sibling'",
+      "bounds": [50, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 30
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='sibling-absolute-sibling-not-contained' class='positionFixed sibling'",
+      "bounds": [50, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 31
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='sibling-absolute-sibling' class='positionFixed sibling'",
+      "bounds": [50, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 32
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='sibling-fixed-sibling-grandchildren' class='positionFixed sibling'",
+      "bounds": [50, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 33
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV id='sibling-fixed-sibling' class='positionFixed sibling'",
+      "bounds": [50, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 34
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-grandchildren-not-contained' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 2
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-grandchildren-not-contained' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 2
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-grandchildren' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 4
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-grandchildren' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 4
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-not-contained' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 6
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-not-contained' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 6
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren-not-contained' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 8
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren-not-contained' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 8
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 10
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 10
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 12
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 12
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 14
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 14
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 16
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 16
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling-grandchildren' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 18
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling-grandchildren' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 18
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 22
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 22
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-grandchildren' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 24
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-grandchildren' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 24
+    },
+    {
+      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled onTop'",
+      "position": [6, 6],
+      "bounds": [75, 24],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
+      "transform": 28
+    },
+    {
+      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled onTop')",
+      "position": [6, 62],
+      "bounds": [75, 80],
+      "transform": 28
+    },
+    {
+      "name": "ContentsLayer for Vertical Scrollbar Layer",
+      "position": [785, 0],
+      "bounds": [15, 600],
+      "contentsOpaque": true
+    }
+  ],
+  "transforms": [
+    {
+      "id": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 2,
+      "parent": 1,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 3,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [130, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 4,
+      "parent": 3,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 6,
+      "parent": 5,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 7,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [370, 10, 0, 1]
+      ]
+    },
+    {
+      "id": 8,
+      "parent": 7,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 9,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 130, 0, 1]
+      ]
+    },
+    {
+      "id": 10,
+      "parent": 9,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 11,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [130, 130, 0, 1]
+      ]
+    },
+    {
+      "id": 12,
+      "parent": 11,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 13,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 130, 0, 1]
+      ]
+    },
+    {
+      "id": 14,
+      "parent": 13,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 15,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [370, 130, 0, 1]
+      ]
+    },
+    {
+      "id": 16,
+      "parent": 15,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 17,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [10, 250, 0, 1]
+      ]
+    },
+    {
+      "id": 18,
+      "parent": 17,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 19,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [35, 315, 0, 1]
+      ]
+    },
+    {
+      "id": 20,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [130, 250, 0, 1]
+      ]
+    },
+    {
+      "id": 21,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [155, 315, 0, 1]
+      ]
+    },
+    {
+      "id": 22,
+      "parent": 20,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 23,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [250, 250, 0, 1]
+      ]
+    },
+    {
+      "id": 24,
+      "parent": 23,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 25,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [275, 315, 0, 1]
+      ]
+    },
+    {
+      "id": 26,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [370, 250, 0, 1]
+      ]
+    },
+    {
+      "id": 27,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [395, 315, 0, 1]
+      ]
+    },
+    {
+      "id": 28,
+      "parent": 26,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [0, -59, 0, 1]
+      ]
+    },
+    {
+      "id": 29,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [375, 20, 0, 1]
+      ]
+    },
+    {
+      "id": 30,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [15, 140, 0, 1]
+      ]
+    },
+    {
+      "id": 31,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [135, 140, 0, 1]
+      ]
+    },
+    {
+      "id": 32,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [255, 140, 0, 1]
+      ]
+    },
+    {
+      "id": 33,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [15, 260, 0, 1]
+      ]
+    },
+    {
+      "id": 34,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [135, 260, 0, 1]
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 0014a98..c529ba8 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1588,6 +1588,7 @@
     getter format
     getter planes
     getter timestamp
+    method clone
     method constructor
     method createImageBitmap
     method destroy
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt
index 6f27e50a..e6514024 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer-expected.txt
@@ -9,7 +9,6 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV class='container'",
       "bounds": [14, 14],
-      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 14, 14]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
index 3f8ba64..f4c7178 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer-expected.txt
@@ -18,6 +18,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV class='containerOverlapsComposited')",
       "position": [12, 12],
       "bounds": [100, 30000],
+      "backgroundColor": "#008000",
       "transform": 2
     },
     {
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
index d0e58ab4..8ea0f33 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll-expected.txt
@@ -12,6 +12,7 @@
       "position": [-360, -90],
       "bounds": [360, 90],
       "contentsOpaque": true,
+      "backgroundColor": "#FFFF00",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/float-under-composited-inline-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/float-under-composited-inline-expected.txt
index 952b8fe..6a81de3 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/float-under-composited-inline-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/float-under-composited-inline-expected.txt
@@ -10,6 +10,7 @@
       "name": "LayoutInline (relative positioned) SPAN",
       "position": [108, 108],
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 100, 100]
       ]
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt
index c421690..415d220f0 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV)",
       "position": [42, 42],
       "bounds": [200, 200],
+      "backgroundColor": "#ADD8E6",
       "invalidations": [
         [0, 0, 200, 200]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt
index bc106d1..6bc15bd 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV)",
       "position": [42, 42],
       "bounds": [251, 251],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [50, 50, 201, 201]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.txt
index 0add6c83..6df4e15 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/new-stacking-context-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [200, 200],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 200, 200]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter-expected.txt
index e04c5380..f468d4f 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter-expected.txt
@@ -15,7 +15,6 @@
     {
       "name": "LayoutNGBlockFlow BODY",
       "bounds": [284, 84],
-      "backgroundColor": "#FFFF00",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
index 9d86bbc3..5cc9bd80 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
@@ -16,6 +16,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='foo')",
       "bounds": [100, 1000],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 1000]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
index 86a609c3..3593e81 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-via-layout-offset-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) SPAN class='child')",
       "position": [42, 42],
       "bounds": [50, 50],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 50, 50]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt
index f207c0ee..fa64b3a 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint-expected.txt
@@ -16,6 +16,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV)",
       "position": [47, 47],
       "bounds": [500, 500],
+      "backgroundColor": "#ADD8E6",
       "invalidations": [
         [0, 0, 500, 500]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
index 7317db9..dc57b41 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 1000, 1000]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt
index 8e4eaae..f480789 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/squashing-inside-preserve-3d-element-expected.txt
@@ -17,6 +17,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='target')",
       "position": [20, 20],
       "bounds": [100, 100],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt b/third_party/blink/web_tests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
index ae3baa49..4c288da 100644
--- a/third_party/blink/web_tests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/reflection/scroll-fixed-layer-with-reflection-expected.txt
@@ -10,6 +10,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt b/third_party/blink/web_tests/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt
index 37a55c4..431d12f 100644
--- a/third_party/blink/web_tests/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/reflection/scroll-fixed-reflected-layer-expected.txt
@@ -11,6 +11,7 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='reflected fixed'",
       "bounds": [100, 100],
       "contentsOpaque": true,
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt b/third_party/blink/web_tests/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt
index 638e45e..a440697 100644
--- a/third_party/blink/web_tests/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [10000, 385],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 10000, 200]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt b/third_party/blink/web_tests/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
index ddf2c69..59e10ec1 100644
--- a/third_party/blink/web_tests/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content-expected.txt
@@ -10,6 +10,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt b/third_party/blink/web_tests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
index ddf2c69..59e10ec1 100644
--- a/third_party/blink/web_tests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/scroll/scroll-in-fixed-layer-expected.txt
@@ -10,6 +10,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='moveMe' class='fixed clipped'",
       "bounds": [100, 100],
+      "backgroundColor": "#008000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt b/third_party/blink/web_tests/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt
index a29056a..9044d18 100644
--- a/third_party/blink/web_tests/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/scroll/scrolled-iframe-scrollbar-change-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [804, 604],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [2, 2, 800, 600]
       ]
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt b/third_party/blink/web_tests/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
index 3885b032..44034b5 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
@@ -9,11 +9,10 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='target'",
       "position": [-2, -2],
-      "bounds": [204, 204],
+      "bounds": [404, 544],
       "backfaceVisibility": "hidden",
-      "backgroundColor": "#FFFF00",
       "invalidations": [
-        [0, 0, 204, 204]
+        [0, 0, 404, 544]
       ],
       "transform": 1
     },
@@ -21,6 +20,7 @@
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV)",
       "position": [100, 100],
       "bounds": [300, 440],
+      "backgroundColor": "#0000FF",
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/paint/invalidation/table/invalidate-cell-in-row-with-offset-expected.txt b/third_party/blink/web_tests/paint/invalidation/table/invalidate-cell-in-row-with-offset-expected.txt
index 3b0b40b..625f998 100644
--- a/third_party/blink/web_tests/paint/invalidation/table/invalidate-cell-in-row-with-offset-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/table/invalidate-cell-in-row-with-offset-expected.txt
@@ -9,8 +9,7 @@
     {
       "name": "LayoutTableRow TR",
       "position": [8, 18],
-      "drawsContent": false,
-      "backgroundColor": "#0000FF"
+      "drawsContent": false
     },
     {
       "name": "LayoutTableRow TR",
diff --git a/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-centered-inline-under-fixed-pos-expected.txt b/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-centered-inline-under-fixed-pos-expected.txt
index 53c75e82..00fb2474 100644
--- a/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-centered-inline-under-fixed-pos-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/window-resize/window-resize-centered-inline-under-fixed-pos-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [600, 250],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
+      "backgroundColor": "#D3D3D3",
       "invalidations": [
         [0, 0, 600, 250]
       ]
@@ -17,7 +17,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [400, 250],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
+      "backgroundColor": "#D3D3D3",
       "invalidations": [
         [0, 0, 400, 250]
       ]
@@ -30,7 +30,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [400, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
+      "backgroundColor": "#D3D3D3",
       "invalidations": [
         [0, 0, 400, 600]
       ]
@@ -43,7 +43,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
+      "backgroundColor": "#D3D3D3",
       "invalidations": [
         [0, 0, 800, 600]
       ]
diff --git a/third_party/blink/web_tests/platform/fuchsia/compositing/geometry/bounds-ignores-hidden-expected.txt b/third_party/blink/web_tests/platform/fuchsia/compositing/geometry/bounds-ignores-hidden-expected.txt
index e9be995..2e3378153 100644
--- a/third_party/blink/web_tests/platform/fuchsia/compositing/geometry/bounds-ignores-hidden-expected.txt
+++ b/third_party/blink/web_tests/platform/fuchsia/compositing/geometry/bounds-ignores-hidden-expected.txt
@@ -10,7 +10,8 @@
       "name": "LayoutNGBlockFlow (positioned) DIV class='composited'",
       "position": [10, 10],
       "bounds": [50, 50],
-      "contentsOpaque": true
+      "contentsOpaque": true,
+      "backgroundColor": "#000000"
     },
     {
       "name": "ContentsLayer for Horizontal Scrollbar Layer",
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-expected.txt
index 5af72821..5daf65f 100644
--- a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-setters-expected.txt
@@ -34,18 +34,18 @@
 FAIL URL: Setting <http://test@example.net>.protocol = 'file' Can’t switch from URL containing username/password/port to file assert_equals: expected "http://test@example.net/" but got "file://test%40example.net/"
 FAIL <a>: Setting <http://test@example.net>.protocol = 'file' Can’t switch from URL containing username/password/port to file assert_equals: expected "http://test@example.net/" but got "file://test%40example.net/"
 FAIL <area>: Setting <http://test@example.net>.protocol = 'file' Can’t switch from URL containing username/password/port to file assert_equals: expected "http://test@example.net/" but got "file://test%40example.net/"
-FAIL URL: Setting <gopher://example.net:1234>.protocol = 'file' assert_equals: expected "gopher://example.net:1234" but got "file://example.net:1234/"
-FAIL <a>: Setting <gopher://example.net:1234>.protocol = 'file' assert_equals: expected "gopher://example.net:1234" but got "file://example.net:1234/"
-FAIL <area>: Setting <gopher://example.net:1234>.protocol = 'file' assert_equals: expected "gopher://example.net:1234" but got "file://example.net:1234/"
+FAIL URL: Setting <https://example.net:1234>.protocol = 'file' assert_equals: expected "https://example.net:1234/" but got "file://example.net:1234/"
+FAIL <a>: Setting <https://example.net:1234>.protocol = 'file' assert_equals: expected "https://example.net:1234/" but got "file://example.net:1234/"
+FAIL <area>: Setting <https://example.net:1234>.protocol = 'file' assert_equals: expected "https://example.net:1234/" but got "file://example.net:1234/"
 FAIL URL: Setting <wss://x:x@example.net:1234>.protocol = 'file' assert_equals: expected "wss://x:x@example.net:1234/" but got "file://x:x%40example.net:1234/"
 FAIL <a>: Setting <wss://x:x@example.net:1234>.protocol = 'file' assert_equals: expected "wss://x:x@example.net:1234/" but got "file://x:x%40example.net:1234/"
 FAIL <area>: Setting <wss://x:x@example.net:1234>.protocol = 'file' assert_equals: expected "wss://x:x@example.net:1234/" but got "file://x:x%40example.net:1234/"
 FAIL URL: Setting <file://localhost/>.protocol = 'http' Can’t switch from file URL with no host assert_equals: expected "file:///" but got "http://localhost/"
 FAIL <a>: Setting <file://localhost/>.protocol = 'http' Can’t switch from file URL with no host assert_equals: expected "file:///" but got "http://localhost/"
 FAIL <area>: Setting <file://localhost/>.protocol = 'http' Can’t switch from file URL with no host assert_equals: expected "file:///" but got "http://localhost/"
-FAIL URL: Setting <file:///test>.protocol = 'gopher' assert_equals: expected "file:///test" but got "gopher:///test"
-FAIL <a>: Setting <file:///test>.protocol = 'gopher' assert_equals: expected "file:///test" but got "gopher:///test"
-FAIL <area>: Setting <file:///test>.protocol = 'gopher' assert_equals: expected "file:///test" but got "gopher:///test"
+FAIL URL: Setting <file:///test>.protocol = 'https' assert_equals: expected "file:///test" but got "https://test/"
+FAIL <a>: Setting <file:///test>.protocol = 'https' assert_equals: expected "file:///test" but got "https://test/"
+FAIL <area>: Setting <file:///test>.protocol = 'https' assert_equals: expected "file:///test" but got "https://test/"
 FAIL URL: Setting <file:>.protocol = 'wss' assert_equals: expected "file:///" but got "wss:"
 FAIL <a>: Setting <file:>.protocol = 'wss' assert_equals: expected "file:///" but got "wss:"
 FAIL <area>: Setting <file:>.protocol = 'wss' assert_equals: expected "file:///" but got "wss:"
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt b/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
deleted file mode 100644
index 31bfd21..0000000
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow (positioned) DIV id='target'",
-      "position": [-2, -2],
-      "bounds": [404, 544],
-      "backfaceVisibility": "hidden",
-      "backgroundColor": "#FFFF00",
-      "invalidations": [
-        [0, 0, 404, 544]
-      ],
-      "transform": 1
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV)",
-      "position": [100, 100],
-      "bounds": [300, 440],
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 58, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-format-style-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-format-style-expected.txt
new file mode 100644
index 0000000..5d9bc538
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-format-style-expected.txt
@@ -0,0 +1,53 @@
+CONSOLE MESSAGE: line 14: %cBlue!. color: blue;
+CONSOLE MESSAGE: line 15: %cBlue! %cRed! color: blue; color: red;
+CONSOLE MESSAGE: line 16: %cBlue!
+%cRed! color: blue; color: red;
+CONSOLE MESSAGE: line 17: %cwww.google.com color: blue
+CONSOLE WARNING: line 18: %cwww.google.com color: blue; background: blue
+CONSOLE ERROR: line 19: %cwww.google.com color: blue; background: blue
+CONSOLE MESSAGE: line 20: 12345678
+CONSOLE MESSAGE: line 21: %d%f%s%d%f%s%d%f 1 1.1 a 2 2.2 b 3 3.3
+Tests that console logging dumps properly styled messages.
+
+console-format-style.js:14 Blue!.
+Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: blue;
+console-format-style.js:15 Blue! Red!
+Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: blue;
+Styled text #1: contain: paint; display: inline-block; max-width: 100%; color: red;
+console-format-style.js:16 Blue!Red!
+Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: blue;
+Styled text #1: NO STYLES DEFINED
+Styled text #2: contain: paint; display: inline-block; max-width: 100%; color: blue;
+Styled text #3: contain: paint; display: inline-block; max-width: 100%; color: red;
+console-format-style.js:17 www.google.com
+Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: blue;
+Styled text #1: -webkit-text-stroke: 0px !important; text-decoration: underline !important; color: rgb(84, 84, 84) !important; background-color: rgb(255, 255, 255) !important;
+console-format-style.js:18 www.google.com
+onload @ console-format-style.js:18
+(anonymous) @ console-format-style.js:22
+Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: blue; background: blue;
+Styled text #1: -webkit-text-stroke: 0px !important; text-decoration: underline !important; color: rgb(84, 84, 84) !important; background-color: rgb(255, 251, 229) !important;
+console-format-style.js:19 www.google.com
+onload @ console-format-style.js:19
+(anonymous) @ console-format-style.js:22
+Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: blue; background: blue;
+Styled text #1: -webkit-text-stroke: 0px !important; text-decoration: underline !important; color: rgb(84, 84, 84) !important; background-color: rgb(255, 240, 240) !important;
+console-format-style.js:20 12345678
+Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: black;
+Styled text #1: contain: paint; display: inline-block; max-width: 100%; color: red;
+Styled text #2: contain: paint; display: inline-block; max-width: 100%; color: darkgray;
+Styled text #3: contain: paint; display: inline-block; max-width: 100%;
+Styled text #4: contain: paint; display: inline-block; max-width: 100%; background: black;
+Styled text #5: contain: paint; display: inline-block; max-width: 100%; background: red;
+Styled text #6: contain: paint; display: inline-block; max-width: 100%; background: darkgray;
+Styled text #7: contain: paint; display: inline-block; max-width: 100%;
+console-format-style.js:21 11.1a22.2b33.3
+Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: black;
+Styled text #1: contain: paint; display: inline-block; max-width: 100%; color: red;
+Styled text #2: contain: paint; display: inline-block; max-width: 100%; color: darkgray;
+Styled text #3: contain: paint; display: inline-block; max-width: 100%;
+Styled text #4: contain: paint; display: inline-block; max-width: 100%; background: black;
+Styled text #5: contain: paint; display: inline-block; max-width: 100%; background: red;
+Styled text #6: contain: paint; display: inline-block; max-width: 100%; background: darkgray;
+Styled text #7: contain: paint; display: inline-block; max-width: 100%;
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-group-click-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-group-click-expected.txt
new file mode 100644
index 0000000..81d900c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-group-click-expected.txt
@@ -0,0 +1,17 @@
+CONSOLE MESSAGE: line 12: group with object [object Object]
+CONSOLE MESSAGE: line 13: Message inside group
+CONSOLE MESSAGE: line 14: console.groupEnd
+Tests that clicks on console.group target the appropriate element.
+
+
+Before
+console-group-click.js:12 group with object {x: 1}
+
+Click on the group
+console-group-click.js:12 group with object {x: 1}
+console-group-click.js:13 Message inside group
+
+Click on the object
+console-group-click.js:12 group with object {x: 1}x: 1__proto__: Object
+console-group-click.js:13 Message inside group
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-link-to-snippet-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-link-to-snippet-expected.txt
new file mode 100644
index 0000000..01f147a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-link-to-snippet-expected.txt
@@ -0,0 +1,30 @@
+CONSOLE MESSAGE: line 1: 239
+CONSOLE ERROR: line 2: 42
+CONSOLE ERROR: line 3: 0
+CONSOLE ERROR: line 4: false
+CONSOLE ERROR: line 5: null
+Test that link to snippet works.
+
+
+Running: testConsoleLogAndReturnMessageLocation
+name1:1 239
+name1:1 42
+
+Running: testSnippetSyntaxError
+Line Message was added: snippet:///name2 Error 'Uncaught SyntaxError: Unexpected token '}'':1:1
+name2:2 Uncaught SyntaxError: Unexpected token '}'
+
+Running: testConsoleErrorHighlight
+Line Message was added: snippet:///name3 Error '42':1:8
+Line Message was added: snippet:///name3 Error '-0':2:8
+Line Message was added: snippet:///name3 Error 'false':3:8
+Line Message was added: snippet:///name3 Error 'null':4:8
+name3:2 42
+(anonymous) @ name3:2
+name3:3 -0
+(anonymous) @ name3:3
+name3:4 false
+(anonymous) @ name3:4
+name3:5 null
+(anonymous) @ name3:5
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-linkify-relative-links-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-linkify-relative-links-expected.txt
new file mode 100644
index 0000000..6082bf1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-linkify-relative-links-expected.txt
@@ -0,0 +1,23 @@
+CONSOLE MESSAGE: line 10: Error with relative links
+    at (foo1.js:10:50)
+    at (//foo2.js:10:50)
+    at (/foo3.js:10:50)
+    at (../foo4.js:10:50)
+    at (./foo5.js:10:50)
+    at (./bar/foo6.js:10:50)
+Test that logging an error in console would linkify relative URLs
+
+console-linkify-relative-links.js:10 Error with relative links
+    at (foo1.js:10)
+    at (foo2.js:10)
+    at (:8000/foo3.js:10)
+    at (:8000/devtools/foo4.js:10)
+    at (foo5.js:10)
+    at (bar/foo6.js:10)
+Link: foo1.js:10, href: http://127.0.0.1:8000/devtools/resources/foo1.js
+Link: foo2.js:10, href: http://foo2.js
+Link: :8000/foo3.js:10, href: http://127.0.0.1:8000/foo3.js
+Link: :8000/devtools/foo4.js:10, href: http://127.0.0.1:8000/devtools/foo4.js
+Link: foo5.js:10, href: http://127.0.0.1:8000/devtools/resources/foo5.js
+Link: bar/foo6.js:10, href: http://127.0.0.1:8000/devtools/resources/bar/foo6.js
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-log-wrapped-in-framework-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-log-wrapped-in-framework-expected.txt
new file mode 100644
index 0000000..6d42fb9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-log-wrapped-in-framework-expected.txt
@@ -0,0 +1,7 @@
+CONSOLE MESSAGE: line 13: direct console.log()
+CONSOLE MESSAGE: line 7: framework log
+Tests console.log() anchor location when the skip-stack-frames feature is enabled.
+
+console-log-wrapped-in-framework.js:13 direct console.log()
+console-log-wrapped-in-framework.js:14 framework log
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-message-contains-async-stack-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-message-contains-async-stack-expected.txt
new file mode 100644
index 0000000..8d44c715
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-message-contains-async-stack-expected.txt
@@ -0,0 +1,7 @@
+CONSOLE ERROR: line 1: Uncaught SyntaxError: Unexpected end of input
+Tests exception message with empty stack in console contains async stack trace.
+
+VM:1 Uncaught SyntaxError: Unexpected end of input
+setTimeout (async)
+(anonymous) @ console-message-cont…s-async-stack.js:14
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-table-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-table-expected.txt
new file mode 100644
index 0000000..25b819c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-table-expected.txt
@@ -0,0 +1,15 @@
+CONSOLE MESSAGE: [object Object],[object Object],[object Object],[object Object]
+CONSOLE MESSAGE: [object Object],[object Object],[object Object],[object Object]
+Tests that console.table is properly rendered on tables with more than 20 columns(maxColumnsToRender).
+
+HEADER (index) | b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | b10 | b11 | b12 | b13 | b14 | a0 | a1 | a2 | a3 | a4 | 
+ROW "b0" | "b1" | "b2" | "b3" | "b4" | "b5" | "b6" | "b7" | "b8" | "b9" | "b10" | "b11" | "b12" | "b13" | "b14" | 
+ROW "b0" | "b1" | "b2" | "b3" | "b4" | "b5" | "b6" | "b7" | "b8" | "b9" | "b10" | "b11" | "b12" | "b13" | "b14" | "a0" | "a1" | "a2" | "a3" | "a4" | 
+ROW "b0" | "b1" | "b2" | "b3" | "b4" | "b5" | "b6" | "b7" | "b8" | "b9" | "b10" | "b11" | "b12" | "b13" | "b14" | 
+ROW "b0" | "b1" | "b2" | "b3" | "b4" | "b5" | "b6" | "b7" | "b8" | "b9" | "b10" | "b11" | "b12" | "b13" | "b14" | "a0" | "a1" | "a2" | "a3" | "a4" | 
+HEADER (index) | a0 | a1 | a2 | a3 | a4 | a5 | a6 | a7 | a8 | a9 | a10 | a11 | a12 | a13 | a14 | b0 | b1 | b2 | b3 | b4 | 
+ROW "a0" | "a1" | "a2" | "a3" | "a4" | "a5" | "a6" | "a7" | "a8" | "a9" | "a10" | "a11" | "a12" | "a13" | "a14" | "b0" | "b1" | "b2" | "b3" | "b4" | 
+ROW "b0" | "b1" | "b2" | "b3" | "b4" | 
+ROW "a0" | "a1" | "a2" | "a3" | "a4" | "a5" | "a6" | "a7" | "a8" | "a9" | "a10" | "a11" | "a12" | "a13" | "a14" | "b0" | "b1" | "b2" | "b3" | "b4" | 
+ROW "b0" | "b1" | "b2" | "b3" | "b4" | 
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-trace-in-eval-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-trace-in-eval-expected.txt
new file mode 100644
index 0000000..7af7cab
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/console-trace-in-eval-expected.txt
@@ -0,0 +1,13 @@
+CONSOLE MESSAGE: line 5: console.trace
+Tests that when console.trace is called in eval'ed script ending with //# sourceURL=url it will dump a stack trace that will have the url as the script source. Bug 47252.
+
+evalURL.js:5 console.trace
+b @ evalURL.js:5
+a @ evalURL.js:10
+evalSource @ evalURL.js:13
+eval @ evalURL.js:14
+(anonymous) @ console-trace-in-eval.js:29
+setTimeout (async)
+doEvalSource @ console-trace-in-eval.js:28
+(anonymous) @ console-trace-in-eval.js:39
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/viewport-testing/console-key-expand-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/viewport-testing/console-key-expand-expected.txt
new file mode 100644
index 0000000..26e2811e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/console/viewport-testing/console-key-expand-expected.txt
@@ -0,0 +1,342 @@
+CONSOLE WARNING: line 26: warning
+CONSOLE MESSAGE: line 35: group
+CONSOLE MESSAGE: line 35: log child
+CONSOLE MESSAGE: line 51: before
+CONSOLE MESSAGE: line 51: text [object Object] [object Object]
+CONSOLE MESSAGE: line 51: after
+CONSOLE MESSAGE: line 74: before
+CONSOLE MESSAGE: line 74: text [object Object] [object Object]
+CONSOLE MESSAGE: line 74: after
+CONSOLE MESSAGE: line 117: before
+CONSOLE WARNING: line 117: warning [object Object]
+CONSOLE MESSAGE: line 117: after
+CONSOLE MESSAGE: line 167: before
+CONSOLE MESSAGE: line 167: [object HTMLDivElement]
+CONSOLE MESSAGE: line 167: after
+CONSOLE MESSAGE: line 181: before
+CONSOLE MESSAGE: line 181: [object Object]
+CONSOLE MESSAGE: line 199: [object Object]
+CONSOLE MESSAGE: line 199: after
+CONSOLE MESSAGE: line 226: [object Object]
+Tests that console artifacts can be expanded, collapsed via keyboard.
+
+
+Running: testExpandingTraces
+Evaluating: console.warn("warning")
+Message count: 1
+
+Force selecting index 0
+Viewport virtual selection: 0
+Is trace expanded: NO
+
+ArrowRight:
+Viewport virtual selection: 0
+Is trace expanded: YES
+
+ArrowLeft:
+Viewport virtual selection: 0
+Is trace expanded: NO
+
+Running: testExpandingGroups
+Evaluating: console.group("group"); console.log("log child");
+Message count: 2
+
+Force selecting index 0
+Viewport virtual selection: 0
+Is group expanded: YES
+console-key-expand.js:35 group
+console-key-expand.js:35 log child
+
+ArrowLeft:
+Viewport virtual selection: 0
+Is group expanded: NO
+console-key-expand.js:35 group
+
+ArrowRight:
+Viewport virtual selection: 0
+Is group expanded: YES
+console-key-expand.js:35 group
+console-key-expand.js:35 log child
+
+Running: testNavigateBetweenObjectsAndLogs
+Evaluating: console.log("before");console.log("text", obj1, obj2);console.log("after");
+Message count: 3
+
+Force selecting index 1
+Viewport virtual selection: 1
+activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
+active text: console-key-expand.js:51 text {x: 1} {y: 2}
+
+ArrowRight:
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {x: 1}
+
+ArrowDown:
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {y: 2}
+
+ArrowDown:
+Viewport virtual selection: 1
+activeElement: SPAN.devtools-link
+active text: console-key-expand.js:51
+
+ArrowDown:
+Viewport virtual selection: 2
+activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
+active text: console-key-expand.js:51 after
+
+ArrowUp:
+Viewport virtual selection: 1
+activeElement: SPAN.devtools-link
+active text: console-key-expand.js:51
+
+ArrowUp:
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {y: 2}
+
+ArrowLeft:
+Viewport virtual selection: 1
+activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
+active text: console-key-expand.js:51 text {x: 1} {y: 2}
+
+Running: testExpandingObjects
+Evaluating: console.log("before");console.log("text", obj1, obj2);console.log("after");
+Message count: 3
+
+Force selecting index 1
+Viewport virtual selection: 1
+activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
+active text: console-key-expand.js:74 text {x: 1} {y: 2}
+
+ArrowRight:
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {x: 1}
+
+ArrowRight:
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.selected.expanded
+active text: {x: 1}
+
+ArrowDown:
+Viewport virtual selection: 1
+activeElement: LI.selected
+active text: x: 1
+
+ArrowDown:
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {y: 2}
+
+ArrowRight:
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.selected.expanded
+active text: {y: 2}
+
+ArrowDown:
+
+ArrowDown:
+
+ArrowDown:
+Viewport virtual selection: 2
+activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
+active text: console-key-expand.js:74 after
+
+ArrowUp:
+
+ArrowUp:
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.expanded.selected
+active text: {y: 2}
+
+ArrowLeft:
+Viewport virtual selection: 1
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {y: 2}
+
+ArrowLeft:
+Viewport virtual selection: 1
+activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
+active text: console-key-expand.js:74 text {x: 1}x: 1 {y: 2}y: 2
+
+Running: testExpandingObjectInTrace
+Evaluating: console.log("before");console.warn("warning", obj1);console.log("after");
+Message count: 3
+
+Force selecting index 1
+Viewport virtual selection: 1
+Has object: collapsed
+Is trace expanded: NO
+activeElement: DIV.console-message-wrapper.console-from-api.console-warning-level.console-selected
+active text: console-key-expand.js:117 warning {x: 1}
+(anonymous) @ console-key-expand.js:117
+
+ArrowRight:
+Viewport virtual selection: 1
+Has object: collapsed
+Is trace expanded: YES
+activeElement: DIV.console-message-wrapper.console-from-api.console-warning-level.console-selected
+active text: console-key-expand.js:117 warning {x: 1}
+(anonymous) @ console-key-expand.js:117
+
+ArrowRight:
+Viewport virtual selection: 1
+Has object: collapsed
+Is trace expanded: YES
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {x: 1}
+
+ArrowRight:
+Viewport virtual selection: 1
+Has object: expanded
+Is trace expanded: YES
+activeElement: LI.parent.object-properties-section-root-element.selected.expanded
+active text: {x: 1}
+
+ArrowDown:
+Viewport virtual selection: 1
+Has object: expanded
+Is trace expanded: YES
+activeElement: LI.selected
+active text: x: 1
+
+ArrowDown:
+
+ArrowDown:
+
+ArrowDown:
+Viewport virtual selection: 2
+Has object: expanded
+Is trace expanded: YES
+activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
+active text: console-key-expand.js:117 after
+
+ArrowUp:
+
+ArrowUp:
+Viewport virtual selection: 1
+Has object: expanded
+Is trace expanded: YES
+activeElement: SPAN.devtools-link
+active text: console-key-expand.js:117
+
+ArrowUp:
+Viewport virtual selection: 1
+Has object: expanded
+Is trace expanded: YES
+activeElement: LI.parent.object-properties-section-root-element.expanded.selected
+active text: {x: 1}
+
+ArrowUp:
+Viewport virtual selection: 1
+Has object: expanded
+Is trace expanded: YES
+activeElement: DIV.console-message-wrapper.console-from-api.console-warning-level.console-selected
+active text: console-key-expand.js:117 warning {x: 1}x: 1
+(anonymous) @ console-key-expand.js:117
+
+ArrowLeft:
+Viewport virtual selection: 1
+Has object: expanded
+Is trace expanded: NO
+activeElement: DIV.console-message-wrapper.console-from-api.console-warning-level.console-selected
+active text: console-key-expand.js:117 warning {x: 1}x: 1
+(anonymous) @ console-key-expand.js:117
+
+ArrowLeft:
+Viewport virtual selection: 1
+Has object: expanded
+Is trace expanded: NO
+activeElement: DIV.console-message-wrapper.console-from-api.console-warning-level.console-selected
+active text: console-key-expand.js:117 warning {x: 1}x: 1
+(anonymous) @ console-key-expand.js:117
+
+Running: testExpandingElement
+Evaluating: console.log("before");console.log(el);console.log("after");
+Message count: 3
+
+Force selecting index 1
+Viewport virtual selection: 1
+activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
+active text: console-key-expand.js:167 <div>​…​</div>​
+
+ArrowDown:
+
+ArrowDown:
+Viewport virtual selection: 1
+activeElement: LI.parent.selected
+active text: <div>​…​</div>​
+
+ArrowRight:
+Viewport virtual selection: 1
+activeElement: LI.parent.selected.expanded
+active text: <div>​
+
+Running: testShiftTabShouldSelectLastObject
+Evaluating: console.log("before");console.log(obj1);
+Message count: 2
+Setting focus in prompt:
+
+Shift+Tab:
+
+ArrowUp:
+Viewport virtual selection: 1
+Has object: collapsed
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {x: 1}
+
+ArrowRight:
+Viewport virtual selection: 1
+Has object: expanded
+activeElement: LI.parent.object-properties-section-root-element.selected.expanded
+active text: {x: 1}
+
+Running: testArrowUpToFirstVisibleMessageShouldSelectLastObject
+Evaluating: console.log(obj1);console.log("after");
+Message count: 2
+Setting focus in prompt:
+
+Shift+Tab:
+
+ArrowUp:
+Viewport virtual selection: 1
+Has object: collapsed
+activeElement: DIV.console-message-wrapper.console-from-api.console-info-level.console-selected
+active text: console-key-expand.js:199 after
+
+ArrowUp:
+
+ArrowUp:
+Viewport virtual selection: 0
+Has object: collapsed
+activeElement: LI.parent.object-properties-section-root-element.selected
+active text: {x: 1}
+
+Running: testFocusLastChildInBigObjectShouldScrollIntoView
+Evaluating: console.log(bigObj);
+Message count: 1
+Setting focus in prompt:
+
+Shift+Tab:
+
+ArrowUp:
+
+ArrowRight:
+
+Tab:
+Viewport virtual selection: -1
+Has object: expanded
+activeElement: TEXTAREA
+
+Shift+Tab:
+
+ArrowUp:
+Viewport virtual selection: 0
+Has object: expanded
+activeElement: LI.parent.object-properties-section-root-element.expanded.selected
+active text: {a0: 0, a1: 1, a2: 2, a3: 3, a4: 4, …}
+Is at bottom: false, should stick: false
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/extensions/extensions-reload-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/extensions/extensions-reload-expected.txt
new file mode 100644
index 0000000..24bdb25d
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/extensions/extensions-reload-expected.txt
@@ -0,0 +1,16 @@
+CONSOLE MESSAGE: 42
+Tests that webInspector.inspectedWindow.reload() successfully injects and preprocesses user's code upon reload
+
+Started extension.
+Running tests...
+RUNNING TEST: extension_testReloadInjectsCode
+Page reloaded.
+Page reloaded.
+With injected code: foo = 42
+Without injected code: foo = undefined
+RUNNING TEST: extension_testReloadInjectsCodeWithMessage
+Page reloaded.
+Source received:
+console.log(42)
+All tests done.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/indexeddb/resources-panel-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/indexeddb/resources-panel-expected.txt
new file mode 100644
index 0000000..864b6cb2e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/indexeddb/resources-panel-expected.txt
@@ -0,0 +1,35 @@
+CONSOLE MESSAGE: line 49: InspectorTest.IndexedDB_callback1
+CONSOLE MESSAGE: line 49: InspectorTest.IndexedDB_callback2
+CONSOLE MESSAGE: line 49: InspectorTest.IndexedDB_callback3
+Tests IndexedDB tree element on resources panel.
+
+Expanded IndexedDB tree element.
+Dumping IndexedDB tree:
+    (empty)
+Creating database.
+Created database.
+Refreshing.
+Refreshed.
+Dumping IndexedDB tree:
+    database: testDatabase - http://127.0.0.1:8000
+        Object store: testObjectStore
+            Index: testIndexName
+Navigating to another security origin.
+Navigated to another security origin.
+Dumping IndexedDB tree:
+    (empty)
+Navigating back.
+Navigated back.
+Refreshing.
+Refreshed.
+Dumping IndexedDB tree:
+    database: testDatabase - http://127.0.0.1:8000
+        Object store: testObjectStore
+            Index: testIndexName
+Deleting database.
+Deleted database.
+Refreshing.
+Refreshed.
+Dumping IndexedDB tree:
+    (empty)
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/search/search-ignore-binary-files-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/search/search-ignore-binary-files-expected.txt
new file mode 100644
index 0000000..aa63e1b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/search/search-ignore-binary-files-expected.txt
@@ -0,0 +1,6 @@
+CONSOLE ERROR: line 6: Uncaught (in promise) ReferenceError: TestRunner is not defined
+Verify that search doesn't search in binary resources.
+
+Search result #1: uiSourceCode.url = http://127.0.0.1:8000/devtools/search/search-ignore-binary-files.js
+  search match #1: lineNumber = 17, lineContent = '    var searchConfig = new Search.SearchConfig('sources.search-in-files', 'AAAAAAA', true, false);'
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/sources/debugger/debugger-scope-resolve-this-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/sources/debugger/debugger-scope-resolve-this-expected.txt
new file mode 100644
index 0000000..b0c0af8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/http/tests/devtools/sources/debugger/debugger-scope-resolve-this-expected.txt
@@ -0,0 +1,14 @@
+CONSOLE MESSAGE: line 7: [object Object]
+Tests resolving this object name via source maps.
+
+Set timer for test function.
+Script execution paused.
+
+Scope variables sidebar pane:
+Local
+    this: Foo {}
+Closure (Foo.bar)
+WindowGlobal
+    <section collapsed>
+Script execution resumed.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/compositing/layer-creation/overflow-scroll-overlap-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/compositing/layer-creation/overflow-scroll-overlap-expected.txt
deleted file mode 100644
index fe614ef..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.13/compositing/layer-creation/overflow-scroll-overlap-expected.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow DIV class='composited'",
-      "bounds": [30, 30],
-      "contentsOpaque": true,
-      "backgroundColor": "#808080",
-      "transform": 1
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='scroller' class='overflow')",
-      "position": [12, 12],
-      "bounds": [306, 206],
-      "transform": 1
-    },
-    {
-      "name": "LayoutNGBlockFlow (relative positioned) DIV class='box'",
-      "position": [23, 58],
-      "bounds": [200, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 3
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV class='box')",
-      "position": [23, 213],
-      "bounds": [210, 100],
-      "transform": 3
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [20, 20, 0, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "parent": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -49, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-auto-with-touch-expected.txt
index c543542..9e8531ab 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-auto-with-touch-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
index c543542..9e8531ab 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-overlay-with-touch-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-overlay-with-touch-expected.txt
index c543542..9e8531ab 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-overlay-with-touch-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/compositing/overflow/overflow-overlay-with-touch-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
index 9d86bbc3..5cc9bd80 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
@@ -16,6 +16,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='foo')",
       "bounds": [100, 1000],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 1000]
       ],
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
deleted file mode 100644
index 31bfd21..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.14/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow (positioned) DIV id='target'",
-      "position": [-2, -2],
-      "bounds": [404, 544],
-      "backfaceVisibility": "hidden",
-      "backgroundColor": "#FFFF00",
-      "invalidations": [
-        [0, 0, 404, 544]
-      ],
-      "transform": 1
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV)",
-      "position": [100, 100],
-      "bounds": [300, 440],
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 58, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/overflow-scroll-overlap-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/overflow-scroll-overlap-expected.txt
index 24c0ac7..d666557d 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/overflow-scroll-overlap-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/overflow-scroll-overlap-expected.txt
@@ -14,21 +14,25 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow (positioned) DIV id='scroller' class='overflow'",
+      "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='scroller' class='overflow')",
+      "position": [12, 12],
       "bounds": [306, 206],
-      "transform": 2
+      "transform": 1
     },
     {
-      "name": "Scrolling Contents Layer",
-      "position": [3, 3],
-      "bounds": [285, 365],
+      "name": "LayoutNGBlockFlow (relative positioned) DIV class='box'",
+      "position": [23, 58],
+      "bounds": [200, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#0000FF",
       "transform": 3
     },
     {
-      "name": "ContentsLayer for Vertical Scrollbar Layer",
-      "position": [288, 3],
-      "bounds": [15, 200],
-      "transform": 2
+      "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (relative positioned) DIV class='box')",
+      "position": [23, 213],
+      "bounds": [210, 100],
+      "backgroundColor": "#0000FF",
+      "transform": 3
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt
index 3fe8b77..4c12a3a 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
index 3fe8b77..4c12a3a 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-overlay-with-touch-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-overlay-with-touch-expected.txt
index 3fe8b77..4c12a3a 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-overlay-with-touch-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-overlay-with-touch-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/html/semantics/forms/input-change-event-properties-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/html/semantics/forms/input-change-event-properties-expected.txt
new file mode 100644
index 0000000..b4fdaf6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/html/semantics/forms/input-change-event-properties-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+PASS <input type="checkbox"> click()
+PASS <input type="radio"> click()
+PASS <input type="text"> typing
+PASS <input type="search"> typing
+PASS <input type="tel"> typing
+PASS <input type="url"> typing
+PASS <input type="email"> typing
+PASS <input type="password"> typing
+PASS <input type="number"> typing
+PASS <textarea></textarea> typing
+FAIL <select> pressing down arrow promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'bubbles' of undefined"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/mathml/presentation-markup/mpadded/mpadded-002-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/mathml/presentation-markup/mpadded/mpadded-002-expected.txt
deleted file mode 100644
index 1a35afc..0000000
--- a/third_party/blink/web_tests/platform/mac/external/wpt/mathml/presentation-markup/mpadded/mpadded-002-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This is a testharness.js-based test.
-FAIL mpadded with no attributes assert_approx_equals: content height expected 150 +/- 1 but got -4
-FAIL Different widths assert_approx_equals: width 0 expected 25 +/- 1 but got 100
-FAIL Different heights assert_approx_equals: height0 expected 25 +/- 1 but got -4
-FAIL Percentage calculation for width, height and depth assert_equals: width expected 50 but got 100
-FAIL Different depths assert_approx_equals: depth0 expected 25 +/- 1 but got 125
-FAIL Various combinations of height, depth and width. assert_approx_equals: width0 expected 25 +/- 1 but got 100
-PASS Preferred width
-PASS dynamic attributes (remove)
-FAIL dynamic attributes (attach) assert_approx_equals: expected 50 +/- 1 but got 100
-FAIL dynamic attributes (modify) assert_approx_equals: expected 50 +/- 1 but got 100
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters-expected.txt
index 5af72821..5daf65f 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-setters-expected.txt
@@ -34,18 +34,18 @@
 FAIL URL: Setting <http://test@example.net>.protocol = 'file' Can’t switch from URL containing username/password/port to file assert_equals: expected "http://test@example.net/" but got "file://test%40example.net/"
 FAIL <a>: Setting <http://test@example.net>.protocol = 'file' Can’t switch from URL containing username/password/port to file assert_equals: expected "http://test@example.net/" but got "file://test%40example.net/"
 FAIL <area>: Setting <http://test@example.net>.protocol = 'file' Can’t switch from URL containing username/password/port to file assert_equals: expected "http://test@example.net/" but got "file://test%40example.net/"
-FAIL URL: Setting <gopher://example.net:1234>.protocol = 'file' assert_equals: expected "gopher://example.net:1234" but got "file://example.net:1234/"
-FAIL <a>: Setting <gopher://example.net:1234>.protocol = 'file' assert_equals: expected "gopher://example.net:1234" but got "file://example.net:1234/"
-FAIL <area>: Setting <gopher://example.net:1234>.protocol = 'file' assert_equals: expected "gopher://example.net:1234" but got "file://example.net:1234/"
+FAIL URL: Setting <https://example.net:1234>.protocol = 'file' assert_equals: expected "https://example.net:1234/" but got "file://example.net:1234/"
+FAIL <a>: Setting <https://example.net:1234>.protocol = 'file' assert_equals: expected "https://example.net:1234/" but got "file://example.net:1234/"
+FAIL <area>: Setting <https://example.net:1234>.protocol = 'file' assert_equals: expected "https://example.net:1234/" but got "file://example.net:1234/"
 FAIL URL: Setting <wss://x:x@example.net:1234>.protocol = 'file' assert_equals: expected "wss://x:x@example.net:1234/" but got "file://x:x%40example.net:1234/"
 FAIL <a>: Setting <wss://x:x@example.net:1234>.protocol = 'file' assert_equals: expected "wss://x:x@example.net:1234/" but got "file://x:x%40example.net:1234/"
 FAIL <area>: Setting <wss://x:x@example.net:1234>.protocol = 'file' assert_equals: expected "wss://x:x@example.net:1234/" but got "file://x:x%40example.net:1234/"
 FAIL URL: Setting <file://localhost/>.protocol = 'http' Can’t switch from file URL with no host assert_equals: expected "file:///" but got "http://localhost/"
 FAIL <a>: Setting <file://localhost/>.protocol = 'http' Can’t switch from file URL with no host assert_equals: expected "file:///" but got "http://localhost/"
 FAIL <area>: Setting <file://localhost/>.protocol = 'http' Can’t switch from file URL with no host assert_equals: expected "file:///" but got "http://localhost/"
-FAIL URL: Setting <file:///test>.protocol = 'gopher' assert_equals: expected "file:///test" but got "gopher:///test"
-FAIL <a>: Setting <file:///test>.protocol = 'gopher' assert_equals: expected "file:///test" but got "gopher:///test"
-FAIL <area>: Setting <file:///test>.protocol = 'gopher' assert_equals: expected "file:///test" but got "gopher:///test"
+FAIL URL: Setting <file:///test>.protocol = 'https' assert_equals: expected "file:///test" but got "https://test/"
+FAIL <a>: Setting <file:///test>.protocol = 'https' assert_equals: expected "file:///test" but got "https://test/"
+FAIL <area>: Setting <file:///test>.protocol = 'https' assert_equals: expected "file:///test" but got "https://test/"
 FAIL URL: Setting <file:>.protocol = 'wss' assert_equals: expected "file:///" but got "wss:"
 FAIL <a>: Setting <file:>.protocol = 'wss' assert_equals: expected "file:///" but got "wss:"
 FAIL <area>: Setting <file:>.protocol = 'wss' assert_equals: expected "file:///" but got "wss:"
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
index 43310aa..1e87888 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
@@ -39,6 +39,7 @@
     {
       "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV id='foo')",
       "bounds": [100, 1000],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 1000]
       ],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt
index df14160..3692673a 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/forms/textarea-caret-expected.txt
@@ -13,6 +13,7 @@
       "name": "LayoutTextControl TEXTAREA id='editor'",
       "position": [-2, -2],
       "bounds": [185, 40],
+      "backgroundColor": "#FFFFFF",
       "invalidations": [
         [0, 0, 185, 40]
       ],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
index a1dbd876..9bd95709 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
@@ -13,6 +13,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='scrollpanel'",
       "bounds": [100, 100],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
index 6b44db0..0c81303d 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
@@ -17,6 +17,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='searchbar'",
       "bounds": [150, 150],
+      "backgroundColor": "#800080",
       "transform": 3
     },
     {
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
deleted file mode 100644
index 31bfd21..0000000
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow (positioned) DIV id='target'",
-      "position": [-2, -2],
-      "bounds": [404, 544],
-      "backfaceVisibility": "hidden",
-      "backgroundColor": "#FFFF00",
-      "invalidations": [
-        [0, 0, 404, 544]
-      ],
-      "transform": 1
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV)",
-      "position": [100, 100],
-      "bounds": [300, 440],
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 58, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-auto-with-touch-expected.txt
similarity index 79%
rename from third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-expected.txt
rename to third_party/blink/web_tests/platform/win/compositing/overflow/overflow-auto-with-touch-expected.txt
index c543542..9e8531ab 100644
--- a/third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-auto-with-touch-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
similarity index 79%
rename from third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
rename to third_party/blink/web_tests/platform/win/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
index c543542..9e8531ab 100644
--- a/third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
+++ b/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-overlay-with-touch-expected.txt
similarity index 79%
copy from third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-expected.txt
copy to third_party/blink/web_tests/platform/win/compositing/overflow/overflow-overlay-with-touch-expected.txt
index c543542..9e8531ab 100644
--- a/third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/platform/win/compositing/overflow/overflow-overlay-with-touch-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/mathml/presentation-markup/mpadded/mpadded-002-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/mathml/presentation-markup/mpadded/mpadded-002-expected.txt
deleted file mode 100644
index c3e17bbc..0000000
--- a/third_party/blink/web_tests/platform/win/external/wpt/mathml/presentation-markup/mpadded/mpadded-002-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This is a testharness.js-based test.
-FAIL mpadded with no attributes assert_approx_equals: content height expected 150 +/- 1 but got -5
-FAIL Different widths assert_approx_equals: width 0 expected 25 +/- 1 but got 100
-FAIL Different heights assert_approx_equals: height0 expected 25 +/- 1 but got -5
-FAIL Percentage calculation for width, height and depth assert_equals: width expected 50 but got 100
-FAIL Different depths assert_approx_equals: depth0 expected 25 +/- 1 but got 125
-FAIL Various combinations of height, depth and width. assert_approx_equals: width0 expected 25 +/- 1 but got 100
-PASS Preferred width
-PASS dynamic attributes (remove)
-FAIL dynamic attributes (attach) assert_approx_equals: expected 50 +/- 1 but got 100
-FAIL dynamic attributes (modify) assert_approx_equals: expected 50 +/- 1 but got 100
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-expected.txt
index 9d2c15e..3a8c219 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-setters-expected.txt
@@ -34,18 +34,18 @@
 FAIL URL: Setting <http://test@example.net>.protocol = 'file' Can’t switch from URL containing username/password/port to file assert_equals: expected "http://test@example.net/" but got "file://test%40example.net/"
 FAIL <a>: Setting <http://test@example.net>.protocol = 'file' Can’t switch from URL containing username/password/port to file assert_equals: expected "http://test@example.net/" but got "file://test%40example.net/"
 FAIL <area>: Setting <http://test@example.net>.protocol = 'file' Can’t switch from URL containing username/password/port to file assert_equals: expected "http://test@example.net/" but got "file://test%40example.net/"
-FAIL URL: Setting <gopher://example.net:1234>.protocol = 'file' assert_equals: expected "gopher://example.net:1234" but got "file://example.net:1234/"
-FAIL <a>: Setting <gopher://example.net:1234>.protocol = 'file' assert_equals: expected "gopher://example.net:1234" but got "file://example.net:1234/"
-FAIL <area>: Setting <gopher://example.net:1234>.protocol = 'file' assert_equals: expected "gopher://example.net:1234" but got "file://example.net:1234/"
+FAIL URL: Setting <https://example.net:1234>.protocol = 'file' assert_equals: expected "https://example.net:1234/" but got "file://example.net:1234/"
+FAIL <a>: Setting <https://example.net:1234>.protocol = 'file' assert_equals: expected "https://example.net:1234/" but got "file://example.net:1234/"
+FAIL <area>: Setting <https://example.net:1234>.protocol = 'file' assert_equals: expected "https://example.net:1234/" but got "file://example.net:1234/"
 FAIL URL: Setting <wss://x:x@example.net:1234>.protocol = 'file' assert_equals: expected "wss://x:x@example.net:1234/" but got "file:///X:/x@example.net:1234/"
 FAIL <a>: Setting <wss://x:x@example.net:1234>.protocol = 'file' assert_equals: expected "wss://x:x@example.net:1234/" but got "file:///X:/x@example.net:1234/"
 FAIL <area>: Setting <wss://x:x@example.net:1234>.protocol = 'file' assert_equals: expected "wss://x:x@example.net:1234/" but got "file:///X:/x@example.net:1234/"
 FAIL URL: Setting <file://localhost/>.protocol = 'http' Can’t switch from file URL with no host assert_equals: expected "file:///" but got "http://localhost/"
 FAIL <a>: Setting <file://localhost/>.protocol = 'http' Can’t switch from file URL with no host assert_equals: expected "file:///" but got "http://localhost/"
 FAIL <area>: Setting <file://localhost/>.protocol = 'http' Can’t switch from file URL with no host assert_equals: expected "file:///" but got "http://localhost/"
-FAIL URL: Setting <file:///test>.protocol = 'gopher' assert_equals: expected "file:///test" but got "gopher:///test"
-FAIL <a>: Setting <file:///test>.protocol = 'gopher' assert_equals: expected "file:///test" but got "gopher:///test"
-FAIL <area>: Setting <file:///test>.protocol = 'gopher' assert_equals: expected "file:///test" but got "gopher:///test"
+FAIL URL: Setting <file:///test>.protocol = 'https' assert_equals: expected "file:///test" but got "https://test/"
+FAIL <a>: Setting <file:///test>.protocol = 'https' assert_equals: expected "file:///test" but got "https://test/"
+FAIL <area>: Setting <file:///test>.protocol = 'https' assert_equals: expected "file:///test" but got "https://test/"
 FAIL URL: Setting <file:>.protocol = 'wss' assert_equals: expected "file:///" but got "wss:"
 FAIL <a>: Setting <file:>.protocol = 'wss' assert_equals: expected "file:///" but got "wss:"
 FAIL <area>: Setting <file:>.protocol = 'wss' assert_equals: expected "file:///" but got "wss:"
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
index 995080d..4a7c6d0 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects-expected.txt
@@ -13,6 +13,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='scrollpanel'",
       "bounds": [100, 100],
+      "backgroundColor": "#FF0000",
       "invalidations": [
         [0, 0, 100, 100]
       ],
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
index b85f352..201318bd 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt
@@ -17,6 +17,7 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='searchbar'",
       "bounds": [150, 150],
+      "backgroundColor": "#800080",
       "transform": 3
     },
     {
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
deleted file mode 100644
index 31bfd21..0000000
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow (positioned) DIV id='target'",
-      "position": [-2, -2],
-      "bounds": [404, 544],
-      "backfaceVisibility": "hidden",
-      "backgroundColor": "#FFFF00",
-      "invalidations": [
-        [0, 0, 404, 544]
-      ],
-      "transform": 1
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutNGBlockFlow (positioned) DIV)",
-      "position": [100, 100],
-      "bounds": [300, 440],
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 58, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html
deleted file mode 100644
index 76adbec3..0000000
--- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables-large-fonts.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../../../resources/testharness.js"></script>
-<script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../../../../../resources/testdriver.js"></script>
-<script src="../../../../../resources/testdriver-vendor.js"></script>
-<script src="resources/test-expectations.js"></script>
-<script src="resources/window-tests-getTables-large-fonts.js"></script>
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables.html b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables.html
deleted file mode 100644
index edeb9aa..0000000
--- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/font-access-window-getTables.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../../../resources/testharness.js"></script>
-<script src="../../../../../resources/testharnessreport.js"></script>
-<script src="../../../../../resources/testdriver.js"></script>
-<script src="../../../../../resources/testdriver-vendor.js"></script>
-<script src="resources/test-expectations.js"></script>
-<script src="resources/window-tests-getTables.js"></script>
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables-large-fonts.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables-large-fonts.js
deleted file mode 100644
index 97d957f8..0000000
--- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables-large-fonts.js
+++ /dev/null
@@ -1,19 +0,0 @@
-'use strict';
-
-promise_test(async t => {
-  await test_driver.set_permission({name: 'font-access'}, 'granted');
-  const iterator = navigator.fonts.query();
-
-  const expectations = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.large]});
-  const expectedFonts = await filterEnumeration(iterator, expectations);
-  const additionalExpectedTables = getMoreExpectedTables(expectations);
-  for (const f of expectedFonts) {
-    const tables = await f.getTables();
-    assert_font_has_tables(f.postscriptName, tables, BASE_TABLES);
-    if (f.postscriptName in additionalExpectedTables) {
-      assert_font_has_tables(f.postscriptName,
-                             tables,
-                             additionalExpectedTables[f.postscriptName]);
-    }
-  }
-}, 'getTables(): large fonts have expected non-empty tables');
diff --git a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables.js b/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables.js
deleted file mode 100644
index ed08979e3..0000000
--- a/third_party/blink/web_tests/virtual/font-access/http/tests/font-access/resources/window-tests-getTables.js
+++ /dev/null
@@ -1,159 +0,0 @@
-'use strict';
-
-promise_test(async t => {
-  await test_driver.set_permission({name: 'font-access'}, 'granted');
-  const iterator = navigator.fonts.query();
-
-  const expectations = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.small]});
-  const expectedFonts = await filterEnumeration(iterator, expectations);
-  const additionalExpectedTables = getMoreExpectedTables(expectations);
-  for (const f of expectedFonts) {
-    const tables = await f.getTables();
-    assert_font_has_tables(f.postscriptName, tables, BASE_TABLES);
-    if (f.postscriptName in additionalExpectedTables) {
-      assert_font_has_tables(f.postscriptName,
-                             tables,
-                             additionalExpectedTables[f.postscriptName]);
-    }
-  }
-}, 'getTables(): small sized fonts have expected non-empty tables');
-
-promise_test(async t => {
-  await test_driver.set_permission({name: 'font-access'}, 'granted');
-  const iterator = navigator.fonts.query();
-
-  const expectations = getEnumerationTestSet({labelFilter: [TEST_SIZE_CATEGORY.medium]});
-  const expectedFonts = await filterEnumeration(iterator, expectations);
-  const additionalExpectedTables = getMoreExpectedTables(expectations);
-  for (const f of expectedFonts) {
-    const tables = await f.getTables();
-    assert_font_has_tables(f.postscriptName, tables, BASE_TABLES);
-    if (f.postscriptName in additionalExpectedTables) {
-      assert_font_has_tables(f.postscriptName,
-                             tables,
-                             additionalExpectedTables[f.postscriptName]);
-    }
-  }
-}, 'getTables(): medium sized fonts have expected non-empty tables');
-
-promise_test(async t => {
-  await test_driver.set_permission({name: 'font-access'}, 'granted');
-  const iterator = navigator.fonts.query();
-
-  const expectedFonts = await filterEnumeration(iterator,
-                                                getEnumerationTestSet({
-                                                  labelFilter: [TEST_SIZE_CATEGORY.small]}));
-  const inputs = [
-    ['cmap'], // Single item.
-    ['cmap', 'head'], // Multiple items.
-    ['head', 'head'], // Duplicate items.
-  ];
-  for (const f of expectedFonts) {
-    for (const tableQuery of inputs) {
-      const tables = await f.getTables(tableQuery);
-      assert_font_has_tables(f.postscriptName, tables, tableQuery);
-
-      const querySet = new Set(tableQuery);
-      assert_true(tables.size == querySet.size,
-                  `Got ${tables.size} entries, want ${querySet.size}.`);
-    }
-  }
-}, 'getTables([...]) returns tables');
-
-promise_test(async t => {
-  await test_driver.set_permission({name: 'font-access'}, 'granted');
-  const iterator = navigator.fonts.query();
-
-  const expectedFonts = await filterEnumeration(iterator,
-                                                getEnumerationTestSet({
-                                                  labelFilter: [TEST_SIZE_CATEGORY.small]}));
-  const inputs = [
-    // Nonexistent Tag.
-    ['ABCD'],
-
-    // Boundary testing.
-    ['\x20\x20\x20\x20'],
-    ['\x7E\x7E\x7E\x7E'],
-  ];
-  for (const f of expectedFonts) {
-    for (const tableQuery of inputs) {
-      const tables = await f.getTables(tableQuery);
-      assert_true(tables.size == 0, `Got {tables.size} entries, want zero.`);
-    }
-  }
-}, 'getTables([tableName,...]) returns if a table name does not exist');
-
-promise_test(async t => {
-  await test_driver.set_permission({name: 'font-access'}, 'granted');
-  const iterator = navigator.fonts.query();
-
-  const expectedFonts = await filterEnumeration(iterator,
-                                                getEnumerationTestSet({
-                                                  labelFilter: [TEST_SIZE_CATEGORY.small]}));
-  const inputs = [
-    // empty string
-    [''],
-
-    // Invalid length.
-    [' '],
-    ['A'],
-    ['AB'],
-    ['ABC'],
-
-    // Boundary testing.
-    ['\x19\x19\x19\x19'],
-    ['\x7F\x7F\x7F\x7F'],
-
-    // Tag too long.
-    ['cmap is useful'],
-
-    // Not ByteString.
-    ['\u6568\u6461'], // UTF-16LE, encodes to the same first four bytes as "head" in ASCII.
-    ['\u6568\u6461\x00\x00'], // 4-character, 8-byte string.
-    ['\u6C34'], // U+6C34 CJK UNIFIED IDEOGRAPH (water)
-    ['\uD834\uDD1E'], // U+1D11E MUSICAL SYMBOL G-CLEF (UTF-16 surrogate pair)
-    ['\uFFFD'], // U+FFFD REPLACEMENT CHARACTER
-    ['\uD800'], // UTF-16 surrogate lead
-    ['\uDC00'], // UTF-16 surrogate trail
-  ];
-  for (const f of expectedFonts) {
-    for (const tableQuery of inputs) {
-      await promise_rejects_js(t, TypeError, f.getTables(tableQuery));
-    }
-  }
-}, 'getTables([tableName,...]) rejects for invalid input');
-
-promise_test(async t => {
-  await test_driver.set_permission({name: 'font-access'}, 'granted');
-  const iterator = navigator.fonts.query();
-
-  const expectedFonts = await filterEnumeration(iterator,
-                                                getEnumerationTestSet({
-                                                  labelFilter: [TEST_SIZE_CATEGORY.small]}));
-  const inputs = [
-    {
-      // One exists, one doesn't.
-      tableQuery: ['head', 'blah'],
-      expected: ['head'],
-    },
-    {
-      tableQuery: ['blah', 'head'],
-      expected: ['head'],
-    },
-    {
-      tableQuery: ['cmap', 'head', 'blah'],
-      expected: ['head', 'cmap'],
-    },
-    {
-      // Duplicate entry.
-      tableQuery: ['cmap', 'head', 'blah', 'cmap'],
-      expected: ['head', 'cmap'],
-    },
-  ];
-  for (const f of expectedFonts) {
-    for (const input of inputs) {
-      const tables = await f.getTables(input.tableQuery);
-      assert_font_has_tables(f.postscriptName, tables, input.expected);
-    }
-  }
-}, 'getTables([tableName,...]) returns even if a requested table is not found');
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
index 3fe8b77..4c12a3a 100644
--- a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
index 3fe8b77..4c12a3a 100644
--- a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
+++ b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-hidden-with-touch-expected.txt
similarity index 79%
copy from third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-expected.txt
copy to third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-hidden-with-touch-expected.txt
index c543542..9e8531ab 100644
--- a/third_party/blink/web_tests/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-hidden-with-touch-expected.txt
@@ -4,7 +4,7 @@
       "name": "Scrolling Contents Layer",
       "bounds": [800, 600],
       "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
+      "backgroundColor": "#C0C0C0"
     }
   ]
 }
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt
index 3fe8b77..4c12a3a 100644
--- a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt
+++ b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-overlay-with-touch-expected.txt
@@ -14,6 +14,7 @@
     {
       "name": "Scrolling Contents Layer",
       "bounds": [1000, 1000],
+      "backgroundColor": "#C0C0C0",
       "transform": 1
     },
     {
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 8cb1f55f4..bec798b 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1672,6 +1672,7 @@
 [Worker]     getter format
 [Worker]     getter planes
 [Worker]     getter timestamp
+[Worker]     method clone
 [Worker]     method constructor
 [Worker]     method createImageBitmap
 [Worker]     method destroy
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 20dc7058..3fc15d4 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
@@ -8787,6 +8787,7 @@
     method reset
 interface VideoEncoder
     attribute @@toStringTag
+    getter encodeQueueSize
     method close
     method configure
     method constructor
@@ -8807,6 +8808,7 @@
     getter format
     getter planes
     getter timestamp
+    method clone
     method constructor
     method createImageBitmap
     method destroy
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index e473039..cf0fa61e 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1466,6 +1466,7 @@
 [Worker]     getter format
 [Worker]     getter planes
 [Worker]     getter timestamp
+[Worker]     method clone
 [Worker]     method constructor
 [Worker]     method createImageBitmap
 [Worker]     method destroy
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/ar/iframe-oopif.sub.https.html b/third_party/blink/web_tests/wpt_internal/webxr/ar/iframe-oopif.sub.https.html
new file mode 100644
index 0000000..28ef51f
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/webxr/ar/iframe-oopif.sub.https.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<head>
+  <script src="/resources/testharness.js"></script>
+  <!-- testharnessreport.js is loaded dynamically in the parent only -->
+  <script src="/webxr/resources/webxr_util.js"></script>
+  <script src="/webxr/resources/webxr_test_constants.js"></script>
+  <script src="/webxr/resources/webxr_test_asserts.js"></script>
+</head>
+<body>
+  <script>
+
+const fakeDeviceInitParams = {
+  supportedModes: ["immersive-ar"],
+  views: VALID_VIEWS,
+  viewerOrigin: IDENTITY_TRANSFORM,
+  supportedFeatures: ALL_FEATURES,
+};
+
+// Arbitrary message for notifying the parent frame
+const FRAME_SESSION_COMPLETE = 'iframe done';
+
+// This test runs inside the iframe, verifies that the session
+// is working as expected, and sends a completion message to the parent.
+const testBasicProperties = function(overlayElement, session,
+                                   fakeDeviceController, t) {
+  assert_equals(session.mode, 'immersive-ar');
+  assert_not_equals(session.environmentBlendMode, 'opaque');
+
+  assert_true(overlayElement != null);
+  assert_true(overlayElement instanceof Element);
+
+  // Verify that the DOM overlay type is one of the known types.
+  assert_in_array(session.domOverlayState.type,
+                  ["screen", "floating", "head-locked"]);
+
+  // Verify SameObject property for domOverlayState
+  assert_true(session.domOverlayState === session.domOverlayState);
+
+  // The overlay element should have a transparent background.
+  assert_equals(window.getComputedStyle(overlayElement).backgroundColor,
+                'rgba(0, 0, 0, 0)');
+
+  // Check that the pseudostyle is set.
+  assert_equals(document.querySelector(':xr-overlay'), overlayElement);
+
+  return new Promise((resolve) => {
+    // Wait for a couple of animation frames to give the optional fullscreen
+    // API integration test time to complete.
+    session.requestAnimationFrame(() => {
+      session.requestAnimationFrame(() => {
+        resolve();
+        parent.postMessage(FRAME_SESSION_COMPLETE, '*');
+      });
+    });
+  });
+};
+
+const run_parent = () => {
+  // Only the parent should use testharnessreport, load it dynamically.
+  const script = document.createElement('script');
+  script.src = '/resources/testharnessreport.js';
+  script.async = false;
+  document.head.append(script);
+
+  const frame = document.createElement('iframe');
+
+  // Optional test - if the WebXR DOM overlay is based on fullscreen
+  // mode (it doesn't have to be), resulting in a fullscreen event,
+  // check that the iframe has a transparent background.
+  const testFullscreen = async_test("Wait for fullscreenchange");
+  let gotFullscreenChange = false;
+  const onFullscreenChange = testFullscreen.step_func_done(() => {
+    gotFullscreenChange = true;
+    // The iframe element should have the :xr-overlay pseudostyle
+    // and a transparent background.
+    assert_equals(document.querySelector(':xr-overlay'), frame);
+    assert_equals(window.getComputedStyle(frame).backgroundColor,
+                  'rgba(0, 0, 0, 0)');
+  });
+  document.addEventListener('fullscreenchange', onFullscreenChange);
+
+  // For the iframe, load the current file from an alternate domain.
+  frame.src = 'https://{{hosts[alt][www]}}:{{ports[https][1]}}' +
+    document.location.pathname;
+  frame.allow = 'xr-spatial-tracking; fullscreen';
+  document.body.appendChild(frame);
+
+  window.addEventListener('message', function(ev) {
+    if (ev.data == FRAME_SESSION_COMPLETE) {
+      // If there was no fullscreen change event, mark the optional
+      // fullscreen integration test as a failed optional test, reported
+      // as NOTRUN by the framework.
+      if (!gotFullscreenChange) {
+        testFullscreen.step(() => {
+          assert_implements_optional(
+            false, 'WebXR DOM overlay is not using fullscreen events');
+          testFullscreen.done();
+        });
+      }
+    }
+  });
+
+  // Add the child tests to the overall test suite, reporting results from them
+  // as part of the overall test result. Note that this call does not wait for
+  // these tests to complete, it just adds them to the list of pending tests.
+  fetch_tests_from_window(frame.contentWindow);
+};
+
+const run_iframe_child = () => {
+  // This is the child iframe. Set up and run the test, its result will
+  // be fetched by the parent.
+
+  document.body.appendChild(document.createElement('canvas'));
+
+  xr_session_promise_test(
+    "DOM Overlay in iframe",
+    testBasicProperties.bind(this, document.body),
+    fakeDeviceInitParams, 'immersive-ar',
+    {requiredFeatures: ['dom-overlay'],
+     domOverlay: { root: document.body } });
+};
+
+if (parent === self) {
+  run_parent();
+} else {
+  run_iframe_child();
+}
+
+  </script>
+</body>
diff --git a/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v2.xml b/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v2.xml
index 3f9a74c..7c70e4d 100644
--- a/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v2.xml
+++ b/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v2.xml
@@ -24,7 +24,7 @@
     DEALINGS IN THE SOFTWARE.
   </copyright>
 
-  <interface name="zcr_gaming_input_v2" version="2">
+  <interface name="zcr_gaming_input_v2" version="1">
     <description summary="extends wl_seat with gaming input devices">
       A global interface to provide gaming input devices for a given seat.
 
@@ -98,7 +98,7 @@
     </event>
   </interface>
 
-  <interface name="zcr_gamepad_v2" version="2">
+  <interface name="zcr_gamepad_v2" version="1">
     <description summary="gamepad input device">
       The zcr_gamepad_v2 interface represents one or more gamepad input devices,
       which are reported as a normalized 'Standard Gamepad' as it is specified
@@ -106,10 +106,7 @@
     </description>
 
     <request name="destroy" type="destructor">
-      <description summary="destroy gamepad">
-        Destroy gamepad. Instances created from this gamepad are unaffected
-        and should be destroyed separately.
-      </description>
+      <description summary="destroy gamepad object"/>
     </request>
 
     <event name="removed">
@@ -194,51 +191,5 @@
         gamepad_added_with_device_info.
       </description>
     </event>
-
-    <!-- added since v2 -->
-    <event name="vibrator_added" since="2">
-      <description summary="a vibrator is added">
-        Adds a vibrator to the gamepad. Only called if server has verified
-        that gamepad has a vibrator. The vibrator(s) for a gamepad are expected
-        to be added before the "activated" event is called.
-      </description>
-      <arg name="vibrator" type="new_id" interface="zcr_gamepad_vibrator_v2" summary="the gamepad vibrator"/>
-    </event>
-  </interface>
-
-  <interface name="zcr_gamepad_vibrator_v2" version="2">
-    <description summary="vibrator interface for a gamepad">
-      An interface that provides access to the vibrator of a gamepad. Requests can be
-      sent to make the gamepad vibrate and to stop an ongoing vibration.
-    </description>
-
-    <request name="vibrate" since="2">
-      <description summary="triggers the vibration event">
-        Triggers the vibration event on the gamepad vibrator. The gamepad is only allowed to
-        vibrate while the window is in focus. The values in the timings array are 64-bit integers
-        and the values in the amplitudes array are unsigned 8-bit integers.
-        The timings array and the amplitudes array are of the same length.
-        For each timing/amplitude pair, the amplitude determines the strength of
-        the vibration and the timing determines the length of the vibration in milliseconds.
-        Amplitude values must be between 0 and 255. An amplitude of 0 implies no vibration
-        and any timing/amplitude pair with a timing value of 0 is ignored.
-        The repeat argument determines the index at which the vibration pattern to repeat begins.
-        A repeat value of -1 disables repetition. If repetition is enabled, the vibration
-        pattern will repeat indefinitely until stopped, or when focus is lost.
-      </description>
-      <arg name="timings" type="array" summary="array of timing values" />
-      <arg name="amplitudes" type="array" summary="array of amplitude values" />
-      <arg name="repeat" type="int" summary="index into the timings array at which to repeat" />
-    </request>
-
-    <request name="cancel_vibration" since="2">
-      <description summary="cancels the existing vibration event">
-        Cancels the currently ongoing vibration event on the gamepad vibrator.
-      </description>
-    </request>
-
-    <request name="destroy" type="destructor" since="2">
-      <description summary="destroy gamepad vibrator"/>
-    </request>
   </interface>
 </protocol>
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 63e665ed2..03709a2 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -135,7 +135,6 @@
       'linux-chromeos-rel': 'chromeos_with_codecs_release_bot',
       'linux-chromeos-dbg': 'chromeos_with_codecs_debug_bot',
       'linux-lacros-builder-rel': 'lacros_on_linux_release_bot',
-      'linux-lacros-rel': 'lacros_on_linux_release_bot',
       'linux-lacros-tester-rel': 'lacros_on_linux_release_bot',
     },
 
@@ -826,6 +825,7 @@
       'linux-chromeos-compile-dbg': 'chromeos_with_codecs_debug_bot',
       'linux-chromeos-dbg': 'chromeos_with_codecs_debug_bot',
       'linux-lacros-compile-rel': 'lacros_on_linux_release_bot',
+      'linux-lacros-rel': 'lacros_on_linux_release_bot',
     },
 
     'tryserver.chromium.codesearch': {
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 9ff7a3f..69be957 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -21425,6 +21425,12 @@
   <int value="770" label="PrintersBulkConfiguration"/>
   <int value="771" label="DeviceReleaseLtsTag"/>
   <int value="772" label="PrintersBulkAccessMode"/>
+  <int value="773" label="DefaultFileSystemReadGuardSetting"/>
+  <int value="774" label="DefaultFileSystemWriteGuardSetting"/>
+  <int value="775" label="FileSystemReadAskForUrls"/>
+  <int value="776" label="FileSystemReadBlockedForUrls"/>
+  <int value="777" label="FileSystemWriteAskForUrls"/>
+  <int value="778" label="FileSystemWriteBlockedForUrls"/>
 </enum>
 
 <enum name="EnterprisePolicyDeviceIdValidity">
@@ -28743,6 +28749,12 @@
   <int value="3399" label="MediaRecorder_MimeType"/>
   <int value="3400" label="MediaRecorder_VideoBitsPerSecond"/>
   <int value="3401" label="MediaRecorder_AudioBitsPerSecond"/>
+  <int value="3402" label="BluetoothRemoteGATTCharacteristic_Uuid"/>
+  <int value="3403" label="BluetoothRemoteGATTDescriptor_Uuid"/>
+  <int value="3404" label="BluetoothRemoteGATTService_Uuid"/>
+  <int value="3405" label="GPUAdapter_Name"/>
+  <int value="3406" label="WindowScreenInternal"/>
+  <int value="3407" label="WindowScreenPrimary"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
@@ -55680,6 +55692,17 @@
   <int value="6" label="Could Not Create Upload Directory"/>
 </enum>
 
+<enum name="PhoneCollectionState">
+  <int value="0" label="Phone Not Collected, WebOTP Not Used, OTC Not Used"/>
+  <int value="1" label="Phone Not Collected, WebOTP Not Used, OTC Used"/>
+  <int value="2" label="Phone Not Collected, WebOTP Used, OTC Not Used"/>
+  <int value="3" label="Phone Not Collected, WebOTP Used, OTC Used"/>
+  <int value="4" label="Phone Collected, WebOTP Not Used, OTC Not Used"/>
+  <int value="5" label="Phone Collected, WebOTP Not Used, OTC Used"/>
+  <int value="6" label="Phone Collected, WebOTP Used, OTC Not Used"/>
+  <int value="7" label="Phone Collected, WebOTP Used, OTC Used"/>
+</enum>
+
 <enum name="PhoneNumberRegexVariantResult">
   <obsolete>
     Removed in M82 as the experiment has been stopped.
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 3b41f1d..2777b6d 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -16761,6 +16761,18 @@
   </summary>
 </histogram>
 
+<histogram name="Autofill.WebOTP.PhonePlusWebOTPPlusOTC"
+    enum="PhoneCollectionState" expires_after="2021-07-01">
+  <owner>yigu@chromium.org</owner>
+  <owner>madjivp@chromium.org</owner>
+  <owner>web-identity@google.com</owner>
+  <summary>
+    Records whether a document collected phone number, and/or used WebOTP,
+    and/or used OneTimeCode (OTC) during its lifecycle. i.e. it's recorded in
+    the browser process when a document is destroyed.
+  </summary>
+</histogram>
+
 <histogram name="Autofill.WebView.AutofillSession" enum="AutofillSessionStates"
     expires_after="2021-06-08">
   <owner>michaelbai@chromium.org</owner>
@@ -26201,6 +26213,17 @@
   </summary>
 </histogram>
 
+<histogram name="Chrome.Tabs.AnimationSmoothness.TabLoading" units="%"
+    expires_after="2021-06-04">
+  <owner>yichenz@chromium.org</owner>
+  <owner>chromeos-wmp@google.com</owner>
+  <summary>
+    Tracks the animation smoothness of tab loading animation. A tracker starts
+    when the first tab loading animation starts and stops after the last one
+    stops for each browser window. The metric is emitted when the tracker stops.
+  </summary>
+</histogram>
+
 <histogram name="Chrome.UmaPageloadCounter" enum="BooleanHit"
     expires_after="2017-06-06">
   <obsolete>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index e6823a8..aafeff3 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -9606,6 +9606,21 @@
   </summary>
 </event>
 
+<event name="PerfectHeuristics" singular="True">
+  <owner>dom@chromium.org</owner>
+  <owner>chrome-loading@google.com</owner>
+  <summary>
+    Metrics recorded for the various Perfect Heuristics experiments being run.
+  </summary>
+  <metric name="delay_async_script_execution_before_finished_parsing"
+      enum="Boolean">
+    <summary>
+      Set to 1 when blink::ScriptRunner sees an async script before the
+      associated document has finished parsing.
+    </summary>
+  </metric>
+</event>
+
 <event name="PeriodicBackgroundSyncEventCompleted">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index d77d68d..fc54f618 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "0819a37f7e3da5b5ede65fa8fdf1c244193e5d5c",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/4c3752c7f6777b6c5d870271a6094db6840eabd7/trace_processor_shell.exe"
+            "hash": "573b9cc4b3d475e3821a467b8155faa387fe1e49",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/22e7f7a0d7d761f391e41ad2b9767e2251cb0749/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "0da168dd179de98eb1e444ff4a7c763dfa2dda47",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/4c3752c7f6777b6c5d870271a6094db6840eabd7/trace_processor_shell"
+            "hash": "f6275dd94812c5b0f13393cba486317ea9ba98a6",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/22e7f7a0d7d761f391e41ad2b9767e2251cb0749/trace_processor_shell"
         },
         "linux": {
-            "hash": "dd01349511a394d6f96824080b48c3d34ae74146",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/a3fcf2574157a93e5eec66c10a9b33d7dc331977/trace_processor_shell"
+            "hash": "8c44a4fca5f5199849583dea0f021f3c3a197132",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/22e7f7a0d7d761f391e41ad2b9767e2251cb0749/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
index 96496079..3a34811 100644
--- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
+++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
@@ -169,7 +169,7 @@
                  const gfx::RectF& contents_rect,
                  const gfx::Rect& rect,
                  unsigned background_color,
-                 bool has_hdr_color_space,
+                 const gfx::ColorSpace& color_space,
                  unsigned edge_aa_mask,
                  float opacity,
                  unsigned filter);
@@ -191,6 +191,8 @@
     gfx::RectF contents_rect;
     gfx::RectF rect;
     unsigned background_color = 0;
+    // The color space of |io_surface|. Used for HDR tonemapping.
+    gfx::ColorSpace io_surface_color_space;
     // Note that the CoreAnimation edge antialiasing mask is not the same as
     // the edge antialiasing mask passed to the constructor.
     CAEdgeAntialiasingMask ca_edge_aa_mask = 0;
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
index 1597008..2b3c354 100644
--- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
+++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
@@ -385,7 +385,7 @@
     const gfx::RectF& contents_rect,
     const gfx::Rect& rect_in,
     unsigned background_color,
-    bool has_hdr_color_space,
+    const gfx::ColorSpace& io_surface_color_space,
     unsigned edge_aa_mask,
     float opacity,
     unsigned filter)
@@ -394,6 +394,7 @@
       contents_rect(contents_rect),
       rect(rect_in),
       background_color(background_color),
+      io_surface_color_space(io_surface_color_space),
       ca_edge_aa_mask(0),
       opacity(opacity),
       ca_filter(filter == GL_LINEAR ? kCAFilterLinear : kCAFilterNearest) {
@@ -439,14 +440,10 @@
   }
 
   // Determine which type of CALayer subclass we should use.
-  if (io_surface) {
+  if (metal::ShouldUseHDRCopier(io_surface, io_surface_color_space)) {
+    type = CALayerType::kHDRCopier;
+  } else if (io_surface) {
     switch (IOSurfaceGetPixelFormat(io_surface)) {
-      case kCVPixelFormatType_64RGBAHalf:
-      case kCVPixelFormatType_ARGB2101010LEPacked:
-        // HDR content can come in either as half-float or as 10-10-10-2.
-        if (has_hdr_color_space)
-          type = CALayerType::kHDRCopier;
-        break;
       case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
       case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange:
         // Only allow 4:2:0 frames which fill the layer's contents to be
@@ -496,6 +493,7 @@
       contents_rect(layer.contents_rect),
       rect(layer.rect),
       background_color(layer.background_color),
+      io_surface_color_space(layer.io_surface_color_space),
       ca_edge_aa_mask(layer.ca_edge_aa_mask),
       opacity(layer.opacity),
       ca_filter(layer.ca_filter),
@@ -571,7 +569,7 @@
     const CARendererLayerParams& params) {
   base::ScopedCFTypeRef<IOSurfaceRef> io_surface;
   base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer;
-  bool has_hdr_color_space = false;
+  gfx::ColorSpace io_surface_color_space;
   if (params.image) {
     gl::GLImageIOSurface* io_surface_image =
         gl::GLImageIOSurface::FromGLImage(params.image);
@@ -585,11 +583,11 @@
     // TODO(ccameron): If this indeed causes the bug to disappear, then
     // extirpate the CVPixelBufferRef path.
     // cv_pixel_buffer = io_surface_image->cv_pixel_buffer();
-    has_hdr_color_space = params.image->color_space().IsHDR();
+    io_surface_color_space = params.image->color_space();
   }
   content_layers.push_back(
       ContentLayer(tree, io_surface, cv_pixel_buffer, params.contents_rect,
-                   params.rect, params.background_color, has_hdr_color_space,
+                   params.rect, params.background_color, io_surface_color_space,
                    params.edge_aa_mask, params.opacity, params.filter));
 }
 
@@ -809,7 +807,10 @@
 
   switch (type) {
     case CALayerType::kHDRCopier:
-      [ca_layer setContents:static_cast<id>(io_surface.get())];
+      if (update_contents) {
+        metal::UpdateHDRCopierLayer(ca_layer.get(), io_surface.get(),
+                                    io_surface_color_space);
+      }
       break;
     case CALayerType::kVideo:
       if (update_contents) {
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc
index c9fdf449..e96bd1b 100644
--- a/ui/accessibility/ax_enum_util.cc
+++ b/ui/accessibility/ax_enum_util.cc
@@ -1882,6 +1882,8 @@
       return "clickable";
     case ax::mojom::BoolAttribute::kClipsChildren:
       return "clipsChildren";
+    case ax::mojom::BoolAttribute::kNotUserSelectableStyle:
+      return "notUserSelectableStyle";
     case ax::mojom::BoolAttribute::kSelected:
       return "selected";
     case ax::mojom::BoolAttribute::kSelectedFromFocus:
@@ -1926,6 +1928,8 @@
     return ax::mojom::BoolAttribute::kClickable;
   if (0 == strcmp(bool_attribute, "clipsChildren"))
     return ax::mojom::BoolAttribute::kClipsChildren;
+  if (0 == strcmp(bool_attribute, "notUserSelectableStyle"))
+    return ax::mojom::BoolAttribute::kNotUserSelectableStyle;
   if (0 == strcmp(bool_attribute, "selected"))
     return ax::mojom::BoolAttribute::kSelected;
   if (0 == strcmp(bool_attribute, "selectedFromFocus"))
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom
index 82370df..9a922b04 100644
--- a/ui/accessibility/ax_enums.mojom
+++ b/ui/accessibility/ax_enums.mojom
@@ -733,6 +733,12 @@
   // overflow: hidden or clip children by default.
   kClipsChildren,
 
+  // Indicates that this node is not selectable because the style has
+  // user-select: none. Note that there may be other reasons why a node is
+  // not selectable - for example, bullets in a list. However, this attribute
+  // is only set on user-select: none.
+  kNotUserSelectableStyle,
+
   // Indicates whether this node is selected or unselected.
   kSelected,
 
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc
index 3973017..0a1178b 100644
--- a/ui/accessibility/ax_node_data.cc
+++ b/ui/accessibility/ax_node_data.cc
@@ -1575,6 +1575,9 @@
       case ax::mojom::BoolAttribute::kClipsChildren:
         result += " clips_children=" + value;
         break;
+      case ax::mojom::BoolAttribute::kNotUserSelectableStyle:
+        result += " not_user_selectable=" + value;
+        break;
       case ax::mojom::BoolAttribute::kSelected:
         result += " selected=" + value;
         break;
diff --git a/ui/aura/test/ui_controls_factory_ozone.cc b/ui/aura/test/ui_controls_factory_ozone.cc
index 23e318e8..dce2708 100644
--- a/ui/aura/test/ui_controls_factory_ozone.cc
+++ b/ui/aura/test/ui_controls_factory_ozone.cc
@@ -48,6 +48,16 @@
                                   bool alt,
                                   bool command,
                                   base::OnceClosure closure) override {
+    WindowTreeHost* optional_host = nullptr;
+    // Send the key event to the window's host, which may not match |host_|.
+    // This logic should probably exist for the non-aura path as well.
+    // TODO(https://crbug.com/1116649) Support non-aura path.
+#if defined(USE_AURA)
+    if (window != nullptr && window->GetHost() != nullptr &&
+        window->GetHost() != host_)
+      optional_host = window->GetHost();
+#endif
+
     int flags = button_down_mask_;
     int64_t display_id =
         display::Screen::GetScreen()->GetDisplayNearestWindow(window).id();
@@ -55,58 +65,62 @@
     if (control) {
       flags |= ui::EF_CONTROL_DOWN;
       PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags, display_id,
-                   base::OnceClosure());
+                   base::OnceClosure(), optional_host);
     }
 
     if (shift) {
       flags |= ui::EF_SHIFT_DOWN;
       PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags, display_id,
-                   base::OnceClosure());
+                   base::OnceClosure(), optional_host);
     }
 
     if (alt) {
       flags |= ui::EF_ALT_DOWN;
       PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags, display_id,
-                   base::OnceClosure());
+                   base::OnceClosure(), optional_host);
     }
 
     if (command) {
       flags |= ui::EF_COMMAND_DOWN;
       PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_LWIN, flags, display_id,
-                   base::OnceClosure());
+                   base::OnceClosure(), optional_host);
     }
 
     PostKeyEvent(ui::ET_KEY_PRESSED, key, flags, display_id,
-                 base::OnceClosure());
+                 base::OnceClosure(), optional_host);
     const bool has_modifier = control || shift || alt || command;
     // Pass the real closure to the last generated KeyEvent.
     PostKeyEvent(ui::ET_KEY_RELEASED, key, flags, display_id,
-                 has_modifier ? base::OnceClosure() : std::move(closure));
+                 has_modifier ? base::OnceClosure() : std::move(closure),
+                 optional_host);
 
     if (alt) {
       flags &= ~ui::EF_ALT_DOWN;
       PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags, display_id,
                    (shift || control || command) ? base::OnceClosure()
-                                                 : std::move(closure));
+                                                 : std::move(closure),
+                   optional_host);
     }
 
     if (shift) {
       flags &= ~ui::EF_SHIFT_DOWN;
       PostKeyEvent(
           ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags, display_id,
-          (control || command) ? base::OnceClosure() : std::move(closure));
+          (control || command) ? base::OnceClosure() : std::move(closure),
+          optional_host);
     }
 
     if (control) {
       flags &= ~ui::EF_CONTROL_DOWN;
       PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags, display_id,
-                   command ? base::OnceClosure() : std::move(closure));
+                   command ? base::OnceClosure() : std::move(closure),
+                   optional_host);
     }
 
     if (command) {
       flags &= ~ui::EF_COMMAND_DOWN;
       PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags, display_id,
-                   std::move(closure));
+                   std::move(closure), optional_host);
     }
 
     return true;
@@ -231,17 +245,21 @@
   }
 #endif
 
+  // Use |optional_host| to specify the host.
+  // When |optional_host| is not null, event will be sent to |optional_host|.
+  // When |optional_host| is null, event will be sent to the default host.
   void SendEventToSink(ui::Event* event,
                        int64_t display_id,
-                       base::OnceClosure closure) {
+                       base::OnceClosure closure,
+                       WindowTreeHost* optional_host = nullptr) {
     // Post the task before processing the event. This is necessary in case
     // processing the event results in a nested message loop.
     if (closure) {
       base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                     std::move(closure));
     }
-
-    ui::EventSourceTestApi event_source_test(host_->GetEventSource());
+    WindowTreeHost* host = optional_host ? optional_host : host_;
+    ui::EventSourceTestApi event_source_test(host->GetEventSource());
     ignore_result(event_source_test.SendEventToSink(event));
   }
 
@@ -249,23 +267,26 @@
                     ui::KeyboardCode key_code,
                     int flags,
                     int64_t display_id,
-                    base::OnceClosure closure) {
+                    base::OnceClosure closure,
+                    WindowTreeHost* optional_host = nullptr) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&UIControlsOzone::PostKeyEventTask,
-                                  base::Unretained(this), type, key_code, flags,
-                                  display_id, std::move(closure)));
+        FROM_HERE,
+        base::BindOnce(&UIControlsOzone::PostKeyEventTask,
+                       base::Unretained(this), type, key_code, flags,
+                       display_id, std::move(closure), optional_host));
   }
 
   void PostKeyEventTask(ui::EventType type,
                         ui::KeyboardCode key_code,
                         int flags,
                         int64_t display_id,
-                        base::OnceClosure closure) {
+                        base::OnceClosure closure,
+                        WindowTreeHost* optional_host) {
     // Do not rewrite injected events. See crbug.com/136465.
     flags |= ui::EF_FINAL;
 
     ui::KeyEvent key_event(type, key_code, flags);
-    SendEventToSink(&key_event, display_id, std::move(closure));
+    SendEventToSink(&key_event, display_id, std::move(closure), optional_host);
   }
 
   void PostMouseEvent(ui::EventType type,
@@ -335,6 +356,8 @@
     return true;
   }
 
+  // This is the default host used for events that are not scoped to a window.
+  // Events scoped to a window always use the window's host.
   WindowTreeHost* host_;
 
   // Mask of the mouse buttons currently down. This is static as it needs to
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index 1db2c6c..12b4786 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -6828,8 +6828,8 @@
       // "TEST_______",
       "TEST some stuff", "WWWWWWWWWW", "gAXAXAXAXAXAXA",
       "g\u00C5X\u00C5X\u00C5X\u00C5X\u00C5X\u00C5X\u00C5",
-      "\u0647\u0654\u0647\u0654\u0647\u0654\u0647\u0654\u0645\u0631\u062D"
-      "\u0628\u0627"};
+      ("\u0647\u0654\u0647\u0654\u0647\u0654\u0647\u0654\u0645\u0631\u062D"
+       "\u0628\u0627")};
   const Size kCanvasSize(300, 50);
   const int kTestSize = 10;
 
diff --git a/ui/webui/resources/cr_components/chromeos/BUILD.gn b/ui/webui/resources/cr_components/chromeos/BUILD.gn
index be17a05..6f4b99a 100644
--- a/ui/webui/resources/cr_components/chromeos/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/BUILD.gn
@@ -29,6 +29,7 @@
 group("polymer3_elements") {
   public_deps = [
     "bluetooth:polymer3_elements",
+    "cellular_setup:polymer3_elements",
     "network:polymer3_elements",
     "network_health:polymer3_elements",
     "quick_unlock:polymer3_elements",
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn b/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
index fc1fdfa..b7a367e3 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
@@ -3,6 +3,9 @@
 # found in the LICENSE file.
 
 import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../os_cr_components.gni")
 
 assert(is_chromeos, "CellularSetup UI is Chrome OS only.")
 
@@ -78,3 +81,42 @@
     "//ui/webui/resources/js:cr",
   ]
 }
+
+# Polymer3 files
+
+js_type_check("closure_compile_module") {
+  is_polymer3 = true
+  deps = [
+    # ":button_bar.m",
+    ":base_page.m",
+    # ":button_bar.m",
+    # ":cellular_setup.m",
+    # ":final_page.m",
+    # ":mojo_interface_provider.m",
+    # ":provisioning_page.m",
+    # ":psim_flow_ui.m",
+    # ":sim_detect_page.m",
+    # ":webview_post_util.m",
+  ]
+}
+
+js_library("base_page.m") {
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/base_page.m.js" ]
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js:i18n_behavior.m",
+  ]
+  extra_deps = [ ":base_page_module" ]
+}
+
+group("polymer3_elements") {
+  public_deps = [ ":base_page_module" ]
+}
+
+polymer_modulizer("base_page") {
+  js_file = "base_page.js"
+  html_file = "base_page.html"
+  html_type = "dom-module"
+  namespace_rewrites = cr_components_chromeos_namespace_rewrites
+  auto_imports = cr_components_chromeos_auto_imports
+}
diff --git a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
index 93db286d..e6da2b2c 100644
--- a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
@@ -267,13 +267,13 @@
     ":network_listener_behavior.m",
 
     #  ":network_nameservers.m",
-    #  ":network_password_input.m",
+    ":network_password_input.m",
     #  ":network_property_list_mojo.m",
     #  ":network_proxy.m",
     #  ":network_proxy_exclusions.m",
     #  ":network_proxy_input.m",
     #  ":network_select.m",
-    #  ":network_shared_css.m",
+    ":network_shared_css.m",
     #  ":network_siminfo.m",
     ":onc_mojo.m",
   ]
@@ -425,7 +425,14 @@
 js_library("network_password_input.m") {
   sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_password_input.m.js" ]
   deps = [
-    # TODO: Fill those in.
+    ":cr_policy_network_behavior_mojo.m",
+    ":cr_policy_network_indicator_mojo.m",
+    ":network_config_element_behavior.m",
+    ":network_shared_css.m",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m",
+    "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
+    "//ui/webui/resources/js:i18n_behavior.m",
   ]
   extra_deps = [ ":network_password_input_module" ]
 }
@@ -531,7 +538,6 @@
   html_type = "dom-module"
   auto_imports = cr_components_chromeos_auto_imports + [
                    "ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.html|CrPolicyIndicatorBehavior,CrPolicyIndicatorType",
-                   "ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.html|CrPolicyNetworkBehaviorMojo",
                  ]
 }
 
@@ -618,6 +624,9 @@
   js_file = "network_password_input.js"
   html_file = "network_password_input.html"
   html_type = "dom-module"
+  auto_imports = cr_components_chromeos_auto_imports + [
+    "ui/webui/resources/cr_components/chromeos/network/network_config_element_behavior.html|NetworkConfigElementBehavior",
+  ]
 }
 
 polymer_modulizer("network_property_list_mojo") {
diff --git a/ui/webui/resources/cr_components/chromeos/os_cr_components.gni b/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
index 31a8608..83b1d00 100644
--- a/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
+++ b/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
@@ -12,6 +12,7 @@
 
 cr_components_chromeos_auto_imports = [
   "ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.html|CrPolicyIndicatorType",
+  "ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.html|CrPolicyNetworkBehaviorMojo",
   "ui/webui/resources/cr_components/chromeos/network/onc_mojo.html|OncMojo",
   "ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.html|NetworkListenerBehavior",
   "ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.html|MojoInterfaceProviderImpl,MojoInterfaceProvider",
diff --git a/ui/webui/resources/cr_components/cr_components_resources_v3.grdp b/ui/webui/resources/cr_components/cr_components_resources_v3.grdp
index 681cdd6..0a5ede2 100644
--- a/ui/webui/resources/cr_components/cr_components_resources_v3.grdp
+++ b/ui/webui/resources/cr_components/cr_components_resources_v3.grdp
@@ -38,6 +38,14 @@
            file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.m.js"
            use_base_dir="false"
            type="BINDATA" />
+    <include name="IDR_WEBUI_CHROMEOS_NETWORK_PASSWORD_INPUT_M_JS"
+           file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_password_input.m.js"
+           use_base_dir="false"
+           type="BINDATA" />
+    <include name="IDR_WEBUI_CHROMEOS_NETWORK_SHARED_CSS_M_JS"
+           file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_shared_css.m.js"
+           use_base_dir="false"
+           type="BINDATA" />
     <include name="IDR_WEBUI_CHROMEOS_ONC_MOJOM_M_JS"
            file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/onc_mojo.m.js"
            use_base_dir="false"
@@ -70,6 +78,10 @@
            file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard_icon.m.js"
            use_base_dir="false"
            type="BINDATA" />
+    <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_BASE_PAGE_M_JS"
+           file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/cellular_setup/base_page.m.js"
+           use_base_dir="false"
+           type="BINDATA" />
   </if>
   <if expr="use_nss_certs">
     <include name="IDR_WEBUI_CA_TRUST_EDIT_DIALOG_JS"