diff --git a/DEPS b/DEPS
index e9984c8..bb2068c 100644
--- a/DEPS
+++ b/DEPS
@@ -105,11 +105,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': '903fb041a2f86e6273afa501e8e15335cd4e9972',
+  'skia_revision': '734b2a859784af0b16dbbe07570e6d2f5da34e76',
   # 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': '22a88d89e037d3e95dc320f09544b16e9959a407',
+  'v8_revision': '696e3951665ffc632c6a154a1d2b14c3b3e92212',
   # 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.
@@ -117,7 +117,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': '522095f7d7fe04bf1479a20a9707372d988a9da2',
+  'angle_revision': '06235df9ff91acdf3cf50f2a6febb38b5e26cc6b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -125,11 +125,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '8fb6f6a129f5ed809db7ba3a8bc862dd5e7bc75d',
+  'swiftshader_revision': 'be5fe7797f1e1dbf96f3f337604a4711e871a30a',
   # 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': 'c62aa207e9acb919c33df5f3694fe159619dda86',
+  'pdfium_revision': 'aa50728980036f07fda232cea974fd80c89b7cb7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -165,7 +165,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': '2a64e6b6d554193f50f82d9557442615457365d9',
+  'catapult_revision': 'ca2b32c844637750526112f1af7fbb28b17a8f83',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -539,7 +539,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'b96253cab7d9acd6c40a22e1f8f192e61fbc027a',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'dad47a9531e45fd79083ff2c0919e39cbafef28c',
       'condition': 'checkout_linux',
   },
 
@@ -912,7 +912,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'ee5a26d974beef5a5bdab7d6cf0e97785a7e1c48',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '43ee74f7bd72edebbe5c7642d4df956dbf52bd03',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1034,7 +1034,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '21dbf06b5aa6c7dc8cf56314d4a3f96f57956c53',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '25cc8ad198731ff8eee35859d82919949afbdff7',
+    Var('webrtc_git') + '/src.git' + '@' + 'e09e6ef947d7bb6c29fa36c331bd855baacfafbc',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni
index 2c0f997..09fd7aa 100644
--- a/android_webview/system_webview_apk_tmpl.gni
+++ b/android_webview/system_webview_apk_tmpl.gni
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//base/android/proguard/proguard.gni")
 import("//build/config/android/config.gni")
 import("//build/config/android/rules.gni")
 import("//build/config/locales.gni")
@@ -53,8 +54,14 @@
         "//android_webview/apk/java/proguard.flags",
         "//base/android/proguard/chromium_apk.flags",
         "//base/android/proguard/chromium_code.flags",
-        "//base/android/proguard/disable_all_obfuscation.flags",
       ]
+      if (enable_proguard_obfuscation) {
+        proguard_configs +=
+            [ "//base/android/proguard/enable_obfuscation.flags" ]
+      } else {
+        proguard_configs +=
+            [ "//base/android/proguard/disable_all_obfuscation.flags" ]
+      }
       png_to_webp = true
     }
     command_line_flags_file = "webview-command-line"
diff --git a/base/allocator/partition_allocator/address_space_randomization.cc b/base/allocator/partition_allocator/address_space_randomization.cc
index a7e17c7c..8701f56 100644
--- a/base/allocator/partition_allocator/address_space_randomization.cc
+++ b/base/allocator/partition_allocator/address_space_randomization.cc
@@ -22,7 +22,7 @@
 
 // This is the same PRNG as used by tcmalloc for mapping address randomness;
 // see http://burtleburtle.net/bob/rand/smallprng.html
-struct ranctx {
+struct RandomContext {
   subtle::SpinLock lock;
   bool initialized;
   uint32_t a;
@@ -31,11 +31,12 @@
   uint32_t d;
 };
 
-static LazyInstance<ranctx>::Leaky s_ranctx = LAZY_INSTANCE_INITIALIZER;
+static LazyInstance<RandomContext>::Leaky s_RandomContext =
+    LAZY_INSTANCE_INITIALIZER;
 
 #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
 
-uint32_t ranvalInternal(ranctx* x) {
+uint32_t RandomValueInternal(RandomContext* x) {
   uint32_t e = x->a - rot(x->b, 27);
   x->a = x->b ^ rot(x->c, 17);
   x->b = x->c + x->d;
@@ -46,7 +47,7 @@
 
 #undef rot
 
-uint32_t ranval(ranctx* x) {
+uint32_t RandomValue(RandomContext* x) {
   subtle::SpinLock::Guard guard(x->lock);
   if (UNLIKELY(!x->initialized)) {
     const uint64_t r1 = RandUint64();
@@ -60,13 +61,13 @@
     x->initialized = true;
   }
 
-  return ranvalInternal(x);
+  return RandomValueInternal(x);
 }
 
 }  // namespace
 
 void SetRandomPageBaseSeed(int64_t seed) {
-  ranctx* x = s_ranctx.Pointer();
+  RandomContext* x = s_RandomContext.Pointer();
   subtle::SpinLock::Guard guard(x->lock);
   // Set RNG to initial state.
   x->initialized = true;
@@ -75,11 +76,12 @@
 }
 
 void* GetRandomPageBase() {
-  uintptr_t random = static_cast<uintptr_t>(ranval(s_ranctx.Pointer()));
+  uintptr_t random =
+      static_cast<uintptr_t>(RandomValue(s_RandomContext.Pointer()));
 
 #if defined(ARCH_CPU_64_BITS)
   random <<= 32ULL;
-  random |= static_cast<uintptr_t>(ranval(s_ranctx.Pointer()));
+  random |= static_cast<uintptr_t>(RandomValue(s_RandomContext.Pointer()));
 
 // The kASLRMask and kASLROffset constants will be suitable for the
 // OS and build configuration.
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc
index 8554673..e730aac 100644
--- a/base/allocator/partition_allocator/partition_alloc.cc
+++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -146,7 +146,7 @@
   // code simpler and the structures more generic.
   size_t i, j;
   size_t current_size = kGenericSmallestBucket;
-  size_t currentIncrement =
+  size_t current_increment =
       kGenericSmallestBucket >> kGenericNumBucketsPerOrderBits;
   internal::PartitionBucket* bucket = &this->buckets[0];
   for (i = 0; i < kGenericNumBucketedOrders; ++i) {
@@ -155,40 +155,40 @@
       // Disable psuedo buckets so that touching them faults.
       if (current_size % kGenericSmallestBucket)
         bucket->active_pages_head = nullptr;
-      current_size += currentIncrement;
+      current_size += current_increment;
       ++bucket;
     }
-    currentIncrement <<= 1;
+    current_increment <<= 1;
   }
   DCHECK(current_size == 1 << kGenericMaxBucketedOrder);
   DCHECK(bucket == &this->buckets[0] + kGenericNumBuckets);
 
   // Then set up the fast size -> bucket lookup table.
   bucket = &this->buckets[0];
-  internal::PartitionBucket** bucketPtr = &this->bucket_lookups[0];
+  internal::PartitionBucket** bucket_ptr = &this->bucket_lookups[0];
   for (order = 0; order <= kBitsPerSizeT; ++order) {
     for (j = 0; j < kGenericNumBucketsPerOrder; ++j) {
       if (order < kGenericMinBucketedOrder) {
         // Use the bucket of the finest granularity for malloc(0) etc.
-        *bucketPtr++ = &this->buckets[0];
+        *bucket_ptr++ = &this->buckets[0];
       } else if (order > kGenericMaxBucketedOrder) {
-        *bucketPtr++ = internal::PartitionBucket::get_sentinel_bucket();
+        *bucket_ptr++ = internal::PartitionBucket::get_sentinel_bucket();
       } else {
-        internal::PartitionBucket* validBucket = bucket;
+        internal::PartitionBucket* valid_bucket = bucket;
         // Skip over invalid buckets.
-        while (validBucket->slot_size % kGenericSmallestBucket)
-          validBucket++;
-        *bucketPtr++ = validBucket;
+        while (valid_bucket->slot_size % kGenericSmallestBucket)
+          valid_bucket++;
+        *bucket_ptr++ = valid_bucket;
         bucket++;
       }
     }
   }
   DCHECK(bucket == &this->buckets[0] + kGenericNumBuckets);
-  DCHECK(bucketPtr == &this->bucket_lookups[0] +
-                          ((kBitsPerSizeT + 1) * kGenericNumBucketsPerOrder));
+  DCHECK(bucket_ptr == &this->bucket_lookups[0] +
+                           ((kBitsPerSizeT + 1) * kGenericNumBucketsPerOrder));
   // And there's one last bucket lookup that will be hit for e.g. malloc(-1),
   // which tries to overflow to a non-existant order.
-  *bucketPtr = internal::PartitionBucket::get_sentinel_bucket();
+  *bucket_ptr = internal::PartitionBucket::get_sentinel_bucket();
 }
 
 bool PartitionReallocDirectMappedInPlace(PartitionRootGeneric* root,
@@ -221,9 +221,9 @@
       return false;
 
     // Shrink by decommitting unneeded pages and making them inaccessible.
-    size_t decommitSize = current_size - new_size;
-    root->DecommitSystemPages(char_ptr + new_size, decommitSize);
-    CHECK(SetSystemPagesAccess(char_ptr + new_size, decommitSize,
+    size_t decommit_size = current_size - new_size;
+    root->DecommitSystemPages(char_ptr + new_size, decommit_size);
+    CHECK(SetSystemPagesAccess(char_ptr + new_size, decommit_size,
                                PageInaccessible));
   } else if (new_size <=
              internal::PartitionDirectMapExtent::FromPage(page)->map_size) {
@@ -303,7 +303,7 @@
   // new size is a significant percentage smaller. We could do the same if we
   // determine it is a win.
   if (actual_new_size == actual_old_size) {
-    // Trying to allocate a block of size new_size would give us a block of
+    // Trying to allocate a block of size |new_size| would give us a block of
     // the same size as the one we've already got, so re-use the allocation
     // after updating statistics (and cookies, if present).
     page->set_raw_size(internal::PartitionCookieSizeAdjustAdd(new_size));
@@ -341,6 +341,13 @@
   return PartitionReallocGenericFlags(this, 0, ptr, new_size, type_name);
 }
 
+void* PartitionRootGeneric::TryRealloc(void* ptr,
+                                       size_t new_size,
+                                       const char* type_name) {
+  return PartitionReallocGenericFlags(this, PartitionAllocReturnNull, ptr,
+                                      new_size, type_name);
+}
+
 static size_t PartitionPurgePage(internal::PartitionPage* page, bool discard) {
   const internal::PartitionBucket* bucket = page->bucket;
   size_t slot_size = bucket->slot_size;
@@ -352,12 +359,12 @@
 
   size_t raw_size = page->get_raw_size();
   if (raw_size) {
-    uint32_t usedBytes = static_cast<uint32_t>(RoundUpToSystemPage(raw_size));
-    discardable_bytes = bucket->slot_size - usedBytes;
+    uint32_t used_bytes = static_cast<uint32_t>(RoundUpToSystemPage(raw_size));
+    discardable_bytes = bucket->slot_size - used_bytes;
     if (discardable_bytes && discard) {
       char* ptr =
           reinterpret_cast<char*>(internal::PartitionPage::ToPointer(page));
-      ptr += usedBytes;
+      ptr += used_bytes;
       DiscardSystemPages(ptr, discardable_bytes);
     }
     return discardable_bytes;
@@ -380,23 +387,23 @@
   // are not in use.
   for (internal::PartitionFreelistEntry* entry = page->freelist_head; entry;
        /**/) {
-    size_t slotIndex = (reinterpret_cast<char*>(entry) - ptr) / slot_size;
-    DCHECK(slotIndex < num_slots);
-    slot_usage[slotIndex] = 0;
+    size_t slot_index = (reinterpret_cast<char*>(entry) - ptr) / slot_size;
+    DCHECK(slot_index < num_slots);
+    slot_usage[slot_index] = 0;
     entry = internal::PartitionFreelistEntry::Transform(entry->next);
 #if !defined(OS_WIN)
-    // If we have a slot where the masked freelist entry is 0, we can
-    // actually discard that freelist entry because touching a discarded
-    // page is guaranteed to return original content or 0.
-    // (Note that this optimization won't fire on big endian machines
-    // because the masking function is negation.)
+    // If we have a slot where the masked freelist entry is 0, we can actually
+    // discard that freelist entry because touching a discarded page is
+    // guaranteed to return original content or 0. (Note that this optimization
+    // won't fire on big-endian machines because the masking function is
+    // negation.)
     if (!internal::PartitionFreelistEntry::Transform(entry))
-      last_slot = slotIndex;
+      last_slot = slot_index;
 #endif
   }
 
-  // If the slot(s) at the end of the slot span are not in used, we can
-  // truncate them entirely and rewrite the freelist.
+  // If the slot(s) at the end of the slot span are not in used, we can truncate
+  // them entirely and rewrite the freelist.
   size_t truncated_slots = 0;
   while (!slot_usage[num_slots - 1]) {
     truncated_slots++;
@@ -411,8 +418,8 @@
     char* end_ptr = begin_ptr + (slot_size * truncated_slots);
     begin_ptr = reinterpret_cast<char*>(
         RoundUpToSystemPage(reinterpret_cast<size_t>(begin_ptr)));
-    // We round the end pointer here up and not down because we're at the
-    // end of a slot span, so we "own" all the way up the page boundary.
+    // We round the end pointer here up and not down because we're at the end of
+    // a slot span, so we "own" all the way up the page boundary.
     end_ptr = reinterpret_cast<char*>(
         RoundUpToSystemPage(reinterpret_cast<size_t>(end_ptr)));
     DCHECK(end_ptr <= ptr + bucket->get_bytes_per_span());
@@ -426,16 +433,16 @@
       page->num_unprovisioned_slots += static_cast<uint16_t>(truncated_slots);
       // Rewrite the freelist.
       internal::PartitionFreelistEntry** entry_ptr = &page->freelist_head;
-      for (size_t slotIndex = 0; slotIndex < num_slots; ++slotIndex) {
-        if (slot_usage[slotIndex])
+      for (size_t slot_index = 0; slot_index < num_slots; ++slot_index) {
+        if (slot_usage[slot_index])
           continue;
         auto* entry = reinterpret_cast<internal::PartitionFreelistEntry*>(
-            ptr + (slot_size * slotIndex));
+            ptr + (slot_size * slot_index));
         *entry_ptr = internal::PartitionFreelistEntry::Transform(entry);
         entry_ptr = reinterpret_cast<internal::PartitionFreelistEntry**>(entry);
         num_new_entries++;
 #if !defined(OS_WIN)
-        last_slot = slotIndex;
+        last_slot = slot_index;
 #endif
       }
       // Terminate the freelist chain.
@@ -449,16 +456,15 @@
     }
   }
 
-  // Next, walk the slots and for any not in use, consider where the system
-  // page boundaries occur. We can release any system pages back to the
-  // system as long as we don't interfere with a freelist pointer or an
-  // adjacent slot.
+  // Next, walk the slots and for any not in use, consider where the system page
+  // boundaries occur. We can release any system pages back to the system as
+  // long as we don't interfere with a freelist pointer or an adjacent slot.
   for (size_t i = 0; i < num_slots; ++i) {
     if (slot_usage[i])
       continue;
     // The first address we can safely discard is just after the freelist
-    // pointer. There's one quirk: if the freelist pointer is actually a
-    // null, we can discard that pointer value too.
+    // pointer. There's one quirk: if the freelist pointer is actually NULL, we
+    // can discard that pointer value too.
     char* begin_ptr = ptr + (i * slot_size);
     char* end_ptr = begin_ptr + slot_size;
 #if !defined(OS_WIN)
@@ -496,9 +502,9 @@
   if (flags & PartitionPurgeDecommitEmptyPages)
     DecommitEmptyPages();
   // We don't currently do anything for PartitionPurgeDiscardUnusedSystemPages
-  // here because that flag is only useful for allocations >= system page
-  // size. We only have allocations that large inside generic partitions
-  // at the moment.
+  // here because that flag is only useful for allocations >= system page size.
+  // We only have allocations that large inside generic partitions at the
+  // moment.
 }
 
 void PartitionRootGeneric::PurgeMemory(int flags) {
@@ -553,9 +559,8 @@
   DCHECK(!bucket->is_direct_mapped());
   stats_out->is_valid = false;
   // If the active page list is empty (==
-  // internal::PartitionPage::get_sentinel_page()),
-  // the bucket might still need to be reported if it has a list of empty,
-  // decommitted or full pages.
+  // internal::PartitionPage::get_sentinel_page()), the bucket might still need
+  // to be reported if it has a list of empty, decommitted or full pages.
   if (bucket->active_pages_head ==
           internal::PartitionPage::get_sentinel_page() &&
       !bucket->empty_pages_head && !bucket->decommitted_pages_head &&
@@ -693,10 +698,10 @@
     memory_stats = std::unique_ptr<PartitionBucketMemoryStats[]>(
         new PartitionBucketMemoryStats[kMaxReportableBuckets]);
 
-  const size_t partitionNumBuckets = this->num_buckets;
-  DCHECK(partitionNumBuckets <= kMaxReportableBuckets);
+  const size_t partition_num_buckets = this->num_buckets;
+  DCHECK(partition_num_buckets <= kMaxReportableBuckets);
 
-  for (size_t i = 0; i < partitionNumBuckets; ++i) {
+  for (size_t i = 0; i < partition_num_buckets; ++i) {
     PartitionBucketMemoryStats bucket_stats = {0};
     PartitionDumpBucketStats(&bucket_stats, &this->buckets()[i]);
     if (bucket_stats.is_valid) {
@@ -716,7 +721,7 @@
     // PartitionsDumpBucketStats is called after collecting stats because it
     // can use PartitionRoot::Alloc() to allocate and this can affect the
     // statistics.
-    for (size_t i = 0; i < partitionNumBuckets; ++i) {
+    for (size_t i = 0; i < partition_num_buckets; ++i) {
       if (memory_stats[i].is_valid)
         dumper->PartitionsDumpBucketStats(partition_name, &memory_stats[i]);
     }
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h
index 79d09053..0294ef92 100644
--- a/base/allocator/partition_allocator/partition_alloc.h
+++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -148,6 +148,9 @@
   ALWAYS_INLINE void Free(void* ptr);
 
   NOINLINE void* Realloc(void* ptr, size_t new_size, const char* type_name);
+  // Overload that may return nullptr if reallocation isn't possible. In this
+  // case, |ptr| remains valid.
+  NOINLINE void* TryRealloc(void* ptr, size_t new_size, const char* type_name);
 
   ALWAYS_INLINE size_t ActualSize(size_t size);
 
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc
index afff0906b..ad91965 100644
--- a/base/allocator/partition_allocator/partition_alloc_unittest.cc
+++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -182,7 +182,13 @@
     }
   }
 
-  void DoReturnNullTest(size_t allocSize, bool use_realloc) {
+  enum ReturnNullTestMode {
+    kPartitionAllocGenericFlags,
+    kPartitionReallocGenericFlags,
+    kPartitionRootGenericTryRealloc,
+  };
+
+  void DoReturnNullTest(size_t alloc_size, ReturnNullTestMode mode) {
     // TODO(crbug.com/678782): Where necessary and possible, disable the
     // platform's OOM-killing behavior. OOM-killing makes this test flaky on
     // low-memory devices.
@@ -195,30 +201,42 @@
     ASSERT_TRUE(SetAddressSpaceLimit());
 
     // Work out the number of allocations for 6 GB of memory.
-    const int numAllocations = (6 * 1024 * 1024) / (allocSize / 1024);
+    const int num_allocations = (6 * 1024 * 1024) / (alloc_size / 1024);
 
     void** ptrs = reinterpret_cast<void**>(generic_allocator.root()->Alloc(
-        numAllocations * sizeof(void*), type_name));
+        num_allocations * sizeof(void*), type_name));
     int i;
 
-    for (i = 0; i < numAllocations; ++i) {
-      if (use_realloc) {
-        ptrs[i] = PartitionAllocGenericFlags(
-            generic_allocator.root(), PartitionAllocReturnNull, 1, type_name);
-        ptrs[i] = PartitionReallocGenericFlags(generic_allocator.root(),
+    for (i = 0; i < num_allocations; ++i) {
+      switch (mode) {
+        case kPartitionAllocGenericFlags: {
+          ptrs[i] = PartitionAllocGenericFlags(generic_allocator.root(),
                                                PartitionAllocReturnNull,
-                                               ptrs[i], allocSize, type_name);
-      } else {
-        ptrs[i] = PartitionAllocGenericFlags(generic_allocator.root(),
-                                             PartitionAllocReturnNull,
-                                             allocSize, type_name);
+                                               alloc_size, type_name);
+          break;
+        }
+        case kPartitionReallocGenericFlags: {
+          ptrs[i] = PartitionAllocGenericFlags(
+              generic_allocator.root(), PartitionAllocReturnNull, 1, type_name);
+          ptrs[i] = PartitionReallocGenericFlags(
+              generic_allocator.root(), PartitionAllocReturnNull, ptrs[i],
+              alloc_size, type_name);
+          break;
+        }
+        case kPartitionRootGenericTryRealloc: {
+          ptrs[i] = PartitionAllocGenericFlags(
+              generic_allocator.root(), PartitionAllocReturnNull, 1, type_name);
+          ptrs[i] = generic_allocator.root()->TryRealloc(ptrs[i], alloc_size,
+                                                         type_name);
+        }
       }
+
       if (!i)
         EXPECT_TRUE(ptrs[0]);
       if (!ptrs[i]) {
         ptrs[i] = PartitionAllocGenericFlags(generic_allocator.root(),
                                              PartitionAllocReturnNull,
-                                             allocSize, type_name);
+                                             alloc_size, type_name);
         EXPECT_FALSE(ptrs[i]);
         break;
       }
@@ -226,14 +244,14 @@
 
     // We shouldn't succeed in allocating all 6 GB of memory. If we do, then
     // we're not actually testing anything here.
-    EXPECT_LT(i, numAllocations);
+    EXPECT_LT(i, num_allocations);
 
     // Free, reallocate and free again each block we allocated. We do this to
     // check that freeing memory also works correctly after a failed allocation.
     for (--i; i >= 0; --i) {
       generic_allocator.root()->Free(ptrs[i]);
       ptrs[i] = PartitionAllocGenericFlags(generic_allocator.root(),
-                                           PartitionAllocReturnNull, allocSize,
+                                           PartitionAllocReturnNull, alloc_size,
                                            type_name);
       EXPECT_TRUE(ptrs[i]);
       generic_allocator.root()->Free(ptrs[i]);
@@ -335,11 +353,11 @@
 // Check that the most basic of allocate / free pairs work.
 TEST_F(PartitionAllocTest, Basic) {
   PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex];
-  PartitionPage* seedPage = PartitionPage::get_sentinel_page();
+  PartitionPage* seed_page = PartitionPage::get_sentinel_page();
 
   EXPECT_FALSE(bucket->empty_pages_head);
   EXPECT_FALSE(bucket->decommitted_pages_head);
-  EXPECT_EQ(seedPage, bucket->active_pages_head);
+  EXPECT_EQ(seed_page, bucket->active_pages_head);
   EXPECT_EQ(nullptr, bucket->active_pages_head->next_page);
 
   void* ptr = allocator.root()->Alloc(kTestAllocSize, type_name);
@@ -467,9 +485,9 @@
   PartitionFree(ptr);
   // Trying to allocate at this time should cause us to cycle around to page2
   // and find the recently freed slot.
-  char* newPtr = reinterpret_cast<char*>(
+  char* new_ptr = reinterpret_cast<char*>(
       allocator.root()->Alloc(kTestAllocSize, type_name));
-  EXPECT_EQ(ptr, newPtr);
+  EXPECT_EQ(ptr, new_ptr);
   EXPECT_EQ(page2, bucket->active_pages_head);
   EXPECT_EQ(page3, page2->next_page);
 
@@ -479,9 +497,9 @@
       reinterpret_cast<char*>(PartitionPage::ToPointer(page1)) + kPointerOffset;
   PartitionFree(ptr);
   // This allocation should be satisfied by page1.
-  newPtr = reinterpret_cast<char*>(
+  new_ptr = reinterpret_cast<char*>(
       allocator.root()->Alloc(kTestAllocSize, type_name));
-  EXPECT_EQ(ptr, newPtr);
+  EXPECT_EQ(ptr, new_ptr);
   EXPECT_EQ(page1, bucket->active_pages_head);
   EXPECT_EQ(page2, page1->next_page);
 
@@ -500,19 +518,19 @@
 TEST_F(PartitionAllocTest, FreePageListPageTransitions) {
   PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex];
 
-  size_t numToFillFreeListPage =
+  size_t num_to_fill_free_list_page =
       kPartitionPageSize / (sizeof(PartitionPage) + kExtraAllocSize);
   // The +1 is because we need to account for the fact that the current page
   // never gets thrown on the freelist.
-  ++numToFillFreeListPage;
-  auto pages = std::make_unique<PartitionPage* []>(numToFillFreeListPage);
+  ++num_to_fill_free_list_page;
+  auto pages = std::make_unique<PartitionPage* []>(num_to_fill_free_list_page);
 
   size_t i;
-  for (i = 0; i < numToFillFreeListPage; ++i) {
+  for (i = 0; i < num_to_fill_free_list_page; ++i) {
     pages[i] = GetFullPage(kTestAllocSize);
   }
-  EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->active_pages_head);
-  for (i = 0; i < numToFillFreeListPage; ++i)
+  EXPECT_EQ(pages[num_to_fill_free_list_page - 1], bucket->active_pages_head);
+  for (i = 0; i < num_to_fill_free_list_page; ++i)
     FreeFullPage(pages[i]);
   EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head);
   EXPECT_TRUE(bucket->empty_pages_head);
@@ -525,12 +543,12 @@
   FreeFullPage(page1);
   FreeFullPage(page2);
 
-  for (i = 0; i < numToFillFreeListPage; ++i) {
+  for (i = 0; i < num_to_fill_free_list_page; ++i) {
     pages[i] = GetFullPage(kTestAllocSize);
   }
-  EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->active_pages_head);
+  EXPECT_EQ(pages[num_to_fill_free_list_page - 1], bucket->active_pages_head);
 
-  for (i = 0; i < numToFillFreeListPage; ++i)
+  for (i = 0; i < num_to_fill_free_list_page; ++i)
     FreeFullPage(pages[i]);
   EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head);
   EXPECT_TRUE(bucket->empty_pages_head);
@@ -541,32 +559,32 @@
 TEST_F(PartitionAllocTest, MultiPageAllocs) {
   // This is guaranteed to cross a super page boundary because the first
   // partition page "slot" will be taken up by a guard page.
-  size_t numPagesNeeded = kNumPartitionPagesPerSuperPage;
+  size_t num_pages_needed = kNumPartitionPagesPerSuperPage;
   // The super page should begin and end in a guard so we one less page in
   // order to allocate a single page in the new super page.
-  --numPagesNeeded;
+  --num_pages_needed;
 
-  EXPECT_GT(numPagesNeeded, 1u);
-  auto pages = std::make_unique<PartitionPage* []>(numPagesNeeded);
-  uintptr_t firstSuperPageBase = 0;
+  EXPECT_GT(num_pages_needed, 1u);
+  auto pages = std::make_unique<PartitionPage* []>(num_pages_needed);
+  uintptr_t first_super_page_base = 0;
   size_t i;
-  for (i = 0; i < numPagesNeeded; ++i) {
+  for (i = 0; i < num_pages_needed; ++i) {
     pages[i] = GetFullPage(kTestAllocSize);
-    void* storagePtr = PartitionPage::ToPointer(pages[i]);
+    void* storage_ptr = PartitionPage::ToPointer(pages[i]);
     if (!i)
-      firstSuperPageBase =
-          reinterpret_cast<uintptr_t>(storagePtr) & kSuperPageBaseMask;
-    if (i == numPagesNeeded - 1) {
-      uintptr_t secondSuperPageBase =
-          reinterpret_cast<uintptr_t>(storagePtr) & kSuperPageBaseMask;
-      uintptr_t secondSuperPageOffset =
-          reinterpret_cast<uintptr_t>(storagePtr) & kSuperPageOffsetMask;
-      EXPECT_FALSE(secondSuperPageBase == firstSuperPageBase);
+      first_super_page_base =
+          reinterpret_cast<uintptr_t>(storage_ptr) & kSuperPageBaseMask;
+    if (i == num_pages_needed - 1) {
+      uintptr_t second_super_page_base =
+          reinterpret_cast<uintptr_t>(storage_ptr) & kSuperPageBaseMask;
+      uintptr_t second_super_page_offset =
+          reinterpret_cast<uintptr_t>(storage_ptr) & kSuperPageOffsetMask;
+      EXPECT_FALSE(second_super_page_base == first_super_page_base);
       // Check that we allocated a guard page for the second page.
-      EXPECT_EQ(kPartitionPageSize, secondSuperPageOffset);
+      EXPECT_EQ(kPartitionPageSize, second_super_page_offset);
     }
   }
-  for (i = 0; i < numPagesNeeded; ++i)
+  for (i = 0; i < num_pages_needed; ++i)
     FreeFullPage(pages[i]);
 }
 
@@ -582,81 +600,81 @@
 
   ptr = generic_allocator.root()->Alloc(1, type_name);
   EXPECT_TRUE(ptr);
-  void* origPtr = ptr;
-  char* charPtr = static_cast<char*>(ptr);
-  *charPtr = 'A';
+  void* orig_ptr = ptr;
+  char* char_ptr = static_cast<char*>(ptr);
+  *char_ptr = 'A';
 
   // Change the size of the realloc, remaining inside the same bucket.
-  void* newPtr = generic_allocator.root()->Realloc(ptr, 2, type_name);
-  EXPECT_EQ(ptr, newPtr);
-  newPtr = generic_allocator.root()->Realloc(ptr, 1, type_name);
-  EXPECT_EQ(ptr, newPtr);
-  newPtr =
+  void* new_ptr = generic_allocator.root()->Realloc(ptr, 2, type_name);
+  EXPECT_EQ(ptr, new_ptr);
+  new_ptr = generic_allocator.root()->Realloc(ptr, 1, type_name);
+  EXPECT_EQ(ptr, new_ptr);
+  new_ptr =
       generic_allocator.root()->Realloc(ptr, kGenericSmallestBucket, type_name);
-  EXPECT_EQ(ptr, newPtr);
+  EXPECT_EQ(ptr, new_ptr);
 
   // Change the size of the realloc, switching buckets.
-  newPtr = generic_allocator.root()->Realloc(ptr, kGenericSmallestBucket + 1,
-                                             type_name);
-  EXPECT_NE(newPtr, ptr);
+  new_ptr = generic_allocator.root()->Realloc(ptr, kGenericSmallestBucket + 1,
+                                              type_name);
+  EXPECT_NE(new_ptr, ptr);
   // Check that the realloc copied correctly.
-  char* newCharPtr = static_cast<char*>(newPtr);
-  EXPECT_EQ(*newCharPtr, 'A');
+  char* new_char_ptr = static_cast<char*>(new_ptr);
+  EXPECT_EQ(*new_char_ptr, 'A');
 #if DCHECK_IS_ON()
   // Subtle: this checks for an old bug where we copied too much from the
   // source of the realloc. The condition can be detected by a trashing of
   // the uninitialized value in the space of the upsized allocation.
-  EXPECT_EQ(kUninitializedByte,
-            static_cast<unsigned char>(*(newCharPtr + kGenericSmallestBucket)));
+  EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(
+                                    *(new_char_ptr + kGenericSmallestBucket)));
 #endif
-  *newCharPtr = 'B';
+  *new_char_ptr = 'B';
   // The realloc moved. To check that the old allocation was freed, we can
   // do an alloc of the old allocation size and check that the old allocation
   // address is at the head of the freelist and reused.
-  void* reusedPtr = generic_allocator.root()->Alloc(1, type_name);
-  EXPECT_EQ(reusedPtr, origPtr);
-  generic_allocator.root()->Free(reusedPtr);
+  void* reused_ptr = generic_allocator.root()->Alloc(1, type_name);
+  EXPECT_EQ(reused_ptr, orig_ptr);
+  generic_allocator.root()->Free(reused_ptr);
 
   // Downsize the realloc.
-  ptr = newPtr;
-  newPtr = generic_allocator.root()->Realloc(ptr, 1, type_name);
-  EXPECT_EQ(newPtr, origPtr);
-  newCharPtr = static_cast<char*>(newPtr);
-  EXPECT_EQ(*newCharPtr, 'B');
-  *newCharPtr = 'C';
+  ptr = new_ptr;
+  new_ptr = generic_allocator.root()->Realloc(ptr, 1, type_name);
+  EXPECT_EQ(new_ptr, orig_ptr);
+  new_char_ptr = static_cast<char*>(new_ptr);
+  EXPECT_EQ(*new_char_ptr, 'B');
+  *new_char_ptr = 'C';
 
   // Upsize the realloc to outside the partition.
-  ptr = newPtr;
-  newPtr = generic_allocator.root()->Realloc(ptr, kGenericMaxBucketed + 1,
-                                             type_name);
-  EXPECT_NE(newPtr, ptr);
-  newCharPtr = static_cast<char*>(newPtr);
-  EXPECT_EQ(*newCharPtr, 'C');
-  *newCharPtr = 'D';
+  ptr = new_ptr;
+  new_ptr = generic_allocator.root()->Realloc(ptr, kGenericMaxBucketed + 1,
+                                              type_name);
+  EXPECT_NE(new_ptr, ptr);
+  new_char_ptr = static_cast<char*>(new_ptr);
+  EXPECT_EQ(*new_char_ptr, 'C');
+  *new_char_ptr = 'D';
 
   // Upsize and downsize the realloc, remaining outside the partition.
-  ptr = newPtr;
-  newPtr = generic_allocator.root()->Realloc(ptr, kGenericMaxBucketed * 10,
-                                             type_name);
-  newCharPtr = static_cast<char*>(newPtr);
-  EXPECT_EQ(*newCharPtr, 'D');
-  *newCharPtr = 'E';
-  ptr = newPtr;
-  newPtr = generic_allocator.root()->Realloc(ptr, kGenericMaxBucketed * 2,
-                                             type_name);
-  newCharPtr = static_cast<char*>(newPtr);
-  EXPECT_EQ(*newCharPtr, 'E');
-  *newCharPtr = 'F';
+  ptr = new_ptr;
+  new_ptr = generic_allocator.root()->Realloc(ptr, kGenericMaxBucketed * 10,
+                                              type_name);
+  new_char_ptr = static_cast<char*>(new_ptr);
+  EXPECT_EQ(*new_char_ptr, 'D');
+  *new_char_ptr = 'E';
+  ptr = new_ptr;
+  new_ptr = generic_allocator.root()->Realloc(ptr, kGenericMaxBucketed * 2,
+                                              type_name);
+  new_char_ptr = static_cast<char*>(new_ptr);
+  EXPECT_EQ(*new_char_ptr, 'E');
+  *new_char_ptr = 'F';
 
   // Downsize the realloc to inside the partition.
-  ptr = newPtr;
-  newPtr = generic_allocator.root()->Realloc(ptr, 1, type_name);
-  EXPECT_NE(newPtr, ptr);
-  EXPECT_EQ(newPtr, origPtr);
-  newCharPtr = static_cast<char*>(newPtr);
-  EXPECT_EQ(*newCharPtr, 'F');
+  ptr = new_ptr;
+  new_ptr = generic_allocator.root()->Realloc(ptr, 1, type_name);
+  EXPECT_NE(new_ptr, ptr);
+  EXPECT_EQ(new_ptr, orig_ptr);
+  new_char_ptr = static_cast<char*>(new_ptr);
+  EXPECT_EQ(*new_char_ptr, 'F');
 
-  generic_allocator.root()->Free(newPtr);
+  generic_allocator.root()->Free(new_ptr);
 }
 
 // Test the generic allocation functions can handle some specific sizes of
@@ -706,10 +724,10 @@
   EXPECT_NE(-1, page->empty_cache_index);
   EXPECT_EQ(0, page->num_allocated_slots);
   EXPECT_EQ(0, page->num_unprovisioned_slots);
-  void* newPtr = generic_allocator.root()->Alloc(size, type_name);
-  EXPECT_EQ(ptr3, newPtr);
-  newPtr = generic_allocator.root()->Alloc(size, type_name);
-  EXPECT_EQ(ptr2, newPtr);
+  void* new_ptr = generic_allocator.root()->Alloc(size, type_name);
+  EXPECT_EQ(ptr3, new_ptr);
+  new_ptr = generic_allocator.root()->Alloc(size, type_name);
+  EXPECT_EQ(ptr2, new_ptr);
 #if defined(OS_LINUX) && !DCHECK_IS_ON()
   // On Linux, we have a guarantee that freelisting a page should cause its
   // contents to be nulled out. We check for null here to detect an bug we
@@ -718,9 +736,9 @@
   // We only run the check when asserts are disabled because when they are
   // enabled, the allocated area is overwritten with an "uninitialized"
   // byte pattern.
-  EXPECT_EQ(0, *(reinterpret_cast<char*>(newPtr) + (size - 1)));
+  EXPECT_EQ(0, *(reinterpret_cast<char*>(new_ptr) + (size - 1)));
 #endif
-  generic_allocator.root()->Free(newPtr);
+  generic_allocator.root()->Free(new_ptr);
   generic_allocator.root()->Free(ptr3);
   generic_allocator.root()->Free(ptr4);
 
@@ -739,8 +757,8 @@
   size -= kSystemPageSize;
   size -= 1;
   ptr = generic_allocator.root()->Alloc(size, type_name);
-  char* charPtr = reinterpret_cast<char*>(ptr);
-  *(charPtr + (size - 1)) = 'A';
+  char* char_ptr = reinterpret_cast<char*>(ptr);
+  *(char_ptr + (size - 1)) = 'A';
   generic_allocator.root()->Free(ptr);
 
   // Can we free null?
@@ -794,8 +812,8 @@
   EXPECT_EQ(predicted_size, actual_size);
   EXPECT_EQ(requested_size + kSystemPageSize, actual_size);
   // Check that we can write at the end of the reported size too.
-  char* charPtr = reinterpret_cast<char*>(ptr);
-  *(charPtr + (actual_size - 1)) = 'A';
+  char* char_ptr = reinterpret_cast<char*>(ptr);
+  *(char_ptr + (actual_size - 1)) = 'A';
   generic_allocator.root()->Free(ptr);
 
   // Allocate something very large, and uneven.
@@ -837,22 +855,22 @@
   memset(ptr, 'A', size);
   ptr2 = generic_allocator.root()->Realloc(ptr, size + 1, type_name);
   EXPECT_NE(ptr, ptr2);
-  char* charPtr2 = static_cast<char*>(ptr2);
-  EXPECT_EQ('A', charPtr2[0]);
-  EXPECT_EQ('A', charPtr2[size - 1]);
+  char* char_ptr2 = static_cast<char*>(ptr2);
+  EXPECT_EQ('A', char_ptr2[0]);
+  EXPECT_EQ('A', char_ptr2[size - 1]);
 #if DCHECK_IS_ON()
-  EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(charPtr2[size]));
+  EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(char_ptr2[size]));
 #endif
 
   // Test that shrinking an allocation with realloc() also copies everything
   // from the old allocation.
   ptr = generic_allocator.root()->Realloc(ptr2, size - 1, type_name);
   EXPECT_NE(ptr2, ptr);
-  char* charPtr = static_cast<char*>(ptr);
-  EXPECT_EQ('A', charPtr[0]);
-  EXPECT_EQ('A', charPtr[size - 2]);
+  char* char_ptr = static_cast<char*>(ptr);
+  EXPECT_EQ('A', char_ptr[0]);
+  EXPECT_EQ('A', char_ptr[size - 2]);
 #if DCHECK_IS_ON()
-  EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(charPtr[size - 1]));
+  EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(char_ptr[size - 1]));
 #endif
 
   generic_allocator.root()->Free(ptr);
@@ -895,10 +913,10 @@
 
   PartitionPage* page =
       PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
-  size_t totalSlots =
+  size_t total_slots =
       (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
       (big_size + kExtraAllocSize);
-  EXPECT_EQ(4u, totalSlots);
+  EXPECT_EQ(4u, total_slots);
   // The freelist should have one entry, because we were able to exactly fit
   // one object slot and one freelist pointer (the null that the head points
   // to) into a system page.
@@ -958,12 +976,12 @@
   EXPECT_TRUE(ptr);
   page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
   EXPECT_EQ(1, page->num_allocated_slots);
-  totalSlots =
+  total_slots =
       (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
       (mediumSize + kExtraAllocSize);
-  size_t firstPageSlots = kSystemPageSize / (mediumSize + kExtraAllocSize);
-  EXPECT_EQ(2u, firstPageSlots);
-  EXPECT_EQ(totalSlots - firstPageSlots, page->num_unprovisioned_slots);
+  size_t first_page_slots = kSystemPageSize / (mediumSize + kExtraAllocSize);
+  EXPECT_EQ(2u, first_page_slots);
+  EXPECT_EQ(total_slots - first_page_slots, page->num_unprovisioned_slots);
 
   PartitionFree(ptr);
 
@@ -976,11 +994,11 @@
   EXPECT_TRUE(ptr);
   page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
   EXPECT_EQ(1, page->num_allocated_slots);
-  totalSlots =
+  total_slots =
       (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
       (smallSize + kExtraAllocSize);
-  firstPageSlots = kSystemPageSize / (smallSize + kExtraAllocSize);
-  EXPECT_EQ(totalSlots - firstPageSlots, page->num_unprovisioned_slots);
+  first_page_slots = kSystemPageSize / (smallSize + kExtraAllocSize);
+  EXPECT_EQ(total_slots - first_page_slots, page->num_unprovisioned_slots);
 
   PartitionFree(ptr);
   EXPECT_TRUE(page->freelist_head);
@@ -995,11 +1013,11 @@
   EXPECT_TRUE(ptr);
   page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
   EXPECT_EQ(1, page->num_allocated_slots);
-  totalSlots =
+  total_slots =
       (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
       (verySmallSize + kExtraAllocSize);
-  firstPageSlots = kSystemPageSize / (verySmallSize + kExtraAllocSize);
-  EXPECT_EQ(totalSlots - firstPageSlots, page->num_unprovisioned_slots);
+  first_page_slots = kSystemPageSize / (verySmallSize + kExtraAllocSize);
+  EXPECT_EQ(total_slots - first_page_slots, page->num_unprovisioned_slots);
 
   PartitionFree(ptr);
   EXPECT_TRUE(page->freelist_head);
@@ -1007,17 +1025,17 @@
 
   // And try an allocation size (against the generic allocator) that is
   // larger than a system page.
-  size_t pageAndAHalfSize =
+  size_t page_and_a_half_size =
       (kSystemPageSize + (kSystemPageSize / 2)) - kExtraAllocSize;
-  ptr = generic_allocator.root()->Alloc(pageAndAHalfSize, type_name);
+  ptr = generic_allocator.root()->Alloc(page_and_a_half_size, type_name);
   EXPECT_TRUE(ptr);
   page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
   EXPECT_EQ(1, page->num_allocated_slots);
   EXPECT_TRUE(page->freelist_head);
-  totalSlots =
+  total_slots =
       (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
-      (pageAndAHalfSize + kExtraAllocSize);
-  EXPECT_EQ(totalSlots - 2, page->num_unprovisioned_slots);
+      (page_and_a_half_size + kExtraAllocSize);
+  EXPECT_EQ(total_slots - 2, page->num_unprovisioned_slots);
   generic_allocator.root()->Free(ptr);
 
   // And then make sure than exactly the page size only faults one page.
@@ -1027,10 +1045,10 @@
   page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
   EXPECT_EQ(1, page->num_allocated_slots);
   EXPECT_FALSE(page->freelist_head);
-  totalSlots =
+  total_slots =
       (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
       (pageSize + kExtraAllocSize);
-  EXPECT_EQ(totalSlots - 1, page->num_unprovisioned_slots);
+  EXPECT_EQ(total_slots - 1, page->num_unprovisioned_slots);
   generic_allocator.root()->Free(ptr);
 }
 
@@ -1092,49 +1110,50 @@
 TEST_F(PartitionAllocTest, MappingCollision) {
   // The -2 is because the first and last partition pages in a super page are
   // guard pages.
-  size_t numPartitionPagesNeeded = kNumPartitionPagesPerSuperPage - 2;
-  auto firstSuperPagePages =
-      std::make_unique<PartitionPage* []>(numPartitionPagesNeeded);
-  auto secondSuperPagePages =
-      std::make_unique<PartitionPage* []>(numPartitionPagesNeeded);
+  size_t num_partition_pages_needed = kNumPartitionPagesPerSuperPage - 2;
+  auto first_super_page_pages =
+      std::make_unique<PartitionPage* []>(num_partition_pages_needed);
+  auto second_super_page_pages =
+      std::make_unique<PartitionPage* []>(num_partition_pages_needed);
 
   size_t i;
-  for (i = 0; i < numPartitionPagesNeeded; ++i)
-    firstSuperPagePages[i] = GetFullPage(kTestAllocSize);
+  for (i = 0; i < num_partition_pages_needed; ++i)
+    first_super_page_pages[i] = GetFullPage(kTestAllocSize);
 
-  char* pageBase =
-      reinterpret_cast<char*>(PartitionPage::ToPointer(firstSuperPagePages[0]));
+  char* page_base = reinterpret_cast<char*>(
+      PartitionPage::ToPointer(first_super_page_pages[0]));
   EXPECT_EQ(kPartitionPageSize,
-            reinterpret_cast<uintptr_t>(pageBase) & kSuperPageOffsetMask);
-  pageBase -= kPartitionPageSize;
+            reinterpret_cast<uintptr_t>(page_base) & kSuperPageOffsetMask);
+  page_base -= kPartitionPageSize;
   // Map a single system page either side of the mapping for our allocations,
   // with the goal of tripping up alignment of the next mapping.
-  void* map1 = AllocPages(pageBase - kPageAllocationGranularity,
+  void* map1 = AllocPages(page_base - kPageAllocationGranularity,
                           kPageAllocationGranularity,
                           kPageAllocationGranularity, PageInaccessible);
   EXPECT_TRUE(map1);
-  void* map2 = AllocPages(pageBase + kSuperPageSize, kPageAllocationGranularity,
-                          kPageAllocationGranularity, PageInaccessible);
+  void* map2 =
+      AllocPages(page_base + kSuperPageSize, kPageAllocationGranularity,
+                 kPageAllocationGranularity, PageInaccessible);
   EXPECT_TRUE(map2);
 
-  for (i = 0; i < numPartitionPagesNeeded; ++i)
-    secondSuperPagePages[i] = GetFullPage(kTestAllocSize);
+  for (i = 0; i < num_partition_pages_needed; ++i)
+    second_super_page_pages[i] = GetFullPage(kTestAllocSize);
 
   FreePages(map1, kPageAllocationGranularity);
   FreePages(map2, kPageAllocationGranularity);
 
-  pageBase = reinterpret_cast<char*>(
-      PartitionPage::ToPointer(secondSuperPagePages[0]));
+  page_base = reinterpret_cast<char*>(
+      PartitionPage::ToPointer(second_super_page_pages[0]));
   EXPECT_EQ(kPartitionPageSize,
-            reinterpret_cast<uintptr_t>(pageBase) & kSuperPageOffsetMask);
-  pageBase -= kPartitionPageSize;
+            reinterpret_cast<uintptr_t>(page_base) & kSuperPageOffsetMask);
+  page_base -= kPartitionPageSize;
   // Map a single system page either side of the mapping for our allocations,
   // with the goal of tripping up alignment of the next mapping.
-  map1 = AllocPages(pageBase - kPageAllocationGranularity,
+  map1 = AllocPages(page_base - kPageAllocationGranularity,
                     kPageAllocationGranularity, kPageAllocationGranularity,
                     PageReadWrite);
   EXPECT_TRUE(map1);
-  map2 = AllocPages(pageBase + kSuperPageSize, kPageAllocationGranularity,
+  map2 = AllocPages(page_base + kSuperPageSize, kPageAllocationGranularity,
                     kPageAllocationGranularity, PageReadWrite);
   EXPECT_TRUE(map2);
   EXPECT_TRUE(
@@ -1142,32 +1161,32 @@
   EXPECT_TRUE(
       SetSystemPagesAccess(map2, kPageAllocationGranularity, PageInaccessible));
 
-  PartitionPage* pageInThirdSuperPage = GetFullPage(kTestAllocSize);
+  PartitionPage* page_in_third_super_page = GetFullPage(kTestAllocSize);
   FreePages(map1, kPageAllocationGranularity);
   FreePages(map2, kPageAllocationGranularity);
 
   EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(
-                    PartitionPage::ToPointer(pageInThirdSuperPage)) &
+                    PartitionPage::ToPointer(page_in_third_super_page)) &
                     kPartitionPageOffsetMask);
 
   // And make sure we really did get a page in a new superpage.
   EXPECT_NE(reinterpret_cast<uintptr_t>(
-                PartitionPage::ToPointer(firstSuperPagePages[0])) &
+                PartitionPage::ToPointer(first_super_page_pages[0])) &
                 kSuperPageBaseMask,
             reinterpret_cast<uintptr_t>(
-                PartitionPage::ToPointer(pageInThirdSuperPage)) &
+                PartitionPage::ToPointer(page_in_third_super_page)) &
                 kSuperPageBaseMask);
   EXPECT_NE(reinterpret_cast<uintptr_t>(
-                PartitionPage::ToPointer(secondSuperPagePages[0])) &
+                PartitionPage::ToPointer(second_super_page_pages[0])) &
                 kSuperPageBaseMask,
             reinterpret_cast<uintptr_t>(
-                PartitionPage::ToPointer(pageInThirdSuperPage)) &
+                PartitionPage::ToPointer(page_in_third_super_page)) &
                 kSuperPageBaseMask);
 
-  FreeFullPage(pageInThirdSuperPage);
-  for (i = 0; i < numPartitionPagesNeeded; ++i) {
-    FreeFullPage(firstSuperPagePages[i]);
-    FreeFullPage(secondSuperPagePages[i]);
+  FreeFullPage(page_in_third_super_page);
+  for (i = 0; i < num_partition_pages_needed; ++i) {
+    FreeFullPage(first_super_page_pages[i]);
+    FreeFullPage(second_super_page_pages[i]);
   }
 }
 
@@ -1315,23 +1334,41 @@
 // process, so they won't pollute other tests.
 TEST_F(PartitionAllocDeathTest, RepeatedAllocReturnNullDirect) {
   // A direct-mapped allocation size.
-  EXPECT_DEATH(DoReturnNullTest(32 * 1024 * 1024, false), "DoReturnNullTest");
+  EXPECT_DEATH(DoReturnNullTest(32 * 1024 * 1024, kPartitionAllocGenericFlags),
+               "DoReturnNullTest");
 }
 
 // Repeating above test with Realloc
 TEST_F(PartitionAllocDeathTest, RepeatedReallocReturnNullDirect) {
-  EXPECT_DEATH(DoReturnNullTest(32 * 1024 * 1024, true), "DoReturnNullTest");
+  EXPECT_DEATH(
+      DoReturnNullTest(32 * 1024 * 1024, kPartitionReallocGenericFlags),
+      "DoReturnNullTest");
+}
+
+// Repeating above test with TryRealloc
+TEST_F(PartitionAllocDeathTest, RepeatedTryReallocReturnNullDirect) {
+  EXPECT_DEATH(
+      DoReturnNullTest(32 * 1024 * 1024, kPartitionRootGenericTryRealloc),
+      "DoReturnNullTest");
 }
 
 // Test "return null" with a 512 kB block size.
 TEST_F(PartitionAllocDeathTest, RepeatedAllocReturnNull) {
   // A single-slot but non-direct-mapped allocation size.
-  EXPECT_DEATH(DoReturnNullTest(512 * 1024, false), "DoReturnNullTest");
+  EXPECT_DEATH(DoReturnNullTest(512 * 1024, kPartitionAllocGenericFlags),
+               "DoReturnNullTest");
 }
 
 // Repeating above test with Realloc.
 TEST_F(PartitionAllocDeathTest, RepeatedReallocReturnNull) {
-  EXPECT_DEATH(DoReturnNullTest(512 * 1024, true), "DoReturnNullTest");
+  EXPECT_DEATH(DoReturnNullTest(512 * 1024, kPartitionReallocGenericFlags),
+               "DoReturnNullTest");
+}
+
+// Repeating above test with TryRealloc.
+TEST_F(PartitionAllocDeathTest, RepeatedTryReallocReturnNull) {
+  EXPECT_DEATH(DoReturnNullTest(512 * 1024, kPartitionRootGenericTryRealloc),
+               "DoReturnNullTest");
 }
 
 #endif  // !defined(ARCH_CPU_64_BITS) || (defined(OS_POSIX) &&
@@ -1398,10 +1435,10 @@
   void* ptr = generic_allocator.root()->Alloc(size, type_name);
 
   EXPECT_TRUE(ptr);
-  char* charPtr = reinterpret_cast<char*>(ptr) - kPointerOffset;
+  char* char_ptr = reinterpret_cast<char*>(ptr) - kPointerOffset;
 
-  EXPECT_DEATH(*(charPtr - 1) = 'A', "");
-  EXPECT_DEATH(*(charPtr + size + kExtraAllocSize) = 'A', "");
+  EXPECT_DEATH(*(char_ptr - 1) = 'A', "");
+  EXPECT_DEATH(*(char_ptr + size + kExtraAllocSize) = 'A', "");
 
   generic_allocator.root()->Free(ptr);
 }
@@ -1428,10 +1465,10 @@
 TEST_F(PartitionAllocTest, DumpMemoryStats) {
   {
     void* ptr = allocator.root()->Alloc(kTestAllocSize, type_name);
-    MockPartitionStatsDumper mockStatsDumper;
+    MockPartitionStatsDumper mock_stats_dumper;
     allocator.root()->DumpStats("mock_allocator", false /* detailed dump */,
-                                &mockStatsDumper);
-    EXPECT_TRUE(mockStatsDumper.IsMemoryAllocationRecorded());
+                                &mock_stats_dumper);
+    EXPECT_TRUE(mock_stats_dumper.IsMemoryAllocationRecorded());
     PartitionFree(ptr);
   }
 
@@ -1720,13 +1757,13 @@
   // state of the free cache ring.
   generic_allocator.root()->PurgeMemory(PartitionPurgeDecommitEmptyPages);
 
-  char* bigPtr = reinterpret_cast<char*>(
+  char* big_ptr = reinterpret_cast<char*>(
       generic_allocator.root()->Alloc(256 * 1024, type_name));
-  generic_allocator.root()->Free(bigPtr);
+  generic_allocator.root()->Free(big_ptr);
   generic_allocator.root()->PurgeMemory(PartitionPurgeDecommitEmptyPages);
 
   CHECK_PAGE_IN_CORE(ptr - kPointerOffset, false);
-  CHECK_PAGE_IN_CORE(bigPtr - kPointerOffset, false);
+  CHECK_PAGE_IN_CORE(big_ptr - kPointerOffset, false);
 }
 
 // Tests that we prefer to allocate into a non-empty partition page over an
diff --git a/base/allocator/partition_allocator/partition_bucket.cc b/base/allocator/partition_allocator/partition_bucket.cc
index fcea5232..01d5b42f 100644
--- a/base/allocator/partition_allocator/partition_bucket.cc
+++ b/base/allocator/partition_allocator/partition_bucket.cc
@@ -38,7 +38,7 @@
   map_size &= kPageAllocationGranularityBaseMask;
 
   // TODO: these pages will be zero-filled. Consider internalizing an
-  // allocZeroed() API so we can avoid a memset() entirely in this case.
+  // AllocZeroed() API so we can avoid a memset() entirely in this case.
   char* ptr = reinterpret_cast<char*>(
       AllocPages(nullptr, map_size, kSuperPageSize, PageReadWrite));
   if (UNLIKELY(!ptr))
@@ -217,9 +217,9 @@
   // address region as much as possible. This is important for not causing
   // page table bloat and not fragmenting address spaces in 32 bit
   // architectures.
-  char* requestedAddress = root->next_super_page;
+  char* requested_address = root->next_super_page;
   char* super_page = reinterpret_cast<char*>(AllocPages(
-      requestedAddress, kSuperPageSize, kSuperPageSize, PageReadWrite));
+      requested_address, kSuperPageSize, kSuperPageSize, PageReadWrite));
   if (UNLIKELY(!super_page))
     return nullptr;
 
@@ -262,7 +262,7 @@
   // distributions will allocate the mapping directly before the last
   // successful mapping, which is far from random. So we just get fresh
   // randomness for the next mapping attempt.
-  if (requestedAddress && requestedAddress != super_page)
+  if (requested_address && requested_address != super_page)
     root->next_super_page = nullptr;
 
   // We allocated a new super page so update super page metadata.
@@ -281,8 +281,8 @@
   latest_extent->next = nullptr;
 
   PartitionSuperPageExtentEntry* current_extent = root->current_extent;
-  bool isNewExtent = (super_page != requestedAddress);
-  if (UNLIKELY(isNewExtent)) {
+  bool is_new_extent = (super_page != requested_address);
+  if (UNLIKELY(is_new_extent)) {
     if (UNLIKELY(!current_extent)) {
       DCHECK(!root->first_extent);
       root->first_extent = latest_extent;
@@ -512,9 +512,9 @@
   } else {
     // Third. If we get here, we need a brand new page.
     uint16_t num_partition_pages = this->get_pages_per_slot_span();
-    void* rawPages = AllocNewSlotSpan(root, flags, num_partition_pages);
-    if (LIKELY(rawPages != nullptr)) {
-      new_page = PartitionPage::FromPointerNoAlignmentCheck(rawPages);
+    void* raw_pages = AllocNewSlotSpan(root, flags, num_partition_pages);
+    if (LIKELY(raw_pages != nullptr)) {
+      new_page = PartitionPage::FromPointerNoAlignmentCheck(raw_pages);
       InitializeSlotSpan(new_page);
     }
   }
diff --git a/base/android/proguard/proguard.gni b/base/android/proguard/proguard.gni
new file mode 100644
index 0000000..1e78bc0
--- /dev/null
+++ b/base/android/proguard/proguard.gni
@@ -0,0 +1,9 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+declare_args() {
+  # Controls whether proguard obfuscation is enabled for targets
+  # configured to use it.
+  enable_proguard_obfuscation = true
+}
diff --git a/base/logging.cc b/base/logging.cc
index 8eabda0e..7752cce 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -852,7 +852,11 @@
       }
 #endif
       // Crash the process to generate a dump.
+#if defined(OFFICIAL_BUILD) && defined(NDEBUG)
+      IMMEDIATE_CRASH();
+#else
       base::debug::BreakDebugger();
+#endif
     }
   }
 }
diff --git a/base/message_loop/incoming_task_queue.cc b/base/message_loop/incoming_task_queue.cc
index 6821730f..c05c38f 100644
--- a/base/message_loop/incoming_task_queue.cc
+++ b/base/message_loop/incoming_task_queue.cc
@@ -72,9 +72,6 @@
   }
 #endif
 
-  if (!delay.is_zero())
-    UMA_HISTOGRAM_LONG_TIMES("MessageLoop.DelayedTaskQueue.PostedDelay", delay);
-
   return PostPendingTask(&pending_task);
 }
 
@@ -85,7 +82,7 @@
 
 void IncomingTaskQueue::ReportMetricsOnIdle() const {
   UMA_HISTOGRAM_COUNTS_1M(
-      "MessageLoop.DelayedTaskQueue.PendingTasksCountOnIdle",
+      "MessageLoop.DelayedTaskQueueForUI.PendingTasksCountOnIdle",
       delayed_tasks_.Size());
 }
 
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 1b76cbb3..3723960a 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -15,7 +15,6 @@
 #include "base/message_loop/message_pump_default.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/message_loop/message_pump_for_ui.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/run_loop.h"
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "base/threading/thread_id_name_manager.h"
@@ -36,37 +35,6 @@
   return pump;
 }
 
-enum class ScheduledWakeupResult {
-  // The MessageLoop went to sleep with a timeout and woke up because of that
-  // timeout.
-  kCompleted,
-  // The MessageLoop went to sleep with a timeout but was woken up before it
-  // fired.
-  kInterrupted,
-};
-
-// Reports a ScheduledWakeup's result when waking up from a non-infinite sleep.
-// Reports are using a 14 day spread (maximum examined delay for
-// https://crbug.com/850450#c3), with 50 buckets that still yields 7 buckets
-// under 16ms and hence plenty of resolution.
-void ReportScheduledWakeupResult(ScheduledWakeupResult result,
-                                 TimeDelta intended_sleep) {
-  switch (result) {
-    case ScheduledWakeupResult::kCompleted:
-      UMA_HISTOGRAM_CUSTOM_TIMES("MessageLoop.ScheduledSleep.Completed",
-                                 intended_sleep,
-                                 base::TimeDelta::FromMilliseconds(1),
-                                 base::TimeDelta::FromDays(14), 50);
-      break;
-    case ScheduledWakeupResult::kInterrupted:
-      UMA_HISTOGRAM_CUSTOM_TIMES("MessageLoop.ScheduledSleep.Interrupted",
-                                 intended_sleep,
-                                 base::TimeDelta::FromMilliseconds(1),
-                                 base::TimeDelta::FromDays(14), 50);
-      break;
-  }
-}
-
 }  // namespace
 
 class MessageLoop::Controller : public internal::IncomingTaskQueue::Observer {
@@ -496,20 +464,6 @@
 
   // Execute oldest task.
   while (incoming_task_queue_->triage_tasks().HasTasks()) {
-    if (!scheduled_wakeup_.next_run_time.is_null()) {
-      // While the frontmost task may racily be ripe. The MessageLoop was awaken
-      // without needing the timeout anyways. Since this metric is about
-      // determining whether sleeping for long periods ever succeeds: it's
-      // easier to just consider any untriaged task as an interrupt (this also
-      // makes the logic simpler for untriaged delayed tasks which may alter the
-      // top of the task queue prior to DoDelayedWork() but did cause a wakeup
-      // regardless -- per currently requiring this immediate triage step even
-      // for long delays).
-      ReportScheduledWakeupResult(ScheduledWakeupResult::kInterrupted,
-                                  scheduled_wakeup_.intended_sleep);
-      scheduled_wakeup_ = ScheduledWakeup();
-    }
-
     PendingTask pending_task = incoming_task_queue_->triage_tasks().Pop();
     if (pending_task.task.IsCancelled())
       continue;
@@ -533,27 +487,9 @@
 }
 
 bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) {
-  if (!task_execution_allowed_) {
+  if (!task_execution_allowed_ ||
+      !incoming_task_queue_->delayed_tasks().HasTasks()) {
     *next_delayed_work_time = TimeTicks();
-    // |scheduled_wakeup_| isn't used in nested loops that don't process
-    // application tasks.
-    DCHECK(scheduled_wakeup_.next_run_time.is_null());
-    return false;
-  }
-
-  if (!incoming_task_queue_->delayed_tasks().HasTasks()) {
-    *next_delayed_work_time = TimeTicks();
-
-    // It's possible to be woken up by a system event and have it cancel the
-    // upcoming delayed task from under us before DoDelayedWork() -- see comment
-    // under |next_run_time > recent_time_|. This condition covers the special
-    // case where such a system event cancelled *all* pending delayed tasks.
-    if (!scheduled_wakeup_.next_run_time.is_null()) {
-      ReportScheduledWakeupResult(ScheduledWakeupResult::kInterrupted,
-                                  scheduled_wakeup_.intended_sleep);
-      scheduled_wakeup_ = ScheduledWakeup();
-    }
-
     return false;
   }
 
@@ -571,36 +507,10 @@
     recent_time_ = TimeTicks::Now();  // Get a better view of Now();
     if (next_run_time > recent_time_) {
       *next_delayed_work_time = CapAtOneDay(next_run_time);
-
-      // If the loop was woken up early by an untriaged task:
-      // |scheduled_wakeup_| will have been handled already in DoWork(). If it
-      // wasn't, it means the early wake up was caused by a system event (e.g.
-      // MessageLoopForUI or IO).
-      if (!scheduled_wakeup_.next_run_time.is_null()) {
-        // Handling the system event may have resulted in cancelling the
-        // upcoming delayed task (and then it being pruned by
-        // DelayedTaskQueue::HasTasks()); hence, we cannot check for strict
-        // equality here. We can however check that the pending task is either
-        // still there or that a later delay replaced it in front of the queue.
-        // There shouldn't have been new tasks added in |delayed_tasks()| per
-        // DoWork() not having triaged new tasks since the last DoIdleWork().
-        DCHECK_GE(next_run_time, scheduled_wakeup_.next_run_time);
-
-        ReportScheduledWakeupResult(ScheduledWakeupResult::kInterrupted,
-                                    scheduled_wakeup_.intended_sleep);
-        scheduled_wakeup_ = ScheduledWakeup();
-      }
-
       return false;
     }
   }
 
-  if (next_run_time == scheduled_wakeup_.next_run_time) {
-    ReportScheduledWakeupResult(ScheduledWakeupResult::kCompleted,
-                                scheduled_wakeup_.intended_sleep);
-    scheduled_wakeup_ = ScheduledWakeup();
-  }
-
   PendingTask pending_task = incoming_task_queue_->delayed_tasks().Pop();
 
   if (incoming_task_queue_->delayed_tasks().HasTasks()) {
@@ -619,43 +529,19 @@
   bool need_high_res_timers = false;
 #endif
 
-  // Do not report idle metrics nor do any logic related to delayed tasks if
-  // about to quit the loop and/or in a nested loop where
-  // |!task_execution_allowed_|. In the former case, the loop isn't going to
-  // sleep and in the latter case DoDelayedWork() will not actually do the work
-  // this is prepping for.
+  // Do not report idle metrics if about to quit the loop and/or in a nested
+  // loop where |!task_execution_allowed_|. In the former case, the loop isn't
+  // going to sleep and in the latter case DoDelayedWork() will not actually do
+  // the work this is prepping for.
   if (ShouldQuitWhenIdle()) {
     pump_->Quit();
   } else if (task_execution_allowed_) {
-    incoming_task_queue_->ReportMetricsOnIdle();
-
-    if (incoming_task_queue_->delayed_tasks().HasTasks()) {
-      TimeTicks scheduled_wakeup_time =
-          incoming_task_queue_->delayed_tasks().Peek().delayed_run_time;
-
-      if (!scheduled_wakeup_.next_run_time.is_null()) {
-        // It's possible for DoIdleWork() to be invoked twice in a row (e.g. if
-        // the MessagePump processed system work and became idle twice in a row
-        // without application tasks in between -- some pumps with a native
-        // message loop do not invoke DoWork() / DoDelayedWork() when awaken for
-        // system work only). As in DoDelayedWork(), we cannot check for strict
-        // equality below as the system work may have cancelled the frontmost
-        // task.
-        DCHECK_GE(scheduled_wakeup_time, scheduled_wakeup_.next_run_time);
-
-        ReportScheduledWakeupResult(ScheduledWakeupResult::kInterrupted,
-                                    scheduled_wakeup_.intended_sleep);
-        scheduled_wakeup_ = ScheduledWakeup();
-      }
-
-      // Store the remaining delay as well as the programmed wakeup time in
-      // order to know next time this MessageLoop wakes up whether it woke up
-      // because of this pending task (is it still the frontmost task in the
-      // queue?) and be able to report the slept delta (which is lost if not
-      // saved here).
-      scheduled_wakeup_ = ScheduledWakeup{
-          scheduled_wakeup_time, scheduled_wakeup_time - TimeTicks::Now()};
-    }
+    // Only track idle metrics in MessageLoopForUI to avoid too much contention
+    // logging the histogram (https://crbug.com/860801) -- there's typically
+    // only one UI thread per process and, for practical purposes, restricting
+    // the MessageLoop diagnostic metrics to it yields similar information.
+    if (type_ == TYPE_UI)
+      incoming_task_queue_->ReportMetricsOnIdle();
 
 #if defined(OS_WIN)
     // On Windows we activate the high resolution timer so that the wait
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index ab49d87..7c31a12 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -287,15 +287,6 @@
   // A recent snapshot of Time::Now(), used to check delayed_work_queue_.
   TimeTicks recent_time_;
 
-  // Non-null when the last thing this MessageLoop did is become idle with
-  // pending delayed tasks. Used to report metrics on the following wake up.
-  struct ScheduledWakeup {
-    // The scheduled time of the next delayed task when this loop became idle.
-    TimeTicks next_run_time;
-    // The delta until |next_run_time| when this loop became idle.
-    TimeDelta intended_sleep;
-  } scheduled_wakeup_;
-
   ObserverList<DestructionObserver> destruction_observers_;
 
   // A boolean which prevents unintentional reentrant task execution (e.g. from
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index 1a21fc5..f0b07d4 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -23,7 +23,9 @@
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task_scheduler/task_scheduler.h"
+#include "base/test/bind_test_util.h"
 #include "base/test/gtest_util.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
@@ -1758,6 +1760,63 @@
   run_loop.Run();
 }
 
+#if defined(OS_MACOSX)
+// This metric is a bit broken on Mac OS because CFRunLoop doesn't
+// deterministically invoke MessageLoop::DoIdleWork(). This being a temporary
+// diagnosis metric, we let this fly and simply not test it on Mac.
+#define MAYBE_MetricsOnlyFromUILoops DISABLED_MetricsOnlyFromUILoops
+#else
+#define MAYBE_MetricsOnlyFromUILoops MetricsOnlyFromUILoops
+#endif
+
+TEST_P(MessageLoopTypedTest, MAYBE_MetricsOnlyFromUILoops) {
+  MessageLoop loop(GetMessageLoopType());
+
+  const bool histograms_expected = GetMessageLoopType() == MessageLoop::TYPE_UI;
+
+  HistogramTester histogram_tester;
+
+  // A delay which is expected to give enough time for the MessageLoop to go
+  // idle after triaging it.
+  TimeDelta delay_that_leads_to_idle = TimeDelta::FromMilliseconds(1);
+
+  // On some platforms testing under emulation, 1 ms is not enough. See how long
+  // it takes to resolve a 1ms delayed task and use 10X that for the real test.
+  {
+    TimeTicks begin_run_loop = TimeTicks::Now();
+
+    RunLoop run_loop;
+    loop.task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(),
+                                        delay_that_leads_to_idle);
+    run_loop.Run();
+
+    delay_that_leads_to_idle = 10 * (TimeTicks::Now() - begin_run_loop);
+  }
+
+  SCOPED_TRACE(delay_that_leads_to_idle);
+
+  // Loop that goes idle with one pending task.
+  RunLoop run_loop;
+  loop.task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(),
+                                      delay_that_leads_to_idle);
+  run_loop.Run();
+
+  const std::vector<Bucket> buckets = histogram_tester.GetAllSamples(
+      "MessageLoop.DelayedTaskQueueForUI.PendingTasksCountOnIdle");
+  if (histograms_expected) {
+    // DoIdleWork() should have triggered at least once in the second RunLoop.
+    // It may also have triggered in the first one if the test environment is
+    // fast enough. It can sometimes also trigger additional times when a system
+    // message (e.g. system ping) interrupts the sleep. All cases should
+    // nonetheless report in the "1" bucket.
+    EXPECT_EQ(buckets.size(), 1U);
+    EXPECT_EQ(buckets[0].min, 1);
+    EXPECT_GE(buckets[0].count, 1);
+  } else {
+    EXPECT_TRUE(buckets.empty());
+  }
+}
+
 INSTANTIATE_TEST_CASE_P(
     ,
     MessageLoopTypedTest,
diff --git a/base/process/process_linux.cc b/base/process/process_linux.cc
index faf39af..5f07012 100644
--- a/base/process/process_linux.cc
+++ b/base/process/process_linux.cc
@@ -5,6 +5,7 @@
 #include "base/process/process.h"
 
 #include <errno.h>
+#include <limits.h>
 #include <sys/resource.h>
 
 #include "base/files/file_util.h"
@@ -74,12 +75,25 @@
 const int kBackgroundPriority = 5;
 #endif  // defined(OS_CHROMEOS)
 
+// NZERO should be defined in <limits.h> per POSIX, and should be at least
+// 20. (NZERO-1) is the highest possible niceness value (i.e. lowest process
+// priority). Most platforms use NZERO=20.
+//
+// RLIMIT_NICE tells us how much we can reduce niceness (increase priority) if
+// we start at NZERO.
+//
+// e.g. if NZERO is 20 and the rlimit is 30, we can lower niceness anywhere
+// within the [-10, 19] range (20 - 30 = -10).
+//
+// So, to re-raise priority to kForegroundPriority, we need at least this much:
+constexpr int kMinNiceRLimitForReraising = NZERO - kForegroundPriority;
+
 bool CanReraisePriority() {
   // We won't be able to raise the priority if we don't have the right rlimit.
   // The limit may be adjusted in /etc/security/limits.conf for PAM systems.
   struct rlimit rlim;
   return (getrlimit(RLIMIT_NICE, &rlim) == 0) &&
-         (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur);
+         static_cast<int>(rlim.rlim_cur) >= kMinNiceRLimitForReraising;
 }
 
 }  // namespace
diff --git a/base/task_scheduler/service_thread.cc b/base/task_scheduler/service_thread.cc
index 12cd3282..7e7731f 100644
--- a/base/task_scheduler/service_thread.cc
+++ b/base/task_scheduler/service_thread.cc
@@ -13,7 +13,6 @@
 #include "base/task_scheduler/task_scheduler.h"
 #include "base/task_scheduler/task_tracker.h"
 #include "base/task_scheduler/task_traits.h"
-#include "build/build_config.h"
 
 namespace base {
 namespace internal {
@@ -37,9 +36,6 @@
   // environment, do not perform the heartbeat report in that case since it
   // relies on such an environment.
   if (task_tracker_ && TaskScheduler::GetInstance()) {
-// Seemingly causing power regression on Android, disable to see if truly at
-// fault : https://crbug.com/848255
-#if !defined(OS_ANDROID)
     // Compute the histogram every hour (with a slight offset to drift if that
     // hour tick happens to line up with specific events). Once per hour per
     // user was deemed sufficient to gather a reliable metric.
@@ -51,7 +47,6 @@
                                           : g_heartbeat_for_testing,
         BindRepeating(&ServiceThread::PerformHeartbeatLatencyReport,
                       Unretained(this)));
-#endif
   }
 }
 
diff --git a/base/task_scheduler/service_thread_unittest.cc b/base/task_scheduler/service_thread_unittest.cc
index 3c42762..0214a72 100644
--- a/base/task_scheduler/service_thread_unittest.cc
+++ b/base/task_scheduler/service_thread_unittest.cc
@@ -52,18 +52,10 @@
   service_thread.FlushForTesting();
 }
 
-#if defined(OS_ANDROID)
-// The heartbeat latency report has been temporarily disabled on Android per
-// https://crbug.com/848255.
-#define MAYBE_HeartbeatLatencyReport DISABLED_HeartbeatLatencyReport
-#else
-#define MAYBE_HeartbeatLatencyReport HeartbeatLatencyReport
-#endif
-
 // Integration test verifying that a service thread running in a fully
 // integrated TaskScheduler environment results in reporting
 // HeartbeatLatencyMicroseconds metrics.
-TEST(TaskSchedulerServiceThreadIntegrationTest, MAYBE_HeartbeatLatencyReport) {
+TEST(TaskSchedulerServiceThreadIntegrationTest, HeartbeatLatencyReport) {
   ServiceThread::SetHeartbeatIntervalForTesting(TimeDelta::FromMilliseconds(1));
 
   TaskScheduler::SetInstance(
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index 65d37d1..9617b51 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -74,6 +74,7 @@
           J('pylib', 'results', 'json_results_test.py'),
           J('pylib', 'symbols', 'apk_native_libs_unittest.py'),
           J('pylib', 'symbols', 'elf_symbolizer_unittest.py'),
+          J('pylib', 'symbols', 'symbol_utils_unittest.py'),
           J('pylib', 'utils', 'decorators_test.py'),
           J('pylib', 'utils', 'device_dependencies_test.py'),
           J('pylib', 'utils', 'dexdump_test.py'),
diff --git a/build/android/asan_symbolize.py b/build/android/asan_symbolize.py
index 19d71ca..9f2e88a 100755
--- a/build/android/asan_symbolize.py
+++ b/build/android/asan_symbolize.py
@@ -14,6 +14,7 @@
 from pylib import constants
 from pylib.constants import host_paths
 
+# pylint: disable=wrong-import-order
 # Uses symbol.py from third_party/android_platform, not python's.
 with host_paths.SysPath(
     host_paths.ANDROID_PLATFORM_DEVELOPMENT_SCRIPTS_PATH,
diff --git a/build/android/devil_chromium.py b/build/android/devil_chromium.py
index af2141a..2ae64367 100644
--- a/build/android/devil_chromium.py
+++ b/build/android/devil_chromium.py
@@ -167,4 +167,3 @@
 
   devil_env.config.Initialize(
       configs=[devil_dynamic_config], config_files=[_DEVIL_CONFIG])
-
diff --git a/build/android/gyp/generate_resource_rewriter.py b/build/android/gyp/generate_resource_rewriter.py
index 82ddc21..ba635a29 100755
--- a/build/android/gyp/generate_resource_rewriter.py
+++ b/build/android/gyp/generate_resource_rewriter.py
@@ -107,4 +107,3 @@
 
 if __name__ == '__main__':
   sys.exit(main())
-
diff --git a/build/android/gyp/java_google_api_keys.py b/build/android/gyp/java_google_api_keys.py
index f57e0b3..349821a8 100755
--- a/build/android/gyp/java_google_api_keys.py
+++ b/build/android/gyp/java_google_api_keys.py
@@ -121,4 +121,3 @@
 
 if __name__ == '__main__':
   _DoMain(sys.argv[1:])
-
diff --git a/build/android/gyp/main_dex_list.py b/build/android/gyp/main_dex_list.py
index 9ccfea0..2435859 100755
--- a/build/android/gyp/main_dex_list.py
+++ b/build/android/gyp/main_dex_list.py
@@ -172,4 +172,3 @@
 
 if __name__ == '__main__':
   sys.exit(main(sys.argv[1:]))
-
diff --git a/build/android/gyp/util/__init__.py b/build/android/gyp/util/__init__.py
index 727e987e..96196cff 100644
--- a/build/android/gyp/util/__init__.py
+++ b/build/android/gyp/util/__init__.py
@@ -1,4 +1,3 @@
 # Copyright (c) 2012 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.
-
diff --git a/build/android/gyp/write_ordered_libraries.py b/build/android/gyp/write_ordered_libraries.py
index e3d87c1..3b9a3374 100755
--- a/build/android/gyp/write_ordered_libraries.py
+++ b/build/android/gyp/write_ordered_libraries.py
@@ -114,5 +114,3 @@
 
 if __name__ == '__main__':
   sys.exit(main())
-
-
diff --git a/build/android/incremental_install/__init__.py b/build/android/incremental_install/__init__.py
index 1aaf0e1..50b23df 100644
--- a/build/android/incremental_install/__init__.py
+++ b/build/android/incremental_install/__init__.py
@@ -1,4 +1,3 @@
 # Copyright 2015 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.
-
diff --git a/build/android/lighttpd_server.py b/build/android/lighttpd_server.py
index 89a828a..c77d740 100755
--- a/build/android/lighttpd_server.py
+++ b/build/android/lighttpd_server.py
@@ -104,7 +104,7 @@
         break
       self.process.close()
 
-      if self.fixed_port or not 'in use' in server_error:
+      if self.fixed_port or 'in use' not in server_error:
         print 'Client error:', client_error
         print 'Server error:', server_error
         return False
diff --git a/build/android/method_count.py b/build/android/method_count.py
index 68823e1..490887a 100755
--- a/build/android/method_count.py
+++ b/build/android/method_count.py
@@ -114,4 +114,3 @@
 
 if __name__ == '__main__':
   sys.exit(main())
-
diff --git a/build/android/pylib/android/__init__.py b/build/android/pylib/android/__init__.py
index 7a90b53..a67c3501 100644
--- a/build/android/pylib/android/__init__.py
+++ b/build/android/pylib/android/__init__.py
@@ -1,4 +1,3 @@
 # Copyright (c) 2016 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
-
diff --git a/build/android/pylib/base/__init__.py b/build/android/pylib/base/__init__.py
index 727e987e..96196cff 100644
--- a/build/android/pylib/base/__init__.py
+++ b/build/android/pylib/base/__init__.py
@@ -1,4 +1,3 @@
 # Copyright (c) 2012 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.
-
diff --git a/build/android/pylib/base/base_test_result.py b/build/android/pylib/base/base_test_result.py
index af9f68f8..a553532 100644
--- a/build/android/pylib/base/base_test_result.py
+++ b/build/android/pylib/base/base_test_result.py
@@ -260,4 +260,3 @@
   def DidRunPass(self):
     """Return whether the test run was successful."""
     return not self.GetNotPass() - self.GetSkip()
-
diff --git a/build/android/pylib/base/test_exception.py b/build/android/pylib/base/test_exception.py
index f00f0d0e..c98d2cb 100644
--- a/build/android/pylib/base/test_exception.py
+++ b/build/android/pylib/base/test_exception.py
@@ -6,4 +6,3 @@
 class TestException(Exception):
   """Base class for exceptions thrown by the test runner."""
   pass
-
diff --git a/build/android/pylib/base/test_instance.py b/build/android/pylib/base/test_instance.py
index cdf678f2..f0ff830 100644
--- a/build/android/pylib/base/test_instance.py
+++ b/build/android/pylib/base/test_instance.py
@@ -32,4 +32,3 @@
 
   def __exit__(self, _exc_type, _exc_val, _exc_tb):
     self.TearDown()
-
diff --git a/build/android/pylib/base/test_run.py b/build/android/pylib/base/test_run.py
index 9b16f89..59e595d 100644
--- a/build/android/pylib/base/test_run.py
+++ b/build/android/pylib/base/test_run.py
@@ -41,4 +41,3 @@
 
   def __exit__(self, exc_type, exc_val, exc_tb):
     self.TearDown()
-
diff --git a/build/android/pylib/base/test_run_factory.py b/build/android/pylib/base/test_run_factory.py
index 1a28728..1f63a059 100644
--- a/build/android/pylib/base/test_run_factory.py
+++ b/build/android/pylib/base/test_run_factory.py
@@ -54,4 +54,3 @@
 
   error_func('Unable to create test run for %s tests in %s environment'
              % (str(test_instance), str(env)))
-
diff --git a/build/android/pylib/base/test_server.py b/build/android/pylib/base/test_server.py
index 085a51e9..763e1212 100644
--- a/build/android/pylib/base/test_server.py
+++ b/build/android/pylib/base/test_server.py
@@ -16,4 +16,3 @@
 
   def TearDown(self):
     raise NotImplementedError
-
diff --git a/build/android/pylib/gtest/__init__.py b/build/android/pylib/gtest/__init__.py
index 727e987e..96196cff 100644
--- a/build/android/pylib/gtest/__init__.py
+++ b/build/android/pylib/gtest/__init__.py
@@ -1,4 +1,3 @@
 # Copyright (c) 2012 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.
-
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py
index d93edc6..7e0923a 100644
--- a/build/android/pylib/gtest/gtest_test_instance.py
+++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -555,4 +555,3 @@
   def TearDown(self):
     """Do nothing."""
     pass
-
diff --git a/build/android/pylib/gtest/gtest_test_instance_test.py b/build/android/pylib/gtest/gtest_test_instance_test.py
index 3466924..a34ab84 100755
--- a/build/android/pylib/gtest/gtest_test_instance_test.py
+++ b/build/android/pylib/gtest/gtest_test_instance_test.py
@@ -260,4 +260,3 @@
 
 if __name__ == '__main__':
   unittest.main(verbosity=2)
-
diff --git a/build/android/pylib/instrumentation/__init__.py b/build/android/pylib/instrumentation/__init__.py
index 727e987e..96196cff 100644
--- a/build/android/pylib/instrumentation/__init__.py
+++ b/build/android/pylib/instrumentation/__init__.py
@@ -1,4 +1,3 @@
 # Copyright (c) 2012 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.
-
diff --git a/build/android/pylib/junit/__init__.py b/build/android/pylib/junit/__init__.py
index 5cac0261..4d6aabb9 100644
--- a/build/android/pylib/junit/__init__.py
+++ b/build/android/pylib/junit/__init__.py
@@ -1,4 +1,3 @@
 # 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.
-
diff --git a/build/android/pylib/linker/__init__.py b/build/android/pylib/linker/__init__.py
index af99437..9228df89 100644
--- a/build/android/pylib/linker/__init__.py
+++ b/build/android/pylib/linker/__init__.py
@@ -1,4 +1,3 @@
 # 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.
-
diff --git a/build/android/pylib/linker/linker_test_instance.py b/build/android/pylib/linker/linker_test_instance.py
index 1de3e17..6ace7a36 100644
--- a/build/android/pylib/linker/linker_test_instance.py
+++ b/build/android/pylib/linker/linker_test_instance.py
@@ -48,4 +48,3 @@
 
   def TestType(self):
     return 'linker'
-
diff --git a/build/android/pylib/local/device/local_device_gtest_run.py b/build/android/pylib/local/device/local_device_gtest_run.py
index 21e9fe85..4734883 100644
--- a/build/android/pylib/local/device/local_device_gtest_run.py
+++ b/build/android/pylib/local/device/local_device_gtest_run.py
@@ -152,6 +152,7 @@
       extras[gtest_test_instance.EXTRA_SHARD_NANO_TIMEOUT] = int(
           kwargs['timeout'] * _SECONDS_TO_NANOS)
 
+    # pylint: disable=redefined-variable-type
     command_line_file = _NullContextManager()
     if flags:
       if len(flags) > _MAX_INLINE_FLAGS_LENGTH:
@@ -169,6 +170,7 @@
         extras[_EXTRA_TEST_LIST] = test_list_file.name
       else:
         extras[_EXTRA_TEST] = test[0]
+    # pylint: enable=redefined-variable-type
 
     stdout_file = device_temp_file.DeviceTempFile(
         device.adb, dir=device.GetExternalStoragePath(), suffix='.gtest_out')
@@ -283,11 +285,13 @@
     assert isinstance(test_instance, gtest_test_instance.GtestTestInstance)
     super(LocalDeviceGtestRun, self).__init__(env, test_instance)
 
+    # pylint: disable=redefined-variable-type
     if self._test_instance.apk:
       self._delegate = _ApkDelegate(self._test_instance, env.tool)
     elif self._test_instance.exe_dist_dir:
       self._delegate = _ExeDelegate(self, self._test_instance.exe_dist_dir,
                                     self._env.tool)
+    # pylint: enable=redefined-variable-type
     self._crashes = set()
     self._servers = collections.defaultdict(list)
 
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index 40b857d..de7ed93 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -153,7 +153,11 @@
           self._replace_package_contextmanager = system_app.ReplaceSystemApp(
               dev, self._test_instance.replace_system_package.package,
               self._test_instance.replace_system_package.replacement_apk)
+          # Pylint is not smart enough to realize that this field has
+          # an __enter__ method, and will complain loudly.
+          # pylint: disable=no-member
           self._replace_package_contextmanager.__enter__()
+          # pylint: enable=no-member
 
         steps.append(replace_package)
 
@@ -308,12 +312,15 @@
       valgrind_tools.SetChromeTimeoutScale(dev, None)
 
       if self._replace_package_contextmanager:
+        # See pylint-related commend above with __enter__()
+        # pylint: disable=no-member
         self._replace_package_contextmanager.__exit__(*sys.exc_info())
+        # pylint: enable=no-member
 
     self._env.parallel_devices.pMap(individual_device_tear_down)
 
   def _CreateFlagChangerIfNeeded(self, device):
-    if not str(device) in self._flag_changers:
+    if str(device) not in self._flag_changers:
       self._flag_changers[str(device)] = flag_changer.FlagChanger(
         device, "test-cmdline-file")
 
diff --git a/build/android/pylib/local/device/local_device_test_run.py b/build/android/pylib/local/device/local_device_test_run.py
index 90e6b67..00d715b 100644
--- a/build/android/pylib/local/device/local_device_test_run.py
+++ b/build/android/pylib/local/device/local_device_test_run.py
@@ -220,7 +220,7 @@
         if hash(self._GetUniqueTestName(t)) % total_shards == shard_index]
 
   def GetTool(self, device):
-    if not str(device) in self._tools:
+    if str(device) not in self._tools:
       self._tools[str(device)] = valgrind_tools.CreateTool(
           self._env.tool, device)
     return self._tools[str(device)]
diff --git a/build/android/pylib/local/local_test_server_spawner.py b/build/android/pylib/local/local_test_server_spawner.py
index 8e416fac..6cd282e 100644
--- a/build/android/pylib/local/local_test_server_spawner.py
+++ b/build/android/pylib/local/local_test_server_spawner.py
@@ -98,4 +98,3 @@
     self.Reset()
     self._spawning_server.Stop()
     forwarder.Forwarder.UnmapDevicePort(self.port, self._device)
-
diff --git a/build/android/pylib/results/flakiness_dashboard/json_results_generator.py b/build/android/pylib/results/flakiness_dashboard/json_results_generator.py
index 9693977..5e5f83f 100644
--- a/build/android/pylib/results/flakiness_dashboard/json_results_generator.py
+++ b/build/android/pylib/results/flakiness_dashboard/json_results_generator.py
@@ -380,6 +380,7 @@
                          urllib2.quote(self._test_type),
                          urllib2.quote(self._master_name)))
 
+    # pylint: disable=redefined-variable-type
     try:
       # FIXME: We should talk to the network via a Host object.
       results_file = urllib2.urlopen(results_file_url)
@@ -391,6 +392,7 @@
         error = http_error
     except urllib2.URLError, url_error:
       error = url_error
+    # pylint: enable=redefined-variable-type
 
     if old_results:
       # Strip the prefix and suffix so we can get the actual JSON object.
diff --git a/build/android/pylib/results/json_results.py b/build/android/pylib/results/json_results.py
index 1243691..3f87b46 100644
--- a/build/android/pylib/results/json_results.py
+++ b/build/android/pylib/results/json_results.py
@@ -175,4 +175,3 @@
                                            duration=tr['elapsed_time_ms'])
           for tr in test_runs])
   return results_list
-
diff --git a/build/android/pylib/results/json_results_test.py b/build/android/pylib/results/json_results_test.py
index 27617135..e8b983b5 100755
--- a/build/android/pylib/results/json_results_test.py
+++ b/build/android/pylib/results/json_results_test.py
@@ -178,4 +178,3 @@
 
 if __name__ == '__main__':
   unittest.main(verbosity=2)
-
diff --git a/build/android/pylib/results/presentation/test_results_presentation.py b/build/android/pylib/results/presentation/test_results_presentation.py
index eaae68f85..82d6c88 100755
--- a/build/android/pylib/results/presentation/test_results_presentation.py
+++ b/build/android/pylib/results/presentation/test_results_presentation.py
@@ -268,6 +268,7 @@
 
 
 def feedback_url(result_details_link):
+  # pylint: disable=redefined-variable-type
   url_args = [
       ('labels', 'Pri-2,Type-Bug,Restrict-View-Google'),
       ('summary', 'Result Details Feedback:'),
@@ -276,6 +277,7 @@
   if result_details_link:
     url_args.append(('comment', 'Please check out: %s' % result_details_link))
   url_args = urllib.urlencode(url_args)
+  # pylint: enable=redefined-variable-type
   return 'https://bugs.chromium.org/p/chromium/issues/entry?%s' % url_args
 
 
@@ -370,6 +372,7 @@
     # This will be reported as an error by result_details, no need to duplicate.
     return None
   ui_screenshots = []
+  # pylint: disable=too-many-nested-blocks
   for testsuite_run in json_object['per_iteration_data']:
     for _, test_runs in testsuite_run.iteritems():
       for test_run in test_runs:
@@ -388,6 +391,7 @@
             test_screenshots = json.loads(
                 screenshot_string)
           ui_screenshots.extend(test_screenshots)
+  # pylint: enable=too-many-nested-blocks
 
   if ui_screenshots:
     return json.dumps(ui_screenshots)
diff --git a/build/android/pylib/symbols/symbol_utils.py b/build/android/pylib/symbols/symbol_utils.py
new file mode 100644
index 0000000..e4e3faa
--- /dev/null
+++ b/build/android/pylib/symbols/symbol_utils.py
@@ -0,0 +1,812 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import bisect
+import collections
+import logging
+import os
+import re
+
+from pylib.constants import host_paths
+from pylib.symbols import elf_symbolizer
+
+
+def _AndroidAbiToCpuArch(android_abi):
+  """Return the Chromium CPU architecture name for a given Android ABI."""
+  _ARCH_MAP = {
+    'armeabi': 'arm',
+    'armeabi-v7a': 'arm',
+    'arm64-v8a': 'arm64',
+    'x86_64': 'x64',
+  }
+  return _ARCH_MAP.get(android_abi, android_abi)
+
+
+def _HexAddressRegexpFor(android_abi):
+  """Return a regexp matching hexadecimal addresses for a given Android ABI."""
+  if android_abi in ['x86_64', 'arm64-v8a', 'mips64']:
+    width = 16
+  else:
+    width = 8
+  return '[0-9a-f]{%d}' % width
+
+
+class HostLibraryFinder(object):
+  """Translate device library path to matching host unstripped library path.
+
+  Usage is the following:
+    1) Create instance.
+    2) Call AddSearchDir() once or more times to add host directory path to
+       look for unstripped native libraries.
+    3) Call Find(device_libpath) repeatedly to translate a device-specific
+       library path into the corresponding host path to the unstripped
+       version.
+  """
+  def __init__(self):
+    """Initialize instance."""
+    self._search_dirs = []
+    self._lib_map = {}        # Map of library name to host file paths.
+
+  def AddSearchDir(self, lib_dir):
+    """Add a directory to the search path for host native shared libraries.
+
+    Args:
+      lib_dir: host path containing native libraries.
+    """
+    if not os.path.exists(lib_dir):
+      logging.warning('Ignoring missing host library directory: %s', lib_dir)
+      return
+    if not os.path.isdir(lib_dir):
+      logging.warning('Ignoring invalid host library directory: %s', lib_dir)
+      return
+    self._search_dirs.append(lib_dir)
+    self._lib_map = {}  # Reset the map.
+
+  def Find(self, device_libpath):
+    """Find the host file path matching a specific device library path.
+
+    Args:
+      device_libpath: device-specific file path to library or executable.
+    Returns:
+      host file path to the unstripped version of the library, or None.
+    """
+    host_lib_path = None
+    lib_name = os.path.basename(device_libpath)
+    host_lib_path = self._lib_map.get(lib_name)
+    if not host_lib_path:
+      for search_dir in self._search_dirs:
+        lib_path = os.path.join(search_dir, lib_name)
+        if os.path.exists(lib_path):
+          host_lib_path = lib_path
+          break
+
+      if not host_lib_path:
+        logging.debug('Could not find host library for: %s', lib_name)
+      self._lib_map[lib_name] = host_lib_path
+
+    return host_lib_path
+
+
+
+class SymbolResolver(object):
+  """A base class for objets that can symbolize library (path, offset)
+     pairs into symbol information strings. Usage is the following:
+
+     1) Create new instance (by calling the constructor of a derived
+        class, since this is only the base one).
+
+     2) Call SetAndroidAbi() before any call to FindSymbolInfo() in order
+        to set the Android CPU ABI used for symbolization.
+
+     3) Before the first call to FindSymbolInfo(), one can call
+        AddLibraryOffset(), or AddLibraryOffsets() to record a set of offsets
+        that you will want to symbolize later through FindSymbolInfo(). Doing
+        so allows some SymbolResolver derived classes to work faster (e.g. the
+        one that invokes the 'addr2line' program, since the latter works faster
+        if the offsets provided as inputs are sorted in increasing order).
+
+     3) Call FindSymbolInfo(path, offset) to return the corresponding
+        symbol information string, or None if this doesn't correspond
+        to anything the instance can handle.
+
+        Note that whether the path is specific to the device or to the
+        host depends on the derived class implementation.
+  """
+  def __init__(self):
+    self._android_abi = None
+    self._lib_offsets_map = collections.defaultdict(set)
+
+  def SetAndroidAbi(self, android_abi):
+    """Set the Android ABI value for this instance.
+
+    Calling this function before FindSymbolInfo() is required by some
+    derived class implementations.
+
+    Args:
+      android_abi: Native Android CPU ABI name (e.g. 'armeabi-v7a').
+    Raises:
+      Exception if the ABI was already set with a different value.
+    """
+    if self._android_abi and self._android_abi != android_abi:
+      raise Exception('Cannot reset Android ABI to new value %s, already set '
+                      'to %s' % (android_abi, self._android_abi))
+
+    self._android_abi = android_abi
+
+  def AddLibraryOffset(self, lib_path, offset):
+    """Associate a single offset to a given device library.
+
+    This must be called before FindSymbolInfo(), otherwise its input arguments
+    will be ignored.
+
+    Args:
+      lib_path: A library path.
+      offset: An integer offset within the corresponding library that will be
+        symbolized by future calls to FindSymbolInfo.
+    """
+    self._lib_offsets_map[lib_path].add(offset)
+
+  def AddLibraryOffsets(self, lib_path, lib_offsets):
+    """Associate a set of wanted offsets to a given device library.
+
+    This must be called before FindSymbolInfo(), otherwise its input arguments
+    will be ignored.
+
+    Args:
+      lib_path: A library path.
+      lib_offsets: An iterable of integer offsets within the corresponding
+        library that will be symbolized by future calls to FindSymbolInfo.
+    """
+    self._lib_offsets_map[lib_path].update(lib_offsets)
+
+  # pylint: disable=unused-argument,no-self-use
+  def FindSymbolInfo(self, lib_path, lib_offset):
+    """Symbolize a device library path and offset.
+
+    Args:
+      lib_path: Library path (device or host specific, depending on the
+        derived class implementation).
+      lib_offset: Integer offset within the library.
+    Returns:
+      Corresponding symbol information string, or None.
+    """
+    # The base implementation cannot symbolize anything.
+    return None
+  # pylint: enable=unused-argument,no-self-use
+
+
+class ElfSymbolResolver(SymbolResolver):
+  """A SymbolResolver that can symbolize host path + offset values using
+     an elf_symbolizer.ELFSymbolizer instance.
+  """
+  def __init__(self, addr2line_path_for_tests=None):
+    super(ElfSymbolResolver, self).__init__()
+    self._addr2line_path = addr2line_path_for_tests
+
+    # Used to cache one ELFSymbolizer instance per library path.
+    self._elf_symbolizer_cache = {}
+
+    # Used to cache FindSymbolInfo() results. Maps host library paths
+    # to (offset -> symbol info string) dictionaries.
+    self._symbol_info_cache = collections.defaultdict(dict)
+    self._allow_symbolizer = True
+
+  def _CreateSymbolizerFor(self, host_path):
+    """Create the ELFSymbolizer instance associated with a given lib path."""
+    addr2line_path = self._addr2line_path
+    if not addr2line_path:
+      if not self._android_abi:
+        raise Exception(
+            'Android CPU ABI must be set before calling FindSymbolInfo!')
+
+      cpu_arch = _AndroidAbiToCpuArch(self._android_abi)
+      self._addr2line_path = host_paths.ToolPath('addr2line', cpu_arch)
+
+    return elf_symbolizer.ELFSymbolizer(
+        elf_file_path=host_path, addr2line_path=self._addr2line_path,
+        callback=ElfSymbolResolver._Callback, inlines=True)
+
+  def DisallowSymbolizerForTesting(self):
+    """Disallow FindSymbolInfo() from using a symbolizer.
+
+    This is used during unit-testing to ensure that the offsets that were
+    recorded via AddLibraryOffset()/AddLibraryOffsets() are properly
+    symbolized, but not anything else.
+    """
+    self._allow_symbolizer = False
+
+  def FindSymbolInfo(self, host_path, offset):
+    """Override SymbolResolver.FindSymbolInfo.
+
+    Args:
+      host_path: Host-specific path to the native shared library.
+      offset: Integer offset within the native library.
+    Returns:
+      A symbol info string, or None.
+    """
+    offset_map = self._symbol_info_cache[host_path]
+    symbol_info = offset_map.get(offset)
+    if symbol_info:
+      return symbol_info
+
+    # Create symbolizer on demand.
+    symbolizer = self._elf_symbolizer_cache.get(host_path)
+    if not symbolizer:
+      symbolizer = self._CreateSymbolizerFor(host_path)
+      self._elf_symbolizer_cache[host_path] = symbolizer
+
+      # If there are pre-recorded offsets for this path, symbolize them now.
+      offsets = self._lib_offsets_map.get(host_path)
+      if offsets:
+        offset_map = {}
+        for pre_offset in offsets:
+          symbolizer.SymbolizeAsync(
+              pre_offset, callback_arg=(offset_map, pre_offset))
+        symbolizer.WaitForIdle()
+        self._symbol_info_cache[host_path] = offset_map
+
+        symbol_info = offset_map.get(offset)
+        if symbol_info:
+          return symbol_info
+
+    if not self._allow_symbolizer:
+      return None
+
+    # Symbolize single offset. Slower if addresses are not provided in
+    # increasing order to addr2line.
+    symbolizer.SymbolizeAsync(offset,
+                              callback_arg=(offset_map, offset))
+    symbolizer.WaitForIdle()
+    return offset_map.get(offset)
+
+  @staticmethod
+  def _Callback(sym_info, callback_arg):
+    offset_map, offset = callback_arg
+    offset_map[offset] = str(sym_info)
+
+
+class DeviceSymbolResolver(SymbolResolver):
+  """A SymbolResolver instance that accepts device-specific path.
+
+  Usage is the following:
+    1) Create new instance, passing a parent SymbolResolver instance that
+       accepts host-specific paths, and a HostLibraryFinder instance.
+
+    2) Optional: call AddApkOffsets() to add offsets from within an APK
+       that contains uncompressed native shared libraries.
+
+    3) Use it as any SymbolResolver instance.
+  """
+  def __init__(self, host_resolver, host_lib_finder):
+    """Initialize instance.
+
+    Args:
+      host_resolver: A parent SymbolResolver instance that will be used
+        to resolve symbols from host library paths.
+      host_lib_finder: A HostLibraryFinder instance used to locate
+        unstripped libraries on the host.
+    """
+    super(DeviceSymbolResolver, self).__init__()
+    self._host_lib_finder = host_lib_finder
+    self._bad_device_lib_paths = set()
+    self._host_resolver = host_resolver
+
+  def SetAndroidAbi(self, android_abi):
+    super(DeviceSymbolResolver, self).SetAndroidAbi(android_abi)
+    self._host_resolver.SetAndroidAbi(android_abi)
+
+  def AddLibraryOffsets(self, device_lib_path, lib_offsets):
+    """Associate a set of wanted offsets to a given device library.
+
+    This must be called before FindSymbolInfo(), otherwise its input arguments
+    will be ignored.
+
+    Args:
+      device_lib_path: A device-specific library path.
+      lib_offsets: An iterable of integer offsets within the corresponding
+        library that will be symbolized by future calls to FindSymbolInfo.
+        want to symbolize.
+    """
+    if device_lib_path in self._bad_device_lib_paths:
+      return
+
+    host_lib_path = self._host_lib_finder.Find(device_lib_path)
+    if not host_lib_path:
+      # NOTE: self._bad_device_lib_paths is only used to only print this
+      #       warning once per bad library.
+      logging.warning('Could not find host library matching device path: %s',
+                      device_lib_path)
+      self._bad_device_lib_paths.add(device_lib_path)
+      return
+
+    self._host_resolver.AddLibraryOffsets(host_lib_path, lib_offsets)
+
+  def AddApkOffsets(self, device_apk_path, apk_offsets, apk_translator):
+    """Associate a set of wanted offsets to a given device APK path.
+
+    This converts the APK-relative offsets into offsets relative to the
+    uncompressed libraries it contains, then calls AddLibraryOffsets()
+    for each one of the libraries.
+
+    Must be called before FindSymbolInfo() as well, otherwise input arguments
+    will be ignored.
+
+    Args:
+      device_apk_path: Device-specific APK path.
+      apk_offsets: Iterable of offsets within the APK file.
+      apk_translator: An ApkLibraryPathTranslator instance used to extract
+        library paths from the APK.
+    """
+    libraries_map = collections.defaultdict(set)
+    for offset in apk_offsets:
+      lib_path, lib_offset = apk_translator.TranslatePath(device_apk_path,
+                                                          offset)
+      libraries_map[lib_path].add(lib_offset)
+
+    for lib_path, lib_offsets in libraries_map.iteritems():
+      self.AddLibraryOffsets(lib_path, lib_offsets)
+
+  def FindSymbolInfo(self, device_path, offset):
+    """Overrides SymbolResolver.FindSymbolInfo.
+
+    Args:
+      device_path: Device-specific library path (e.g.
+        '/data/app/com.example.app-1/lib/x86/libfoo.so')
+      offset: Offset in device library path.
+    Returns:
+      Corresponding symbol information string, or None.
+    """
+    host_path = self._host_lib_finder.Find(device_path)
+    if not host_path:
+      return None
+
+    return self._host_resolver.FindSymbolInfo(host_path, offset)
+
+
+class MemoryMap(object):
+  """Models the memory map of a given process. Usage is:
+
+    1) Create new instance, passing the Android ABI.
+
+    2) Call TranslateLine() whenever you want to detect and translate any
+       memory map input line.
+
+    3) Otherwise, it is possible to parse the whole memory map input with
+       ParseLines(), then call FindSectionForAddress() repeatedly in order
+       to translate a memory address into the corresponding mapping and
+       file information tuple (e.g. to symbolize stack entries).
+  """
+
+  # A named tuple describing interesting memory map line items.
+  # Fields:
+  #   addr_start: Mapping start address in memory.
+  #   file_offset: Corresponding file offset.
+  #   file_size: Corresponding mapping size in bytes.
+  #   file_path: Input file path.
+  #   match: Corresponding regular expression match object.
+  LineTuple = collections.namedtuple('MemoryMapLineTuple',
+                                     'addr_start,file_offset,file_size,'
+                                     'file_path, match')
+
+  # A name tuple describing a memory map section.
+  # Fields:
+  #   address: Memory address.
+  #   size: Size in bytes in memory
+  #   offset: Starting file offset.
+  #   path: Input file path.
+  SectionTuple = collections.namedtuple('MemoryMapSection',
+                                        'address,size,offset,path')
+
+  def __init__(self, android_abi):
+    """Initializes instance.
+
+    Args:
+      android_abi: Android CPU ABI name (e.g. 'armeabi-v7a')
+    """
+    hex_addr = _HexAddressRegexpFor(android_abi)
+
+    # pylint: disable=line-too-long
+    # A regular expression used to match memory map entries which look like:
+    #    b278c000-b2790fff r--   4fda000      5000  /data/app/com.google.android.apps.chrome-2/base.apk
+    # pylint: enable=line-too-long
+    self._re_map_section = re.compile(
+        r'\s*(?P<addr_start>' + hex_addr + r')-(?P<addr_end>' + hex_addr + ')' +
+        r'\s+' +
+        r'(?P<perm>...)\s+' +
+        r'(?P<file_offset>[0-9a-f]+)\s+' +
+        r'(?P<file_size>[0-9a-f]+)\s*' +
+        r'(?P<file_path>[^ \t]+)?')
+
+    self._addr_map = []  # Sorted list of (address, size, path, offset) tuples.
+    self._sorted_addresses = []  # Sorted list of address fields in _addr_map.
+    self._in_section = False
+
+  def TranslateLine(self, line, apk_path_translator):
+    """Try to translate a memory map input line, if detected.
+
+    This only takes care of converting mapped APK file path and offsets
+    into a corresponding uncompressed native library file path + new offsets,
+    e.g. '..... <offset> <size> /data/.../base.apk' gets
+    translated into '.... <new-offset> <size> /data/.../base.apk!lib/libfoo.so'
+
+    This function should always work, even if ParseLines() was not called
+    previously.
+
+    Args:
+      line: Input memory map / tombstone line.
+      apk_translator: An ApkLibraryPathTranslator instance, used to map
+        APK offsets into uncompressed native libraries + new offsets.
+    Returns:
+      Translated memory map line, if relevant, or unchanged input line
+      otherwise.
+    """
+    t = self._ParseLine(line.rstrip())
+    if not t:
+      return line
+
+    new_path, new_offset = apk_path_translator.TranslatePath(
+        t.file_path, t.file_offset)
+
+    if new_path == t.file_path:
+      return line
+
+    pos = t.match.start('file_path')
+    return '%s%s (offset 0x%x)%s' % (line[0:pos], new_path, new_offset,
+                                     line[t.match.end('file_path'):])
+
+  def ParseLines(self, input_lines, in_section=False):
+    """Parse a list of input lines and extract the APK memory map out of it.
+
+    Args:
+      input_lines: list, or iterable, of input lines.
+      in_section: Optional. If true, considers that the input lines are
+        already part of the memory map. Otherwise, wait until the start of
+        the section appears in the input before trying to record data.
+    Returns:
+      True iff APK-related memory map entries were found. False otherwise.
+    """
+    addr_list = []  # list of (address, size, file_path, file_offset) tuples.
+    self._in_section = in_section
+    for line in input_lines:
+      t = self._ParseLine(line.rstrip())
+      if not t:
+        continue
+
+      addr_list.append(t)
+
+    self._addr_map = sorted(addr_list,
+                            lambda x, y: cmp(x.addr_start, y.addr_start))
+    self._sorted_addresses = [e.addr_start for e in self._addr_map]
+    return bool(self._addr_map)
+
+  def _ParseLine(self, line):
+    """Used internally to recognized memory map input lines.
+
+    Args:
+      line: Input logcat or tomstone line.
+    Returns:
+      A LineTuple instance on success, or None on failure.
+    """
+    if not self._in_section:
+      self._in_section = line.startswith('memory map:')
+      return None
+
+    m = self._re_map_section.match(line)
+    if not m:
+      self._in_section = False  # End of memory map section
+      return None
+
+    # Only accept .apk and .so files that are not from the system partitions.
+    file_path = m.group('file_path')
+    if not file_path:
+      return None
+
+    if file_path.startswith('/system') or file_path.startswith('/vendor'):
+      return None
+
+    if not (file_path.endswith('.apk') or file_path.endswith('.so')):
+      return None
+
+    addr_start = int(m.group('addr_start'), 16)
+    file_offset = int(m.group('file_offset'), 16)
+    file_size = int(m.group('file_size'), 16)
+
+    return self.LineTuple(addr_start, file_offset, file_size, file_path, m)
+
+  def Dump(self):
+    """Print memory map for debugging."""
+    print 'MEMORY MAP ['
+    for t in self._addr_map:
+      print '[%08x-%08x %08x %08x %s]' % (
+          t.addr_start, t.addr_start + t.file_size, t.file_size, t.file_offset,
+          t.file_path)
+    print '] MEMORY MAP'
+
+  def FindSectionForAddress(self, addr):
+    """Find the map section corresponding to a specific memory address.
+
+    Call this method only after using ParseLines() was called to extract
+    relevant information from the memory map.
+
+    Args:
+      addr: Memory address
+    Returns:
+      A SectionTuple instance on success, or None on failure.
+    """
+    pos = bisect.bisect_right(self._sorted_addresses, addr)
+    if pos > 0:
+      # All values in [0,pos) are <= addr, just ensure that the last
+      # one contains the address as well.
+      entry = self._addr_map[pos - 1]
+      if entry.addr_start + entry.file_size > addr:
+        return self.SectionTuple(entry.addr_start, entry.file_size,
+                                 entry.file_offset, entry.file_path)
+    return None
+
+
+class BacktraceTranslator(object):
+  """Translates backtrace-related lines in a tombstone or crash report.
+
+  Usage is the following:
+    1) Create new instance with appropriate arguments.
+    2) If the tombstone / logcat input is available, one can call
+       FindLibraryOffsets() in order to detect which library offsets
+       will need to be symbolized during a future parse. Doing so helps
+       speed up the ELF symbolizer.
+    3) For each tombstone/logcat input line, call TranslateLine() to
+       try to detect and symbolize backtrace lines.
+  """
+
+  # A named tuple for relevant input backtrace lines.
+  # Fields:
+  #   rel_pc: Instruction pointer, relative to offset in library start.
+  #   location: Library or APK file path.
+  #   offset: Load base of executable code in library or apk file path.
+  #   match: The corresponding regular expression match object.
+  # Note:
+  #   The actual instruction pointer always matches the position at
+  #   |offset + rel_pc| in |location|.
+  LineTuple = collections.namedtuple('BacktraceLineTuple',
+                                      'rel_pc,location,offset,match')
+
+  def __init__(self, android_abi, apk_translator):
+    """Initialize instance.
+
+    Args:
+      android_abi: Android CPU ABI name (e.g. 'armeabi-v7a').
+      apk_translator: ApkLibraryPathTranslator instance used to convert
+        mapped APK file offsets into uncompressed library file paths with
+        new offsets.
+    """
+    hex_addr = _HexAddressRegexpFor(android_abi)
+
+    # A regular expression used to match backtrace lines.
+    self._re_backtrace = re.compile(
+        r'.*#(?P<frame>[0-9]{2})\s+' +
+        r'(..)\s+' +
+        r'(?P<rel_pc>' + hex_addr + r')\s+' +
+        r'(?P<location>[^ \t]+)' +
+        r'(\s+\(offset 0x(?P<offset>[0-9a-f]+)\))?')
+
+    # In certain cases, offset will be provided as <location>+0x<offset>
+    # instead of <location> (offset 0x<offset>). This is a regexp to detect
+    # this.
+    self._re_location_offset = re.compile(
+        r'.*\+0x(?P<offset>[0-9a-f]+)$')
+
+    self._apk_translator = apk_translator
+    self._in_section = False
+
+  def _ParseLine(self, line):
+    """Used internally to detect and decompose backtrace input lines.
+
+    Args:
+      line: input tombstone line.
+    Returns:
+      A LineTuple instance on success, None on failure.
+    """
+    if not self._in_section:
+      self._in_section = line.startswith('backtrace:')
+      return None
+
+    line = line.rstrip()
+    m = self._re_backtrace.match(line)
+    if not m:
+      self._in_section = False
+      return None
+
+    location = m.group('location')
+    offset = m.group('offset')
+    if not offset:
+      m2 = self._re_location_offset.match(location)
+      if m2:
+        offset = m2.group('offset')
+        location = location[0:m2.start('offset') - 3]
+
+    if not offset:
+      return None
+
+    offset = int(offset, 16)
+    rel_pc = int(m.group('rel_pc'), 16)
+
+    # Two cases to consider here:
+    #
+    # * If this is a library file directly mapped in memory, then |rel_pc|
+    #   if the direct offset within the library, and doesn't need any kind
+    #   of adjustement.
+    #
+    # * If this is a library mapped directly from an .apk file, then
+    #   |rel_pc| is the offset in the APK, and |offset| happens to be the
+    #   load base of the corresponding library.
+    #
+    if location.endswith('.so'):
+      # For a native library directly mapped from the file system,
+      return self.LineTuple(rel_pc, location, offset, m)
+
+    if location.endswith('.apk'):
+      # For a native library inside an memory-mapped APK file,
+      new_location, new_offset = self._apk_translator.TranslatePath(
+          location, offset)
+
+      return self.LineTuple(rel_pc, new_location, new_offset, m)
+
+    # Ignore anything else (e.g. .oat or .odex files).
+    return None
+
+  def FindLibraryOffsets(self, input_lines, in_section=False):
+    """Parse a tombstone's backtrace section and find all library offsets in it.
+
+    Args:
+      input_lines: List or iterables of intput tombstone lines.
+      in_section: Optional. If True, considers that the stack section has
+        already started.
+    Returns:
+      A dictionary mapping device library paths to sets of offsets within
+      then.
+    """
+    self._in_section = in_section
+    result = collections.defaultdict(set)
+    for line in input_lines:
+      t = self._ParseLine(line)
+      if not t:
+        continue
+
+      result[t.location].add(t.offset + t.rel_pc)
+    return result
+
+  def TranslateLine(self, line, symbol_resolver):
+    """Symbolize backtrace line if recognized.
+
+    Args:
+      line: input backtrace line.
+      symbol_resolver: symbol resolver instance to use. This method will
+        call its FindSymbolInfo(device_lib_path, lib_offset) method to
+        convert offsets into symbol informations strings.
+    Returns:
+      Translated line (unchanged if not recognized as a back trace).
+    """
+    t = self._ParseLine(line)
+    if not t:
+      return line
+
+    symbol_info = symbol_resolver.FindSymbolInfo(t.location,
+                                                 t.offset + t.rel_pc)
+    if not symbol_info:
+      symbol_info = 'offset 0x%x' % t.offset
+
+    pos = t.match.start('location')
+    pos2 = t.match.end('offset') + 1
+    if pos2 <= 0:
+      pos2 = t.match.end('location')
+    return '%s%s (%s)%s' % (line[:pos], t.location, symbol_info, line[pos2:])
+
+
+class StackTranslator(object):
+  """Translates stack-related lines in a tombstone or crash report."""
+
+  # A named tuple describing relevant stack input lines.
+  # Fields:
+  #  address: Address as it appears in the stack.
+  #  lib_path: Library path where |address| is mapped.
+  #  lib_offset: Library load base offset. for |lib_path|.
+  #  match: Corresponding regular expression match object.
+  LineTuple = collections.namedtuple('StackLineTuple',
+                                     'address, lib_path, lib_offset, match')
+
+  def __init__(self, android_abi, memory_map, apk_translator):
+    """Initialize instance."""
+    hex_addr = _HexAddressRegexpFor(android_abi)
+
+    # pylint: disable=line-too-long
+    # A regular expression used to recognize stack entries like:
+    #
+    #    #05  bf89a180  bf89a1e4  [stack]
+    #         bf89a1c8  a0c01c51  /data/app/com.google.android.apps.chrome-2/base.apk
+    #         bf89a080  00000000
+    #         ........  ........
+    # pylint: enable=line-too-long
+    self._re_stack_line = re.compile(
+        r'\s+(?P<frame_number>#[0-9]+)?\s*' +
+        r'(?P<stack_addr>' + hex_addr + r')\s+' +
+        r'(?P<stack_value>' + hex_addr + r')' +
+        r'(\s+(?P<location>[^ \t]+))?')
+
+    self._re_stack_abbrev = re.compile(r'\s+[.]+\s+[.]+')
+
+    self._memory_map = memory_map
+    self._apk_translator = apk_translator
+    self._in_section = False
+
+  def _ParseLine(self, line):
+    """Check a given input line for a relevant _re_stack_line match.
+
+    Args:
+      line: input tombstone line.
+    Returns:
+      A LineTuple instance on success, None on failure.
+    """
+    line = line.rstrip()
+    if not self._in_section:
+      self._in_section = line.startswith('stack:')
+      return None
+
+    m = self._re_stack_line.match(line)
+    if not m:
+      if not self._re_stack_abbrev.match(line):
+        self._in_section = False
+      return None
+
+    location = m.group('location')
+    if not location:
+      return None
+
+    if not location.endswith('.apk') and not location.endswith('.so'):
+      return None
+
+    addr = int(m.group('stack_value'), 16)
+    t = self._memory_map.FindSectionForAddress(addr)
+    if t is None:
+      return None
+
+    lib_path = t.path
+    lib_offset = t.offset + (addr - t.address)
+
+    if lib_path.endswith('.apk'):
+      lib_path, lib_offset = self._apk_translator.TranslatePath(
+          lib_path, lib_offset)
+
+    return self.LineTuple(addr, lib_path, lib_offset, m)
+
+  def FindLibraryOffsets(self, input_lines, in_section=False):
+    """Parse a tombstone's stack section and find all library offsets in it.
+
+    Args:
+      input_lines: List or iterables of intput tombstone lines.
+      in_section: Optional. If True, considers that the stack section has
+        already started.
+    Returns:
+      A dictionary mapping device library paths to sets of offsets within
+      then.
+    """
+    result = collections.defaultdict(set)
+    self._in_section = in_section
+    for line in input_lines:
+      t = self._ParseLine(line)
+      if t:
+        result[t.lib_path].add(t.lib_offset)
+    return result
+
+  def TranslateLine(self, line, symbol_resolver=None):
+    """Try to translate a line of the stack dump."""
+    t = self._ParseLine(line)
+    if not t:
+      return line
+
+    symbol_info = symbol_resolver.FindSymbolInfo(t.lib_path, t.lib_offset)
+    if not symbol_info:
+      return line
+
+    pos = t.match.start('location')
+    pos2 = t.match.end('location')
+    return '%s%s (%s)%s' % (line[:pos], t.lib_path, symbol_info, line[pos2:])
diff --git a/build/android/pylib/symbols/symbol_utils_unittest.py b/build/android/pylib/symbols/symbol_utils_unittest.py
new file mode 100644
index 0000000..d350c17
--- /dev/null
+++ b/build/android/pylib/symbols/symbol_utils_unittest.py
@@ -0,0 +1,944 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import contextlib
+import logging
+import os
+import re
+import shutil
+import tempfile
+import unittest
+
+from pylib.symbols import apk_native_libs_unittest
+from pylib.symbols import mock_addr2line
+from pylib.symbols import symbol_utils
+
+_MOCK_ELF_DATA = apk_native_libs_unittest.MOCK_ELF_DATA
+
+_MOCK_A2L_PATH = os.path.join(os.path.dirname(mock_addr2line.__file__),
+                              'mock_addr2line')
+
+
+# pylint: disable=line-too-long
+
+# list of (start_offset, end_offset, size, libpath) tuples corresponding
+# to the content of base.apk. This was taken from an x86 ChromeModern.apk
+# component build.
+_TEST_APK_LIBS = [
+  (0x01331000, 0x013696bc, 0x000386bc, 'libaccessibility.cr.so'),
+  (0x0136a000, 0x013779c4, 0x0000d9c4, 'libanimation.cr.so'),
+  (0x01378000, 0x0137f7e8, 0x000077e8, 'libapdu.cr.so'),
+  (0x01380000, 0x0155ccc8, 0x001dccc8, 'libbase.cr.so'),
+  (0x0155d000, 0x015ab98c, 0x0004e98c, 'libbase_i18n.cr.so'),
+  (0x015ac000, 0x015dff4c, 0x00033f4c, 'libbindings.cr.so'),
+  (0x015e0000, 0x015f5a54, 0x00015a54, 'libbindings_base.cr.so'),
+  (0x015f6000, 0x0160d770, 0x00017770, 'libblink_android_mojo_bindings_shared.cr.so'),
+  (0x0160e000, 0x01731960, 0x00123960, 'libblink_common.cr.so'),
+  (0x01732000, 0x0174ce54, 0x0001ae54, 'libblink_controller.cr.so'),
+  (0x0174d000, 0x0318c528, 0x01a3f528, 'libblink_core.cr.so'),
+  (0x0318d000, 0x03191700, 0x00004700, 'libblink_core_mojo_bindings_shared.cr.so'),
+  (0x03192000, 0x03cd7918, 0x00b45918, 'libblink_modules.cr.so'),
+  (0x03cd8000, 0x03d137d0, 0x0003b7d0, 'libblink_mojo_bindings_shared.cr.so'),
+  (0x03d14000, 0x03d2670c, 0x0001270c, 'libblink_offscreen_canvas_mojo_bindings_shared.cr.so'),
+  (0x03d27000, 0x046c7054, 0x009a0054, 'libblink_platform.cr.so'),
+  (0x046c8000, 0x0473fbfc, 0x00077bfc, 'libbluetooth.cr.so'),
+  (0x04740000, 0x04878f40, 0x00138f40, 'libboringssl.cr.so'),
+  (0x04879000, 0x0498466c, 0x0010b66c, 'libc++_shared.so'),
+  (0x04985000, 0x0498d93c, 0x0000893c, 'libcaptive_portal.cr.so'),
+  (0x0498e000, 0x049947cc, 0x000067cc, 'libcapture_base.cr.so'),
+  (0x04995000, 0x04b39f18, 0x001a4f18, 'libcapture_lib.cr.so'),
+  (0x04b3a000, 0x04b488ec, 0x0000e8ec, 'libcbor.cr.so'),
+  (0x04b49000, 0x04e9ea5c, 0x00355a5c, 'libcc.cr.so'),
+  (0x04e9f000, 0x04ed6404, 0x00037404, 'libcc_animation.cr.so'),
+  (0x04ed7000, 0x04ef5ab4, 0x0001eab4, 'libcc_base.cr.so'),
+  (0x04ef6000, 0x04fd9364, 0x000e3364, 'libcc_blink.cr.so'),
+  (0x04fda000, 0x04fe2758, 0x00008758, 'libcc_debug.cr.so'),
+  (0x04fe3000, 0x0500ae0c, 0x00027e0c, 'libcc_ipc.cr.so'),
+  (0x0500b000, 0x05078f38, 0x0006df38, 'libcc_paint.cr.so'),
+  (0x05079000, 0x0507e734, 0x00005734, 'libcdm_manager.cr.so'),
+  (0x0507f000, 0x06f4d744, 0x01ece744, 'libchrome.cr.so'),
+  (0x06f54000, 0x06feb830, 0x00097830, 'libchromium_sqlite3.cr.so'),
+  (0x06fec000, 0x0706f554, 0x00083554, 'libclient.cr.so'),
+  (0x07070000, 0x0708da60, 0x0001da60, 'libcloud_policy_proto_generated_compile.cr.so'),
+  (0x0708e000, 0x07121f28, 0x00093f28, 'libcodec.cr.so'),
+  (0x07122000, 0x07134ab8, 0x00012ab8, 'libcolor_space.cr.so'),
+  (0x07135000, 0x07138614, 0x00003614, 'libcommon.cr.so'),
+  (0x07139000, 0x0717c938, 0x00043938, 'libcompositor.cr.so'),
+  (0x0717d000, 0x0923d78c, 0x020c078c, 'libcontent.cr.so'),
+  (0x0923e000, 0x092ae87c, 0x0007087c, 'libcontent_common_mojo_bindings_shared.cr.so'),
+  (0x092af000, 0x092be718, 0x0000f718, 'libcontent_public_common_mojo_bindings_shared.cr.so'),
+  (0x092bf000, 0x092d9a20, 0x0001aa20, 'libcrash_key.cr.so'),
+  (0x092da000, 0x092eda58, 0x00013a58, 'libcrcrypto.cr.so'),
+  (0x092ee000, 0x092f16e0, 0x000036e0, 'libdevice_base.cr.so'),
+  (0x092f2000, 0x092fe8d8, 0x0000c8d8, 'libdevice_event_log.cr.so'),
+  (0x092ff000, 0x093026a4, 0x000036a4, 'libdevice_features.cr.so'),
+  (0x09303000, 0x093f1220, 0x000ee220, 'libdevice_gamepad.cr.so'),
+  (0x093f2000, 0x09437f54, 0x00045f54, 'libdevice_vr_mojo_bindings.cr.so'),
+  (0x09438000, 0x0954c168, 0x00114168, 'libdevice_vr_mojo_bindings_blink.cr.so'),
+  (0x0954d000, 0x0955d720, 0x00010720, 'libdevice_vr_mojo_bindings_shared.cr.so'),
+  (0x0955e000, 0x0956b9c0, 0x0000d9c0, 'libdevices.cr.so'),
+  (0x0956c000, 0x0957cae8, 0x00010ae8, 'libdiscardable_memory_client.cr.so'),
+  (0x0957d000, 0x09588854, 0x0000b854, 'libdiscardable_memory_common.cr.so'),
+  (0x09589000, 0x0959cbb4, 0x00013bb4, 'libdiscardable_memory_service.cr.so'),
+  (0x0959d000, 0x095b6b90, 0x00019b90, 'libdisplay.cr.so'),
+  (0x095b7000, 0x095be930, 0x00007930, 'libdisplay_types.cr.so'),
+  (0x095bf000, 0x095c46c4, 0x000056c4, 'libdisplay_util.cr.so'),
+  (0x095c5000, 0x095f54a4, 0x000304a4, 'libdomain_reliability.cr.so'),
+  (0x095f6000, 0x0966fe08, 0x00079e08, 'libembedder.cr.so'),
+  (0x09670000, 0x096735f8, 0x000035f8, 'libembedder_switches.cr.so'),
+  (0x09674000, 0x096a3460, 0x0002f460, 'libevents.cr.so'),
+  (0x096a4000, 0x096b6d40, 0x00012d40, 'libevents_base.cr.so'),
+  (0x096b7000, 0x0981a778, 0x00163778, 'libffmpeg.cr.so'),
+  (0x0981b000, 0x09945c94, 0x0012ac94, 'libfido.cr.so'),
+  (0x09946000, 0x09a330dc, 0x000ed0dc, 'libfingerprint.cr.so'),
+  (0x09a34000, 0x09b53170, 0x0011f170, 'libfreetype_harfbuzz.cr.so'),
+  (0x09b54000, 0x09bc5c5c, 0x00071c5c, 'libgcm.cr.so'),
+  (0x09bc6000, 0x09cc8584, 0x00102584, 'libgeolocation.cr.so'),
+  (0x09cc9000, 0x09cdc8d4, 0x000138d4, 'libgeometry.cr.so'),
+  (0x09cdd000, 0x09cec8b4, 0x0000f8b4, 'libgeometry_skia.cr.so'),
+  (0x09ced000, 0x09d10e14, 0x00023e14, 'libgesture_detection.cr.so'),
+  (0x09d11000, 0x09d7595c, 0x0006495c, 'libgfx.cr.so'),
+  (0x09d76000, 0x09d7d7cc, 0x000077cc, 'libgfx_ipc.cr.so'),
+  (0x09d7e000, 0x09d82708, 0x00004708, 'libgfx_ipc_buffer_types.cr.so'),
+  (0x09d83000, 0x09d89748, 0x00006748, 'libgfx_ipc_color.cr.so'),
+  (0x09d8a000, 0x09d8f6f4, 0x000056f4, 'libgfx_ipc_geometry.cr.so'),
+  (0x09d90000, 0x09d94754, 0x00004754, 'libgfx_ipc_skia.cr.so'),
+  (0x09d95000, 0x09d9869c, 0x0000369c, 'libgfx_switches.cr.so'),
+  (0x09d99000, 0x09dba0ac, 0x000210ac, 'libgin.cr.so'),
+  (0x09dbb000, 0x09e0a8cc, 0x0004f8cc, 'libgl_in_process_context.cr.so'),
+  (0x09e0b000, 0x09e17a18, 0x0000ca18, 'libgl_init.cr.so'),
+  (0x09e18000, 0x09ee34e4, 0x000cb4e4, 'libgl_wrapper.cr.so'),
+  (0x09ee4000, 0x0a1a2e00, 0x002bee00, 'libgles2.cr.so'),
+  (0x0a1a3000, 0x0a24556c, 0x000a256c, 'libgles2_implementation.cr.so'),
+  (0x0a246000, 0x0a267038, 0x00021038, 'libgles2_utils.cr.so'),
+  (0x0a268000, 0x0a3288e4, 0x000c08e4, 'libgpu.cr.so'),
+  (0x0a329000, 0x0a3627ec, 0x000397ec, 'libgpu_ipc_service.cr.so'),
+  (0x0a363000, 0x0a388a18, 0x00025a18, 'libgpu_util.cr.so'),
+  (0x0a389000, 0x0a506d8c, 0x0017dd8c, 'libhost.cr.so'),
+  (0x0a507000, 0x0a6f0ec0, 0x001e9ec0, 'libicui18n.cr.so'),
+  (0x0a6f1000, 0x0a83b4c8, 0x0014a4c8, 'libicuuc.cr.so'),
+  (0x0a83c000, 0x0a8416e4, 0x000056e4, 'libinterfaces_shared.cr.so'),
+  (0x0a842000, 0x0a87e2a0, 0x0003c2a0, 'libipc.cr.so'),
+  (0x0a87f000, 0x0a88c98c, 0x0000d98c, 'libipc_mojom.cr.so'),
+  (0x0a88d000, 0x0a8926e4, 0x000056e4, 'libipc_mojom_shared.cr.so'),
+  (0x0a893000, 0x0a8a1e18, 0x0000ee18, 'libkeyed_service_content.cr.so'),
+  (0x0a8a2000, 0x0a8b4a30, 0x00012a30, 'libkeyed_service_core.cr.so'),
+  (0x0a8b5000, 0x0a930a80, 0x0007ba80, 'libleveldatabase.cr.so'),
+  (0x0a931000, 0x0a9b3908, 0x00082908, 'libmanager.cr.so'),
+  (0x0a9b4000, 0x0aea9bb4, 0x004f5bb4, 'libmedia.cr.so'),
+  (0x0aeaa000, 0x0b08cb88, 0x001e2b88, 'libmedia_blink.cr.so'),
+  (0x0b08d000, 0x0b0a4728, 0x00017728, 'libmedia_devices_mojo_bindings_shared.cr.so'),
+  (0x0b0a5000, 0x0b1943ec, 0x000ef3ec, 'libmedia_gpu.cr.so'),
+  (0x0b195000, 0x0b2d07d4, 0x0013b7d4, 'libmedia_mojo_services.cr.so'),
+  (0x0b2d1000, 0x0b2d4760, 0x00003760, 'libmessage_center.cr.so'),
+  (0x0b2d5000, 0x0b2e0938, 0x0000b938, 'libmessage_support.cr.so'),
+  (0x0b2e1000, 0x0b2f3ad0, 0x00012ad0, 'libmetrics_cpp.cr.so'),
+  (0x0b2f4000, 0x0b313bb8, 0x0001fbb8, 'libmidi.cr.so'),
+  (0x0b314000, 0x0b31b848, 0x00007848, 'libmojo_base_lib.cr.so'),
+  (0x0b31c000, 0x0b3329f8, 0x000169f8, 'libmojo_base_mojom.cr.so'),
+  (0x0b333000, 0x0b34b98c, 0x0001898c, 'libmojo_base_mojom_blink.cr.so'),
+  (0x0b34c000, 0x0b354700, 0x00008700, 'libmojo_base_mojom_shared.cr.so'),
+  (0x0b355000, 0x0b3608b0, 0x0000b8b0, 'libmojo_base_shared_typemap_traits.cr.so'),
+  (0x0b361000, 0x0b3ad454, 0x0004c454, 'libmojo_edk.cr.so'),
+  (0x0b3ae000, 0x0b3c4a20, 0x00016a20, 'libmojo_edk_ports.cr.so'),
+  (0x0b3c5000, 0x0b3d38a0, 0x0000e8a0, 'libmojo_mojom_bindings.cr.so'),
+  (0x0b3d4000, 0x0b3da6e8, 0x000066e8, 'libmojo_mojom_bindings_shared.cr.so'),
+  (0x0b3db000, 0x0b3e27f0, 0x000077f0, 'libmojo_public_system.cr.so'),
+  (0x0b3e3000, 0x0b3fa9fc, 0x000179fc, 'libmojo_public_system_cpp.cr.so'),
+  (0x0b3fb000, 0x0b407728, 0x0000c728, 'libmojom_core_shared.cr.so'),
+  (0x0b408000, 0x0b421744, 0x00019744, 'libmojom_platform_shared.cr.so'),
+  (0x0b422000, 0x0b43451c, 0x0001251c, 'libnative_theme.cr.so'),
+  (0x0b435000, 0x0baaa1bc, 0x006751bc, 'libnet.cr.so'),
+  (0x0baab000, 0x0bac3c08, 0x00018c08, 'libnet_with_v8.cr.so'),
+  (0x0bac4000, 0x0bb74670, 0x000b0670, 'libnetwork_cpp.cr.so'),
+  (0x0bb75000, 0x0bbaee8c, 0x00039e8c, 'libnetwork_cpp_base.cr.so'),
+  (0x0bbaf000, 0x0bd21844, 0x00172844, 'libnetwork_service.cr.so'),
+  (0x0bd22000, 0x0bd256e4, 0x000036e4, 'libnetwork_session_configurator.cr.so'),
+  (0x0bd26000, 0x0bd33734, 0x0000d734, 'libonc.cr.so'),
+  (0x0bd34000, 0x0bd9ce18, 0x00068e18, 'libperfetto.cr.so'),
+  (0x0bd9d000, 0x0bda4854, 0x00007854, 'libplatform.cr.so'),
+  (0x0bda5000, 0x0bec5ce4, 0x00120ce4, 'libpolicy_component.cr.so'),
+  (0x0bec6000, 0x0bf5ab58, 0x00094b58, 'libpolicy_proto.cr.so'),
+  (0x0bf5b000, 0x0bf86fbc, 0x0002bfbc, 'libprefs.cr.so'),
+  (0x0bf87000, 0x0bfa5d74, 0x0001ed74, 'libprinting.cr.so'),
+  (0x0bfa6000, 0x0bfe0e80, 0x0003ae80, 'libprotobuf_lite.cr.so'),
+  (0x0bfe1000, 0x0bff0a18, 0x0000fa18, 'libproxy_config.cr.so'),
+  (0x0bff1000, 0x0c0f6654, 0x00105654, 'libpublic.cr.so'),
+  (0x0c0f7000, 0x0c0fa6a4, 0x000036a4, 'librange.cr.so'),
+  (0x0c0fb000, 0x0c118058, 0x0001d058, 'libraster.cr.so'),
+  (0x0c119000, 0x0c133d00, 0x0001ad00, 'libresource_coordinator_cpp.cr.so'),
+  (0x0c134000, 0x0c1396a0, 0x000056a0, 'libresource_coordinator_cpp_base.cr.so'),
+  (0x0c13a000, 0x0c1973b8, 0x0005d3b8, 'libresource_coordinator_public_mojom.cr.so'),
+  (0x0c198000, 0x0c2033e8, 0x0006b3e8, 'libresource_coordinator_public_mojom_blink.cr.so'),
+  (0x0c204000, 0x0c219744, 0x00015744, 'libresource_coordinator_public_mojom_shared.cr.so'),
+  (0x0c21a000, 0x0c21e700, 0x00004700, 'libsandbox.cr.so'),
+  (0x0c21f000, 0x0c22f96c, 0x0001096c, 'libsandbox_services.cr.so'),
+  (0x0c230000, 0x0c249d58, 0x00019d58, 'libseccomp_bpf.cr.so'),
+  (0x0c24a000, 0x0c24e714, 0x00004714, 'libseccomp_starter_android.cr.so'),
+  (0x0c24f000, 0x0c4ae9f0, 0x0025f9f0, 'libservice.cr.so'),
+  (0x0c4af000, 0x0c4c3ae4, 0x00014ae4, 'libservice_manager_cpp.cr.so'),
+  (0x0c4c4000, 0x0c4cb708, 0x00007708, 'libservice_manager_cpp_types.cr.so'),
+  (0x0c4cc000, 0x0c4fbe30, 0x0002fe30, 'libservice_manager_mojom.cr.so'),
+  (0x0c4fc000, 0x0c532e78, 0x00036e78, 'libservice_manager_mojom_blink.cr.so'),
+  (0x0c533000, 0x0c53669c, 0x0000369c, 'libservice_manager_mojom_constants.cr.so'),
+  (0x0c537000, 0x0c53e85c, 0x0000785c, 'libservice_manager_mojom_constants_blink.cr.so'),
+  (0x0c53f000, 0x0c542668, 0x00003668, 'libservice_manager_mojom_constants_shared.cr.so'),
+  (0x0c543000, 0x0c54d700, 0x0000a700, 'libservice_manager_mojom_shared.cr.so'),
+  (0x0c54e000, 0x0c8fc6ec, 0x003ae6ec, 'libsessions.cr.so'),
+  (0x0c8fd000, 0x0c90a924, 0x0000d924, 'libshared_memory_support.cr.so'),
+  (0x0c90b000, 0x0c9148ec, 0x000098ec, 'libshell_dialogs.cr.so'),
+  (0x0c915000, 0x0cf8de70, 0x00678e70, 'libskia.cr.so'),
+  (0x0cf8e000, 0x0cf978bc, 0x000098bc, 'libsnapshot.cr.so'),
+  (0x0cf98000, 0x0cfb7d9c, 0x0001fd9c, 'libsql.cr.so'),
+  (0x0cfb8000, 0x0cfbe744, 0x00006744, 'libstartup_tracing.cr.so'),
+  (0x0cfbf000, 0x0d19b4e4, 0x001dc4e4, 'libstorage_browser.cr.so'),
+  (0x0d19c000, 0x0d2a773c, 0x0010b73c, 'libstorage_common.cr.so'),
+  (0x0d2a8000, 0x0d2ac6fc, 0x000046fc, 'libsurface.cr.so'),
+  (0x0d2ad000, 0x0d2baa98, 0x0000da98, 'libtracing.cr.so'),
+  (0x0d2bb000, 0x0d2f36b0, 0x000386b0, 'libtracing_cpp.cr.so'),
+  (0x0d2f4000, 0x0d326e70, 0x00032e70, 'libtracing_mojom.cr.so'),
+  (0x0d327000, 0x0d33270c, 0x0000b70c, 'libtracing_mojom_shared.cr.so'),
+  (0x0d333000, 0x0d46d804, 0x0013a804, 'libui_android.cr.so'),
+  (0x0d46e000, 0x0d4cb3f8, 0x0005d3f8, 'libui_base.cr.so'),
+  (0x0d4cc000, 0x0d4dbc40, 0x0000fc40, 'libui_base_ime.cr.so'),
+  (0x0d4dc000, 0x0d4e58d4, 0x000098d4, 'libui_data_pack.cr.so'),
+  (0x0d4e6000, 0x0d51d1e0, 0x000371e0, 'libui_devtools.cr.so'),
+  (0x0d51e000, 0x0d52b984, 0x0000d984, 'libui_message_center_cpp.cr.so'),
+  (0x0d52c000, 0x0d539a48, 0x0000da48, 'libui_touch_selection.cr.so'),
+  (0x0d53a000, 0x0d55bc60, 0x00021c60, 'liburl.cr.so'),
+  (0x0d55c000, 0x0d55f6b4, 0x000036b4, 'liburl_ipc.cr.so'),
+  (0x0d560000, 0x0d5af110, 0x0004f110, 'liburl_matcher.cr.so'),
+  (0x0d5b0000, 0x0d5e2fac, 0x00032fac, 'libuser_manager.cr.so'),
+  (0x0d5e3000, 0x0d5e66e4, 0x000036e4, 'libuser_prefs.cr.so'),
+  (0x0d5e7000, 0x0e3e1cc8, 0x00dfacc8, 'libv8.cr.so'),
+  (0x0e3e2000, 0x0e400ae0, 0x0001eae0, 'libv8_libbase.cr.so'),
+  (0x0e401000, 0x0e4d91d4, 0x000d81d4, 'libviz_common.cr.so'),
+  (0x0e4da000, 0x0e4df7e4, 0x000057e4, 'libviz_resource_format.cr.so'),
+  (0x0e4e0000, 0x0e5b7120, 0x000d7120, 'libweb_dialogs.cr.so'),
+  (0x0e5b8000, 0x0e5c7a18, 0x0000fa18, 'libwebdata_common.cr.so'),
+  (0x0e5c8000, 0x0e61bfe4, 0x00053fe4, 'libwtf.cr.so'),
+]
+
+
+# A small memory map fragment extracted from a tombstone for a process that
+# had loaded the APK corresponding to _TEST_APK_LIBS above.
+_TEST_MEMORY_MAP = r'''memory map:
+12c00000-12ccafff rw-         0     cb000  /dev/ashmem/dalvik-main space (deleted)
+12ccb000-130cafff rw-     cb000    400000  /dev/ashmem/dalvik-main space (deleted)
+130cb000-32bfffff ---    4cb000  1fb35000  /dev/ashmem/dalvik-main space (deleted)
+32c00000-32c00fff rw-         0      1000  /dev/ashmem/dalvik-main space 1 (deleted)
+32c01000-52bfffff ---      1000  1ffff000  /dev/ashmem/dalvik-main space 1 (deleted)
+6f3b8000-6fd90fff rw-         0    9d9000  /data/dalvik-cache/x86/system@framework@boot.art
+6fd91000-71c42fff r--         0   1eb2000  /data/dalvik-cache/x86/system@framework@boot.oat
+71c43000-7393efff r-x   1eb2000   1cfc000  /data/dalvik-cache/x86/system@framework@boot.oat (load base 0x71c43000)
+7393f000-7393ffff rw-   3bae000      1000  /data/dalvik-cache/x86/system@framework@boot.oat
+73940000-73a1bfff rw-         0     dc000  /dev/ashmem/dalvik-zygote space (deleted)
+73a1c000-73a1cfff rw-         0      1000  /dev/ashmem/dalvik-non moving space (deleted)
+73a1d000-73a2dfff rw-      1000     11000  /dev/ashmem/dalvik-non moving space (deleted)
+73a2e000-77540fff ---     12000   3b13000  /dev/ashmem/dalvik-non moving space (deleted)
+77541000-7793ffff rw-   3b25000    3ff000  /dev/ashmem/dalvik-non moving space (deleted)
+923aa000-92538fff r--    8a9000    18f000  /data/app/com.example.app-2/base.apk
+92539000-9255bfff r--         0     23000  /data/data/com.example.app/app_data/paks/es.pak@162db1c6689
+9255c000-92593fff r--    213000     38000  /data/app/com.example.app-2/base.apk
+92594000-925c0fff r--    87d000     2d000  /data/app/com.example.app-2/base.apk
+925c1000-927d3fff r--    a37000    213000  /data/app/com.example.app-2/base.apk
+927d4000-92e07fff r--    24a000    634000  /data/app/com.example.app-2/base.apk
+92e08000-92e37fff r--   a931000     30000  /data/app/com.example.app-2/base.apk
+92e38000-92e86fff r-x   a961000     4f000  /data/app/com.example.app-2/base.apk
+92e87000-92e8afff rw-   a9b0000      4000  /data/app/com.example.app-2/base.apk
+92e8b000-92e8bfff rw-         0      1000
+92e8c000-92e9dfff r--   d5b0000     12000  /data/app/com.example.app-2/base.apk
+92e9e000-92ebcfff r-x   d5c2000     1f000  /data/app/com.example.app-2/base.apk
+92ebd000-92ebefff rw-   d5e1000      2000  /data/app/com.example.app-2/base.apk
+92ebf000-92ebffff rw-         0      1000
+'''
+
+# list of (address, size, path, offset)  tuples that must appear in
+# _TEST_MEMORY_MAP. Not all sections need to be listed.
+_TEST_MEMORY_MAP_SECTIONS = [
+  (0x923aa000, 0x18f000, '/data/app/com.example.app-2/base.apk', 0x8a9000),
+  (0x9255c000, 0x038000, '/data/app/com.example.app-2/base.apk', 0x213000),
+  (0x92594000, 0x02d000, '/data/app/com.example.app-2/base.apk', 0x87d000),
+  (0x925c1000, 0x213000, '/data/app/com.example.app-2/base.apk', 0xa37000),
+]
+
+_EXPECTED_TEST_MEMORY_MAP = r'''memory map:
+12c00000-12ccafff rw-         0     cb000  /dev/ashmem/dalvik-main space (deleted)
+12ccb000-130cafff rw-     cb000    400000  /dev/ashmem/dalvik-main space (deleted)
+130cb000-32bfffff ---    4cb000  1fb35000  /dev/ashmem/dalvik-main space (deleted)
+32c00000-32c00fff rw-         0      1000  /dev/ashmem/dalvik-main space 1 (deleted)
+32c01000-52bfffff ---      1000  1ffff000  /dev/ashmem/dalvik-main space 1 (deleted)
+6f3b8000-6fd90fff rw-         0    9d9000  /data/dalvik-cache/x86/system@framework@boot.art
+6fd91000-71c42fff r--         0   1eb2000  /data/dalvik-cache/x86/system@framework@boot.oat
+71c43000-7393efff r-x   1eb2000   1cfc000  /data/dalvik-cache/x86/system@framework@boot.oat (load base 0x71c43000)
+7393f000-7393ffff rw-   3bae000      1000  /data/dalvik-cache/x86/system@framework@boot.oat
+73940000-73a1bfff rw-         0     dc000  /dev/ashmem/dalvik-zygote space (deleted)
+73a1c000-73a1cfff rw-         0      1000  /dev/ashmem/dalvik-non moving space (deleted)
+73a1d000-73a2dfff rw-      1000     11000  /dev/ashmem/dalvik-non moving space (deleted)
+73a2e000-77540fff ---     12000   3b13000  /dev/ashmem/dalvik-non moving space (deleted)
+77541000-7793ffff rw-   3b25000    3ff000  /dev/ashmem/dalvik-non moving space (deleted)
+923aa000-92538fff r--    8a9000    18f000  /data/app/com.example.app-2/base.apk
+92539000-9255bfff r--         0     23000  /data/data/com.example.app/app_data/paks/es.pak@162db1c6689
+9255c000-92593fff r--    213000     38000  /data/app/com.example.app-2/base.apk
+92594000-925c0fff r--    87d000     2d000  /data/app/com.example.app-2/base.apk
+925c1000-927d3fff r--    a37000    213000  /data/app/com.example.app-2/base.apk
+927d4000-92e07fff r--    24a000    634000  /data/app/com.example.app-2/base.apk
+92e08000-92e37fff r--   a931000     30000  /data/app/com.example.app-2/base.apk!lib/libmanager.cr.so (offset 0x0)
+92e38000-92e86fff r-x   a961000     4f000  /data/app/com.example.app-2/base.apk!lib/libmanager.cr.so (offset 0x30000)
+92e87000-92e8afff rw-   a9b0000      4000  /data/app/com.example.app-2/base.apk!lib/libmanager.cr.so (offset 0x7f000)
+92e8b000-92e8bfff rw-         0      1000
+92e8c000-92e9dfff r--   d5b0000     12000  /data/app/com.example.app-2/base.apk!lib/libuser_manager.cr.so (offset 0x0)
+92e9e000-92ebcfff r-x   d5c2000     1f000  /data/app/com.example.app-2/base.apk!lib/libuser_manager.cr.so (offset 0x12000)
+92ebd000-92ebefff rw-   d5e1000      2000  /data/app/com.example.app-2/base.apk!lib/libuser_manager.cr.so (offset 0x31000)
+92ebf000-92ebffff rw-         0      1000
+'''
+
+# Example stack section, taken from the same tombstone that _TEST_MEMORY_MAP
+# was extracted from.
+_TEST_STACK = r'''stack:
+        bf89a070  b7439468  /system/lib/libc.so
+        bf89a074  bf89a1e4  [stack]
+        bf89a078  932d4000  /data/app/com.example.app-2/base.apk
+        bf89a07c  b73bfbc9  /system/lib/libc.so (pthread_mutex_lock+65)
+        bf89a080  00000000
+        bf89a084  4000671c  /dev/ashmem/dalvik-main space 1 (deleted)
+        bf89a088  932d1d86  /data/app/com.example.app-2/base.apk
+        bf89a08c  b743671c  /system/lib/libc.so
+        bf89a090  b77f8c00  /system/bin/linker
+        bf89a094  b743cc90
+        bf89a098  932d1d4a  /data/app/com.example.app-2/base.apk
+        bf89a09c  b73bf271  /system/lib/libc.so (__pthread_internal_find(long)+65)
+        bf89a0a0  b743cc90
+        bf89a0a4  bf89a0b0  [stack]
+        bf89a0a8  bf89a0b8  [stack]
+        bf89a0ac  00000008
+        ........  ........
+  #00  bf89a0b0  00000006
+        bf89a0b4  00000002
+        bf89a0b8  b743671c  /system/lib/libc.so
+        bf89a0bc  b73bf5d9  /system/lib/libc.so (pthread_kill+71)
+  #01  bf89a0c0  00006937
+        bf89a0c4  00006937
+        bf89a0c8  00000006
+        bf89a0cc  b77fd3a9  /system/bin/app_process32 (sigprocmask+141)
+        bf89a0d0  00000002
+        bf89a0d4  bf89a0ec  [stack]
+        bf89a0d8  00000000
+        bf89a0dc  b743671c  /system/lib/libc.so
+        bf89a0e0  bf89a12c  [stack]
+        bf89a0e4  bf89a1e4  [stack]
+        bf89a0e8  932d1d4a  /data/app/com.example.app-2/base.apk
+        bf89a0ec  b7365206  /system/lib/libc.so (raise+37)
+  #02  bf89a0f0  b77f8c00  /system/bin/linker
+        bf89a0f4  00000006
+        bf89a0f8  b7439468  /system/lib/libc.so
+        bf89a0fc  b743671c  /system/lib/libc.so
+        bf89a100  bf89a12c  [stack]
+        bf89a104  b743671c  /system/lib/libc.so
+        bf89a108  bf89a12c  [stack]
+        bf89a10c  b735e9e5  /system/lib/libc.so (abort+81)
+  #03  bf89a110  00000006
+        bf89a114  bf89a12c  [stack]
+        bf89a118  00000000
+        bf89a11c  b55a3d3b  /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::DefaultLogHandler(google::protobuf::LogLevel, char const*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)+99)
+        bf89a120  b7439468  /system/lib/libc.so
+        bf89a124  b55ba38d  /system/lib/libprotobuf-cpp-lite.so
+        bf89a128  b55ba408  /system/lib/libprotobuf-cpp-lite.so
+        bf89a12c  ffffffdf
+        bf89a130  0000003d
+        bf89a134  adfedf00  [anon:libc_malloc]
+        bf89a138  bf89a158  [stack]
+  #04  bf89a13c  a0cee7f0  /data/app/com.example.app-2/base.apk
+        bf89a140  b55c1cb0  /system/lib/libprotobuf-cpp-lite.so
+        bf89a144  bf89a1e4  [stack]
+'''
+
+# Expected value of _TEST_STACK after translation of addresses in the APK
+# into offsets into libraries.
+_EXPECTED_STACK = r'''stack:
+        bf89a070  b7439468  /system/lib/libc.so
+        bf89a074  bf89a1e4  [stack]
+        bf89a078  932d4000  /data/app/com.example.app-2/base.apk
+        bf89a07c  b73bfbc9  /system/lib/libc.so (pthread_mutex_lock+65)
+        bf89a080  00000000
+        bf89a084  4000671c  /dev/ashmem/dalvik-main space 1 (deleted)
+        bf89a088  932d1d86  /data/app/com.example.app-2/base.apk
+        bf89a08c  b743671c  /system/lib/libc.so
+        bf89a090  b77f8c00  /system/bin/linker
+        bf89a094  b743cc90
+        bf89a098  932d1d4a  /data/app/com.example.app-2/base.apk
+        bf89a09c  b73bf271  /system/lib/libc.so (__pthread_internal_find(long)+65)
+        bf89a0a0  b743cc90
+        bf89a0a4  bf89a0b0  [stack]
+        bf89a0a8  bf89a0b8  [stack]
+        bf89a0ac  00000008
+        ........  ........
+  #00  bf89a0b0  00000006
+        bf89a0b4  00000002
+        bf89a0b8  b743671c  /system/lib/libc.so
+        bf89a0bc  b73bf5d9  /system/lib/libc.so (pthread_kill+71)
+  #01  bf89a0c0  00006937
+        bf89a0c4  00006937
+        bf89a0c8  00000006
+        bf89a0cc  b77fd3a9  /system/bin/app_process32 (sigprocmask+141)
+        bf89a0d0  00000002
+        bf89a0d4  bf89a0ec  [stack]
+        bf89a0d8  00000000
+        bf89a0dc  b743671c  /system/lib/libc.so
+        bf89a0e0  bf89a12c  [stack]
+        bf89a0e4  bf89a1e4  [stack]
+        bf89a0e8  932d1d4a  /data/app/com.example.app-2/base.apk
+        bf89a0ec  b7365206  /system/lib/libc.so (raise+37)
+  #02  bf89a0f0  b77f8c00  /system/bin/linker
+        bf89a0f4  00000006
+        bf89a0f8  b7439468  /system/lib/libc.so
+        bf89a0fc  b743671c  /system/lib/libc.so
+        bf89a100  bf89a12c  [stack]
+        bf89a104  b743671c  /system/lib/libc.so
+        bf89a108  bf89a12c  [stack]
+        bf89a10c  b735e9e5  /system/lib/libc.so (abort+81)
+  #03  bf89a110  00000006
+        bf89a114  bf89a12c  [stack]
+        bf89a118  00000000
+        bf89a11c  b55a3d3b  /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::DefaultLogHandler(google::protobuf::LogLevel, char const*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)+99)
+        bf89a120  b7439468  /system/lib/libc.so
+        bf89a124  b55ba38d  /system/lib/libprotobuf-cpp-lite.so
+        bf89a128  b55ba408  /system/lib/libprotobuf-cpp-lite.so
+        bf89a12c  ffffffdf
+        bf89a130  0000003d
+        bf89a134  adfedf00  [anon:libc_malloc]
+        bf89a138  bf89a158  [stack]
+  #04  bf89a13c  a0cee7f0  /data/app/com.example.app-2/base.apk
+        bf89a140  b55c1cb0  /system/lib/libprotobuf-cpp-lite.so
+        bf89a144  bf89a1e4  [stack]
+'''
+
+_TEST_BACKTRACE = r'''backtrace:
+    #00 pc 00084126  /system/lib/libc.so (tgkill+22)
+    #01 pc 000815d8  /system/lib/libc.so (pthread_kill+70)
+    #02 pc 00027205  /system/lib/libc.so (raise+36)
+    #03 pc 000209e4  /system/lib/libc.so (abort+80)
+    #04 pc 0000cf73  /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::LogMessage::Finish()+117)
+    #05 pc 0000cf8e  /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::LogFinisher::operator=(google::protobuf::internal::LogMessage&)+26)
+    #06 pc 0000d27f  /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::VerifyVersion(int, int, char const*)+574)
+    #07 pc 007cd236  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #08 pc 000111a9  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0xbfc2000)
+    #09 pc 00013228  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0xbfc2000)
+    #10 pc 000131de  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0xbfc2000)
+    #11 pc 007cd2d8  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #12 pc 007cd956  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #13 pc 007c2d4a  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #14 pc 009fc9f1  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #15 pc 009fc8ea  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #16 pc 00561c63  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #17 pc 0106fbdb  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #18 pc 004d7371  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #19 pc 004d8159  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #20 pc 004d7b96  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #21 pc 004da4b6  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #22 pc 005ab66c  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
+    #23 pc 005afca2  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
+    #24 pc 0000cae8  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x598d000)
+    #25 pc 00ce864f  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
+    #26 pc 00ce8dfa  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
+    #27 pc 00ce74c6  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
+    #28 pc 00004616  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x961e000)
+    #29 pc 00ce8215  /data/app/com.google.android.apps.chrome-2/base.apk (offset 0x7daa000)
+    #30 pc 0013d8c7  /system/lib/libart.so (art_quick_generic_jni_trampoline+71)
+    #31 pc 00137c52  /system/lib/libart.so (art_quick_invoke_static_stub+418)
+    #32 pc 00143651  /system/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+353)
+    #33 pc 005e06ae  /system/lib/libart.so (artInterpreterToCompiledCodeBridge+190)
+    #34 pc 00328b5d  /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
+    #35 pc 0032cfc0  /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)0, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+160)
+    #36 pc 000fc703  /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29891)
+    #37 pc 00300af7  /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
+    #38 pc 00328b5d  /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
+    #39 pc 0032cfc0  /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)0, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+160)
+    #40 pc 000fc703  /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29891)
+    #41 pc 00300af7  /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
+    #42 pc 00328b5d  /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
+    #43 pc 0032ebf9  /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)2, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+297)
+    #44 pc 000fc955  /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+30485)
+    #45 pc 00300af7  /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
+    #46 pc 00328b5d  /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
+    #47 pc 0033090c  /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)4, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+636)
+    #48 pc 000fc67f  /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29759)
+    #49 pc 00300700  /system/lib/libart.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*)+128)
+    #50 pc 00667c73  /system/lib/libart.so (artQuickToInterpreterBridge+808)
+    #51 pc 0013d98d  /system/lib/libart.so (art_quick_to_interpreter_bridge+77)
+    #52 pc 7264bc5b  /data/dalvik-cache/x86/system@framework@boot.oat (offset 0x1eb2000)
+'''
+
+_EXPECTED_BACKTRACE = r'''backtrace:
+    #00 pc 00084126  /system/lib/libc.so (tgkill+22)
+    #01 pc 000815d8  /system/lib/libc.so (pthread_kill+70)
+    #02 pc 00027205  /system/lib/libc.so (raise+36)
+    #03 pc 000209e4  /system/lib/libc.so (abort+80)
+    #04 pc 0000cf73  /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::LogMessage::Finish()+117)
+    #05 pc 0000cf8e  /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::LogFinisher::operator=(google::protobuf::internal::LogMessage&)+26)
+    #06 pc 0000d27f  /system/lib/libprotobuf-cpp-lite.so (google::protobuf::internal::VerifyVersion(int, int, char const*)+574)
+    #07 pc 007cd236  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #08 pc 000111a9  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libprotobuf_lite.cr.so (offset 0x1c000)
+    #09 pc 00013228  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libprotobuf_lite.cr.so (offset 0x1c000)
+    #10 pc 000131de  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libprotobuf_lite.cr.so (offset 0x1c000)
+    #11 pc 007cd2d8  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #12 pc 007cd956  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #13 pc 007c2d4a  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #14 pc 009fc9f1  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #15 pc 009fc8ea  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #16 pc 00561c63  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #17 pc 0106fbdb  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #18 pc 004d7371  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #19 pc 004d8159  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #20 pc 004d7b96  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #21 pc 004da4b6  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #22 pc 005ab66c  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
+    #23 pc 005afca2  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
+    #24 pc 0000cae8  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so (offset 0x90e000)
+    #25 pc 00ce864f  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
+    #26 pc 00ce8dfa  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
+    #27 pc 00ce74c6  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
+    #28 pc 00004616  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libembedder.cr.so (offset 0x28000)
+    #29 pc 00ce8215  /data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so (offset 0xc2d000)
+    #30 pc 0013d8c7  /system/lib/libart.so (art_quick_generic_jni_trampoline+71)
+    #31 pc 00137c52  /system/lib/libart.so (art_quick_invoke_static_stub+418)
+    #32 pc 00143651  /system/lib/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+353)
+    #33 pc 005e06ae  /system/lib/libart.so (artInterpreterToCompiledCodeBridge+190)
+    #34 pc 00328b5d  /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
+    #35 pc 0032cfc0  /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)0, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+160)
+    #36 pc 000fc703  /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29891)
+    #37 pc 00300af7  /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
+    #38 pc 00328b5d  /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
+    #39 pc 0032cfc0  /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)0, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+160)
+    #40 pc 000fc703  /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29891)
+    #41 pc 00300af7  /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
+    #42 pc 00328b5d  /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
+    #43 pc 0032ebf9  /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)2, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+297)
+    #44 pc 000fc955  /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+30485)
+    #45 pc 00300af7  /system/lib/libart.so (artInterpreterToInterpreterBridge+188)
+    #46 pc 00328b5d  /system/lib/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+445)
+    #47 pc 0033090c  /system/lib/libart.so (bool art::interpreter::DoInvoke<(art::InvokeType)4, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+636)
+    #48 pc 000fc67f  /system/lib/libart.so (art::JValue art::interpreter::ExecuteGotoImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)+29759)
+    #49 pc 00300700  /system/lib/libart.so (art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*)+128)
+    #50 pc 00667c73  /system/lib/libart.so (artQuickToInterpreterBridge+808)
+    #51 pc 0013d98d  /system/lib/libart.so (art_quick_to_interpreter_bridge+77)
+    #52 pc 7264bc5b  /data/dalvik-cache/x86/system@framework@boot.oat (offset 0x1eb2000)
+'''
+
+_EXPECTED_BACKTRACE_OFFSETS_MAP = {
+  '/data/app/com.google.android.apps.chrome-2/base.apk!lib/libprotobuf_lite.cr.so':
+      set([
+          0x1c000 + 0x111a9,
+          0x1c000 + 0x13228,
+          0x1c000 + 0x131de,
+      ]),
+
+  '/data/app/com.google.android.apps.chrome-2/base.apk!lib/libchrome.cr.so':
+      set([
+          0x90e000 + 0x7cd236,
+          0x90e000 + 0x7cd2d8,
+          0x90e000 + 0x7cd956,
+          0x90e000 + 0x7c2d4a,
+          0x90e000 + 0x9fc9f1,
+          0x90e000 + 0x9fc8ea,
+          0x90e000 + 0x561c63,
+          0x90e000 + 0x106fbdb,
+          0x90e000 + 0x4d7371,
+          0x90e000 + 0x4d8159,
+          0x90e000 + 0x4d7b96,
+          0x90e000 + 0x4da4b6,
+          0x90e000 + 0xcae8,
+      ]),
+  '/data/app/com.google.android.apps.chrome-2/base.apk!lib/libcontent.cr.so':
+      set([
+          0xc2d000 + 0x5ab66c,
+          0xc2d000 + 0x5afca2,
+          0xc2d000 + 0xce864f,
+          0xc2d000 + 0xce8dfa,
+          0xc2d000 + 0xce74c6,
+          0xc2d000 + 0xce8215,
+      ]),
+  '/data/app/com.google.android.apps.chrome-2/base.apk!lib/libembedder.cr.so':
+      set([
+          0x28000 + 0x4616,
+      ])
+}
+
+# pylint: enable=line-too-long
+
+_ONE_MB = 1024 * 1024
+_TEST_SYMBOL_DATA = {
+  # Regular symbols
+  0: 'mock_sym_for_addr_0 [mock_src/libmock1.so.c:0]',
+  0x1000: 'mock_sym_for_addr_4096 [mock_src/libmock1.so.c:4096]',
+
+  # Symbols without source file path.
+  _ONE_MB: 'mock_sym_for_addr_1048576 [??:0]',
+  _ONE_MB + 0x8234: 'mock_sym_for_addr_1081908 [??:0]',
+
+  # Unknown symbol.
+  2 * _ONE_MB: '?? [??:0]',
+
+  # Inlined symbol.
+  3 * _ONE_MB:
+    'mock_sym_for_addr_3145728_inner [mock_src/libmock1.so.c:3145728]',
+}
+
+@contextlib.contextmanager
+def _TempDir():
+  dirname = tempfile.mkdtemp()
+  try:
+    yield dirname
+  finally:
+    shutil.rmtree(dirname)
+
+
+def _TouchFile(path):
+  # Create parent directories.
+  try:
+    os.makedirs(os.path.dirname(path))
+  except OSError:
+    pass
+  with open(path, 'a'):
+    os.utime(path, None)
+
+class MockApkTranslator(object):
+  """A mock ApkLibraryPathTranslator object used for testing."""
+
+  # Regex that matches the content of APK native library map files generated
+  # with apk_lib_dump.py.
+  _RE_MAP_FILE = re.compile(
+      r'0x(?P<file_start>[0-9a-f]+)\s+' +
+      r'0x(?P<file_end>[0-9a-f]+)\s+' +
+      r'0x(?P<file_size>[0-9a-f]+)\s+' +
+      r'0x(?P<lib_path>[0-9a-f]+)\s+')
+
+  def __init__(self, test_apk_libs=None):
+    """Initialize instance.
+
+    Args:
+      test_apk_libs: Optional list of (file_start, file_end, size, lib_path)
+        tuples, like _TEST_APK_LIBS for example. This will be used to
+        implement TranslatePath().
+    """
+    self._apk_libs = []
+    if test_apk_libs:
+      self._AddLibEntries(test_apk_libs)
+
+  def _AddLibEntries(self, entries):
+    self._apk_libs = sorted(self._apk_libs + entries,
+                            lambda x, y: cmp(x[0], y[0]))
+
+  def ReadMapFile(self, file_path):
+    """Read an .apk.native-libs file that was produced with apk_lib_dump.py.
+
+    Args:
+      file_path: input path to .apk.native-libs file. Its format is
+        essentially: 0x<start>  0x<end> 0x<size> <library-path>
+    """
+    new_libs = []
+    with open(file_path) as f:
+      for line in f.readlines():
+        m = MockApkTranslator._RE_MAP_FILE.match(line)
+        if m:
+          file_start = int(m.group('file_start'), 16)
+          file_end = int(m.group('file_end'), 16)
+          file_size = int(m.group('file_size'), 16)
+          lib_path = m.group('lib_path')
+          # Sanity check
+          if file_start + file_size != file_end:
+            logging.warning('%s: Inconsistent (start, end, size) values '
+                            '(0x%x, 0x%x, 0x%x)',
+                            file_path, file_start, file_end, file_size)
+          else:
+            new_libs.append((file_start, file_end, file_size, lib_path))
+
+    self._AddLibEntries(new_libs)
+
+  def TranslatePath(self, lib_path, lib_offset):
+    """Translate an APK file path + offset into a library path + offset."""
+    min_pos = 0
+    max_pos = len(self._apk_libs)
+    while min_pos < max_pos:
+      mid_pos = (min_pos + max_pos) / 2
+      mid_entry = self._apk_libs[mid_pos]
+      mid_offset = mid_entry[0]
+      mid_size = mid_entry[2]
+      if lib_offset < mid_offset:
+        max_pos = mid_pos
+      elif lib_offset >= mid_offset + mid_size:
+        min_pos = mid_pos + 1
+      else:
+        # Found it
+        new_path = '%s!lib/%s' % (lib_path, mid_entry[3])
+        new_offset = lib_offset - mid_offset
+        return (new_path, new_offset)
+
+    return lib_path, lib_offset
+
+
+class HostLibraryFinderTest(unittest.TestCase):
+
+  def testEmpty(self):
+    finder = symbol_utils.HostLibraryFinder()
+    self.assertIsNone(finder.Find('/data/data/com.example.app-1/lib/libfoo.so'))
+    self.assertIsNone(
+        finder.Find('/data/data/com.example.app-1/base.apk!lib/libfoo.so'))
+
+
+  def testSimpleDirectory(self):
+    finder = symbol_utils.HostLibraryFinder()
+    with _TempDir() as tmp_dir:
+      host_libfoo_path = os.path.join(tmp_dir, 'libfoo.so')
+      host_libbar_path = os.path.join(tmp_dir, 'libbar.so')
+      _TouchFile(host_libfoo_path)
+      _TouchFile(host_libbar_path)
+
+      finder.AddSearchDir(tmp_dir)
+
+      # Regular library path (extracted at installation by the PackageManager).
+      # Note that the extraction path has changed between Android releases,
+      # i.e. it can be /data/app/, /data/data/ or /data/app-lib/ depending
+      # on the system.
+      self.assertEqual(
+          host_libfoo_path,
+          finder.Find('/data/app-lib/com.example.app-1/lib/libfoo.so'))
+
+      # Verify that the path doesn't really matter
+      self.assertEqual(
+          host_libfoo_path,
+          finder.Find('/whatever/what.apk!lib/libfoo.so'))
+
+      self.assertEqual(
+          host_libbar_path,
+          finder.Find('/data/data/com.example.app-1/lib/libbar.so'))
+
+      self.assertIsNone(
+          finder.Find('/data/data/com.example.app-1/lib/libunknown.so'))
+
+
+  def testMultipleDirectories(self):
+    with _TempDir() as tmp_dir:
+      # Create the following files:
+      #   <tmp_dir>/aaa/
+      #      libfoo.so
+      #   <tmp_dir>/bbb/
+      #      libbar.so
+      #      libfoo.so    (this one should never be seen because 'aaa'
+      #                    shall be first in the search path list).
+      #
+      aaa_dir = os.path.join(tmp_dir, 'aaa')
+      bbb_dir = os.path.join(tmp_dir, 'bbb')
+      os.makedirs(aaa_dir)
+      os.makedirs(bbb_dir)
+
+      host_libfoo_path = os.path.join(aaa_dir, 'libfoo.so')
+      host_libbar_path = os.path.join(bbb_dir, 'libbar.so')
+      host_libfoo2_path = os.path.join(bbb_dir, 'libfoo.so')
+
+      _TouchFile(host_libfoo_path)
+      _TouchFile(host_libbar_path)
+      _TouchFile(host_libfoo2_path)
+
+      finder = symbol_utils.HostLibraryFinder()
+      finder.AddSearchDir(aaa_dir)
+      finder.AddSearchDir(bbb_dir)
+
+      self.assertEqual(
+          host_libfoo_path,
+          finder.Find('/data/data/com.example.app-1/lib/libfoo.so'))
+
+      self.assertEqual(
+          host_libfoo_path,
+          finder.Find('/data/whatever/base.apk!lib/libfoo.so'))
+
+      self.assertEqual(
+          host_libbar_path,
+          finder.Find('/data/data/com.example.app-1/lib/libbar.so'))
+
+      self.assertIsNone(
+          finder.Find('/data/data/com.example.app-1/lib/libunknown.so'))
+
+
+class ElfSymbolResolverTest(unittest.TestCase):
+
+  def testCreation(self):
+    resolver = symbol_utils.ElfSymbolResolver(
+        addr2line_path_for_tests=_MOCK_A2L_PATH)
+    self.assertTrue(resolver)
+
+  def testWithSimpleOffsets(self):
+    resolver = symbol_utils.ElfSymbolResolver(
+        addr2line_path_for_tests=_MOCK_A2L_PATH)
+    resolver.SetAndroidAbi('ignored-abi')
+
+    for addr, expected_sym in _TEST_SYMBOL_DATA.iteritems():
+      self.assertEqual(resolver.FindSymbolInfo('/some/path/libmock1.so', addr),
+                       expected_sym)
+
+  def testWithPreResolvedSymbols(self):
+    resolver = symbol_utils.ElfSymbolResolver(
+        addr2line_path_for_tests=_MOCK_A2L_PATH)
+    resolver.SetAndroidAbi('ignored-abi')
+    resolver.AddLibraryOffsets('/some/path/libmock1.so',
+                               _TEST_SYMBOL_DATA.keys())
+
+    resolver.DisallowSymbolizerForTesting()
+
+    for addr, expected_sym in _TEST_SYMBOL_DATA.iteritems():
+      sym_info = resolver.FindSymbolInfo('/some/path/libmock1.so', addr)
+      self.assertIsNotNone(sym_info, 'None symbol info for addr %x' % addr)
+      self.assertEqual(
+          sym_info, expected_sym,
+          'Invalid symbol info for addr %x [%s] expected [%s]' % (
+              addr, sym_info, expected_sym))
+
+
+class MemoryMapTest(unittest.TestCase):
+
+  def testCreation(self):
+    mem_map = symbol_utils.MemoryMap('test-abi32')
+    self.assertIsNone(mem_map.FindSectionForAddress(0))
+
+  def testParseLines(self):
+    mem_map = symbol_utils.MemoryMap('test-abi32')
+    mem_map.ParseLines(_TEST_MEMORY_MAP.splitlines())
+    for exp_addr, exp_size, exp_path, exp_offset in _TEST_MEMORY_MAP_SECTIONS:
+      text = '(addr:%x, size:%x, path:%s, offset=%x)' % (
+          exp_addr, exp_size, exp_path, exp_offset)
+
+      t = mem_map.FindSectionForAddress(exp_addr)
+      self.assertTrue(t, 'Could not find %s' % text)
+      self.assertEqual(t.address, exp_addr)
+      self.assertEqual(t.size, exp_size)
+      self.assertEqual(t.offset, exp_offset)
+      self.assertEqual(t.path, exp_path)
+
+  def testTranslateLine(self):
+    android_abi = 'test-abi'
+    apk_translator = MockApkTranslator(_TEST_APK_LIBS)
+    mem_map = symbol_utils.MemoryMap(android_abi)
+    for line, expected_line in zip(_TEST_MEMORY_MAP.splitlines(),
+                                   _EXPECTED_TEST_MEMORY_MAP.splitlines()):
+      self.assertEqual(mem_map.TranslateLine(line, apk_translator),
+                       expected_line)
+
+class StackTranslatorTest(unittest.TestCase):
+
+  def testSimpleStack(self):
+    android_abi = 'test-abi32'
+    mem_map = symbol_utils.MemoryMap(android_abi)
+    mem_map.ParseLines(_TEST_MEMORY_MAP)
+    apk_translator = MockApkTranslator(_TEST_APK_LIBS)
+    stack_translator = symbol_utils.StackTranslator(android_abi, mem_map,
+                                                    apk_translator)
+    input_stack = _TEST_STACK.splitlines()
+    expected_stack = _EXPECTED_STACK.splitlines()
+    self.assertEqual(len(input_stack), len(expected_stack))
+    for stack_line, expected_line in zip(input_stack, expected_stack):
+      new_line = stack_translator.TranslateLine(stack_line)
+      self.assertEqual(new_line, expected_line)
+
+
+class MockSymbolResolver(symbol_utils.SymbolResolver):
+
+  # A regex matching a symbol definition as it appears in a test symbol file.
+  # Format is: <hex-offset> <whitespace> <symbol-string>
+  _RE_SYMBOL_DEFINITION = re.compile(
+      r'(?P<offset>[0-9a-f]+)\s+(?P<symbol>.*)')
+
+  def __init__(self):
+    super(MockSymbolResolver, self).__init__()
+    self._map = collections.defaultdict(dict)
+
+  def AddTestLibrarySymbols(self, lib_name, offsets_map):
+    """Add a new test entry for a given library name.
+
+    Args:
+      lib_name: Library name (e.g. 'libfoo.so')
+      offsets_map: A mapping from offsets to symbol info strings.
+    """
+    self._map[lib_name] = offsets_map
+
+  def ReadTestFile(self, file_path, lib_name):
+    """Read a single test symbol file, matching a given library.
+
+    Args:
+      file_path: Input file path.
+      lib_name: Library name these symbols correspond to (e.g. 'libfoo.so')
+    """
+    with open(file_path) as f:
+      for line in f.readlines():
+        line = line.rstrip()
+        m = MockSymbolResolver._RE_SYMBOL_DEFINITION.match(line)
+        if m:
+          offset = int(m.group('offset'))
+          symbol = m.group('symbol')
+          self._map[lib_name][offset] = symbol
+
+  def ReadTestFilesInDir(self, dir_path, file_suffix):
+    """Read all symbol test files in a given directory.
+
+    Args:
+      dir_path: Directory path.
+      file_suffix: File suffix used to detect test symbol files.
+    """
+    for filename in os.listdir(dir_path):
+      if filename.endswith(file_suffix):
+        lib_name = filename[:-len(file_suffix)]
+        self.ReadTestFile(os.path.join(dir_path, filename), lib_name)
+
+  def FindSymbolInfo(self, device_path, device_offset):
+    """Implement SymbolResolver.FindSymbolInfo."""
+    lib_name = os.path.basename(device_path)
+    offsets = self._map.get(lib_name)
+    if not offsets:
+      return None
+
+    return offsets.get(device_offset)
+
+
+class BacktraceTranslatorTest(unittest.TestCase):
+
+  def testEmpty(self):
+    android_abi = 'test-abi'
+    apk_translator = MockApkTranslator()
+    backtrace_translator = symbol_utils.BacktraceTranslator(android_abi,
+                                                            apk_translator)
+    self.assertTrue(backtrace_translator)
+
+  def testFindLibraryOffsets(self):
+    android_abi = 'test-abi'
+    apk_translator = MockApkTranslator(_TEST_APK_LIBS)
+    backtrace_translator = symbol_utils.BacktraceTranslator(android_abi,
+                                                            apk_translator)
+    input_backtrace = _EXPECTED_BACKTRACE.splitlines()
+    expected_lib_offsets_map = _EXPECTED_BACKTRACE_OFFSETS_MAP
+    offset_map = backtrace_translator.FindLibraryOffsets(input_backtrace)
+    for lib_path, offsets in offset_map.iteritems():
+      self.assertTrue(lib_path in expected_lib_offsets_map,
+                      '%s is not in expected library-offsets map!' % lib_path)
+      sorted_offsets = sorted(offsets)
+      sorted_expected_offsets = sorted(expected_lib_offsets_map[lib_path])
+      self.assertEqual(sorted_offsets, sorted_expected_offsets,
+                       '%s has invalid offsets %s expected %s' % (
+                          lib_path, sorted_offsets, sorted_expected_offsets))
+
+  def testTranslateLine(self):
+    android_abi = 'test-abi'
+    apk_translator = MockApkTranslator(_TEST_APK_LIBS)
+    backtrace_translator = symbol_utils.BacktraceTranslator(android_abi,
+                                                            apk_translator)
+    input_backtrace = _TEST_BACKTRACE.splitlines()
+    expected_backtrace = _EXPECTED_BACKTRACE.splitlines()
+    self.assertEqual(len(input_backtrace), len(expected_backtrace))
+    for trace_line, expected_line in zip(input_backtrace, expected_backtrace):
+      line = backtrace_translator.TranslateLine(trace_line,
+                                                MockSymbolResolver())
+      self.assertEqual(line, expected_line)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/build/android/pylib/utils/google_storage_helper.py b/build/android/pylib/utils/google_storage_helper.py
index 3101d71..d184810 100644
--- a/build/android/pylib/utils/google_storage_helper.py
+++ b/build/android/pylib/utils/google_storage_helper.py
@@ -79,10 +79,7 @@
 
   cmd = [_GSUTIL_PATH, '-q', 'stat', gs_path]
   return_code = cmd_helper.RunCmd(cmd)
-  if return_code == 0:
-    return True
-  else:
-    return False
+  return return_code == 0
 
 
 # TODO(jbudorick): Delete this function. Only one user of it.
diff --git a/build/android/pylib/utils/logdog_helper.py b/build/android/pylib/utils/logdog_helper.py
index 58fe781..68a7ba5 100644
--- a/build/android/pylib/utils/logdog_helper.py
+++ b/build/android/pylib/utils/logdog_helper.py
@@ -92,4 +92,3 @@
 def get_logdog_client():
   logging.info('Getting logdog client.')
   return bootstrap.ButlerBootstrap.probe().stream_client()
-
diff --git a/build/android/pylib/valgrind_tools.py b/build/android/pylib/valgrind_tools.py
index 3dc2488..4c27b08 100644
--- a/build/android/pylib/valgrind_tools.py
+++ b/build/android/pylib/valgrind_tools.py
@@ -127,4 +127,3 @@
     print 'Unknown tool %s, available tools: %s' % (
         tool_name, ', '.join(sorted(TOOL_REGISTRY.keys())))
     sys.exit(1)
-
diff --git a/build/android/pylintrc b/build/android/pylintrc
index 8005a5d..2a721bf2 100644
--- a/build/android/pylintrc
+++ b/build/android/pylintrc
@@ -4,7 +4,7 @@
 
 [MESSAGES CONTROL]
 
-disable=abstract-class-not-used,bad-continuation,bad-indentation,duplicate-code,fixme,invalid-name,locally-disabled,locally-enabled,missing-docstring,star-args,too-few-public-methods,too-many-arguments,too-many-branches,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-statements,
+disable=abstract-class-not-used,bad-continuation,bad-indentation,duplicate-code,fixme,invalid-name,locally-disabled,locally-enabled,missing-docstring,star-args,too-few-public-methods,too-many-arguments,too-many-branches,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-statements,wrong-import-position
 
 [REPORTS]
 
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index a83d9ab..8512acc 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -25,6 +25,7 @@
 # See http://crbug.com/724524 and https://bugs.python.org/issue7980.
 import _strptime  # pylint: disable=unused-import
 
+# pylint: disable=ungrouped-imports
 from pylib.constants import host_paths
 
 if host_paths.DEVIL_PATH not in sys.path:
@@ -49,7 +50,6 @@
 
 from py_utils import contextlib_ext
 
-
 _DEVIL_STATIC_CONFIG_FILE = os.path.abspath(os.path.join(
     host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'devil_config.json'))
 
@@ -212,10 +212,12 @@
 def ProcessCommonOptions(args):
   """Processes and handles all common options."""
   run_tests_helper.SetLogLevel(args.verbose_count, add_handler=False)
+  # pylint: disable=redefined-variable-type
   if args.verbose_count > 0:
     handler = logging_utils.ColorStreamHandler()
   else:
     handler = logging.StreamHandler(sys.stdout)
+  # pylint: enable=redefined-variable-type
   handler.setFormatter(run_tests_helper.CustomFormatter())
   logging.getLogger().addHandler(handler)
 
@@ -429,6 +431,7 @@
     split_arg = arg.split(',')
     if len(split_arg) != 2:
       raise argparse.ArgumentError(
+          arg,
           'Expected two comma-separated strings for --replace-system-package, '
           'received %d' % len(split_arg))
     PackageReplacement = collections.namedtuple('PackageReplacement',
diff --git a/build/check_gn_headers_whitelist.txt b/build/check_gn_headers_whitelist.txt
index 9547f35..d570a03f 100644
--- a/build/check_gn_headers_whitelist.txt
+++ b/build/check_gn_headers_whitelist.txt
@@ -51,7 +51,6 @@
 chrome/browser/download/download_file_icon_extractor.h
 chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h
 chrome/browser/extensions/api/omnibox/omnibox_api_testbase.h
-chrome/browser/extensions/api/socket/mock_tcp_client_socket.h
 chrome/browser/mac/bluetooth_utility.h
 chrome/browser/media/router/mojo/media_route_provider_util_win.h
 chrome/browser/media/webrtc/desktop_media_list_ash.h
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 6aea38e..7af1b221 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//base/android/linker/config.gni")
+import("//base/android/proguard/proguard.gni")
 import("//build/config/android/rules.gni")
 import("//build/config/locales.gni")
 import("//build/config/android/extract_unwind_tables.gni")
@@ -13,9 +14,6 @@
 import("channel.gni")
 
 declare_args() {
-  # Enables ProGuard obfuscation of Chromium packages.
-  enable_proguard_obfuscation = true
-
   # Enable multidex in release builds.
   multidex_in_release = false
 }
@@ -105,7 +103,7 @@
             [ "//base/android/proguard/enable_obfuscation.flags" ]
       } else {
         proguard_configs +=
-            [ "//base/android/proguard/disable_chromium_obfuscation.flags" ]
+            [ "//base/android/proguard/disable_all_obfuscation.flags" ]
       }
     }
 
diff --git a/chrome/android/java/res/layout/toolbar_phone_common.xml b/chrome/android/java/res/layout/toolbar_phone_common.xml
index e136f91..f456850 100644
--- a/chrome/android/java/res/layout/toolbar_phone_common.xml
+++ b/chrome/android/java/res/layout/toolbar_phone_common.xml
@@ -44,23 +44,27 @@
             android:layout_width="4dp"
             android:layout_height="match_parent" />
 
-        <ViewStub
-            android:id="@+id/experimental_button_stub"
-            android:inflatedId="@+id/experimental_toolbar_button"
-            android:layout="@layout/experimental_toolbar_button"
-            style="@style/ToolbarButton"
-            android:paddingStart="8dp"
-            android:layout_gravity="top"
-            android:visibility="gone" />
+        <FrameLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="top" >
 
-        <ViewStub
-            android:id="@+id/incognito_button_stub"
-            android:inflatedId="@+id/incognito_button"
-            android:layout="@layout/toolbar_phone_incognito_button"
-            style="@style/ToolbarButton"
-            android:layout_gravity="top"
-            android:contentDescription="@string/accessibility_tabstrip_btn_incognito_toggle_standard"
-            android:visibility="gone" />
+            <ViewStub
+                android:id="@+id/experimental_button_stub"
+                android:inflatedId="@+id/experimental_toolbar_button"
+                android:layout="@layout/experimental_toolbar_button"
+                style="@style/ToolbarButton"
+                android:paddingStart="8dp"
+                android:visibility="gone" />
+
+            <ViewStub
+                android:id="@+id/incognito_button_stub"
+                android:inflatedId="@+id/incognito_button"
+                android:layout="@layout/toolbar_phone_incognito_button"
+                style="@style/ToolbarButton"
+                android:contentDescription="@string/accessibility_tabstrip_btn_incognito_toggle_standard"
+                android:visibility="gone" />
+        </FrameLayout>
 
         <ImageButton android:id="@+id/tab_switcher_button"
             style="@style/ToolbarButton"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
index 13a4a44..fd948bb77 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
@@ -217,9 +217,9 @@
      */
     private void prefetchDnsForUrlInBackground(final String url) {
         mDnsRequestsInFlight.add(url);
-        new AsyncTask<String, Void, Void>() {
+        new AsyncTask<Void, Void, Void>() {
             @Override
-            protected Void doInBackground(String... params) {
+            protected Void doInBackground(Void... params) {
                 try (TraceEvent e =
                                 TraceEvent.scoped("WarmupManager.prefetchDnsForUrlInBackground")) {
                     InetAddress.getByName(new URL(url).getHost());
@@ -242,7 +242,8 @@
                     maybePreconnectUrlAndSubResources(profile, url);
                 }
             }
-        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url);
+        }
+                .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
     /** Launches a background DNS query for a given URL if the data reduction proxy is not in use.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSourceAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSourceAdapter.java
index dae4a74d..2ce8121 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSourceAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSourceAdapter.java
@@ -23,7 +23,7 @@
 public abstract class AsyncFeedbackSourceAdapter<Result> implements AsyncFeedbackSource {
     private Worker mWorker;
 
-    private class Worker extends AsyncTask<Context, Void, Result> {
+    private class Worker extends AsyncTask<Void, Void, Result> {
         private final Runnable mCallback;
 
         public Worker(Runnable callback) {
@@ -32,14 +32,13 @@
 
         // AsyncTask implementation.
         @Override
-        protected Result doInBackground(Context... params) {
-            return AsyncFeedbackSourceAdapter.this.doInBackground(params[0]);
+        protected Result doInBackground(Void... params) {
+            return AsyncFeedbackSourceAdapter.this.doInBackground(
+                    ContextUtils.getApplicationContext());
         }
 
         @Override
         protected void onPostExecute(Result result) {
-            super.onPostExecute(result);
-
             mCallback.run();
         }
     }
@@ -75,7 +74,6 @@
     public final void start(Runnable callback) {
         if (mWorker != null) return;
         mWorker = new Worker(callback);
-        mWorker.executeOnExecutor(
-                AsyncTask.THREAD_POOL_EXECUTOR, ContextUtils.getApplicationContext());
+        mWorker.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 }
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java
index bb9aafb4..45a70997 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/evaluation/OfflinePageEvaluationBridge.java
@@ -66,12 +66,18 @@
      * Class used for writing logs to external log file asynchronously to prevent violating strict
      * mode during test.
      */
-    private class LogTask extends AsyncTask<String, Void, Void> {
+    private class LogTask extends AsyncTask<Void, Void, Void> {
+        final String mLogString;
+
+        LogTask(String logString) {
+            mLogString = logString;
+        }
+
         @Override
-        protected Void doInBackground(String... strings) {
+        protected Void doInBackground(Void... params) {
             try {
                 synchronized (mLogOutput) {
-                    mLogOutput.write(strings[0]);
+                    mLogOutput.write(mLogString);
                     mLogOutput.flush();
                 }
             } catch (IOException e) {
@@ -198,9 +204,9 @@
                 new SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.getDefault());
         String logString = formatter.format(date) + ": " + sourceTag + " | " + message
                 + System.getProperty("line.separator");
-        LogTask logTask = new LogTask();
+        LogTask logTask = new LogTask(logString);
         Log.d(TAG, logString);
-        logTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, logString);
+        logTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
     }
 
     public void closeLog() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/BitmapScalerTask.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/BitmapScalerTask.java
index 123f0d3b..656b023 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/BitmapScalerTask.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/BitmapScalerTask.java
@@ -17,18 +17,21 @@
 /**
  * A worker task to scale bitmaps in the background.
  */
-class BitmapScalerTask extends AsyncTask<Bitmap, Void, Bitmap> {
+class BitmapScalerTask extends AsyncTask<Void, Void, Bitmap> {
     private final LruCache<String, Bitmap> mCache;
     private final String mFilePath;
     private final int mSize;
+    private final Bitmap mBitmap;
 
     /**
      * A BitmapScalerTask constructor.
      */
-    public BitmapScalerTask(LruCache<String, Bitmap> cache, String filePath, int size) {
+    public BitmapScalerTask(
+            LruCache<String, Bitmap> cache, String filePath, int size, Bitmap bitmap) {
         mCache = cache;
         mFilePath = filePath;
         mSize = size;
+        mBitmap = bitmap;
     }
 
     /**
@@ -37,13 +40,13 @@
      * @return A sorted list of images (by last-modified first).
      */
     @Override
-    protected Bitmap doInBackground(Bitmap... bitmaps) {
+    protected Bitmap doInBackground(Void... params) {
         assert !ThreadUtils.runningOnUiThread();
 
         if (isCancelled()) return null;
 
         long begin = SystemClock.elapsedRealtime();
-        Bitmap bitmap = BitmapUtils.scale(bitmaps[0], mSize, false);
+        Bitmap bitmap = BitmapUtils.scale(mBitmap, mSize, false);
         long scaleTime = SystemClock.elapsedRealtime() - begin;
         RecordHistogram.recordTimesHistogram(
                 "Android.PhotoPicker.BitmapScalerTask", scaleTime, TimeUnit.MILLISECONDS);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerBitmapViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerBitmapViewHolder.java
index 72a39c69..ef22a284 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerBitmapViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerBitmapViewHolder.java
@@ -55,8 +55,9 @@
         if (mCategoryView.getLowResBitmaps().get(filePath) == null) {
             Resources resources = mItemView.getContext().getResources();
             new BitmapScalerTask(mCategoryView.getLowResBitmaps(), filePath,
-                    resources.getDimensionPixelSize(R.dimen.photo_picker_grainy_thumbnail_size))
-                    .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, bitmap);
+                    resources.getDimensionPixelSize(R.dimen.photo_picker_grainy_thumbnail_size),
+                    bitmap)
+                    .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
         }
 
         if (!TextUtils.equals(mBitmapDetails.getFilePath(), filePath)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
index 4803507..8da8a34c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -868,8 +868,12 @@
         // We set the incognito toggle button's visibility from GONE to VISIBLE when the tab
         // switcher starts to open, but we don't want this to affect the Omnibox's size during the
         // animation, so we have to make an adjustment here.
+        // However, if the experimental button is showing it sits in a FrameLayout with the
+        // incognito button and the omnibox will be appropriately sized without an explicit
+        // adjustment.
         int incognitoButtonWidth = 0;
-        if (mIncognitoToggleButton != null && mIncognitoToggleButton.getVisibility() == VISIBLE) {
+        if (mIncognitoToggleButton != null && mIncognitoToggleButton.getVisibility() == VISIBLE
+                && (mExperimentalButton == null || mExperimentalButton.getVisibility() == GONE)) {
             incognitoButtonWidth += mIncognitoToggleButton.getMeasuredWidth();
         }
         return Math.max(mToolbarSidePadding,
@@ -1392,10 +1396,15 @@
 
         // Draw the experimental button if necessary.
         if (mExperimentalButton != null && mExperimentalButton.getVisibility() != View.GONE) {
+            canvas.save();
+            translateCanvasToView(mToolbarButtonsContainer, mExperimentalButton, canvas);
+
             previousAlpha = mExperimentalButton.getAlpha();
             mExperimentalButton.setAlpha(previousAlpha * floatAlpha);
             drawChild(canvas, mExperimentalButton, SystemClock.uptimeMillis());
             mExperimentalButton.setAlpha(previousAlpha);
+
+            canvas.restore();
         }
 
         // Draw the tab stack button and associated text.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellImpl.java
index 94467d3..3ac2c5c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellImpl.java
@@ -164,12 +164,6 @@
             mActivity.getFindToolbarManager().hideToolbar();
         }
 
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.VR_BROWSING_NATIVE_ANDROID_UI)) {
-            mNonVrUiWidgetFactory = UiWidgetFactory.getInstance();
-            UiWidgetFactory.setInstance(
-                    new VrUiWidgetFactory(this, mActivity.getModalDialogManager()));
-        }
-
         // This overrides the default intent created by GVR to return to Chrome when the DON flow
         // is triggered by resuming the GvrLayout, which is the usual way Daydream apps enter VR.
         // See VrShellDelegate#getEnterVrPendingIntent for why we need to do this.
@@ -200,6 +194,13 @@
 
         if (mVrBrowsingEnabled) injectVrHostedUiView();
 
+        // This has to happen after VrModalDialogManager is created.
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.VR_BROWSING_NATIVE_ANDROID_UI)) {
+            mNonVrUiWidgetFactory = UiWidgetFactory.getInstance();
+            UiWidgetFactory.setInstance(
+                    new VrUiWidgetFactory(this, mActivity.getModalDialogManager()));
+        }
+
         mTabRedirectHandler = new TabRedirectHandler(mActivity) {
             @Override
             public boolean shouldStayInChrome(boolean hasExternalProtocol) {
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
index a10297901..695ccbb 100644
--- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
+++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
@@ -71,7 +71,7 @@
         try {
             String hostPackage = getHostBrowserPackageName(context);
             return context.getApplicationContext().createPackageContext(
-                    hostPackage, Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
+                    hostPackage, 0);
         } catch (NameNotFoundException e) {
             e.printStackTrace();
         }
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index d3d5d68a..7d4f3f8c 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -961,6 +961,9 @@
         </message>
       </if>
       <if expr="chromeos">
+        <message name="IDS_UPDATE_RECOMMENDED_DIALOG_TITLE" desc="The window title for the Update Recommended dialog.">
+          Restart Chromium OS
+        </message>
         <message name="IDS_UPDATE_RECOMMENDED" desc="The main text of the Update Recommended dialog.">
           Chromium OS needs to be restarted to apply the update.
         </message>
@@ -1187,40 +1190,79 @@
         </message>
       </if>
       <!-- Relaunch notification bubble and dialog. -->
-      <if expr="not is_android and not chromeos">
-        <message name="IDS_RELAUNCH_RECOMMENDED_TITLE" desc="The title of a dialog that tells users that a browser relaunch is recommended for an update available for some number of days.">
-          {0, plural,
-           =0 {A Chromium update is available}
-           =1 {A Chromium update is available}
-           other {A Chromium update has been available for # days}}
-        </message>
-        <message name="IDS_RELAUNCH_RECOMMENDED_BODY" desc="The body text of a dialog that tells users that a browser relaunch is recommended for an update.">
-          Your administrator asks that you relaunch Chromium to apply this update
-        </message>
-        <message name="IDS_RELAUNCH_REQUIRED_TITLE_DAYS" desc="The title of a dialog that tells users the browser must be relaunched within two or more days.">
-          {0, plural,
-           =1 {Relaunch Chromium within a day}
-           other {Relaunch Chromium within # days}}
-        </message>
-        <message name="IDS_RELAUNCH_REQUIRED_TITLE_HOURS" desc="The title of a dialog that tells users the browser must be relaunched within one or more hours.">
-          {0, plural,
-           =1 {Chromium will relaunch in an hour}
-           other {Chromium will relaunch in # hours}}
-        </message>
-        <message name="IDS_RELAUNCH_REQUIRED_TITLE_MINUTES" desc="The title of a dialog that tells users the browser must be relaunched within one or more minutes.">
-          {0, plural,
-           =1 {Chromium will relaunch in 1 minute}
-           other {Chromium will relaunch in # minutes}}
-        </message>
-        <message name="IDS_RELAUNCH_REQUIRED_TITLE_SECONDS" desc="The title of a dialog that tells users the browser must be relaunched within some number of seconds.">
-          {0, plural,
-           =0 {Chromium will relaunch now}
-           =1 {Chromium will relaunch in 1 second}
-           other {Chromium will relaunch in # seconds}}
-        </message>
-        <message name="IDS_RELAUNCH_REQUIRED_BODY" desc="The body text of a dialog that tells users the browser must be relaunched.">
-          Your administrator requires that you relaunch Chromium to apply an update
-        </message>
+      <if expr="not is_android">
+        <if expr="not chromeos">
+          <then>
+            <message name="IDS_RELAUNCH_RECOMMENDED_TITLE" desc="The title of a dialog that tells users that a browser relaunch is recommended for an update available for some number of days.">
+              {0, plural,
+               =0 {A Chromium update is available}
+               =1 {A Chromium update is available}
+               other {A Chromium update has been available for # days}}
+            </message>
+            <message name="IDS_RELAUNCH_RECOMMENDED_BODY" desc="The body text of a dialog that tells users that a browser relaunch is recommended for an update.">
+              Your administrator asks that you relaunch Chromium to apply this update
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_DAYS" desc="The title of a dialog that tells users the browser must be relaunched within two or more days.">
+              {0, plural,
+               =1 {Relaunch Chromium within a day}
+               other {Relaunch Chromium within # days}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_HOURS" desc="The title of a dialog that tells users the browser must be relaunched within one or more hours.">
+              {0, plural,
+               =1 {Chromium will relaunch in an hour}
+               other {Chromium will relaunch in # hours}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_MINUTES" desc="The title of a dialog that tells users the browser must be relaunched within one or more minutes.">
+              {0, plural,
+               =1 {Chromium will relaunch in 1 minute}
+               other {Chromium will relaunch in # minutes}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_SECONDS" desc="The title of a dialog that tells users the browser must be relaunched within some number of seconds.">
+              {0, plural,
+               =0 {Chromium will relaunch now}
+               =1 {Chromium will relaunch in 1 second}
+               other {Chromium will relaunch in # seconds}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_BODY" desc="The body text of a dialog that tells users the browser must be relaunched.">
+              Your administrator requires that you relaunch Chromium to apply an update
+            </message>
+          </then>
+          <else>
+            <message name="IDS_RELAUNCH_RECOMMENDED_TITLE" desc="The title of a dialog that tells users that a device restart is recommended for an update available for some number of days.">
+              {0, plural,
+               =0 {A Chromium OS update is available}
+               =1 {A Chromium OS update is available}
+               other {A Chromium OS update has been available for # days}}
+            </message>
+            <message name="IDS_RELAUNCH_RECOMMENDED_BODY" desc="The body text of a dialog that tells users that a device restart is recommended for an update.">
+              Your administrator asks that you restart Chromium OS to apply this update
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_DAYS" desc="The title of a dialog that tells users the device must be restarted within two or more days.">
+              {0, plural,
+               =1 {Restart Chromium OS within a day}
+               other {Restart Chromium OS within # days}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_HOURS" desc="The title of a dialog that tells users the device must be restarted within one or more hours.">
+              {0, plural,
+               =1 {Chromium OS will restart in an hour}
+               other {Chromium OS will restart in # hours}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_MINUTES" desc="The title of a dialog that tells users the device must be restarted within one or more minutes.">
+              {0, plural,
+               =1 {Chromium OS will restart in 1 minute}
+               other {Chromium OS will restart in # minutes}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_SECONDS" desc="The title of a dialog that tells users the device must be restarted within some number of seconds.">
+              {0, plural,
+               =0 {Chromium OS will restart now}
+               =1 {Chromium OS will restart in 1 second}
+               other {Chromium OS will restart in # seconds}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_BODY" desc="The body text of a dialog that tells users the device must be restarted.">
+              Your administrator requires that you restart Chromium OS to apply an update
+            </message>
+          </else>
+        </if>
       </if>
       <!-- Chroium launch blocking dialog. -->
       <if expr="not is_android and not chromeos">
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 7c9aa1a..7356de0 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -9018,10 +9018,17 @@
       Upload
     </message>
     <!-- Relaunch notification bubble and dialog. -->
-    <if expr="not is_android and not chromeos">
-      <message name="IDS_RELAUNCH_ACCEPT_BUTTON" desc="The text in the accept button of a dialog that causes the browser to be relaunched immediately.">
-        Relaunch now
-      </message>
+    <if expr="not is_android">
+      <if expr="not chromeos">
+        <message name="IDS_RELAUNCH_ACCEPT_BUTTON" desc="The text in the accept button of a dialog that causes the browser to be relaunched immediately.">
+          Relaunch now
+        </message>
+      </if>
+      <if expr="chromeos">
+        <message name="IDS_RELAUNCH_ACCEPT_BUTTON" desc="The text in the accept button of a dialog that causes the device to be restarted immediately.">
+          Restart now
+        </message>
+      </if>
       <message name="IDS_RELAUNCH_REQUIRED_CANCEL_BUTTON" desc="The text in the cancel button that dismisses a dialog telling users the browser must be relaunched.">
         Got it
       </message>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 4552b231..ec8b999c9 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -979,6 +979,9 @@
         </message>
       </if>
       <if expr="chromeos">
+        <message name="IDS_UPDATE_RECOMMENDED_DIALOG_TITLE" desc="The window title for the Update Recommended dialog.">
+          Restart Chrome OS
+        </message>
         <message name="IDS_UPDATE_RECOMMENDED" desc="The main text of the Update Recommended dialog.">
           Chrome OS needs to be restarted to apply the update.
         </message>
@@ -1205,40 +1208,79 @@
         </message>
       </if>
       <!-- Relaunch notification bubble and dialog. -->
-      <if expr="not is_android and not chromeos">
-        <message name="IDS_RELAUNCH_RECOMMENDED_TITLE" desc="The title of a dialog that tells users that a browser relaunch is recommended for an update available for some number of days.">
-          {0, plural,
-           =0 {A Chrome update is available}
-           =1 {A Chrome update is available}
-           other {A Chrome update has been available for # days}}
-        </message>
-        <message name="IDS_RELAUNCH_RECOMMENDED_BODY" desc="The body text of a dialog that tells users that a browser relaunch is recommended for an update.">
-          Your administrator asks that you relaunch Chrome to apply this update
-        </message>
-        <message name="IDS_RELAUNCH_REQUIRED_TITLE_DAYS" desc="The title of a dialog that tells users the browser must be relaunched within two or more days.">
-          {0, plural,
-           =1 {Relaunch Chrome within a day}
-           other {Relaunch Chrome within # days}}
-        </message>
-        <message name="IDS_RELAUNCH_REQUIRED_TITLE_HOURS" desc="The title of a dialog that tells users the browser must be relaunched within one or more hours.">
-          {0, plural,
-           =1 {Chrome will relaunch in an hour}
-           other {Chrome will relaunch in # hours}}
-        </message>
-        <message name="IDS_RELAUNCH_REQUIRED_TITLE_MINUTES" desc="The title of a dialog that tells users the browser must be relaunched within one or more minutes.">
-          {0, plural,
-           =1 {Chrome will relaunch in 1 minute}
-           other {Chrome will relaunch in # minutes}}
-        </message>
-        <message name="IDS_RELAUNCH_REQUIRED_TITLE_SECONDS" desc="The title of a dialog that tells users the browser must be relaunched within some number of seconds.">
-          {0, plural,
-           =0 {Chrome will relaunch now}
-           =1 {Chrome will relaunch in 1 second}
-           other {Chrome will relaunch in # seconds}}
-        </message>
-        <message name="IDS_RELAUNCH_REQUIRED_BODY" desc="The body text of a dialog that tells users the browser must be relaunched.">
-          Your administrator requires that you relaunch Chrome to apply an update
-        </message>
+      <if expr="not is_android">
+        <if expr="not chromeos">
+          <then>
+            <message name="IDS_RELAUNCH_RECOMMENDED_TITLE" desc="The title of a dialog that tells users that a browser relaunch is recommended for an update available for some number of days.">
+              {0, plural,
+               =0 {A Chrome update is available}
+               =1 {A Chrome update is available}
+               other {A Chrome update has been available for # days}}
+            </message>
+            <message name="IDS_RELAUNCH_RECOMMENDED_BODY" desc="The body text of a dialog that tells users that a browser relaunch is recommended for an update.">
+              Your administrator asks that you relaunch Chrome to apply this update
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_DAYS" desc="The title of a dialog that tells users the browser must be relaunched within two or more days.">
+              {0, plural,
+               =1 {Relaunch Chrome within a day}
+               other {Relaunch Chrome within # days}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_HOURS" desc="The title of a dialog that tells users the browser must be relaunched within one or more hours.">
+              {0, plural,
+               =1 {Chrome will relaunch in an hour}
+               other {Chrome will relaunch in # hours}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_MINUTES" desc="The title of a dialog that tells users the browser must be relaunched within one or more minutes.">
+              {0, plural,
+               =1 {Chrome will relaunch in 1 minute}
+               other {Chrome will relaunch in # minutes}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_SECONDS" desc="The title of a dialog that tells users the browser must be relaunched within some number of seconds.">
+              {0, plural,
+               =0 {Chrome will relaunch now}
+               =1 {Chrome will relaunch in 1 second}
+               other {Chrome will relaunch in # seconds}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_BODY" desc="The body text of a dialog that tells users the browser must be relaunched.">
+              Your administrator requires that you relaunch Chrome to apply an update
+            </message>
+          </then>
+          <else>
+            <message name="IDS_RELAUNCH_RECOMMENDED_TITLE" desc="The title of a dialog that tells users that a device restart is recommended for an update available for some number of days.">
+              {0, plural,
+               =0 {A Chrome OS update is available}
+               =1 {A Chrome OS update is available}
+               other {A Chrome OS update has been available for # days}}
+            </message>
+            <message name="IDS_RELAUNCH_RECOMMENDED_BODY" desc="The body text of a dialog that tells users that a device restart is recommended for an update.">
+              Your administrator asks that you restart Chrome OS to apply this update
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_DAYS" desc="The title of a dialog that tells users the device must be restarted within two or more days.">
+              {0, plural,
+               =1 {Restart Chrome OS within a day}
+               other {Restart Chrome OS within # days}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_HOURS" desc="The title of a dialog that tells users the device must be restarted within one or more hours.">
+              {0, plural,
+               =1 {Chrome OS will restart in an hour}
+               other {Chrome OS will restart in # hours}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_MINUTES" desc="The title of a dialog that tells users the device must be restarted within one or more minutes.">
+              {0, plural,
+               =1 {Chrome OS will restart in 1 minute}
+               other {Chrome OS will restart in # minutes}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_TITLE_SECONDS" desc="The title of a dialog that tells users the device must be restarted within some number of seconds.">
+              {0, plural,
+               =0 {Chrome OS will restart now}
+               =1 {Chrome OS will restart in 1 second}
+               other {Chrome OS will restart in # seconds}}
+            </message>
+            <message name="IDS_RELAUNCH_REQUIRED_BODY" desc="The body text of a dialog that tells users the device must be restarted.">
+              Your administrator requires that you restart Chrome OS to apply an update
+            </message>
+          </else>
+        </if>
       </if>
 
       <!-- Chrome launch blocking dialog. -->
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index ddb5ad4b..0aaade1f2 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1678,6 +1678,11 @@
      flag_descriptions::kNewPasswordFormParsingName,
      flag_descriptions::kNewPasswordFormParsingDescription, kOsAll,
      FEATURE_VALUE_TYPE(password_manager::features::kNewPasswordFormParsing)},
+    {"new-password-form-parsing-for-saving",
+     flag_descriptions::kNewPasswordFormParsingForSavingName,
+     flag_descriptions::kNewPasswordFormParsingForSavingDescription, kOsAll,
+     FEATURE_VALUE_TYPE(
+         password_manager::features::kNewPasswordFormParsingForSaving)},
     {"enable-show-autofill-signatures",
      flag_descriptions::kShowAutofillSignaturesName,
      flag_descriptions::kShowAutofillSignaturesDescription, kOsAll,
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device.cc b/chrome/browser/android/vr/arcore_device/arcore_device.cc
index d49ff76..0b1b6f9e 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_device.cc
@@ -277,7 +277,7 @@
 }
 
 void ARCoreDevice::OnMagicWindowFrameDataRequest(
-    mojom::VRMagicWindowProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   TRACE_EVENT0("gpu", __FUNCTION__);
   DCHECK(IsOnMainThread());
   // We should not be able to reach this point if we are not initialized.
@@ -312,7 +312,7 @@
 
 void ARCoreDevice::RequestHitTest(
     mojom::XRRayPtr ray,
-    mojom::VRMagicWindowProvider::RequestHitTestCallback callback) {
+    mojom::XREnviromentIntegrationProvider::RequestHitTestCallback callback) {
   DCHECK(IsOnMainThread());
 
   PostTaskToGlThread(base::BindOnce(
@@ -441,16 +441,19 @@
         &ARCoreGl::Resume, arcore_gl_thread_->GetARCoreGl()->GetWeakPtr()));
   }
 
-  // TODO(offenwanger) When the XRMagicWindowProvider or equivalent is returned
-  // here, clean out this dummy code.
-  auto connection = mojom::XRPresentationConnection::New();
-  mojom::VRSubmitFrameClientPtr submit_client;
-  connection->client_request = mojo::MakeRequest(&submit_client);
-  mojom::VRPresentationProviderPtr provider;
-  mojo::MakeRequest(&provider);
-  connection->provider = provider.PassInterface();
-  connection->transport_options = mojom::VRDisplayFrameTransportOptions::New();
-  std::move(callback).Run(std::move(connection), nullptr);
+  auto session = mojom::XRSession::New();
+
+  mojom::XRFrameDataProviderPtr data_provider;
+  mojom::XREnviromentIntegrationProviderPtr enviroment_provider;
+  mojom::XRSessionControllerPtr controller;
+  magic_window_sessions_.push_back(std::make_unique<VRDisplayImpl>(
+      this, mojo::MakeRequest(&data_provider),
+      mojo::MakeRequest(&enviroment_provider), mojo::MakeRequest(&controller)));
+
+  session->data_provider = data_provider.PassInterface();
+  session->enviroment_provider = enviroment_provider.PassInterface();
+
+  std::move(callback).Run(std::move(session), std::move(controller));
 }
 
 void ARCoreDevice::OnRequestAndroidCameraPermissionResult(
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device.h b/chrome/browser/android/vr/arcore_device/arcore_device.h
index ad09a36..d3ecff7 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_device.h
@@ -52,10 +52,11 @@
   // VRDeviceBase implementation
   bool ShouldPauseTrackingWhenFrameDataRestricted() override;
   void OnMagicWindowFrameDataRequest(
-      mojom::VRMagicWindowProvider::GetFrameDataCallback callback) override;
+      mojom::XRFrameDataProvider::GetFrameDataCallback callback) override;
   void RequestHitTest(
       mojom::XRRayPtr ray,
-      mojom::VRMagicWindowProvider::RequestHitTestCallback callback) override;
+      mojom::XREnviromentIntegrationProvider::RequestHitTestCallback callback)
+      override;
 
   void OnMailboxBridgeReady();
   void OnARCoreGlThreadInitialized();
diff --git a/chrome/browser/android/vr/arcore_device/arcore_gl.cc b/chrome/browser/android/vr/arcore_device/arcore_gl.cc
index 891ed17..a7dd48da 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_gl.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_gl.cc
@@ -83,7 +83,7 @@
   ARCoreHitTestRequest() = default;
   ~ARCoreHitTestRequest() = default;
   mojom::XRRayPtr ray;
-  mojom::VRMagicWindowProvider::RequestHitTestCallback callback;
+  mojom::XREnviromentIntegrationProvider::RequestHitTestCallback callback;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ARCoreHitTestRequest);
@@ -176,7 +176,7 @@
 void ARCoreGl::ProduceFrame(
     const gfx::Size& frame_size,
     display::Display::Rotation display_rotation,
-    mojom::VRMagicWindowProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   TRACE_EVENT0("gpu", __FUNCTION__);
   DCHECK(IsOnGlThread());
   DCHECK(is_initialized_);
@@ -252,7 +252,7 @@
 
 void ARCoreGl::RequestHitTest(
     mojom::XRRayPtr ray,
-    mojom::VRMagicWindowProvider::RequestHitTestCallback callback) {
+    mojom::XREnviromentIntegrationProvider::RequestHitTestCallback callback) {
   DCHECK(IsOnGlThread());
   DCHECK(is_initialized_);
 
@@ -266,7 +266,7 @@
 void ARCoreGl::ProcessFrame(
     mojom::XRFrameDataPtr frame_data,
     const gfx::Size& frame_size,
-    mojom::VRMagicWindowProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   DCHECK(IsOnGlThread());
   DCHECK(is_initialized_);
 
diff --git a/chrome/browser/android/vr/arcore_device/arcore_gl.h b/chrome/browser/android/vr/arcore_device/arcore_gl.h
index d190193..2262ca97 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_gl.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_gl.h
@@ -50,7 +50,7 @@
 
   void ProduceFrame(const gfx::Size& frame_size,
                     display::Display::Rotation display_rotation,
-                    mojom::VRMagicWindowProvider::GetFrameDataCallback);
+                    mojom::XRFrameDataProvider::GetFrameDataCallback);
   void Pause();
   void Resume();
 
@@ -58,17 +58,17 @@
     return gl_thread_task_runner_;
   }
 
-  void RequestHitTest(mojom::XRRayPtr,
-                      mojom::VRMagicWindowProvider::RequestHitTestCallback);
+  void RequestHitTest(
+      mojom::XRRayPtr,
+      mojom::XREnviromentIntegrationProvider::RequestHitTestCallback);
 
   base::WeakPtr<ARCoreGl> GetWeakPtr();
 
  private:
   // TODO(https://crbug/835948): remove frame_size.
-  void ProcessFrame(
-      mojom::XRFrameDataPtr frame_data,
-      const gfx::Size& frame_size,
-      mojom::VRMagicWindowProvider::GetFrameDataCallback callback);
+  void ProcessFrame(mojom::XRFrameDataPtr frame_data,
+                    const gfx::Size& frame_size,
+                    mojom::XRFrameDataProvider::GetFrameDataCallback callback);
 
   bool InitializeGl();
   bool IsOnGlThread() const;
diff --git a/chrome/browser/android/vr/gl_browser_interface.h b/chrome/browser/android/vr/gl_browser_interface.h
index 77959c2..0e03d914 100644
--- a/chrome/browser/android/vr/gl_browser_interface.h
+++ b/chrome/browser/android/vr/gl_browser_interface.h
@@ -32,11 +32,8 @@
   virtual void ContentOverlaySurfaceCreated(jobject surface,
                                             gl::SurfaceTexture* texture) = 0;
   virtual void GvrDelegateReady(gvr::ViewerType viewer_type) = 0;
-  virtual void SendRequestPresentReply(
-      bool success,
-      device::mojom::VRSubmitFrameClientRequest,
-      device::mojom::VRPresentationProviderPtr,
-      device::mojom::VRDisplayFrameTransportOptionsPtr) = 0;
+  // XRSessionPtr is optional, if null, the request failed.
+  virtual void SendRequestPresentReply(device::mojom::XRSessionPtr) = 0;
   virtual void DialogSurfaceCreated(jobject surface,
                                     gl::SurfaceTexture* texture) = 0;
   virtual void UpdateGamepadData(device::GvrGamepadData) = 0;
diff --git a/chrome/browser/android/vr/vr_gl_thread.cc b/chrome/browser/android/vr/vr_gl_thread.cc
index 0e88057..22b57b5 100644
--- a/chrome/browser/android/vr/vr_gl_thread.cc
+++ b/chrome/browser/android/vr/vr_gl_thread.cc
@@ -131,17 +131,11 @@
       base::BindOnce(&VrShell::GvrDelegateReady, weak_vr_shell_, viewer_type));
 }
 
-void VrGLThread::SendRequestPresentReply(
-    bool success,
-    device::mojom::VRSubmitFrameClientRequest request,
-    device::mojom::VRPresentationProviderPtr provider,
-    device::mojom::VRDisplayFrameTransportOptionsPtr transport_options) {
+void VrGLThread::SendRequestPresentReply(device::mojom::XRSessionPtr session) {
   DCHECK(OnGlThread());
   main_thread_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&VrShell::SendRequestPresentReply, weak_vr_shell_, success,
-                     std::move(request), provider.PassInterface(),
-                     std::move(transport_options)));
+      FROM_HERE, base::BindOnce(&VrShell::SendRequestPresentReply,
+                                weak_vr_shell_, std::move(session)));
 }
 
 void VrGLThread::UpdateGamepadData(device::GvrGamepadData pad) {
diff --git a/chrome/browser/android/vr/vr_gl_thread.h b/chrome/browser/android/vr/vr_gl_thread.h
index 127aef7..2a490eb 100644
--- a/chrome/browser/android/vr/vr_gl_thread.h
+++ b/chrome/browser/android/vr/vr_gl_thread.h
@@ -65,11 +65,7 @@
   void ContentOverlaySurfaceCreated(jobject surface,
                                     gl::SurfaceTexture* texture) override;
   void GvrDelegateReady(gvr::ViewerType viewer_type) override;
-  void SendRequestPresentReply(
-      bool success,
-      device::mojom::VRSubmitFrameClientRequest,
-      device::mojom::VRPresentationProviderPtr,
-      device::mojom::VRDisplayFrameTransportOptionsPtr) override;
+  void SendRequestPresentReply(device::mojom::XRSessionPtr) override;
   void DialogSurfaceCreated(jobject surface,
                             gl::SurfaceTexture* texture) override;
   void UpdateGamepadData(device::GvrGamepadData) override;
diff --git a/chrome/browser/android/vr/vr_shell.cc b/chrome/browser/android/vr/vr_shell.cc
index f6ac330f..8da7fd7 100644
--- a/chrome/browser/android/vr/vr_shell.cc
+++ b/chrome/browser/android/vr/vr_shell.cc
@@ -92,9 +92,6 @@
 constexpr base::TimeDelta kPollCapturingStateInterval =
     base::TimeDelta::FromSecondsD(0.2);
 
-constexpr base::TimeDelta kExitVrDueToUnsupportedModeDelay =
-    base::TimeDelta::FromSeconds(5);
-
 constexpr base::TimeDelta kAssetsComponentWaitDelay =
     base::TimeDelta::FromSeconds(2);
 
@@ -754,17 +751,8 @@
   delegate_provider_->SetDelegate(this, viewer_type);
 }
 
-void VrShell::SendRequestPresentReply(
-    bool success,
-    device::mojom::VRSubmitFrameClientRequest request,
-    device::mojom::VRPresentationProviderPtrInfo provider_info,
-    device::mojom::VRDisplayFrameTransportOptionsPtr transport_options) {
-  device::mojom::VRPresentationProviderPtr provider;
-  provider.Bind(std::move(provider_info));
-
-  delegate_provider_->SendRequestPresentReply(success, std::move(request),
-                                              std::move(provider),
-                                              std::move(transport_options));
+void VrShell::SendRequestPresentReply(device::mojom::XRSessionPtr session) {
+  delegate_provider_->SendRequestPresentReply(std::move(session));
 }
 
 void VrShell::BufferBoundsChanged(JNIEnv* env,
@@ -866,28 +854,15 @@
                             UiUnsupportedMode::kCount);
 }
 
-void VrShell::ExitVrDueToUnsupportedMode(UiUnsupportedMode mode) {
-  ui_->SetIsExiting();
-  PostToGlThread(FROM_HERE, base::BindOnce(&VrShellGl::set_is_exiting,
-                                           gl_thread_->GetVrShellGl(), true));
-  main_thread_task_runner_->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(&VrShell::ForceExitVr, weak_ptr_factory_.GetWeakPtr()),
-      kExitVrDueToUnsupportedModeDelay);
-  LogUnsupportedModeUserMetric(mode);
-}
-
 content::WebContents* VrShell::GetNonNativePageWebContents() const {
   return !web_contents_is_native_page_ ? web_contents_ : nullptr;
 }
 
 void VrShell::OnUnsupportedMode(UiUnsupportedMode mode) {
   switch (mode) {
-    case UiUnsupportedMode::kUnhandledCodePoint:  // Fall through.
-    case UiUnsupportedMode::kUnhandledCertificateInfo:
-    case UiUnsupportedMode::kUnhandledConnectionSecurityInfo:
-    case UiUnsupportedMode::kGenericUnsupportedFeature:
-      ExitVrDueToUnsupportedMode(mode);
+    case UiUnsupportedMode::kUnhandledCodePoint:
+      // We should never have this case.
+      CHECK(false);
       return;
     case UiUnsupportedMode::kVoiceSearchNeedsRecordAudioOsPermission: {
       JNIEnv* env = base::android::AttachCurrentThread();
@@ -899,20 +874,21 @@
       Java_VrShellImpl_onNeedsKeyboardUpdate(env, j_vr_shell_);
       return;
     }
-    // Is not sent by the UI anymore. Enum value still exists to show correct
-    // exit prompt if vr-browsing-native-android-ui flag is false.
+    // These modes are not sent by the UI anymore. Enum values still exist to
+    // show correct exit prompt if vr-browsing-native-android-ui flag is false.
     case UiUnsupportedMode::kUnhandledPageInfo:
+    case UiUnsupportedMode::kUnhandledCertificateInfo:
+    case UiUnsupportedMode::kUnhandledConnectionSecurityInfo:
+    case UiUnsupportedMode::kGenericUnsupportedFeature:
     // kSearchEnginePromo should directly DOFF without showing a promo. So it
     // should never be used from VR ui thread.
     case UiUnsupportedMode::kSearchEnginePromo:
-    // Should never be used as a mode.
     case UiUnsupportedMode::kCount:
       NOTREACHED();
       return;
   }
 
   NOTREACHED();
-  ExitVrDueToUnsupportedMode(mode);
 }
 
 void VrShell::OnExitVrPromptResult(UiUnsupportedMode reason,
diff --git a/chrome/browser/android/vr/vr_shell.h b/chrome/browser/android/vr/vr_shell.h
index da2d1e9..fb7a271 100644
--- a/chrome/browser/android/vr/vr_shell.h
+++ b/chrome/browser/android/vr/vr_shell.h
@@ -181,11 +181,7 @@
   void ContentOverlaySurfaceCreated(jobject surface,
                                     gl::SurfaceTexture* texture);
   void GvrDelegateReady(gvr::ViewerType viewer_type);
-  void SendRequestPresentReply(
-      bool success,
-      device::mojom::VRSubmitFrameClientRequest,
-      device::mojom::VRPresentationProviderPtrInfo,
-      device::mojom::VRDisplayFrameTransportOptionsPtr);
+  void SendRequestPresentReply(device::mojom::XRSessionPtr);
 
   void DialogSurfaceCreated(jobject surface, gl::SurfaceTexture* texture);
 
@@ -302,8 +298,6 @@
 
   bool HasDaydreamSupport(JNIEnv* env);
 
-  void ExitVrDueToUnsupportedMode(UiUnsupportedMode mode);
-
   content::WebContents* GetNonNativePageWebContents() const;
 
   void LoadAssets();
diff --git a/chrome/browser/android/vr/vr_shell_delegate.cc b/chrome/browser/android/vr/vr_shell_delegate.cc
index f843dd95..f754485 100644
--- a/chrome/browser/android/vr/vr_shell_delegate.cc
+++ b/chrome/browser/android/vr/vr_shell_delegate.cc
@@ -187,7 +187,7 @@
 
   if (!vr_shell_) {
     // We have to wait until the GL thread is ready since we have to get the
-    // VRSubmitFrameClient.
+    // XRPresentationClient.
     pending_successful_present_request_ = true;
     on_present_result_callback_ = base::BindOnce(
         &VrShellDelegate::OnPresentResult, base::Unretained(this),
@@ -211,30 +211,15 @@
 }
 
 void VrShellDelegate::SendRequestPresentReply(
-    bool success,
-    device::mojom::VRSubmitFrameClientRequest request,
-    device::mojom::VRPresentationProviderPtr provider,
-    device::mojom::VRDisplayFrameTransportOptionsPtr transport_options) {
+    device::mojom::XRSessionPtr session) {
   DVLOG(1) << __FUNCTION__;
   if (!request_present_response_callback_) {
     DLOG(ERROR) << __FUNCTION__ << ": ERROR: no callback";
     return;
   }
 
-  if (success) {
-    auto connection = device::mojom::XRPresentationConnection::New();
-    connection->client_request = std::move(request);
-    connection->provider = provider.PassInterface();
-    connection->transport_options = std::move(transport_options);
-
-    device::mojom::XRSessionPtr xr_session = device::mojom::XRSession::New();
-    xr_session->connection = std::move(connection);
-
-    base::ResetAndReturn(&request_present_response_callback_)
-        .Run(std::move(xr_session));
-  } else {
-    base::ResetAndReturn(&request_present_response_callback_).Run(nullptr);
-  }
+  base::ResetAndReturn(&request_present_response_callback_)
+      .Run(std::move(session));
 }
 
 void VrShellDelegate::DisplayActivate(JNIEnv* env,
diff --git a/chrome/browser/android/vr/vr_shell_delegate.h b/chrome/browser/android/vr/vr_shell_delegate.h
index 859f616..b523ac0 100644
--- a/chrome/browser/android/vr/vr_shell_delegate.h
+++ b/chrome/browser/android/vr/vr_shell_delegate.h
@@ -68,11 +68,7 @@
 
   device::GvrDevice* GetDevice();
 
-  void SendRequestPresentReply(
-      bool success,
-      device::mojom::VRSubmitFrameClientRequest request,
-      device::mojom::VRPresentationProviderPtr provider,
-      device::mojom::VRDisplayFrameTransportOptionsPtr);
+  void SendRequestPresentReply(device::mojom::XRSessionPtr session);
 
   // device::GvrDelegateProvider implementation.
   void ExitWebVRPresent() override;
diff --git a/chrome/browser/android/vr/vr_shell_gl.cc b/chrome/browser/android/vr/vr_shell_gl.cc
index 9a1d110..e4c9811 100644
--- a/chrome/browser/android/vr/vr_shell_gl.cc
+++ b/chrome/browser/android/vr/vr_shell_gl.cc
@@ -338,7 +338,8 @@
       daydream_support_(daydream_support),
       content_paused_(pause_content),
       task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      binding_(this),
+      presentation_binding_(this),
+      frame_data_binding_(this),
       browser_(browser_interface),
       vr_ui_fps_meter_(),
       webvr_fps_meter_(),
@@ -681,7 +682,8 @@
     DVLOG(1) << __FUNCTION__ << ": wrong frame index, got " << frame_index
              << ", expected " << animating_frame->index;
     mojo::ReportBadMessage("SubmitFrame called with wrong frame index");
-    binding_.Close();
+    presentation_binding_.Close();
+    frame_data_binding_.Close();
     return false;
   }
 
@@ -846,8 +848,10 @@
     device::mojom::XRDeviceRuntimeSessionOptionsPtr options) {
   ClosePresentationBindings();
 
-  device::mojom::VRPresentationProviderPtr provider;
-  binding_.Bind(mojo::MakeRequest(&provider));
+  device::mojom::XRPresentationProviderPtr presentation_provider;
+  presentation_binding_.Bind(mojo::MakeRequest(&presentation_provider));
+  device::mojom::XRFrameDataProviderPtr frame_data_provider;
+  frame_data_binding_.Bind(mojo::MakeRequest(&frame_data_provider));
 
   gfx::Size webvr_size(
       display_info->leftEye->renderWidth + display_info->rightEye->renderWidth,
@@ -857,7 +861,7 @@
 
   // Decide which transport mechanism we want to use. This sets
   // the webxr_use_* options as a side effect.
-  device::mojom::VRDisplayFrameTransportOptionsPtr transport_options =
+  device::mojom::XRPresentationTransportOptionsPtr transport_options =
       GetWebVrFrameTransportOptions(options);
 
   if (webxr_use_shared_buffer_draw_) {
@@ -877,9 +881,16 @@
 
   ScheduleOrCancelWebVrFrameTimeout();
 
-  browser_->SendRequestPresentReply(true, mojo::MakeRequest(&submit_client_),
-                                    std::move(provider),
-                                    std::move(transport_options));
+  auto submit_frame_sink = device::mojom::XRPresentationConnection::New();
+  submit_frame_sink->client_request = mojo::MakeRequest(&submit_client_);
+  submit_frame_sink->provider = presentation_provider.PassInterface();
+  submit_frame_sink->transport_options = std::move(transport_options);
+
+  auto session = device::mojom::XRSession::New();
+  session->data_provider = frame_data_provider.PassInterface();
+  session->submit_frame_sink = std::move(submit_frame_sink);
+
+  browser_->SendRequestPresentReply(std::move(session));
 }
 
 void VrShellGl::OnSwapContents(int new_content_id) {
@@ -1077,7 +1088,7 @@
   }
 }
 
-device::mojom::VRDisplayFrameTransportOptionsPtr
+device::mojom::XRPresentationTransportOptionsPtr
 VrShellGl::GetWebVrFrameTransportOptions(
     const device::mojom::XRDeviceRuntimeSessionOptionsPtr& options) {
   DVLOG(1) << __FUNCTION__;
@@ -1120,19 +1131,19 @@
   DVLOG(1) << __FUNCTION__ << ": render_path=" << static_cast<int>(render_path);
   MetricsUtilAndroid::LogXrRenderPathUsed(render_path);
 
-  device::mojom::VRDisplayFrameTransportOptionsPtr transport_options =
-      device::mojom::VRDisplayFrameTransportOptions::New();
+  device::mojom::XRPresentationTransportOptionsPtr transport_options =
+      device::mojom::XRPresentationTransportOptions::New();
   // Only set boolean options that we need. Default is false, and we should be
   // able to safely ignore ones that our implementation doesn't care about.
   transport_options->wait_for_transfer_notification = true;
   if (webxr_use_shared_buffer_draw_) {
     transport_options->transport_method =
-        device::mojom::VRDisplayFrameTransportMethod::DRAW_INTO_TEXTURE_MAILBOX;
+        device::mojom::XRPresentationTransportMethod::DRAW_INTO_TEXTURE_MAILBOX;
     DCHECK(webxr_use_gpu_fence_);
     transport_options->wait_for_gpu_fence = true;
   } else {
     transport_options->transport_method =
-        device::mojom::VRDisplayFrameTransportMethod::SUBMIT_AS_MAILBOX_HOLDER;
+        device::mojom::XRPresentationTransportMethod::SUBMIT_AS_MAILBOX_HOLDER;
     transport_options->wait_for_transfer_notification = true;
     if (webxr_use_gpu_fence_) {
       transport_options->wait_for_gpu_fence = true;
@@ -1244,13 +1255,6 @@
                                       const RenderInfo& render_info,
                                       base::TimeTicks current_time) {
   gfx::Vector3dF head_direction = GetForwardVector(render_info.head_pose);
-  if (is_exiting_) {
-    // When we're exiting, we don't show the reticle and the only input
-    // processing we do is to handle immediate exits.
-    SendImmediateExitRequestIfNecessary();
-    return;
-  }
-
   gfx::Vector3dF ergo_neutral_pose;
   if (!controller_->IsConnected()) {
     // No controller detected, set up a gaze cursor that tracks the
@@ -1323,19 +1327,6 @@
   ui_->OnControllerUpdated(controller_model, reticle_model);
 }
 
-void VrShellGl::SendImmediateExitRequestIfNecessary() {
-  gvr::ControllerButton buttons[] = {
-      gvr::kControllerButtonClick, gvr::kControllerButtonApp,
-      gvr::kControllerButtonHome,
-  };
-  for (size_t i = 0; i < arraysize(buttons); ++i) {
-    if (controller_->ButtonUpHappened(buttons[i]) ||
-        controller_->ButtonDownHappened(buttons[i])) {
-      browser_->ForceExitVr();
-    }
-  }
-}
-
 bool VrShellGl::ResizeForWebVR(int16_t frame_index) {
   // Process all pending_bounds_ changes targeted for before this frame, being
   // careful of wrapping frame indices.
@@ -2252,7 +2243,7 @@
 }
 
 void VrShellGl::GetFrameData(
-    device::mojom::VRPresentationProvider::GetFrameDataCallback callback) {
+    device::mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   TRACE_EVENT0("gpu", __FUNCTION__);
   if (!get_frame_data_callback_.is_null()) {
     DLOG(WARNING) << ": previous get_frame_data_callback_ was not used yet";
@@ -2286,14 +2277,16 @@
                                   const gfx::Size& source_size) {
   if (!ValidateRect(left_bounds) || !ValidateRect(right_bounds)) {
     mojo::ReportBadMessage("UpdateLayerBounds called with invalid bounds");
-    binding_.Close();
+    presentation_binding_.Close();
+    frame_data_binding_.Close();
     return;
   }
 
   if (frame_index >= 0 && !webxr_->HaveAnimatingFrame()) {
     // The optional UpdateLayerBounds call must happen before SubmitFrame.
     mojo::ReportBadMessage("UpdateLayerBounds called without animating frame");
-    binding_.Close();
+    presentation_binding_.Close();
+    frame_data_binding_.Close();
     return;
   }
 
@@ -2467,7 +2460,8 @@
     // the connection is closing.
     base::ResetAndReturn(&get_frame_data_callback_).Run(nullptr);
   }
-  binding_.Close();
+  presentation_binding_.Close();
+  frame_data_binding_.Close();
 }
 
 device::mojom::XRInputSourceStatePtr VrShellGl::GetGazeInputSourceState() {
diff --git a/chrome/browser/android/vr/vr_shell_gl.h b/chrome/browser/android/vr/vr_shell_gl.h
index e227dcd..619a81e 100644
--- a/chrome/browser/android/vr/vr_shell_gl.h
+++ b/chrome/browser/android/vr/vr_shell_gl.h
@@ -264,7 +264,8 @@
 
 // This class manages all GLThread owned objects and GL rendering for VrShell.
 // It is not threadsafe and must only be used on the GL thread.
-class VrShellGl : public device::mojom::VRPresentationProvider {
+class VrShellGl : public device::mojom::XRPresentationProvider,
+                  public device::mojom::XRFrameDataProvider {
  public:
   VrShellGl(GlBrowserInterface* browser_interface,
             std::unique_ptr<UiInterface> ui,
@@ -309,8 +310,6 @@
       device::mojom::VRDisplayInfoPtr display_info,
       device::mojom::XRDeviceRuntimeSessionOptionsPtr options);
 
-  void set_is_exiting(bool exiting) { is_exiting_ = exiting; }
-
   void OnSwapContents(int new_content_id);
 
   void EnableAlertDialog(PlatformInputHandler* input_handler,
@@ -333,7 +332,7 @@
  private:
   void GvrInit(gvr_context* gvr_api);
 
-  device::mojom::VRDisplayFrameTransportOptionsPtr
+  device::mojom::XRPresentationTransportOptionsPtr
   GetWebVrFrameTransportOptions(
       const device::mojom::XRDeviceRuntimeSessionOptionsPtr&);
 
@@ -362,7 +361,6 @@
   void UpdateController(const RenderInfo& render_info,
                         base::TimeTicks current_time);
 
-  void SendImmediateExitRequestIfNecessary();
   void HandleControllerInput(const gfx::Point3F& laser_origin,
                              const RenderInfo& render_info,
                              base::TimeTicks current_time);
@@ -386,9 +384,11 @@
 
   bool IsSubmitFrameExpected(int16_t frame_index);
 
-  // VRPresentationProvider
-  void GetFrameData(device::mojom::VRPresentationProvider::GetFrameDataCallback
+  // XRFrameDataProvider
+  void GetFrameData(device::mojom::XRFrameDataProvider::GetFrameDataCallback
                         callback) override;
+
+  // XRPresentationProvider
   void SubmitFrameMissing(int16_t frame_index, const gpu::SyncToken&) override;
   void SubmitFrame(int16_t frame_index,
                    const gpu::MailboxHolder& mailbox,
@@ -530,7 +530,6 @@
   bool paused_ = true;
   const bool surfaceless_rendering_;
   bool daydream_support_;
-  bool is_exiting_ = false;
   bool content_paused_;
   bool cardboard_trigger_pressed_ = false;
   bool cardboard_trigger_clicked_ = false;
@@ -550,11 +549,12 @@
   // updated in OnVSync and used as the rAF animation timer in SendVSync.
   base::TimeTicks pending_time_;
   bool pending_vsync_ = false;
-  device::mojom::VRPresentationProvider::GetFrameDataCallback
+  device::mojom::XRFrameDataProvider::GetFrameDataCallback
       get_frame_data_callback_;
 
-  mojo::Binding<device::mojom::VRPresentationProvider> binding_;
-  device::mojom::VRSubmitFrameClientPtr submit_client_;
+  mojo::Binding<device::mojom::XRPresentationProvider> presentation_binding_;
+  mojo::Binding<device::mojom::XRFrameDataProvider> frame_data_binding_;
+  device::mojom::XRPresentationClientPtr submit_client_;
 
   GlBrowserInterface* browser_;
 
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index b0625b33..e22fae5 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -143,8 +143,8 @@
       <include name="IDR_DOWNLOAD_INTERNALS_JS" file="resources\download_internals\download_internals.js" type="BINDATA" compress="gzip" />
       <include name="IDR_DOWNLOAD_INTERNALS_BROWSER_PROXY_JS" file="resources\download_internals\download_internals_browser_proxy.js" type="BINDATA" compress="gzip" />
       <include name="IDR_DOWNLOAD_INTERNALS_VISUALS_JS" file="resources\download_internals\download_internals_visuals.js" type="BINDATA" compress="gzip" />
-      <include name="IDR_UKM_INTERNALS_HTML" file="resources/ukm/ukm_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
-      <include name="IDR_UKM_INTERNALS_JS" file="resources/ukm/ukm_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
+      <include name="IDR_UKM_INTERNALS_HTML" file="../../components/ukm/debug/ukm_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+      <include name="IDR_UKM_INTERNALS_JS" file="../../components/ukm/debug/ukm_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
       <if expr="not is_android">
         <include name="IDR_MD_DOWNLOADS_1X_INCOGNITO_MARKER_PNG" file="resources\md_downloads\1x\incognito_marker.png" type="BINDATA" />
         <include name="IDR_MD_DOWNLOADS_2X_INCOGNITO_MARKER_PNG" file="resources\md_downloads\2x\incognito_marker.png" type="BINDATA" />
diff --git a/chrome/browser/extensions/api/socket/combined_socket_unittest.cc b/chrome/browser/extensions/api/socket/combined_socket_unittest.cc
deleted file mode 100644
index 6feb6fe9..0000000
--- a/chrome/browser/extensions/api/socket/combined_socket_unittest.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-
-#include "chrome/browser/extensions/api/socket/mock_tcp_client_socket.h"
-#include "extensions/browser/api/socket/socket.h"
-#include "extensions/browser/api/socket/tcp_socket.h"
-#include "extensions/browser/api/socket/tls_socket.h"
-#include "net/socket/stream_socket.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace extensions {
-
-const int kBufferLength = 10;
-
-template <typename T>
-std::unique_ptr<T> CreateTestSocket(
-    std::unique_ptr<MockTCPClientSocket> stream);
-
-template <>
-std::unique_ptr<TCPSocket> CreateTestSocket(
-    std::unique_ptr<MockTCPClientSocket> stream) {
-  return std::make_unique<TCPSocket>(std::move(stream), "fake id",
-                                     true /* is_connected */);
-}
-
-template <>
-std::unique_ptr<TLSSocket> CreateTestSocket(
-    std::unique_ptr<MockTCPClientSocket> stream) {
-  return std::make_unique<TLSSocket>(std::move(stream), "fake id");
-}
-
-class CombinedSocketTest : public testing::Test {
- public:
-  CombinedSocketTest() : count_(0), io_buffer_(nullptr) {}
-
-  // Strict test for synchronous (immediate) read behavior
-  template <typename T>
-  void TestRead() {
-    net::IOBuffer* buffer = nullptr;
-
-    std::unique_ptr<MockTCPClientSocket> stream(
-        new testing::StrictMock<MockTCPClientSocket>());
-    EXPECT_CALL(*stream, Read(testing::NotNull(), kBufferLength, testing::_))
-        .WillOnce(DoAll(testing::SaveArg<0>(&buffer),
-                        testing::Return(kBufferLength)));
-    EXPECT_CALL(*stream, Disconnect());
-
-    std::unique_ptr<T> socket = CreateTestSocket<T>(std::move(stream));
-    ReadCompletionCallback read_callback =
-        base::Bind(&CombinedSocketTest::OnRead, base::Unretained(this));
-    socket->Read(kBufferLength, read_callback);
-    EXPECT_EQ(kBufferLength, count_);
-    EXPECT_NE(nullptr, buffer);
-    EXPECT_EQ(buffer, io_buffer_);
-  }
-
-  // Strict test for async read behavior (read returns PENDING)
-  template <typename T>
-  void TestReadPending() {
-    net::IOBuffer* buffer = nullptr;
-    net::CompletionCallback socket_cb;
-
-    std::unique_ptr<MockTCPClientSocket> stream(
-        new testing::StrictMock<MockTCPClientSocket>());
-    EXPECT_CALL(*stream, Read(testing::NotNull(), kBufferLength, testing::_))
-        .WillOnce(DoAll(testing::SaveArg<0>(&buffer),
-                        testing::SaveArg<2>(&socket_cb),
-                        testing::Return(net::ERR_IO_PENDING)));
-    EXPECT_CALL(*stream, Disconnect());
-
-    std::unique_ptr<T> socket = CreateTestSocket<T>(std::move(stream));
-    ReadCompletionCallback read_callback =
-        base::Bind(&CombinedSocketTest::OnRead, base::Unretained(this));
-    socket->Read(kBufferLength, read_callback);
-    EXPECT_EQ(0, count_);
-    EXPECT_EQ(nullptr, io_buffer_);
-    socket_cb.Run(kBufferLength);
-    EXPECT_EQ(kBufferLength, count_);
-    EXPECT_NE(nullptr, buffer);
-    EXPECT_EQ(buffer, io_buffer_);
-  }
-
-  // Even if the socket is closed, it may still have data left to read.
-  template <typename T>
-  void TestReadAfterDisconnect() {
-    net::IOBuffer* buffer = nullptr;
-
-    std::unique_ptr<MockTCPClientSocket> stream(
-        new testing::NiceMock<MockTCPClientSocket>());
-    EXPECT_CALL(*stream, Read(testing::NotNull(), kBufferLength, testing::_))
-        .WillOnce(DoAll(testing::SaveArg<0>(&buffer),
-                        testing::Return(kBufferLength)));
-    ON_CALL(*stream, IsConnected()).WillByDefault(testing::Return(false));
-    EXPECT_CALL(*stream, Disconnect());
-
-    std::unique_ptr<T> socket = CreateTestSocket<T>(std::move(stream));
-    ReadCompletionCallback read_callback =
-        base::Bind(&CombinedSocketTest::OnRead, base::Unretained(this));
-    socket->Read(kBufferLength, read_callback);
-    EXPECT_EQ(kBufferLength, count_);
-    EXPECT_NE(nullptr, buffer);
-    EXPECT_EQ(buffer, io_buffer_);
-  }
-
-  void OnRead(int count,
-              scoped_refptr<net::IOBuffer> io_buffer,
-              bool socket_destroying) {
-    count_ = count;
-    io_buffer_ = io_buffer.get();
-  }
-
- protected:
-  int count_;
-  net::IOBuffer* io_buffer_;
-};
-
-TEST_F(CombinedSocketTest, TlsRead) {
-  TestRead<TLSSocket>();
-}
-
-TEST_F(CombinedSocketTest, TcpRead) {
-  TestRead<TCPSocket>();
-}
-
-TEST_F(CombinedSocketTest, TlsReadPending) {
-  TestReadPending<TLSSocket>();
-}
-
-TEST_F(CombinedSocketTest, TcpReadPending) {
-  TestReadPending<TCPSocket>();
-}
-
-TEST_F(CombinedSocketTest, TlsReadAfterDisconnect) {
-  TestReadAfterDisconnect<TLSSocket>();
-}
-
-TEST_F(CombinedSocketTest, TcpReadAfterDisconnect) {
-  TestReadAfterDisconnect<TCPSocket>();
-}
-
-}  //  namespace extensions
diff --git a/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h b/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h
deleted file mode 100644
index fddad10..0000000
--- a/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_
-#define CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_
-
-#include "base/callback_helpers.h"
-#include "net/log/net_log_source.h"
-#include "net/log/net_log_with_source.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace extensions {
-class MockTCPClientSocket : public net::TCPClientSocket {
- public:
-  MockTCPClientSocket();
-  ~MockTCPClientSocket() override;
-
-  int Read(net::IOBuffer* buffer,
-           int bytes,
-           net::CompletionOnceCallback callback) override {
-    return Read(buffer, bytes,
-                base::AdaptCallbackForRepeating(std::move(callback)));
-  }
-
-  int Write(net::IOBuffer* buffer,
-            int bytes,
-            net::CompletionOnceCallback callback,
-            const net::NetworkTrafficAnnotationTag& tag) override {
-    return Write(buffer, bytes,
-                 base::AdaptCallbackForRepeating(std::move(callback)), tag);
-  }
-
-  int Connect(net::CompletionOnceCallback callback) override {
-    return Connect(base::AdaptCallbackForRepeating(std::move(callback)));
-  }
-
-  MOCK_METHOD3(Read, int(net::IOBuffer*, int, const net::CompletionCallback&));
-  MOCK_METHOD4(Write,
-               int(net::IOBuffer*,
-                   int,
-                   const net::CompletionCallback&,
-                   const net::NetworkTrafficAnnotationTag&));
-  MOCK_METHOD1(SetReceiveBufferSize, int(int32_t));
-  MOCK_METHOD1(SetSendBufferSize, int(int32_t));
-  MOCK_METHOD1(Connect, int(const net::CompletionCallback&));
-  MOCK_METHOD0(Disconnect, void());
-  MOCK_CONST_METHOD0(IsConnected, bool());
-  MOCK_CONST_METHOD0(IsConnectedAndIdle, bool());
-  MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*));
-  MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*));
-  MOCK_CONST_METHOD0(NetLog, const net::NetLogWithSource&());
-  MOCK_CONST_METHOD0(WasEverUsed, bool());
-  MOCK_CONST_METHOD0(UsingTCPFastOpen, bool());
-  MOCK_CONST_METHOD0(NumBytesRead, int64_t());
-  MOCK_CONST_METHOD0(GetConnectTimeMicros, base::TimeDelta());
-  MOCK_CONST_METHOD0(WasAlpnNegotiated, bool());
-  MOCK_CONST_METHOD0(GetNegotiatedProtocol, net::NextProto());
-  MOCK_METHOD1(GetSSLInfo, bool(net::SSLInfo*));
-  MOCK_CONST_METHOD1(GetConnectionAttempts, void(net::ConnectionAttempts*));
-  MOCK_METHOD0(ClearConnectionAttempts, void());
-  MOCK_METHOD1(AddConnectionAttempts, void(const net::ConnectionAttempts&));
-  MOCK_CONST_METHOD0(GetTotalReceivedBytes, int64_t());
-
-  // Methods specific to MockTCPClientSocket
-  MOCK_METHOD1(Bind, int(const net::IPEndPoint&));
-  MOCK_METHOD2(SetKeepAlive, bool(bool, int));
-  MOCK_METHOD1(SetNoDelay, bool(bool));
-};
-
-MockTCPClientSocket::MockTCPClientSocket()
-    : TCPClientSocket(net::AddressList(),
-                      nullptr,
-                      nullptr,
-                      net::NetLogSource()) {}
-MockTCPClientSocket::~MockTCPClientSocket() {}
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_
diff --git a/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc b/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
index 6351e3d..90c7937 100644
--- a/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
+++ b/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
@@ -4,274 +4,717 @@
 
 #include <memory>
 
-#include "base/callback_helpers.h"
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/extensions/extension_service_test_base.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/test/test_storage_partition.h"
 #include "extensions/browser/api/socket/tcp_socket.h"
 #include "net/base/address_list.h"
 #include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
-#include "net/log/net_log_source.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/socket/tcp_server_socket.h"
+#include "net/base/test_completion_callback.h"
+#include "net/socket/socket_test_util.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-using testing::_;
-using testing::DoAll;
-using testing::Return;
-using testing::SaveArg;
+#include "net/url_request/url_request_test_util.h"
+#include "services/network/network_context.h"
+#include "services/network/public/mojom/network_context.mojom.h"
 
 namespace extensions {
 
-class MockTCPSocket : public net::TCPClientSocket {
- public:
-  explicit MockTCPSocket(const net::AddressList& address_list)
-      : net::TCPClientSocket(address_list, NULL, NULL, net::NetLogSource()) {}
+namespace {
 
-  int Read(net::IOBuffer* buffer,
-           int bytes,
-           net::CompletionOnceCallback callback) override {
-    return Read(buffer, bytes,
-                base::AdaptCallbackForRepeating(std::move(callback)));
-  }
-
-  int Write(net::IOBuffer* buffer,
-            int bytes,
-            net::CompletionOnceCallback callback,
-            const net::NetworkTrafficAnnotationTag& tag) override {
-    return Write(buffer, bytes,
-                 base::AdaptCallbackForRepeating(std::move(callback)), tag);
-  }
-
-  MOCK_METHOD3(Read, int(net::IOBuffer* buf, int buf_len,
-                         const net::CompletionCallback& callback));
-  MOCK_METHOD4(Write,
-               int(net::IOBuffer* buf,
-                   int buf_len,
-                   const net::CompletionCallback& callback,
-                   const net::NetworkTrafficAnnotationTag&));
-  MOCK_METHOD2(SetKeepAlive, bool(bool enable, int delay));
-  MOCK_METHOD1(SetNoDelay, bool(bool no_delay));
-  bool IsConnected() const override {
-    return true;
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockTCPSocket);
-};
-
-class MockTCPServerSocket : public net::TCPServerSocket {
- public:
-  MockTCPServerSocket() : net::TCPServerSocket(NULL, net::NetLogSource()) {}
-  MOCK_METHOD2(Listen, int(const net::IPEndPoint& address, int backlog));
-  MOCK_METHOD2(Accept,
-               int(std::unique_ptr<net::StreamSocket>* socket,
-                   const net::CompletionCallback& callback));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockTCPServerSocket);
-};
-
-class CompleteHandler {
- public:
-  CompleteHandler() {}
-  MOCK_METHOD1(OnComplete, void(int result_code));
-  MOCK_METHOD3(OnReadComplete,
-               void(int result_code,
-                    scoped_refptr<net::IOBuffer> io_buffer,
-                    bool socket_destroying));
-
-  // MOCK_METHOD cannot mock a scoped_ptr argument.
-  MOCK_METHOD2(OnAcceptMock, void(int, net::TCPClientSocket*));
-  void OnAccept(int count, std::unique_ptr<net::TCPClientSocket> socket) {
-    OnAcceptMock(count, socket.get());
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CompleteHandler);
-};
+const char kTestMsg[] = "abcdefghij";
+const int kTestMsgLength = strlen(kTestMsg);
 
 const char FAKE_ID[] = "abcdefghijklmnopqrst";
 
-TEST(SocketTest, TestTCPSocketRead) {
-  net::AddressList address_list;
-  std::unique_ptr<MockTCPSocket> tcp_client_socket(
-      new MockTCPSocket(address_list));
-  CompleteHandler handler;
+class TCPSocketUnitTestBase : public extensions::ExtensionServiceTestBase {
+ public:
+  TCPSocketUnitTestBase()
+      : url_request_context_(true /* delay_initialization */) {}
+  ~TCPSocketUnitTestBase() override {}
 
-  EXPECT_CALL(*tcp_client_socket, Read(_, _, _))
-      .Times(1);
-  EXPECT_CALL(handler, OnReadComplete(_, _, _)).Times(1);
+  std::unique_ptr<TCPSocket> CreateSocket() {
+    auto socket = std::make_unique<TCPSocket>(&profile_, FAKE_ID);
+    socket->SetStoragePartitionForTest(&partition_);
+    return socket;
+  }
 
-  std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting(
-      std::move(tcp_client_socket), FAKE_ID, true));
+  std::unique_ptr<TCPSocket> CreateAndConnectSocketWithAddress(
+      const net::IPEndPoint& ip_end_point) {
+    auto socket = CreateSocket();
+    net::AddressList address(ip_end_point);
+    net::TestCompletionCallback callback;
+    socket->Connect(address, callback.callback());
+    EXPECT_EQ(net::OK, callback.WaitForResult());
+    return socket;
+  }
+
+  std::unique_ptr<TCPSocket> CreateAndConnectSocket() {
+    net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), 1234);
+    return CreateAndConnectSocketWithAddress(ip_end_point);
+  }
+
+  // Reads data from |socket| and compares it with |expected_data|.
+  void ReadData(Socket* socket, const std::string& expected_data) {
+    std::string received_data;
+    const int count = 512;
+    while (true) {
+      base::RunLoop run_loop;
+      int net_error = net::ERR_FAILED;
+      socket->Read(count,
+                   base::BindLambdaForTesting(
+                       [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+                           bool socket_destroying) {
+                         net_error = result;
+                         EXPECT_FALSE(socket_destroying);
+                         if (result > 0)
+                           received_data.append(io_buffer->data(), result);
+                         run_loop.Quit();
+                       }));
+      run_loop.Run();
+      if (net_error <= 0)
+        break;
+    }
+    EXPECT_EQ(expected_data, received_data);
+  }
+
+ protected:
+  // extensions::ExtensionServiceTestBase implementation.
+  void SetUp() override { InitializeEmptyExtensionService(); }
+
+  void Initialize() {
+    url_request_context_.Init();
+    network_context_ = std::make_unique<network::NetworkContext>(
+        nullptr, mojo::MakeRequest(&network_context_ptr_),
+        &url_request_context_);
+    partition_.set_network_context(network_context_ptr_.get());
+  }
+
+  net::TestURLRequestContext url_request_context_;
+
+ private:
+  TestingProfile profile_;
+  content::TestStoragePartition partition_;
+  std::unique_ptr<network::NetworkContext> network_context_;
+  network::mojom::NetworkContextPtr network_context_ptr_;
+};
+
+}  // namespace
+
+class TCPSocketUnitTest : public TCPSocketUnitTestBase,
+                          public ::testing::WithParamInterface<net::IoMode> {
+ public:
+  TCPSocketUnitTest() : TCPSocketUnitTestBase() {
+    mock_client_socket_factory_.set_enable_read_if_ready(true);
+    url_request_context_.set_client_socket_factory(
+        &mock_client_socket_factory_);
+    Initialize();
+  }
+  ~TCPSocketUnitTest() override {}
+
+  net::MockClientSocketFactory* mock_client_socket_factory() {
+    return &mock_client_socket_factory_;
+  }
+
+ private:
+  net::MockClientSocketFactory mock_client_socket_factory_;
+};
+
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+                        TCPSocketUnitTest,
+                        testing::Values(net::SYNCHRONOUS, net::ASYNC));
+
+TEST_F(TCPSocketUnitTest, SocketConnectError) {
+  net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), 1234);
+  net::StaticSocketDataProvider data_provider((base::span<net::MockRead>()),
+                                              base::span<net::MockWrite>());
+  data_provider.set_connect_data(
+      net::MockConnect(net::ASYNC, net::ERR_FAILED, ip_end_point));
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TCPSocket> socket = CreateSocket();
+
+  net::AddressList address(ip_end_point);
+  net::TestCompletionCallback callback;
+  socket->Connect(address, callback.callback());
+  EXPECT_EQ(net::ERR_FAILED, callback.WaitForResult());
+}
+
+TEST_P(TCPSocketUnitTest, SocketConnectAfterDisconnect) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {net::MockRead(io_mode, net::OK)};
+  net::StaticSocketDataProvider data_provider1(kReads,
+                                               base::span<net::MockWrite>());
+  net::StaticSocketDataProvider data_provider2(kReads,
+                                               base::span<net::MockWrite>());
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider1);
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider2);
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+  socket->Disconnect(false /* socket_destroying */);
+  net::TestCompletionCallback callback2;
+  net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), 1234);
+  net::AddressList address(ip_end_point);
+  socket->Connect(address, callback2.callback());
+  EXPECT_EQ(net::OK, callback2.WaitForResult());
+
+  EXPECT_TRUE(data_provider1.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider1.AllWriteDataConsumed());
+  EXPECT_TRUE(data_provider2.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider2.AllWriteDataConsumed());
+}
+
+TEST_F(TCPSocketUnitTest, DestroyWhileReadPending) {
+  const net::MockRead kReads[] = {
+      net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+  net::StaticSocketDataProvider data_provider(kReads,
+                                              base::span<net::MockWrite>());
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+  int net_result = net::ERR_FAILED;
+  base::RunLoop run_loop;
+  int count = 1;
+  // Read one byte, and it should be pending.
+  socket->Read(count,
+               base::BindLambdaForTesting(
+                   [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+                       bool socket_destroying) {
+                     net_result = result;
+                     // |socket_destroying| should correctly denote that this
+                     // read callback is invoked through the destructor of
+                     // TCPSocket.
+                     EXPECT_TRUE(socket_destroying);
+                     run_loop.Quit();
+                   }));
+  // Destroy socket.
+  socket = nullptr;
+  // Wait for read callback.
+  run_loop.Run();
+  EXPECT_EQ(net::ERR_CONNECTION_CLOSED, net_result);
+}
+
+TEST_P(TCPSocketUnitTest, Read) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(io_mode, kTestMsg, kTestMsgLength),
+      net::MockRead(io_mode, net::OK)};
+  net::StaticSocketDataProvider data_provider(kReads,
+                                              base::span<net::MockWrite>());
+
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+  ReadData(socket.get(), kTestMsg);
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
+
+// Tests the case where a message is split over two separate socket reads.
+TEST_P(TCPSocketUnitTest, SocketMultipleRead) {
+  const char kFirstHalfTestMsg[] = "abcde";
+  const char kSecondHalfTestMsg[] = "fghij";
+  EXPECT_EQ(kTestMsg, std::string(kFirstHalfTestMsg) + kSecondHalfTestMsg);
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(io_mode, kFirstHalfTestMsg, strlen(kFirstHalfTestMsg)),
+      net::MockRead(io_mode, kSecondHalfTestMsg, strlen(kSecondHalfTestMsg)),
+      net::MockRead(io_mode, net::OK)};
+  net::StaticSocketDataProvider data_provider(kReads,
+                                              base::span<net::MockWrite>());
+
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+  ReadData(socket.get(), kTestMsg);
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
+
+// Tests the case where read size is smaller than the actual message.
+TEST_P(TCPSocketUnitTest, SocketPartialRead) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(io_mode, kTestMsg, kTestMsgLength),
+      net::MockRead(io_mode, net::OK)};
+  net::StaticSocketDataProvider data_provider(kReads,
+                                              base::span<net::MockWrite>());
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+  int count = 1;
+  std::string received_data;
+  while (true) {
+    int net_result = net::ERR_FAILED;
+    base::RunLoop run_loop;
+    socket->Read(count,
+                 base::BindLambdaForTesting(
+                     [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+                         bool socket_destroying) {
+                       net_result = result;
+                       EXPECT_FALSE(socket_destroying);
+                       if (result > 0)
+                         received_data.append(io_buffer->data(), result);
+                       run_loop.Quit();
+                     }));
+    run_loop.Run();
+    if (net_result <= 0)
+      break;
+    // Double the read size in the next iteration.
+    count *= 2;
+  }
+  EXPECT_EQ(kTestMsg, received_data);
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
+
+TEST_P(TCPSocketUnitTest, ReadError) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(io_mode, kTestMsg, kTestMsgLength),
+      net::MockRead(io_mode, net::ERR_INSUFFICIENT_RESOURCES)};
+  net::StaticSocketDataProvider data_provider(kReads,
+                                              base::span<net::MockWrite>());
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
 
   const int count = 512;
-  socket->Read(count, base::Bind(&CompleteHandler::OnReadComplete,
-        base::Unretained(&handler)));
-}
-
-TEST(SocketTest, TestTCPSocketWrite) {
-  net::AddressList address_list;
-  std::unique_ptr<MockTCPSocket> tcp_client_socket(
-      new MockTCPSocket(address_list));
-  CompleteHandler handler;
-
-  net::CompletionCallback callback;
-  EXPECT_CALL(*tcp_client_socket, Write(_, _, _, _))
-      .Times(2)
-      .WillRepeatedly(testing::DoAll(SaveArg<2>(&callback), Return(128)));
-  EXPECT_CALL(handler, OnComplete(_))
-      .Times(1);
-
-  std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting(
-      std::move(tcp_client_socket), FAKE_ID, true));
-
-  scoped_refptr<net::IOBufferWithSize> io_buffer(
-      new net::IOBufferWithSize(256));
-  socket->Write(io_buffer.get(), io_buffer->size(),
-      base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler)));
-}
-
-TEST(SocketTest, TestTCPSocketBlockedWrite) {
-  net::AddressList address_list;
-  std::unique_ptr<MockTCPSocket> tcp_client_socket(
-      new MockTCPSocket(address_list));
-  CompleteHandler handler;
-
-  net::CompletionCallback callback;
-  EXPECT_CALL(*tcp_client_socket, Write(_, _, _, _))
-      .Times(2)
-      .WillRepeatedly(
-          testing::DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING)));
-
-  std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting(
-      std::move(tcp_client_socket), FAKE_ID, true));
-
-  scoped_refptr<net::IOBufferWithSize> io_buffer(new net::IOBufferWithSize(42));
-  socket->Write(io_buffer.get(), io_buffer->size(),
-      base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler)));
-
-  // Good. Original call came back unable to complete. Now pretend the socket
-  // finished, and confirm that we passed the error back.
-  EXPECT_CALL(handler, OnComplete(42))
-      .Times(1);
-  callback.Run(40);
-  callback.Run(2);
-}
-
-TEST(SocketTest, TestTCPSocketBlockedWriteReentry) {
-  net::AddressList address_list;
-  std::unique_ptr<MockTCPSocket> tcp_client_socket(
-      new MockTCPSocket(address_list));
-  CompleteHandler handlers[5];
-
-  net::CompletionCallback callback;
-  EXPECT_CALL(*tcp_client_socket, Write(_, _, _, _))
-      .Times(5)
-      .WillRepeatedly(
-          testing::DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING)));
-
-  std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting(
-      std::move(tcp_client_socket), FAKE_ID, true));
-
-  scoped_refptr<net::IOBufferWithSize> io_buffers[5];
-  int i;
-  for (i = 0; i < 5; i++) {
-    io_buffers[i] = new net::IOBufferWithSize(128 + i * 50);
-    scoped_refptr<net::IOBufferWithSize> io_buffer1(
-        new net::IOBufferWithSize(42));
-    socket->Write(io_buffers[i].get(), io_buffers[i]->size(),
-        base::Bind(&CompleteHandler::OnComplete,
-            base::Unretained(&handlers[i])));
-
-    EXPECT_CALL(handlers[i], OnComplete(io_buffers[i]->size()))
-        .Times(1);
+  int net_error = net::OK;
+  while (true) {
+    base::RunLoop run_loop;
+    socket->Read(count,
+                 base::BindLambdaForTesting(
+                     [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+                         bool socket_destroying) {
+                       net_error = result;
+                       EXPECT_FALSE(socket_destroying);
+                       if (result <= 0) {
+                         EXPECT_FALSE(socket->IsConnected());
+                         EXPECT_EQ(nullptr, io_buffer);
+                       } else {
+                         EXPECT_TRUE(socket->IsConnected());
+                       }
+                       run_loop.Quit();
+                     }));
+    run_loop.Run();
+    if (net_error < 0)
+      break;
   }
-
-  for (i = 0; i < 5; i++) {
-    callback.Run(128 + i * 50);
-  }
+  // Note that TCPSocket only detects that receive pipe is broken and propagates
+  // it as a net::ERR_FAILED. It doesn't know the specific net error code. To do
+  // that, it needs to register itself as a network::mojom::SocketObserver.
+  EXPECT_EQ(net::ERR_FAILED, net_error);
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
 }
 
-TEST(SocketTest, TestTCPSocketSetNoDelay) {
-  net::AddressList address_list;
-  std::unique_ptr<MockTCPSocket> tcp_client_socket(
-      new MockTCPSocket(address_list));
+TEST_P(TCPSocketUnitTest, Write) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(io_mode, kTestMsg, kTestMsgLength)};
 
-  bool no_delay = false;
+  net::StaticSocketDataProvider data_provider(kReads, kWrites);
+
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  net::TestCompletionCallback write_callback;
+  socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback());
+  EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult());
+}
+
+// Tests the case where a message is split over two separate socket writes.
+TEST_P(TCPSocketUnitTest, MultipleWrite) {
+  const char kFirstHalfTestMsg[] = "abcde";
+  const char kSecondHalfTestMsg[] = "fghij";
+  EXPECT_EQ(kTestMsg, std::string(kFirstHalfTestMsg) + kSecondHalfTestMsg);
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(io_mode, kFirstHalfTestMsg, strlen(kFirstHalfTestMsg)),
+      net::MockWrite(io_mode, kSecondHalfTestMsg, strlen(kSecondHalfTestMsg))};
+
+  net::StaticSocketDataProvider data_provider(kReads, kWrites);
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+  int num_bytes_written = 0;
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>(
+      io_buffer.get(), kTestMsgLength);
+  while (num_bytes_written < kTestMsgLength) {
+    net::TestCompletionCallback write_callback;
+    socket->Write(drainable_io_buffer.get(), kTestMsgLength - num_bytes_written,
+                  write_callback.callback());
+    int result = write_callback.WaitForResult();
+    ASSERT_GT(result, net::OK);
+    drainable_io_buffer->DidConsume(result);
+    num_bytes_written += result;
+    // Flushes the write.
+    base::RunLoop().RunUntilIdle();
+  }
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
+
+TEST_P(TCPSocketUnitTest, PartialWrite) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(io_mode, "a", 1), net::MockWrite(io_mode, "bc", 2),
+      net::MockWrite(io_mode, "defg", 4), net::MockWrite(io_mode, "hij", 3)};
+
+  net::StaticSocketDataProvider data_provider(kReads, kWrites);
+
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+  // Start with writing one byte, and double that in the next iteration.
+  int num_bytes_to_write = 1;
+  int num_bytes_written = 0;
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>(
+      io_buffer.get(), kTestMsgLength);
+  while (num_bytes_written < kTestMsgLength) {
+    net::TestCompletionCallback write_callback;
+    socket->Write(
+        drainable_io_buffer.get(),
+        std::max(kTestMsgLength - num_bytes_written, num_bytes_to_write),
+        write_callback.callback());
+    int result = write_callback.WaitForResult();
+    ASSERT_GT(result, net::OK);
+    drainable_io_buffer->DidConsume(result);
+    num_bytes_written += result;
+    num_bytes_to_write *= 2;
+    // Flushes the write.
+    base::RunLoop().RunUntilIdle();
+  }
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
+
+TEST_P(TCPSocketUnitTest, WriteError) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(io_mode, net::ERR_INSUFFICIENT_RESOURCES)};
+
+  net::StaticSocketDataProvider data_provider(kReads, kWrites);
+
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+  // Mojo data pipe might buffer some write data, so continue writing until the
+  // write error is received.
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  int net_error = net::OK;
+  while (true) {
+    base::RunLoop run_loop;
+    socket->Write(io_buffer.get(), kTestMsgLength,
+                  base::BindLambdaForTesting([&](int result) {
+                    EXPECT_EQ(result > 0, socket->IsConnected());
+                    net_error = result;
+                    run_loop.Quit();
+                  }));
+    run_loop.Run();
+    if (net_error <= 0)
+      break;
+  }
+  // Note that TCPSocket only detects that send pipe is broken and propagates
+  // it as a net::ERR_FAILED. It doesn't know the specific net error code. To do
+  // that, it needs to register itself as a network::mojom::SocketObserver.
+  EXPECT_EQ(net::ERR_FAILED, net_error);
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
+
+namespace {
+
+class ExtensionsMockClientSocket : public net::MockTCPClientSocket {
+ public:
+  ExtensionsMockClientSocket(net::SocketDataProvider* provider, bool success)
+      : MockTCPClientSocket(
+            net::AddressList(
+                net::IPEndPoint(net::IPAddress::IPv4Localhost(), 1234)),
+            nullptr /* netlog */,
+            provider),
+        success_(success) {
+    this->set_enable_read_if_ready(true);
+  }
+  ~ExtensionsMockClientSocket() override {}
+
+  bool SetNoDelay(bool no_delay) override { return success_; }
+  bool SetKeepAlive(bool enable, int delay) override { return success_; }
+
+ private:
+  // Whether to return success for SetNoDelay() and SetKeepAlive().
+  const bool success_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionsMockClientSocket);
+};
+
+static const net::MockRead kMockReads[] = {net::MockRead(net::ASYNC, net::OK)};
+
+// A ClientSocketFactory to create sockets that simulate SetNoDelay and
+// SetKeepAlive success and failures.
+class TestSocketFactory : public net::ClientSocketFactory {
+ public:
+  explicit TestSocketFactory(bool success) : success_(success) {}
+  ~TestSocketFactory() override = default;
+
+  std::unique_ptr<net::DatagramClientSocket> CreateDatagramClientSocket(
+      net::DatagramSocket::BindType,
+      net::NetLog*,
+      const net::NetLogSource&) override {
+    NOTIMPLEMENTED();
+    return nullptr;
+  }
+  std::unique_ptr<net::TransportClientSocket> CreateTransportClientSocket(
+      const net::AddressList&,
+      std::unique_ptr<net::SocketPerformanceWatcher>,
+      net::NetLog*,
+      const net::NetLogSource&) override {
+    providers_.push_back(std::make_unique<net::StaticSocketDataProvider>(
+        kMockReads, base::span<net::MockWrite>()));
+    return std::make_unique<ExtensionsMockClientSocket>(providers_.back().get(),
+                                                        success_);
+  }
+  std::unique_ptr<net::SSLClientSocket> CreateSSLClientSocket(
+      std::unique_ptr<net::ClientSocketHandle>,
+      const net::HostPortPair&,
+      const net::SSLConfig&,
+      const net::SSLClientSocketContext&) override {
+    NOTIMPLEMENTED();
+    return std::unique_ptr<net::SSLClientSocket>();
+  }
+  std::unique_ptr<net::ProxyClientSocket> CreateProxyClientSocket(
+      std::unique_ptr<net::ClientSocketHandle> transport_socket,
+      const std::string& user_agent,
+      const net::HostPortPair& endpoint,
+      net::HttpAuthController* http_auth_controller,
+      bool tunnel,
+      bool using_spdy,
+      net::NextProto negotiated_protocol,
+      bool is_https_proxy,
+      const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
+    NOTIMPLEMENTED();
+    return nullptr;
+  }
+  void ClearSSLSessionCache() override { NOTIMPLEMENTED(); }
+
+ private:
+  std::vector<std::unique_ptr<net::StaticSocketDataProvider>> providers_;
+  // Whether to return success for net::TransportClientSocket::SetNoDelay() and
+  // SetKeepAlive().
+  const bool success_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestSocketFactory);
+};
+
+}  // namespace
+
+class TCPSocketSettingsTest : public TCPSocketUnitTestBase,
+                              public ::testing::WithParamInterface<bool> {
+ public:
+  TCPSocketSettingsTest()
+      : TCPSocketUnitTestBase(), client_socket_factory_(GetParam()) {
+    url_request_context_.set_client_socket_factory(&client_socket_factory_);
+    Initialize();
+  }
+  ~TCPSocketSettingsTest() override {}
+
+ private:
+  TestSocketFactory client_socket_factory_;
+};
+
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+                        TCPSocketSettingsTest,
+                        testing::Bool());
+
+TEST_P(TCPSocketSettingsTest, SetNoDelay) {
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+  bool expected_success = GetParam();
   {
-    testing::InSequence dummy;
-    EXPECT_CALL(*tcp_client_socket, SetNoDelay(_))
-        .WillOnce(testing::DoAll(SaveArg<0>(&no_delay), Return(true)));
-    EXPECT_CALL(*tcp_client_socket, SetNoDelay(_))
-        .WillOnce(testing::DoAll(SaveArg<0>(&no_delay), Return(false)));
+    base::RunLoop run_loop;
+    socket->SetNoDelay(true, base::BindLambdaForTesting([&](bool success) {
+                         EXPECT_EQ(expected_success, success);
+                         run_loop.Quit();
+                       }));
+    run_loop.Run();
   }
 
-  std::unique_ptr<TCPSocket> socket(
-      TCPSocket::CreateSocketForTesting(std::move(tcp_client_socket), FAKE_ID));
-
-  EXPECT_FALSE(no_delay);
-  int result = socket->SetNoDelay(true);
-  EXPECT_TRUE(result);
-  EXPECT_TRUE(no_delay);
-
-  result = socket->SetNoDelay(false);
-  EXPECT_FALSE(result);
-  EXPECT_FALSE(no_delay);
-}
-
-TEST(SocketTest, TestTCPSocketSetKeepAlive) {
-  net::AddressList address_list;
-  std::unique_ptr<MockTCPSocket> tcp_client_socket(
-      new MockTCPSocket(address_list));
-
-  bool enable = false;
-  int delay = 0;
   {
-    testing::InSequence dummy;
-    EXPECT_CALL(*tcp_client_socket, SetKeepAlive(_, _))
-        .WillOnce(testing::DoAll(SaveArg<0>(&enable), SaveArg<1>(&delay),
-                                 Return(true)));
-    EXPECT_CALL(*tcp_client_socket, SetKeepAlive(_, _))
-        .WillOnce(testing::DoAll(SaveArg<0>(&enable), SaveArg<1>(&delay),
-                                 Return(false)));
+    base::RunLoop run_loop;
+    socket->SetNoDelay(false, base::BindLambdaForTesting([&](bool success) {
+                         EXPECT_EQ(expected_success, success);
+                         run_loop.Quit();
+                       }));
+    run_loop.Run();
   }
-
-  std::unique_ptr<TCPSocket> socket(
-      TCPSocket::CreateSocketForTesting(std::move(tcp_client_socket), FAKE_ID));
-
-  EXPECT_FALSE(enable);
-  int result = socket->SetKeepAlive(true, 4500);
-  EXPECT_TRUE(result);
-  EXPECT_TRUE(enable);
-  EXPECT_EQ(4500, delay);
-
-  result = socket->SetKeepAlive(false, 0);
-  EXPECT_FALSE(result);
-  EXPECT_FALSE(enable);
-  EXPECT_EQ(0, delay);
 }
 
-TEST(SocketTest, TestTCPServerSocketListenAccept) {
-  std::unique_ptr<MockTCPServerSocket> tcp_server_socket(
-      new MockTCPServerSocket());
-  CompleteHandler handler;
+TEST_P(TCPSocketSettingsTest, SetKeepAlive) {
+  std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+  bool expected_success = GetParam();
+  {
+    base::RunLoop run_loop;
+    socket->SetKeepAlive(true /* enable */, 123 /* delay */,
+                         base::BindLambdaForTesting([&](bool success) {
+                           EXPECT_EQ(expected_success, success);
+                           run_loop.Quit();
+                         }));
+    run_loop.Run();
+  }
 
-  EXPECT_CALL(*tcp_server_socket, Accept(_, _)).Times(1);
-  EXPECT_CALL(*tcp_server_socket, Listen(_, _)).Times(1);
+  {
+    base::RunLoop run_loop;
+    socket->SetKeepAlive(false /* enable */, 123 /* delay */,
+                         base::BindLambdaForTesting([&](bool success) {
+                           EXPECT_EQ(expected_success, success);
+                           run_loop.Quit();
+                         }));
+    run_loop.Run();
+  }
+}
 
-  std::unique_ptr<TCPSocket> socket(TCPSocket::CreateServerSocketForTesting(
-      std::move(tcp_server_socket), FAKE_ID));
+class TCPSocketServerTest : public TCPSocketUnitTestBase {
+ public:
+  TCPSocketServerTest() : TCPSocketUnitTestBase() { Initialize(); }
+  ~TCPSocketServerTest() override {}
 
-  EXPECT_CALL(handler, OnAcceptMock(_, _));
+ private:
+  net::MockClientSocketFactory mock_client_socket_factory_;
+};
 
-  std::string err_msg;
-  EXPECT_EQ(net::OK, socket->Listen("127.0.0.1", 9999, 10, &err_msg));
-  socket->Accept(base::Bind(&CompleteHandler::OnAccept,
-        base::Unretained(&handler)));
+TEST_F(TCPSocketServerTest, ListenAccept) {
+  // Create a server socket.
+  std::unique_ptr<TCPSocket> socket = CreateSocket();
+  net::TestCompletionCallback callback;
+  base::RunLoop run_loop;
+  socket->Listen(
+      "127.0.0.1", 0 /* port */, 1 /* backlog */,
+      base::BindLambdaForTesting([&](int result, const std::string& error_msg) {
+        EXPECT_EQ(net::OK, result);
+        run_loop.Quit();
+      }));
+  run_loop.Run();
+  net::IPEndPoint server_addr;
+  EXPECT_TRUE(socket->GetLocalAddress(&server_addr));
+
+  base::RunLoop accept_run_loop;
+  net::IPEndPoint accept_client_addr;
+  socket->Accept(base::BindLambdaForTesting(
+      [&](int result, network::mojom::TCPConnectedSocketPtr accepted_socket,
+          const base::Optional<net::IPEndPoint>& remote_addr,
+          mojo::ScopedDataPipeConsumerHandle receive_handle,
+          mojo::ScopedDataPipeProducerHandle send_handle) {
+        EXPECT_EQ(net::OK, result);
+        accept_client_addr = remote_addr.value();
+        accept_run_loop.Quit();
+      }));
+
+  // Create a client socket to talk to the server socket.
+  auto client_socket = CreateAndConnectSocketWithAddress(server_addr);
+  accept_run_loop.Run();
+
+  net::IPEndPoint peer_addr;
+  EXPECT_TRUE(client_socket->GetPeerAddress(&peer_addr));
+  net::IPEndPoint client_addr;
+  EXPECT_TRUE(client_socket->GetLocalAddress(&client_addr));
+  EXPECT_EQ(server_addr, peer_addr);
+  EXPECT_EQ(client_addr, accept_client_addr);
+}
+
+TEST_F(TCPSocketServerTest, ReadAndWrite) {
+  // Create a server socket.
+  std::unique_ptr<TCPSocket> socket = CreateSocket();
+  net::TestCompletionCallback callback;
+  base::RunLoop run_loop;
+  socket->Listen(
+      "127.0.0.1", 0 /* port */, 1 /* backlog */,
+      base::BindLambdaForTesting([&](int result, const std::string& error_msg) {
+        EXPECT_EQ(net::OK, result);
+        run_loop.Quit();
+      }));
+  run_loop.Run();
+  net::IPEndPoint server_addr;
+  EXPECT_TRUE(socket->GetLocalAddress(&server_addr));
+
+  base::RunLoop accept_run_loop;
+  std::unique_ptr<TCPSocket> accepted_socket;
+
+  socket->Accept(base::BindLambdaForTesting(
+      [&](int result, network::mojom::TCPConnectedSocketPtr connected_socket,
+          const base::Optional<net::IPEndPoint>& remote_addr,
+          mojo::ScopedDataPipeConsumerHandle receive_handle,
+          mojo::ScopedDataPipeProducerHandle send_handle) {
+        EXPECT_EQ(net::OK, result);
+        accepted_socket = std::make_unique<TCPSocket>(
+            std::move(connected_socket), std::move(receive_handle),
+            std::move(send_handle), remote_addr, FAKE_ID);
+        accept_run_loop.Quit();
+      }));
+
+  // Create a client socket to talk to the server socket.
+  auto client_socket = CreateAndConnectSocketWithAddress(server_addr);
+  net::TestCompletionCallback connect_callback;
+  accept_run_loop.Run();
+
+  // Send data from the client to the server.
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  net::TestCompletionCallback write_callback;
+  client_socket->Write(io_buffer.get(), kTestMsgLength,
+                       write_callback.callback());
+  EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult());
+
+  std::string received_contents;
+  while (received_contents.size() < kTestMsgLength) {
+    base::RunLoop run_loop;
+    accepted_socket->Read(
+        kTestMsgLength,
+        base::BindLambdaForTesting([&](int result,
+                                       scoped_refptr<net::IOBuffer> io_buffer,
+                                       bool socket_destroying) {
+          ASSERT_GT(result, 0);
+          EXPECT_FALSE(socket_destroying);
+          received_contents.append(std::string(io_buffer->data(), result));
+          run_loop.Quit();
+        }));
+    run_loop.Run();
+  }
+  EXPECT_EQ(kTestMsg, received_contents);
+
+  // Send data from the server to the client.
+  net::TestCompletionCallback write_callback2;
+  accepted_socket->Write(io_buffer.get(), kTestMsgLength,
+                         write_callback2.callback());
+  EXPECT_EQ(kTestMsgLength, write_callback2.WaitForResult());
+
+  std::string sent_contents;
+  while (sent_contents.size() < kTestMsgLength) {
+    base::RunLoop run_loop;
+    client_socket->Read(
+        kTestMsgLength,
+        base::BindLambdaForTesting([&](int result,
+                                       scoped_refptr<net::IOBuffer> io_buffer,
+                                       bool socket_destroying) {
+          ASSERT_GT(result, 0);
+          EXPECT_FALSE(socket_destroying);
+          sent_contents.append(std::string(io_buffer->data(), result));
+          run_loop.Quit();
+        }));
+    run_loop.Run();
+  }
+  EXPECT_EQ(kTestMsg, sent_contents);
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/socket/tls_socket_unittest.cc b/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
index 678b630..5e25fcf0 100644
--- a/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
+++ b/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
@@ -2,372 +2,482 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <stddef.h>
-#include <stdint.h>
-
 #include <memory>
 #include <utility>
 
-#include "base/callback_helpers.h"
-#include "base/containers/circular_deque.h"
 #include "base/macros.h"
-#include "base/strings/string_piece.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/extensions/extension_service_test_base.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/test/test_storage_partition.h"
 #include "extensions/browser/api/socket/tls_socket.h"
 #include "net/base/address_list.h"
 #include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
-#include "net/log/net_log_source.h"
-#include "net/log/net_log_with_source.h"
-#include "net/socket/next_proto.h"
-#include "net/socket/socket_tag.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-using testing::_;
-using testing::DoAll;
-using testing::Invoke;
-using testing::Gt;
-using testing::Return;
-using testing::SaveArg;
-using testing::WithArgs;
-using base::StringPiece;
+#include "net/base/test_completion_callback.h"
+#include "net/socket/socket_test_util.h"
+#include "net/url_request/url_request_test_util.h"
+#include "services/network/network_context.h"
+#include "services/network/public/mojom/network_context.mojom.h"
 
 namespace extensions {
 
-class MockSSLClientSocket : public net::SSLClientSocket {
+namespace {
+
+const char kTestMsg[] = "abcdefghij";
+const int kTestMsgLength = strlen(kTestMsg);
+
+const char FAKE_ID[] = "abcdefghijklmnopqrst";
+
+class TLSSocketTestBase : public extensions::ExtensionServiceTestBase {
  public:
-  MockSSLClientSocket() {}
-  int Read(net::IOBuffer* buffer,
-           int bytes,
-           net::CompletionOnceCallback callback) override {
-    return Read(buffer, bytes,
-                base::AdaptCallbackForRepeating(std::move(callback)));
+  TLSSocketTestBase() : url_request_context_(true) {}
+  ~TLSSocketTestBase() override {}
+
+  // Creates a TCP socket.
+  std::unique_ptr<TCPSocket> CreateTCPSocket() {
+    auto socket = std::make_unique<TCPSocket>(&profile_, FAKE_ID);
+    socket->SetStoragePartitionForTest(&partition_);
+    net::TestCompletionCallback connect_callback;
+    net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), kPort);
+    socket->Connect(net::AddressList(ip_end_point),
+                    connect_callback.callback());
+    if (net::OK != connect_callback.WaitForResult()) {
+      return nullptr;
+    }
+    return socket;
   }
 
-  int Write(net::IOBuffer* buffer,
-            int bytes,
-            net::CompletionOnceCallback callback,
-            const net::NetworkTrafficAnnotationTag& tag) override {
-    return Write(buffer, bytes,
-                 base::AdaptCallbackForRepeating(std::move(callback)), tag);
+  // Create a TCP socket and upgrade it to TLS.
+  std::unique_ptr<TLSSocket> CreateSocket() {
+    auto socket = CreateTCPSocket();
+    if (!socket)
+      return nullptr;
+    base::RunLoop run_loop;
+    net::HostPortPair host_port_pair("example.com", kPort);
+    net::IPEndPoint local_addr;
+    net::IPEndPoint peer_addr;
+    if (!socket->GetLocalAddress(&local_addr) ||
+        !socket->GetPeerAddress(&peer_addr)) {
+      return nullptr;
+    }
+    std::unique_ptr<TLSSocket> tls_socket;
+    socket->UpgradeToTLS(
+        nullptr /* options */,
+        base::BindLambdaForTesting(
+            [&](int result, network::mojom::TLSClientSocketPtr tls_socket_ptr,
+                const net::IPEndPoint& local_addr,
+                const net::IPEndPoint& peer_addr,
+                mojo::ScopedDataPipeConsumerHandle receive_handle,
+                mojo::ScopedDataPipeProducerHandle send_handle) {
+              if (net::OK == result) {
+                tls_socket = std::make_unique<TLSSocket>(
+                    std::move(tls_socket_ptr), local_addr, peer_addr,
+                    std::move(receive_handle), std::move(send_handle), FAKE_ID);
+              }
+              run_loop.Quit();
+            }));
+    run_loop.Run();
+    return tls_socket;
   }
 
-  int Connect(net::CompletionOnceCallback callback) override {
-    return Connect(base::AdaptCallbackForRepeating(std::move(callback)));
-  }
-
-  MOCK_METHOD0(Disconnect, void());
-  MOCK_METHOD3(Read,
-               int(net::IOBuffer* buf,
-                   int buf_len,
-                   const net::CompletionCallback& callback));
-  MOCK_METHOD4(Write,
-               int(net::IOBuffer* buf,
-                   int buf_len,
-                   const net::CompletionCallback& callback,
-                   const net::NetworkTrafficAnnotationTag&));
-  MOCK_METHOD1(SetReceiveBufferSize, int(int32_t));
-  MOCK_METHOD1(SetSendBufferSize, int(int32_t));
-  MOCK_METHOD1(Connect, int(const CompletionCallback&));
-  MOCK_CONST_METHOD0(IsConnectedAndIdle, bool());
-  MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*));
-  MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*));
-  MOCK_CONST_METHOD0(NetLog, const net::NetLogWithSource&());
-  MOCK_CONST_METHOD0(WasEverUsed, bool());
-  MOCK_CONST_METHOD0(UsingTCPFastOpen, bool());
-  MOCK_CONST_METHOD0(WasAlpnNegotiated, bool());
-  MOCK_CONST_METHOD0(GetNegotiatedProtocol, net::NextProto());
-  MOCK_METHOD1(GetSSLInfo, bool(net::SSLInfo*));
-  MOCK_CONST_METHOD1(GetConnectionAttempts, void(net::ConnectionAttempts*));
-  MOCK_METHOD0(ClearConnectionAttempts, void());
-  MOCK_METHOD1(AddConnectionAttempts, void(const net::ConnectionAttempts&));
-  MOCK_CONST_METHOD0(GetTotalReceivedBytes, int64_t());
-  MOCK_METHOD1(ApplySocketTag, void(const net::SocketTag&));
-  MOCK_METHOD5(ExportKeyingMaterial,
-               int(const StringPiece&,
-                   bool,
-                   const StringPiece&,
-                   unsigned char*,
-                   unsigned int));
-  MOCK_CONST_METHOD1(GetSSLCertRequestInfo, void(net::SSLCertRequestInfo*));
-  MOCK_CONST_METHOD0(GetUnverifiedServerCertificateChain,
-                     scoped_refptr<net::X509Certificate>());
-  MOCK_CONST_METHOD0(GetChannelIDService, net::ChannelIDService*());
-  MOCK_METHOD3(GetTokenBindingSignature,
-               net::Error(crypto::ECPrivateKey*,
-                          net::TokenBindingType,
-                          std::vector<uint8_t>*));
-  MOCK_CONST_METHOD0(GetChannelIDKey, crypto::ECPrivateKey*());
-  bool IsConnected() const override { return true; }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockSSLClientSocket);
-};
-
-class MockTCPSocket : public net::TCPClientSocket {
- public:
-  explicit MockTCPSocket(const net::AddressList& address_list)
-      : net::TCPClientSocket(address_list, NULL, NULL, net::NetLogSource()) {}
-
-  int Read(net::IOBuffer* buffer,
-           int bytes,
-           net::CompletionOnceCallback callback) override {
-    return Read(buffer, bytes,
-                base::AdaptCallbackForRepeating(std::move(callback)));
-  }
-
-  int Write(net::IOBuffer* buffer,
-            int bytes,
-            net::CompletionOnceCallback callback,
-            const net::NetworkTrafficAnnotationTag& tag) override {
-    return Write(buffer, bytes,
-                 base::AdaptCallbackForRepeating(std::move(callback)), tag);
-  }
-
-  MOCK_METHOD3(Read,
-               int(net::IOBuffer* buf,
-                   int buf_len,
-                   const net::CompletionCallback& callback));
-  MOCK_METHOD4(Write,
-               int(net::IOBuffer* buf,
-                   int buf_len,
-                   const net::CompletionCallback& callback,
-                   const net::NetworkTrafficAnnotationTag&));
-  MOCK_METHOD2(SetKeepAlive, bool(bool enable, int delay));
-  MOCK_METHOD1(SetNoDelay, bool(bool no_delay));
-
-  bool IsConnected() const override { return true; }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockTCPSocket);
-};
-
-class CompleteHandler {
- public:
-  CompleteHandler() {}
-  MOCK_METHOD1(OnComplete, void(int result_code));
-  MOCK_METHOD3(OnReadComplete,
-               void(int result_code,
-                    scoped_refptr<net::IOBuffer> io_buffer,
-                    bool socket_destroying));
-  MOCK_METHOD2(OnAccept, void(int, net::TCPClientSocket*));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CompleteHandler);
-};
-
-class TLSSocketTest : public ::testing::Test {
- public:
-  TLSSocketTest() {}
-
-  void SetUp() override {
-    net::AddressList address_list;
-    // |ssl_socket_| is owned by |socket_|. TLSSocketTest keeps a pointer to
-    // it to expect invocations from TLSSocket to |ssl_socket_|.
-    std::unique_ptr<MockSSLClientSocket> ssl_sock(new MockSSLClientSocket);
-    ssl_socket_ = ssl_sock.get();
-    socket_.reset(new TLSSocket(std::move(ssl_sock), "test_extension_id"));
-    EXPECT_CALL(*ssl_socket_, Disconnect()).Times(1);
-  };
-
-  void TearDown() override {
-    ssl_socket_ = NULL;
-    socket_.reset();
-  };
-
  protected:
-  MockSSLClientSocket* ssl_socket_;
-  std::unique_ptr<TLSSocket> socket_;
+  // extensions::ExtensionServiceTestBase implementation.
+  void SetUp() override { InitializeEmptyExtensionService(); }
+
+  void Initialize() {
+    url_request_context_.Init();
+    network_context_ = std::make_unique<network::NetworkContext>(
+        nullptr, mojo::MakeRequest(&network_context_ptr_),
+        &url_request_context_);
+    partition_.set_network_context(network_context_ptr_.get());
+  }
+
+  net::TestURLRequestContext url_request_context_;
+
+ private:
+  static const int kPort = 1234;
+  TestingProfile profile_;
+  content::TestStoragePartition partition_;
+  std::unique_ptr<network::NetworkContext> network_context_;
+  network::mojom::NetworkContextPtr network_context_ptr_;
 };
 
-// Verify that a Read() on TLSSocket will pass through into a Read() on
-// |ssl_socket_| and invoke its completion callback.
-TEST_F(TLSSocketTest, TestTLSSocketRead) {
-  CompleteHandler handler;
+}  // namespace
 
-  EXPECT_CALL(*ssl_socket_, Read(_, _, _)).Times(1);
-  EXPECT_CALL(handler, OnReadComplete(_, _, _)).Times(1);
+class TLSSocketTest : public TLSSocketTestBase,
+                      public ::testing::WithParamInterface<net::IoMode> {
+ public:
+  TLSSocketTest() : TLSSocketTestBase() {
+    mock_client_socket_factory_.set_enable_read_if_ready(true);
+    url_request_context_.set_client_socket_factory(
+        &mock_client_socket_factory_);
+    Initialize();
+  }
+  ~TLSSocketTest() override {}
+
+  net::MockClientSocketFactory* mock_client_socket_factory() {
+    return &mock_client_socket_factory_;
+  }
+
+ private:
+  net::MockClientSocketFactory mock_client_socket_factory_;
+};
+
+TEST_F(TLSSocketTest, DestroyWhileReadPending) {
+  const net::MockRead kReads[] = {net::MockRead(net::SYNCHRONOUS, net::OK, 1)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(net::ASYNC, kTestMsg, kTestMsgLength, 0)};
+  net::StaticSocketDataProvider data_provider(kReads, kWrites);
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
+  mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+
+  std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+  int net_result = net::ERR_FAILED;
+  base::RunLoop run_loop;
+  int count = 1;
+  // Read one byte, and it should be pending because it is blocked on the mock
+  // write.
+  socket->Read(count,
+               base::BindLambdaForTesting(
+                   [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+                       bool socket_destroying) {
+                     net_result = result;
+                     // |socket_destroying| should correctly denote that this
+                     // read callback is invoked through the destructor of
+                     // TLSSocket.
+                     EXPECT_TRUE(socket_destroying);
+                     run_loop.Quit();
+                   }));
+  // Destroy socket.
+  socket = nullptr;
+  // Wait for read callback.
+  run_loop.Run();
+  EXPECT_EQ(net::ERR_CONNECTION_CLOSED, net_result);
+}
+
+// UpgradeToTLS() fails when there is a pending read.
+TEST_F(TLSSocketTest, UpgradeToTLSWhilePendingRead) {
+  const net::MockRead kReads[] = {
+      net::MockRead(net::ASYNC, net::ERR_IO_PENDING)};
+  net::StaticSocketDataProvider data_provider(kReads,
+                                              base::span<net::MockWrite>());
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  auto socket = CreateTCPSocket();
+  // This read will be pending when UpgradeToTLS() is called.
+  socket->Read(1 /* count */, base::DoNothing());
+  network::mojom::TLSClientSocketPtr tls_socket_ptr;
+  base::RunLoop run_loop;
+  socket->UpgradeToTLS(
+      nullptr /* options */,
+      base::BindLambdaForTesting(
+          [&](int result, network::mojom::TLSClientSocketPtr tls_socket_ptr,
+              const net::IPEndPoint& local_addr,
+              const net::IPEndPoint& peer_addr,
+              mojo::ScopedDataPipeConsumerHandle receive_handle,
+              mojo::ScopedDataPipeProducerHandle send_handle) {
+            EXPECT_EQ(net::ERR_FAILED, result);
+            run_loop.Quit();
+          }));
+  run_loop.Run();
+}
+
+TEST_F(TLSSocketTest, UpgradeToTLSWithCustomOptions) {
+  // Mock data are not consumed. These are here so that net::StreamSocket::Read
+  // is always pending and blocked on the write. Otherwise, mock socket data
+  // will complains that there aren't any data to read.
+  const net::MockRead kReads[] = {
+      net::MockRead(net::ASYNC, kTestMsg, kTestMsgLength, 1),
+      net::MockRead(net::ASYNC, net::OK, 2)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(net::ASYNC, kTestMsg, kTestMsgLength, 0)};
+  net::SequencedSocketData data_provider(kReads, kWrites);
+  net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
+  ssl_socket.expected_ssl_version_min = net::SSL_PROTOCOL_VERSION_TLS1_1;
+  ssl_socket.expected_ssl_version_max = net::SSL_PROTOCOL_VERSION_TLS1_2;
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+
+  auto socket = CreateTCPSocket();
+  network::mojom::TLSClientSocketPtr tls_socket_ptr;
+  api::socket::SecureOptions options;
+  options.tls_version = std::make_unique<api::socket::TLSVersionConstraints>();
+  options.tls_version->min = std::make_unique<std::string>("tls1.1");
+  options.tls_version->max = std::make_unique<std::string>("tls1.2");
+  int net_error = net::ERR_FAILED;
+  base::RunLoop run_loop;
+  socket->UpgradeToTLS(
+      &options,
+      base::BindLambdaForTesting(
+          [&](int result, network::mojom::TLSClientSocketPtr tls_socket_ptr,
+              const net::IPEndPoint& local_addr,
+              const net::IPEndPoint& peer_addr,
+              mojo::ScopedDataPipeConsumerHandle receive_handle,
+              mojo::ScopedDataPipeProducerHandle send_handle) {
+            net_error = result;
+            run_loop.Quit();
+          }));
+  run_loop.Run();
+  EXPECT_EQ(net::OK, net_error);
+  EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
+}
+
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+                        TLSSocketTest,
+                        testing::Values(net::SYNCHRONOUS, net::ASYNC));
+
+TEST_P(TLSSocketTest, ReadWrite) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(net::ASYNC, kTestMsg, kTestMsgLength, 1),
+      net::MockRead(io_mode, net::OK, 2)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(net::SYNCHRONOUS, kTestMsg, kTestMsgLength, 0)};
+  net::SequencedSocketData data_provider(kReads, kWrites);
+  net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
+
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+  std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  net::TestCompletionCallback write_callback;
+  socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback());
+  EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult());
+
+  std::string received_data;
+  int count = 512;
+  while (true) {
+    base::RunLoop run_loop;
+    int net_error = net::ERR_FAILED;
+    socket->Read(count,
+                 base::BindLambdaForTesting(
+                     [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+                         bool socket_destroying) {
+                       net_error = result;
+                       EXPECT_FALSE(socket_destroying);
+                       if (result > 0)
+                         received_data.append(io_buffer->data(), result);
+                       run_loop.Quit();
+                     }));
+    run_loop.Run();
+    if (net_error <= 0)
+      break;
+  }
+  EXPECT_EQ(kTestMsg, received_data);
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+  EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
+}
+
+// Tests the case where read size is smaller than the actual message.
+TEST_P(TLSSocketTest, PartialRead) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(net::ASYNC, kTestMsg, kTestMsgLength, 1),
+      net::MockRead(io_mode, net::OK, 2)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(net::SYNCHRONOUS, kTestMsg, kTestMsgLength, 0)};
+  net::SequencedSocketData data_provider(kReads, kWrites);
+  net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+  std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  net::TestCompletionCallback write_callback;
+  socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback());
+  EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult());
+
+  int count = 1;
+  std::string received_data;
+  while (true) {
+    int net_result = net::ERR_FAILED;
+    base::RunLoop run_loop;
+    socket->Read(count,
+                 base::BindLambdaForTesting(
+                     [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+                         bool socket_destroying) {
+                       net_result = result;
+                       EXPECT_FALSE(socket_destroying);
+                       if (result > 0)
+                         received_data.append(io_buffer->data(), result);
+                       run_loop.Quit();
+                     }));
+    run_loop.Run();
+    if (net_result <= 0)
+      break;
+    // Double the read size in the next iteration.
+    count *= 2;
+  }
+  EXPECT_EQ(kTestMsg, received_data);
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+  EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
+}
+
+TEST_P(TLSSocketTest, ReadError) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {
+      net::MockRead(net::ASYNC, net::ERR_INSUFFICIENT_RESOURCES, 1)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(net::SYNCHRONOUS, kTestMsg, kTestMsgLength, 0)};
+  net::SequencedSocketData data_provider(kReads, kWrites);
+  net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+
+  std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  net::TestCompletionCallback write_callback;
+  socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback());
+  EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult());
 
   const int count = 512;
-  socket_->Read(
-      count,
-      base::Bind(&CompleteHandler::OnReadComplete, base::Unretained(&handler)));
+  int net_error = net::OK;
+  while (true) {
+    base::RunLoop run_loop;
+    socket->Read(count,
+                 base::BindLambdaForTesting(
+                     [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+                         bool socket_destroying) {
+                       net_error = result;
+                       EXPECT_FALSE(socket_destroying);
+                       if (result <= 0) {
+                         EXPECT_FALSE(socket->IsConnected());
+                         EXPECT_EQ(nullptr, io_buffer);
+                       } else {
+                         EXPECT_TRUE(socket->IsConnected());
+                       }
+                       run_loop.Quit();
+                     }));
+    run_loop.Run();
+    if (net_error < 0)
+      break;
+  }
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+  EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
 }
 
-// Verify that a Write() on a TLSSocket will pass through to Write()
-// invocations on |ssl_socket_|, handling partial writes correctly, and calls
-// the completion callback correctly.
-TEST_F(TLSSocketTest, TestTLSSocketWrite) {
-  CompleteHandler handler;
-  net::CompletionCallback callback;
+// Tests the case where a message is split over two separate socket writes.
+TEST_P(TLSSocketTest, MultipleWrite) {
+  const char kFirstHalfTestMsg[] = "abcde";
+  const char kSecondHalfTestMsg[] = "fghij";
+  EXPECT_EQ(kTestMsg, std::string(kFirstHalfTestMsg) + kSecondHalfTestMsg);
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 2)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(io_mode, kFirstHalfTestMsg, strlen(kFirstHalfTestMsg), 0),
+      net::MockWrite(io_mode, kSecondHalfTestMsg, strlen(kSecondHalfTestMsg),
+                     1)};
+  net::SequencedSocketData data_provider(kReads, kWrites);
+  net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+  std::unique_ptr<TLSSocket> socket = CreateSocket();
 
-  EXPECT_CALL(*ssl_socket_, Write(_, _, _, _))
-      .Times(2)
-      .WillRepeatedly(DoAll(SaveArg<2>(&callback), Return(128)));
-  EXPECT_CALL(handler, OnComplete(_)).Times(1);
-
-  scoped_refptr<net::IOBufferWithSize> io_buffer(
-      new net::IOBufferWithSize(256));
-  socket_->Write(
-      io_buffer.get(),
-      io_buffer->size(),
-      base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler)));
+  int num_bytes_written = 0;
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>(
+      io_buffer.get(), kTestMsgLength);
+  while (num_bytes_written < kTestMsgLength) {
+    net::TestCompletionCallback write_callback;
+    socket->Write(drainable_io_buffer.get(), kTestMsgLength - num_bytes_written,
+                  write_callback.callback());
+    int result = write_callback.WaitForResult();
+    ASSERT_GT(result, net::OK);
+    drainable_io_buffer->DidConsume(result);
+    num_bytes_written += result;
+    // Flushes the write.
+    base::RunLoop().RunUntilIdle();
+  }
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+  EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
 }
 
-// Simulate a blocked Write, and verify that, when simulating the Write going
-// through, the callback gets invoked.
-TEST_F(TLSSocketTest, TestTLSSocketBlockedWrite) {
-  CompleteHandler handler;
-  net::CompletionCallback callback;
+TEST_P(TLSSocketTest, PartialWrite) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 4)};
+  const net::MockWrite kWrites[] = {net::MockWrite(io_mode, "a", 1, 0),
+                                    net::MockWrite(io_mode, "bc", 2, 1),
+                                    net::MockWrite(io_mode, "defg", 4, 2),
+                                    net::MockWrite(io_mode, "hij", 3, 3)};
 
-  // Return ERR_IO_PENDING to say the Write()'s blocked. Save the |callback|
-  // Write()'s passed.
-  EXPECT_CALL(*ssl_socket_, Write(_, _, _, _))
-      .Times(2)
-      .WillRepeatedly(
-          DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING)));
+  net::SequencedSocketData data_provider(kReads, kWrites);
+  net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
 
-  scoped_refptr<net::IOBufferWithSize> io_buffer(new net::IOBufferWithSize(42));
-  socket_->Write(
-      io_buffer.get(),
-      io_buffer->size(),
-      base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler)));
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
 
-  // After the simulated asynchronous writes come back (via calls to
-  // callback.Run()), hander's OnComplete() should get invoked with the total
-  // amount written.
-  EXPECT_CALL(handler, OnComplete(42)).Times(1);
-  callback.Run(40);
-  callback.Run(2);
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+  // Start with writing one byte, and double that in the next iteration.
+  int num_bytes_to_write = 1;
+  int num_bytes_written = 0;
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>(
+      io_buffer.get(), kTestMsgLength);
+  while (num_bytes_written < kTestMsgLength) {
+    net::TestCompletionCallback write_callback;
+    socket->Write(
+        drainable_io_buffer.get(),
+        std::max(kTestMsgLength - num_bytes_written, num_bytes_to_write),
+        write_callback.callback());
+    int result = write_callback.WaitForResult();
+    ASSERT_GT(result, net::OK);
+    drainable_io_buffer->DidConsume(result);
+    num_bytes_written += result;
+    num_bytes_to_write *= 2;
+    // Flushes the write.
+    base::RunLoop().RunUntilIdle();
+  }
+  EXPECT_TRUE(data_provider.AllReadDataConsumed());
+  EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+  EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
 }
 
-// Simulate multiple blocked Write()s.
-TEST_F(TLSSocketTest, TestTLSSocketBlockedWriteReentry) {
-  const int kNumIOs = 5;
-  CompleteHandler handlers[kNumIOs];
-  net::CompletionCallback callback;
-  scoped_refptr<net::IOBufferWithSize> io_buffers[kNumIOs];
+TEST_P(TLSSocketTest, WriteError) {
+  net::IoMode io_mode = GetParam();
+  const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 1)};
+  const net::MockWrite kWrites[] = {
+      net::MockWrite(io_mode, net::ERR_INSUFFICIENT_RESOURCES, 0)};
 
-  // The implementation of TLSSocket::Write() is inherited from
-  // Socket::Write(), which implements an internal write queue that wraps
-  // TLSSocket::WriteImpl(). Each call from TLSSocket::WriteImpl() will invoke
-  // |ssl_socket_|'s Write() (mocked here). Save the |callback| (assume they
-  // will all be equivalent), and return ERR_IO_PENDING, to indicate a blocked
-  // request. The mocked SSLClientSocket::Write() will get one request per
-  // TLSSocket::Write() request invoked on |socket_| below.
-  EXPECT_CALL(*ssl_socket_, Write(_, _, _, _))
-      .Times(kNumIOs)
-      .WillRepeatedly(
-          DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING)));
+  net::SequencedSocketData data_provider(kReads, kWrites);
+  net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
 
-  // Send out |kNuMIOs| requests, each with a different size.
-  for (int i = 0; i < kNumIOs; i++) {
-    io_buffers[i] = new net::IOBufferWithSize(128 + i * 50);
-    socket_->Write(io_buffers[i].get(),
-                   io_buffers[i]->size(),
-                   base::Bind(&CompleteHandler::OnComplete,
-                              base::Unretained(&handlers[i])));
+  mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+  mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+  std::unique_ptr<TLSSocket> socket = CreateSocket();
 
-    // Set up expectations on all |kNumIOs| handlers.
-    EXPECT_CALL(handlers[i], OnComplete(io_buffers[i]->size())).Times(1);
+  // Mojo data pipe might buffer some write data, so continue writing until the
+  // write error is received.
+  auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+  int net_error = net::OK;
+  while (true) {
+    base::RunLoop run_loop;
+    socket->Write(io_buffer.get(), kTestMsgLength,
+                  base::BindLambdaForTesting([&](int result) {
+                    if (result == net::ERR_FAILED)
+                      EXPECT_FALSE(socket->IsConnected());
+                    net_error = result;
+                    run_loop.Quit();
+                  }));
+    run_loop.Run();
+    if (net_error <= 0)
+      break;
   }
-
-  // Finish each pending I/O. This should satisfy the expectations on the
-  // handlers.
-  for (int i = 0; i < kNumIOs; i++) {
-    callback.Run(128 + i * 50);
-  }
-}
-
-typedef std::pair<net::CompletionCallback, int> PendingCallback;
-
-class CallbackList : public base::circular_deque<PendingCallback> {
- public:
-  void append(const net::CompletionCallback& cb, int arg) {
-    push_back(std::make_pair(cb, arg));
-  }
-};
-
-// Simulate Write()s above and below a SSLClientSocket size limit.
-TEST_F(TLSSocketTest, TestTLSSocketLargeWrites) {
-  const int kSizeIncrement = 4096;
-  const int kNumIncrements = 10;
-  const int kFragmentIncrement = 4;
-  const int kSizeLimit = kSizeIncrement * kFragmentIncrement;
-  net::CompletionCallback callback;
-  CompleteHandler handler;
-  scoped_refptr<net::IOBufferWithSize> io_buffers[kNumIncrements];
-  CallbackList pending_callbacks;
-  size_t total_bytes_requested = 0;
-  size_t total_bytes_written = 0;
-
-  // Some implementations of SSLClientSocket may have write-size limits (e.g,
-  // max 1 TLS record, which is 16k). This test mocks a size limit at
-  // |kSizeIncrement| and calls Write() above and below that limit. It
-  // simulates SSLClientSocket::Write() behavior in only writing up to the size
-  // limit, requiring additional calls for the remaining data to be sent.
-  // Socket::Write() (and supporting methods) execute the additional calls as
-  // needed. This test verifies that this inherited implementation does
-  // properly issue additional calls, and that the total amount returned from
-  // all mocked SSLClientSocket::Write() calls is the same as originally
-  // requested.
-
-  // |ssl_socket_|'s Write() will write at most |kSizeLimit| bytes. The
-  // inherited Socket::Write() will repeatedly call |ssl_socket_|'s Write()
-  // until the entire original request is sent. Socket::Write() will queue any
-  // additional write requests until the current request is complete. A
-  // request is complete when the callback passed to Socket::WriteImpl() is
-  // invoked with an argument equal to the original number of bytes requested
-  // from Socket::Write(). If the callback is invoked with a smaller number,
-  // Socket::WriteImpl() will get repeatedly invoked until the sum of the
-  // callbacks' arguments is equal to the original requested amount.
-  EXPECT_CALL(*ssl_socket_, Write(_, _, _, _))
-      .WillRepeatedly(DoAll(
-          WithArgs<2, 1>(Invoke(&pending_callbacks, &CallbackList::append)),
-          Return(net::ERR_IO_PENDING)));
-
-  // Observe what comes back from Socket::Write() here.
-  EXPECT_CALL(handler, OnComplete(Gt(0))).Times(kNumIncrements);
-
-  // Send out |kNumIncrements| requests, each with a different size. The
-  // last request is the same size as the first, and the ones in the middle
-  // are monotonically increasing from the first.
-  for (int i = 0; i < kNumIncrements; i++) {
-    const bool last = i == (kNumIncrements - 1);
-    io_buffers[i] = new net::IOBufferWithSize(last ? kSizeIncrement
-                                                   : kSizeIncrement * (i + 1));
-    total_bytes_requested += io_buffers[i]->size();
-
-    // Invoke Socket::Write(). This will invoke |ssl_socket_|'s Write(), which
-    // this test mocks out. That mocked Write() is in an asynchronous waiting
-    // state until the passed callback (saved in the EXPECT_CALL for
-    // |ssl_socket_|'s Write()) is invoked.
-    socket_->Write(
-        io_buffers[i].get(),
-        io_buffers[i]->size(),
-        base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler)));
-  }
-
-  // Invoke callbacks for pending I/Os. These can synchronously invoke more of
-  // |ssl_socket_|'s Write() as needed. The callback checks how much is left
-  // in the request, and then starts issuing any queued Socket::Write()
-  // invocations.
-  while (!pending_callbacks.empty()) {
-    PendingCallback cb = pending_callbacks.front();
-    pending_callbacks.pop_front();
-
-    int amount_written_invocation = std::min(kSizeLimit, cb.second);
-    total_bytes_written += amount_written_invocation;
-    cb.first.Run(amount_written_invocation);
-  }
-
-  ASSERT_EQ(total_bytes_requested, total_bytes_written)
-      << "There should be exactly as many bytes written as originally "
-      << "requested to Write().";
+  // Note that TCPSocket only detects that send pipe is broken and propagates
+  // it as a net::ERR_FAILED. It doesn't know the specific net error code. To do
+  // that, it needs to register itself as a network::mojom::SocketObserver.
+  EXPECT_EQ(net::ERR_FAILED, net_error);
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index d5fccec..09755bb5 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1134,11 +1134,19 @@
 const char kNewBookmarkAppsDescription[] =
     "Enables the new system for creating bookmark apps.";
 
-const char kNewPasswordFormParsingName[] = "New password form parsing";
+const char kNewPasswordFormParsingName[] =
+    "New password form parsing for filling passwords";
 const char kNewPasswordFormParsingDescription[] =
-    "Replaces existing form parsing in password manager with a new version, "
-    "currently under development. WARNING: when enabled Password Manager might "
-    "stop working";
+    "Replaces existing form parsing for filling in password manager with a new "
+    "version, currently under development. WARNING: when enabled, Password "
+    "Manager might stop working";
+
+const char kNewPasswordFormParsingForSavingName[] =
+    "New password form parsing for saving passwords";
+const char kNewPasswordFormParsingForSavingDescription[] =
+    "Replaces existing form parsing for saving in password manager with a new "
+    "version, currently under development. WARNING: when enabled, Password "
+    "Manager might stop working";
 
 const char kNewRemotePlaybackPipelineName[] =
     "Enable the new remote playback pipeline.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index dd9999c..3a55f66 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -711,6 +711,9 @@
 extern const char kNewPasswordFormParsingName[];
 extern const char kNewPasswordFormParsingDescription[];
 
+extern const char kNewPasswordFormParsingForSavingName[];
+extern const char kNewPasswordFormParsingForSavingDescription[];
+
 extern const char kNewRemotePlaybackPipelineName[];
 extern const char kNewRemotePlaybackPipelineDescription[];
 
diff --git a/chrome/browser/history/top_sites_factory.cc b/chrome/browser/history/top_sites_factory.cc
index 5ca3310..a8746a8 100644
--- a/chrome/browser/history/top_sites_factory.cc
+++ b/chrome/browser/history/top_sites_factory.cc
@@ -30,6 +30,7 @@
 #include "components/history/core/browser/top_sites_impl.h"
 #include "components/history/core/browser/top_sites_provider.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/ntp_tiles/constants.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -44,23 +45,22 @@
 }
 
 struct RawPrepopulatedPage {
-  int url_id;        // The resource for the page URL.
-  int title_id;      // The resource for the page title.
-  int favicon_id;    // The raw data resource for the favicon.
-  int thumbnail_id;  // The raw data resource for the thumbnail.
-  SkColor color;     // The best color to highlight the page (should roughly
-                     // match favicon).
+  int url_id;            // The resource for the page URL.
+  int title_id;          // The resource for the page title.
+  int favicon_id;        // The raw data resource for the favicon.
+  int large_favicon_id;  // The raw data resource for the larger favicon.
+  int thumbnail_id;      // The raw data resource for the thumbnail.
+  SkColor color;         // The best color to highlight the page (should
+                         // roughly match favicon).
 };
 
 #if !defined(OS_ANDROID)
 // Android does not use prepopulated pages.
 const RawPrepopulatedPage kRawPrepopulatedPages[] = {
     {
-     IDS_WEBSTORE_URL,
-     IDS_EXTENSION_WEB_STORE_TITLE,
-     IDR_WEBSTORE_ICON_16,
-     IDR_NEWTAB_WEBSTORE_THUMBNAIL,
-     SkColorSetRGB(63, 132, 197),
+        IDS_WEBSTORE_URL, IDS_EXTENSION_WEB_STORE_TITLE, IDR_WEBSTORE_ICON_16,
+        IDR_WEBSTORE_ICON_32, IDR_NEWTAB_WEBSTORE_THUMBNAIL,
+        SkColorSetRGB(63, 132, 197),
     },
 };
 #endif
@@ -74,7 +74,8 @@
     const RawPrepopulatedPage& page = kRawPrepopulatedPages[i];
     prepopulated_pages->push_back(history::PrepopulatedPage(
         GURL(l10n_util::GetStringUTF8(page.url_id)),
-        l10n_util::GetStringUTF16(page.title_id), page.favicon_id,
+        l10n_util::GetStringUTF16(page.title_id),
+        ntp_tiles::IsMDIconsEnabled() ? page.large_favicon_id : page.favicon_id,
         page.thumbnail_id, page.color));
   }
 #endif
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn
index 880e6ae4..498fae2 100644
--- a/chrome/browser/media/router/BUILD.gn
+++ b/chrome/browser/media/router/BUILD.gn
@@ -14,6 +14,7 @@
     "//components/keyed_service/core",
     "//content/public/browser",
     "//content/public/common",
+    "//crypto",
     "//net",
     "//third_party/icu",
     "//url",
@@ -93,6 +94,8 @@
       "providers/cast/cast_app_availability_tracker.h",
       "providers/cast/cast_app_discovery_service.cc",
       "providers/cast/cast_app_discovery_service.h",
+      "providers/cast/cast_internal_message_util.cc",
+      "providers/cast/cast_internal_message_util.h",
       "providers/cast/cast_media_route_provider.cc",
       "providers/cast/cast_media_route_provider.h",
       "providers/cast/cast_media_route_provider_metrics.cc",
diff --git a/chrome/browser/media/router/media_router_feature.cc b/chrome/browser/media/router/media_router_feature.cc
index 487e2f34..8f9385c 100644
--- a/chrome/browser/media/router/media_router_feature.cc
+++ b/chrome/browser/media/router/media_router_feature.cc
@@ -4,10 +4,13 @@
 
 #include "chrome/browser/media/router/media_router_feature.h"
 
+#include "base/base64.h"
 #include "base/feature_list.h"
+#include "base/strings/string_util.h"
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_context.h"
+#include "crypto/random.h"
 #include "extensions/buildflags/buildflags.h"
 #include "ui/base/ui_features.h"
 
@@ -73,6 +76,12 @@
                                 PrefRegistry::PUBLIC);
 }
 
+void RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  // TODO(imcheng): Migrate existing Media Router prefs to here.
+  registry->RegisterStringPref(prefs::kMediaRouterReceiverIdHashToken, "",
+                               PrefRegistry::PUBLIC);
+}
+
 const base::Feature kCastAllowAllIPsFeature{"CastAllowAllIPs",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
 
@@ -90,6 +99,19 @@
   return allow_all_ips;
 }
 
+std::string GetReceiverIdHashToken(PrefService* pref_service) {
+  static constexpr size_t kHashTokenSize = 64;
+  std::string token =
+      pref_service->GetString(prefs::kMediaRouterReceiverIdHashToken);
+  if (token.empty()) {
+    crypto::RandBytes(base::WriteInto(&token, kHashTokenSize + 1),
+                      kHashTokenSize);
+    base::Base64Encode(token, &token);
+    pref_service->SetString(prefs::kMediaRouterReceiverIdHashToken, token);
+  }
+  return token;
+}
+
 bool DialMediaRouteProviderEnabled() {
   return base::FeatureList::IsEnabled(kDialMediaRouteProvider);
 }
diff --git a/chrome/browser/media/router/media_router_feature.h b/chrome/browser/media/router/media_router_feature.h
index 73791ef..400912d3 100644
--- a/chrome/browser/media/router/media_router_feature.h
+++ b/chrome/browser/media/router/media_router_feature.h
@@ -25,11 +25,18 @@
 // Pref name for the enterprise policy for allowing Cast devices on all IPs.
 constexpr char kMediaRouterCastAllowAllIPs[] =
     "media_router.cast_allow_all_ips";
+// Pref name for the per-profile randomly generated token to include with the
+// hash when externalizing MediaSink IDs.
+constexpr char kMediaRouterReceiverIdHashToken[] =
+    "media_router.receiver_id_hash_token";
 }  // namespace prefs
 
 // Registers |kMediaRouterCastAllowAllIPs| with local state pref |registry|.
 void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
 
+// Registers Media Router related preferences with per-profile pref |registry|.
+void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
 // If enabled, allows Media Router to connect to Cast devices on all IP
 // addresses, not just RFC1918/RFC4913 private addresses. Workaround for
 // https://crbug.com/813974.
@@ -39,6 +46,11 @@
 // all IPs, as determined by local state |pref_service| / feature flag.
 bool GetCastAllowAllIPsPref(PrefService* pref_service);
 
+// Returns the hash token to use for externalizing MediaSink IDs from
+// |pref_service|. If the token does not exist, the token will be created from a
+// randomly generated string and stored in |pref_service|.
+std::string GetReceiverIdHashToken(PrefService* pref_service);
+
 extern const base::Feature kEnableDialSinkQuery;
 extern const base::Feature kEnableCastDiscovery;
 extern const base::Feature kCastMediaRouteProvider;
diff --git a/chrome/browser/media/router/media_router_feature_unittest.cc b/chrome/browser/media/router/media_router_feature_unittest.cc
index 16ed5b7..e61e9d4 100644
--- a/chrome/browser/media/router/media_router_feature_unittest.cc
+++ b/chrome/browser/media/router/media_router_feature_unittest.cc
@@ -30,4 +30,16 @@
   EXPECT_FALSE(GetCastAllowAllIPsPref(pref_service.get()));
 }
 
+TEST(MediaRouterFeatureTest, GetReceiverIdHashToken) {
+  auto pref_service = std::make_unique<TestingPrefServiceSimple>();
+  pref_service->registry()->RegisterStringPref(
+      prefs::kMediaRouterReceiverIdHashToken, "");
+
+  std::string token = GetReceiverIdHashToken(pref_service.get());
+  EXPECT_FALSE(token.empty());
+
+  // Token stays the same on subsequent invocation.
+  EXPECT_EQ(token, GetReceiverIdHashToken(pref_service.get()));
+}
+
 }  // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/cast_app_availability_tracker_unittest.cc b/chrome/browser/media/router/providers/cast/cast_app_availability_tracker_unittest.cc
index 591ef24..f2fd454 100644
--- a/chrome/browser/media/router/providers/cast/cast_app_availability_tracker_unittest.cc
+++ b/chrome/browser/media/router/providers/cast/cast_app_availability_tracker_unittest.cc
@@ -76,7 +76,7 @@
 
 TEST_F(CastAppAvailabilityTrackerTest, MultipleAppIdsAlreadyTrackingOne) {
   // One of the mirroring app IDs.
-  auto source1 = CastMediaSource::From("cast:0F5096E8");
+  auto source1 = CastMediaSource::From("cast:0F5096E8?clientId=123");
   ASSERT_TRUE(source1);
 
   base::flat_set<std::string> new_app_ids = {"0F5096E8"};
diff --git a/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc b/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc
new file mode 100644
index 0000000..a73dfe7
--- /dev/null
+++ b/chrome/browser/media/router/providers/cast/cast_internal_message_util.cc
@@ -0,0 +1,394 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/router/providers/cast/cast_internal_message_util.h"
+
+#include "base/base64url.h"
+#include "base/json/json_writer.h"
+#include "base/memory/ptr_util.h"
+#include "base/sha1.h"
+#include "chrome/common/media_router/discovery/media_sink_internal.h"
+#include "chrome/common/media_router/providers/cast/cast_media_source.h"
+#include "components/cast_channel/cast_socket.h"
+#include "components/cast_channel/proto/cast_channel.pb.h"
+#include "net/base/escape.h"
+
+namespace media_router {
+
+namespace {
+
+constexpr char kClientConnect[] = "client_connect";
+constexpr char kAppMessage[] = "app_message";
+constexpr char kReceiverAction[] = "receiver_action";
+constexpr char kNewSession[] = "new_session";
+
+bool GetString(const base::Value& value,
+               const std::string& key,
+               std::string* out) {
+  const base::Value* string_value =
+      value.FindKeyOfType(key, base::Value::Type::STRING);
+  if (!string_value)
+    return false;
+
+  *out = string_value->GetString();
+  return !out->empty();
+}
+
+void CopyValueWithDefault(const base::Value& from,
+                          const std::string& key,
+                          base::Value default_value,
+                          base::Value* to) {
+  const base::Value* value = from.FindKey(key);
+  to->SetKey(key, value ? value->Clone() : std::move(default_value));
+}
+
+void CopyValue(const base::Value& from,
+               const std::string& key,
+               base::Value* to) {
+  const base::Value* value = from.FindKey(key);
+  if (value)
+    to->SetKey(key, value->Clone());
+}
+
+CastInternalMessage::Type CastInternalMessageTypeFromString(
+    const std::string& type) {
+  if (type == kClientConnect)
+    return CastInternalMessage::Type::kClientConnect;
+  if (type == kAppMessage)
+    return CastInternalMessage::Type::kAppMessage;
+  if (type == kReceiverAction)
+    return CastInternalMessage::Type::kReceiverAction;
+  if (type == kNewSession)
+    return CastInternalMessage::Type::kNewSession;
+
+  return CastInternalMessage::Type::kOther;
+}
+
+std::string CastInternalMessageTypeToString(CastInternalMessage::Type type) {
+  switch (type) {
+    case CastInternalMessage::Type::kClientConnect:
+      return kClientConnect;
+    case CastInternalMessage::Type::kAppMessage:
+      return kAppMessage;
+    case CastInternalMessage::Type::kReceiverAction:
+      return kReceiverAction;
+    case CastInternalMessage::Type::kNewSession:
+      return kNewSession;
+    case CastInternalMessage::Type::kOther:
+      NOTREACHED();
+      return "";
+  }
+  NOTREACHED();
+  return "";
+}
+
+// Possible types in a receiver_action message.
+constexpr char kReceiverActionTypeCast[] = "cast";
+constexpr char kReceiverActionTypeStop[] = "stop";
+
+base::ListValue CapabilitiesToListValue(uint8_t capabilities) {
+  base::ListValue value;
+  auto& storage = value.GetList();
+  if (capabilities & cast_channel::VIDEO_OUT)
+    storage.emplace_back("video_out");
+  if (capabilities & cast_channel::VIDEO_IN)
+    storage.emplace_back("video_in");
+  if (capabilities & cast_channel::AUDIO_OUT)
+    storage.emplace_back("audio_out");
+  if (capabilities & cast_channel::AUDIO_IN)
+    storage.emplace_back("audio_in");
+  if (capabilities & cast_channel::MULTIZONE_GROUP)
+    storage.emplace_back("multizone_group");
+  return value;
+}
+
+base::Value CreateReceiver(const MediaSinkInternal& sink,
+                           const std::string& hash_token) {
+  base::Value receiver(base::Value::Type::DICTIONARY);
+
+  std::string label = base::SHA1HashString(sink.sink().id() + hash_token);
+  base::Base64UrlEncode(label, base::Base64UrlEncodePolicy::OMIT_PADDING,
+                        &label);
+  receiver.SetKey("label", base::Value(label));
+
+  receiver.SetKey("friendlyName",
+                  base::Value(net::EscapeForHTML(sink.sink().name())));
+  receiver.SetKey("capabilities",
+                  CapabilitiesToListValue(sink.cast_data().capabilities));
+  receiver.SetKey("volume", base::Value());
+  receiver.SetKey("isActiveInput", base::Value());
+  receiver.SetKey("displayStatus", base::Value());
+
+  receiver.SetKey("receiverType", base::Value("cast"));
+  return receiver;
+}
+
+base::Value CreateReceiverActionMessage(const std::string& client_id,
+                                        const MediaSinkInternal& sink,
+                                        const std::string& hash_token,
+                                        const char* action_type) {
+  base::Value message(base::Value::Type::DICTIONARY);
+  message.SetKey("receiver", CreateReceiver(sink, hash_token));
+  message.SetKey("action", base::Value(action_type));
+
+  base::Value value(base::Value::Type::DICTIONARY);
+  value.SetKey("type", base::Value(CastInternalMessageTypeToString(
+                           CastInternalMessage::Type::kReceiverAction)));
+  value.SetKey("message", std::move(message));
+  value.SetKey("sequenceNumber", base::Value(-1));
+  value.SetKey("timeoutMillis", base::Value(0));
+  value.SetKey("clientId", base::Value(client_id));
+  return value;
+}
+
+base::Value CreateAppMessageBody(
+    const std::string& session_id,
+    const cast_channel::CastMessage& cast_message) {
+  // TODO(https://crbug.com/862532): Investigate whether it is possible to move
+  // instead of copying the contents of |cast_message|. Right now copying is
+  // done because the message is passed as a const ref at the
+  // CastSocket::Observer level.
+  base::Value message(base::Value::Type::DICTIONARY);
+  message.SetKey("sessionId", base::Value(session_id));
+  message.SetKey("namespaceName", base::Value(cast_message.namespace_()));
+  switch (cast_message.payload_type()) {
+    case cast_channel::CastMessage_PayloadType_STRING:
+      message.SetKey("message", base::Value(cast_message.payload_utf8()));
+      break;
+    case cast_channel::CastMessage_PayloadType_BINARY: {
+      const auto& payload = cast_message.payload_binary();
+      message.SetKey("message",
+                     base::Value(base::Value::BlobStorage(
+                         payload.front(), payload.front() + payload.size())));
+      break;
+    }
+    default:
+      NOTREACHED();
+      break;
+  }
+  return message;
+}
+
+}  // namespace
+
+// static
+std::unique_ptr<CastInternalMessage> CastInternalMessage::From(
+    base::Value message) {
+  if (!message.is_dict()) {
+    DVLOG(2) << "Failed to read JSON message: " << message;
+    return nullptr;
+  }
+
+  std::string str_type;
+  if (!GetString(message, "type", &str_type)) {
+    DVLOG(2) << "Missing type value, message: " << message;
+    return nullptr;
+  }
+
+  CastInternalMessage::Type message_type =
+      CastInternalMessageTypeFromString(str_type);
+  if (message_type == CastInternalMessage::Type::kOther) {
+    DVLOG(2) << __func__ << ": Unsupported message type: " << str_type
+             << ", message: " << message;
+    return nullptr;
+  }
+
+  std::string client_id;
+  if (!GetString(message, "clientId", &client_id)) {
+    DVLOG(2) << "Missing clientId, message: " << message;
+    return nullptr;
+  }
+
+  base::Value* message_body_value = message.FindKey("message");
+  if (!message_body_value ||
+      (!message_body_value->is_dict() && !message_body_value->is_string())) {
+    DVLOG(2) << "Missing message body, message: " << message;
+    return nullptr;
+  }
+
+  auto internal_message =
+      std::make_unique<CastInternalMessage>(message_type, client_id);
+
+  base::Value* sequence_number_value =
+      message.FindKeyOfType("sequenceNumber", base::Value::Type::INTEGER);
+  if (sequence_number_value)
+    internal_message->sequence_number = sequence_number_value->GetInt();
+
+  if (message_type == CastInternalMessage::Type::kAppMessage) {
+    if (!message_body_value->is_dict())
+      return nullptr;
+
+    if (!GetString(*message_body_value, "namespaceName",
+                   &internal_message->app_message_namespace) ||
+        !GetString(*message_body_value, "sessionId",
+                   &internal_message->app_message_session_id)) {
+      DVLOG(2) << "Missing namespace or session ID, message: " << message;
+      return nullptr;
+    }
+
+    base::Value* app_message_value = message_body_value->FindKey("message");
+    if (!app_message_value ||
+        (!app_message_value->is_dict() && !app_message_value->is_string())) {
+      DVLOG(2) << "Missing app message, message: " << message;
+      return nullptr;
+    }
+    internal_message->app_message_body = std::move(*app_message_value);
+  }
+
+  return internal_message;
+}
+
+CastInternalMessage::CastInternalMessage(CastInternalMessage::Type type,
+                                         const std::string& client_id)
+    : type(type), client_id(client_id) {}
+
+CastInternalMessage::~CastInternalMessage() = default;
+
+blink::mojom::PresentationConnectionMessagePtr
+CreatePresentationConnectionMessage(const base::Value& message) {
+  std::string str;
+  CHECK(base::JSONWriter::Write(message, &str));
+  return blink::mojom::PresentationConnectionMessage::NewMessage(str);
+}
+
+blink::mojom::PresentationConnectionMessagePtr CreateReceiverActionCastMessage(
+    const std::string& client_id,
+    const MediaSinkInternal& sink,
+    const std::string& hash_token) {
+  return CreatePresentationConnectionMessage(CreateReceiverActionMessage(
+      client_id, sink, hash_token, kReceiverActionTypeCast));
+}
+
+blink::mojom::PresentationConnectionMessagePtr CreateReceiverActionStopMessage(
+    const std::string& client_id,
+    const MediaSinkInternal& sink,
+    const std::string& hash_token) {
+  return CreatePresentationConnectionMessage(CreateReceiverActionMessage(
+      client_id, sink, hash_token, kReceiverActionTypeStop));
+}
+
+// static
+std::unique_ptr<CastSession> CastSession::From(
+    const MediaSinkInternal& sink,
+    const std::string& hash_token,
+    const base::Value& receiver_status) {
+  // There should be only 1 app on |receiver_status|.
+  const base::Value* app_list_value =
+      receiver_status.FindKeyOfType("applications", base::Value::Type::LIST);
+  if (!app_list_value || app_list_value->GetList().size() != 1) {
+    DVLOG(2) << "receiver_status does not contain exactly one app: "
+             << receiver_status;
+    return nullptr;
+  }
+
+  auto session = std::make_unique<CastSession>();
+
+  // Fill in mandatory Session fields.
+  const base::Value& app_value = app_list_value->GetList()[0];
+  if (!GetString(app_value, "sessionId", &session->session_id) ||
+      !GetString(app_value, "appId", &session->app_id) ||
+      !GetString(app_value, "transportId", &session->transport_id) ||
+      !GetString(app_value, "displayName", &session->display_name)) {
+    DVLOG(2) << "app_value missing mandatory fields: " << app_value;
+    return nullptr;
+  }
+
+  // Optional Session fields.
+  GetString(app_value, "statusText", &session->status);
+
+  base::Value receiver_value = CreateReceiver(sink, hash_token);
+  CopyValue(receiver_status, "volume", &receiver_value);
+  CopyValue(receiver_status, "isActiveInput", &receiver_value);
+
+  // Create |session->value|.
+  session->value = base::Value(base::Value::Type::DICTIONARY);
+  auto& session_value = session->value;
+  session_value.SetKey("sessionId", base::Value(session->session_id));
+  session_value.SetKey("appId", base::Value(session->app_id));
+  session_value.SetKey("transportId", base::Value(session->transport_id));
+  session_value.SetKey("receiver", std::move(receiver_value));
+
+  CopyValueWithDefault(app_value, "displayName", base::Value(""),
+                       &session_value);
+  CopyValueWithDefault(app_value, "senderApps", base::ListValue(),
+                       &session_value);
+  CopyValueWithDefault(app_value, "statusText", base::Value(), &session_value);
+  CopyValueWithDefault(app_value, "appImages", base::ListValue(),
+                       &session_value);
+  CopyValueWithDefault(app_value, "namespaces", base::ListValue(),
+                       &session_value);
+
+  const base::Value* namespaces_value =
+      app_value.FindKeyOfType("namespaces", base::Value::Type::LIST);
+  if (!namespaces_value || namespaces_value->GetList().empty()) {
+    // A session without namespaces is invalid, except for a multizone leader.
+    if (session->app_id != kMultizoneLeaderAppId)
+      return nullptr;
+  } else {
+    for (const auto& namespace_value : namespaces_value->GetList()) {
+      std::string message_namespace;
+      if (!namespace_value.is_dict() ||
+          !GetString(namespace_value, "name", &message_namespace))
+        return nullptr;
+
+      session->message_namespaces.insert(std::move(message_namespace));
+    }
+  }
+
+  session_value.SetKey("namespaces",
+                       namespaces_value ? namespaces_value->Clone()
+                                        : base::Value(base::Value::Type::LIST));
+
+  return session;
+}
+
+CastSession::CastSession() = default;
+CastSession::~CastSession() = default;
+
+// static
+std::string CastSession::GetRouteDescription(const CastSession& session) {
+  return !session.status.empty() ? session.status : session.display_name;
+}
+
+blink::mojom::PresentationConnectionMessagePtr CreateNewSessionMessage(
+    const CastSession& session,
+    const std::string& client_id) {
+  base::Value message(base::Value::Type::DICTIONARY);
+  message.SetKey("type", base::Value(CastInternalMessageTypeToString(
+                             CastInternalMessage::Type::kNewSession)));
+  message.SetKey("message", session.value.Clone());
+  message.SetKey("sequenceNumber", base::Value(-1));
+  message.SetKey("timeoutMillis", base::Value(0));
+  message.SetKey("clientId", base::Value(client_id));
+  return CreatePresentationConnectionMessage(message);
+}
+
+blink::mojom::PresentationConnectionMessagePtr CreateAppMessageAck(
+    const std::string& client_id,
+    int sequence_number) {
+  base::Value message(base::Value::Type::DICTIONARY);
+  message.SetKey("type", base::Value(CastInternalMessageTypeToString(
+                             CastInternalMessage::Type::kAppMessage)));
+  message.SetKey("message", base::Value());
+  message.SetKey("sequenceNumber", base::Value(sequence_number));
+  message.SetKey("timeoutMillis", base::Value(0));
+  message.SetKey("clientId", base::Value(client_id));
+  return CreatePresentationConnectionMessage(message);
+}
+
+blink::mojom::PresentationConnectionMessagePtr CreateAppMessage(
+    const std::string& session_id,
+    const std::string& client_id,
+    const cast_channel::CastMessage& cast_message) {
+  base::Value message(base::Value::Type::DICTIONARY);
+  message.SetKey("type", base::Value(CastInternalMessageTypeToString(
+                             CastInternalMessage::Type::kAppMessage)));
+  message.SetKey("message", CreateAppMessageBody(session_id, cast_message));
+  message.SetKey("sequenceNumber", base::Value(-1));
+  message.SetKey("timeoutMillis", base::Value(0));
+  message.SetKey("clientId", base::Value(client_id));
+  return CreatePresentationConnectionMessage(message);
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/cast_internal_message_util.h b/chrome/browser/media/router/providers/cast/cast_internal_message_util.h
new file mode 100644
index 0000000..f1755f03
--- /dev/null
+++ b/chrome/browser/media/router/providers/cast/cast_internal_message_util.h
@@ -0,0 +1,123 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_INTERNAL_MESSAGE_UTIL_H_
+#define CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_INTERNAL_MESSAGE_UTIL_H_
+
+#include "base/containers/flat_set.h"
+#include "base/macros.h"
+#include "base/values.h"
+#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h"
+
+namespace cast_channel {
+class CastMessage;
+}
+
+namespace media_router {
+
+class MediaSinkInternal;
+
+// Represents a message sent or received by the Cast SDK via a
+// PresentationConnection.
+struct CastInternalMessage {
+  // TODO(crbug.com/809249): Add other types of messages.
+  enum class Type {
+    kClientConnect,   // Initial message sent by SDK client to connect to MRP.
+    kAppMessage,      // App messages to pass through between SDK client and the
+                      // receiver.
+    kReceiverAction,  // Message sent by MRP to inform SDK client of action.
+    kNewSession,      // Message sent by MRP to inform SDK client of new
+                      // session.
+    kOther            // All other types of messages which are not considered
+                      // part of communication with Cast SDK.
+  };
+
+  // Returns a CastInternalMessage for |message|, or nullptr is |message| is not
+  // a valid Cast internal message.
+  static std::unique_ptr<CastInternalMessage> From(base::Value message);
+
+  CastInternalMessage(Type type, const std::string& client_id);
+  ~CastInternalMessage();
+
+  Type type;
+  std::string client_id;
+  int sequence_number = -1;
+
+  // The following are set if |type| is |kAppMessage|.
+  std::string app_message_namespace;
+  std::string app_message_session_id;
+  base::Value app_message_body;
+
+  DISALLOW_COPY_AND_ASSIGN(CastInternalMessage);
+};
+
+// Represents a Cast session on a Cast device. Cast sessions are derived from
+// RECEIVER_STATUS messages sent by Cast devices.
+class CastSession {
+ public:
+  // Returns a CastSession from |receiver_status| message sent by |sink|, or
+  // nullptr if |receiver_status| is not a valid RECEIVER_STATUS message.
+  // |hash_token| is a per-profile value that is used to hash the sink ID.
+  static std::unique_ptr<CastSession> From(const MediaSinkInternal& sink,
+                                           const std::string& hash_token,
+                                           const base::Value& receiver_status);
+
+  // Returns a string that can be used as the description of the MediaRoute
+  // associated with this session.
+  static std::string GetRouteDescription(const CastSession& session);
+
+  CastSession();
+  ~CastSession();
+
+  // ID of the session.
+  std::string session_id;
+
+  // ID of the app in the session.
+  std::string app_id;
+
+  // ID used for communicating with the session over the Cast channel.
+  std::string transport_id;
+
+  // The set of accepted message namespaces. Must be non-empty, unless the
+  // session represents a multizone leader.
+  base::flat_set<std::string> message_namespaces;
+
+  // The human-readable name of the Cast application, for example, "YouTube".
+  // Mandatory.
+  std::string display_name;
+
+  // Descriptive text for the current application content, for example “My
+  // Wedding Slideshow”. May be empty.
+  std::string status;
+
+  // The dictionary representing this session, derived from |receiver_status|.
+  // For convenience, this is used for generating messages sent to the SDK that
+  // include the session value.
+  base::Value value;
+};
+
+// Utility methods for generating messages sent to the SDK.
+// |hash_token| is a per-profile value that is used to hash the sink ID.
+blink::mojom::PresentationConnectionMessagePtr CreateReceiverActionCastMessage(
+    const std::string& client_id,
+    const MediaSinkInternal& sink,
+    const std::string& hash_token);
+blink::mojom::PresentationConnectionMessagePtr CreateReceiverActionStopMessage(
+    const std::string& client_id,
+    const MediaSinkInternal& sink,
+    const std::string& hash_token);
+blink::mojom::PresentationConnectionMessagePtr CreateNewSessionMessage(
+    const CastSession& session,
+    const std::string& client_id);
+blink::mojom::PresentationConnectionMessagePtr CreateAppMessageAck(
+    const std::string& client_id,
+    int sequence_number);
+blink::mojom::PresentationConnectionMessagePtr CreateAppMessage(
+    const std::string& session_id,
+    const std::string& client_id,
+    const cast_channel::CastMessage& cast_message);
+
+}  // namespace media_router
+
+#endif  // CHROME_BROWSER_MEDIA_ROUTER_PROVIDERS_CAST_CAST_INTERNAL_MESSAGE_UTIL_H_
diff --git a/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc b/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc
new file mode 100644
index 0000000..ceed43cf
--- /dev/null
+++ b/chrome/browser/media/router/providers/cast/cast_internal_message_util_unittest.cc
@@ -0,0 +1,404 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/router/providers/cast/cast_internal_message_util.h"
+
+#include "base/json/json_reader.h"
+#include "chrome/browser/media/router/test/test_helper.h"
+#include "chrome/common/media_router/test/test_helper.h"
+#include "components/cast_channel/cast_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media_router {
+
+namespace {
+
+static constexpr char kReceiverIdToken[] = "token";
+
+std::unique_ptr<base::Value> ReceiverStatus() {
+  std::string receiver_status_str = R"({
+      "applications": [{
+        "appId": "ABCDEFGH",
+        "displayName": "App display name",
+        "namespaces": [
+          {"name": "urn:x-cast:com.google.cast.media"},
+          {"name": "urn:x-cast:com.google.foo"}
+        ],
+        "sessionId": "sessionId",
+        "statusText":"App status",
+        "transportId":"transportId"
+      }]
+  })";
+  return base::JSONReader::Read(receiver_status_str);
+}
+
+void ExpectNoCastSession(const MediaSinkInternal& sink,
+                         const std::string& receiver_status_str,
+                         const std::string& reason) {
+  auto receiver_status = base::JSONReader::Read(receiver_status_str);
+  ASSERT_TRUE(receiver_status);
+  auto session = CastSession::From(sink, kReceiverIdToken, *receiver_status);
+  EXPECT_FALSE(session) << "Shouldn't have created session because of "
+                        << reason;
+}
+
+void ExpectJSONMessagesEqual(const std::string& expected_message,
+                             const std::string& message) {
+  auto expected_message_value = base::JSONReader::Read(expected_message);
+  ASSERT_TRUE(expected_message_value);
+
+  auto message_value = base::JSONReader::Read(message);
+  ASSERT_TRUE(message_value);
+
+  EXPECT_EQ(*expected_message_value, *message_value);
+}
+
+void ExpectInvalidCastInternalMessage(const std::string& message_str,
+                                      const std::string& invalid_reason) {
+  auto message_value = base::JSONReader::Read(message_str);
+  ASSERT_TRUE(message_value);
+  EXPECT_FALSE(CastInternalMessage::From(std::move(*message_value)))
+      << "message expected to be invlaid: " << invalid_reason;
+}
+
+}  // namespace
+
+TEST(CastInternalMessageUtilTest, CastInternalMessageFromAppMessageString) {
+  std::string message_str = R"({
+    "type": "app_message",
+    "clientId": "12345",
+    "sequenceNumber": 999,
+    "message": {
+      "namespaceName": "urn:x-cast:com.google.foo",
+      "sessionId": "sessionId",
+      "message": { "foo": "bar" }
+    }
+  })";
+  auto message_value = base::JSONReader::Read(message_str);
+  ASSERT_TRUE(message_value);
+
+  auto message = CastInternalMessage::From(std::move(*message_value));
+  ASSERT_TRUE(message);
+  EXPECT_EQ(CastInternalMessage::Type::kAppMessage, message->type);
+  EXPECT_EQ("12345", message->client_id);
+  EXPECT_EQ(999, message->sequence_number);
+  EXPECT_EQ("urn:x-cast:com.google.foo", message->app_message_namespace);
+  EXPECT_EQ("sessionId", message->app_message_session_id);
+  base::Value message_body(base::Value::Type::DICTIONARY);
+  message_body.SetKey("foo", base::Value("bar"));
+  EXPECT_EQ(message_body, message->app_message_body);
+}
+
+TEST(CastInternalMessageUtilTest, CastInternalMessageFromClientConnectString) {
+  std::string message_str = R"({
+      "type": "client_connect",
+      "clientId": "12345",
+      "message": {}
+    })";
+  auto message_value = base::JSONReader::Read(message_str);
+  ASSERT_TRUE(message_value);
+
+  auto message = CastInternalMessage::From(std::move(*message_value));
+  ASSERT_TRUE(message);
+  EXPECT_EQ(CastInternalMessage::Type::kClientConnect, message->type);
+  EXPECT_EQ("12345", message->client_id);
+  EXPECT_EQ(-1, message->sequence_number);
+  EXPECT_TRUE(message->app_message_namespace.empty());
+  EXPECT_TRUE(message->app_message_session_id.empty());
+  EXPECT_EQ(base::Value(), message->app_message_body);
+}
+
+TEST(CastInternalMessageUtilTest, CastInternalMessageFromInvalidStrings) {
+  std::string unknown_type = R"({
+      "type": "some_unknown_type",
+      "clientId": "12345",
+      "message": {}
+    })";
+  ExpectInvalidCastInternalMessage(unknown_type, "unknown_type");
+
+  std::string missing_client_id = R"({
+      "type": "client_connect",
+      "message": {}
+    })";
+  ExpectInvalidCastInternalMessage(missing_client_id, "missing client ID");
+
+  std::string missing_message = R"({
+      "type": "client_connect",
+      "clientId": "12345"
+    })";
+  ExpectInvalidCastInternalMessage(missing_message, "missing message");
+
+  std::string app_message_missing_namespace = R"({
+    "type": "app_message",
+    "clientId": "12345",
+    "sequenceNumber": 999,
+    "message": {
+      "sessionId": "sessionId",
+      "message": { "foo": "bar" }
+    }
+  })";
+  ExpectInvalidCastInternalMessage(app_message_missing_namespace,
+                                   "missing namespace");
+
+  std::string app_message_missing_session_id = R"({
+    "type": "app_message",
+    "clientId": "12345",
+    "sequenceNumber": 999,
+    "message": {
+      "namespaceName": "urn:x-cast:com.google.foo",
+      "message": { "foo": "bar" }
+    }
+  })";
+  ExpectInvalidCastInternalMessage(app_message_missing_session_id,
+                                   "missing session ID");
+
+  std::string app_message_missing_message = R"({
+    "type": "app_message",
+    "clientId": "12345",
+    "sequenceNumber": 999,
+    "message": {
+      "namespaceName": "urn:x-cast:com.google.foo",
+      "sessionId": "sessionId"
+    }
+  })";
+  ExpectInvalidCastInternalMessage(app_message_missing_message,
+                                   "missing app message");
+}
+
+TEST(CastInternalMessageUtilTest, CastSessionFromReceiverStatusNoStatusText) {
+  MediaSinkInternal sink = CreateCastSink(1);
+  std::string receiver_status_str = R"({
+      "applications": [{
+        "appId": "ABCDEFGH",
+        "displayName": "App display name",
+        "namespaces": [
+          {"name": "urn:x-cast:com.google.cast.media"},
+          {"name": "urn:x-cast:com.google.foo"}
+        ],
+        "sessionId": "sessionId",
+        "transportId":"transportId"
+      }]
+  })";
+  auto receiver_status = base::JSONReader::Read(receiver_status_str);
+  ASSERT_TRUE(receiver_status);
+  auto session = CastSession::From(sink, kReceiverIdToken, *receiver_status);
+  ASSERT_TRUE(session);
+  EXPECT_EQ("sessionId", session->session_id);
+  EXPECT_EQ("ABCDEFGH", session->app_id);
+  EXPECT_EQ("transportId", session->transport_id);
+  base::flat_set<std::string> message_namespaces = {
+      "urn:x-cast:com.google.cast.media", "urn:x-cast:com.google.foo"};
+  EXPECT_EQ(message_namespaces, session->message_namespaces);
+  EXPECT_TRUE(session->value.is_dict());
+  EXPECT_EQ("App display name", CastSession::GetRouteDescription(*session));
+}
+
+TEST(CastInternalMessageUtilTest, CastSessionFromInvalidReceiverStatuses) {
+  MediaSinkInternal sink = CreateCastSink(1);
+  std::string missing_app_id = R"({
+      "applications": [{
+        "displayName": "App display name",
+        "namespaces": [
+          {"name": "urn:x-cast:com.google.cast.media"},
+          {"name": "urn:x-cast:com.google.foo"}
+        ],
+        "sessionId": "sessionId",
+        "statusText":"App status",
+        "transportId":"transportId"
+      }]
+  })";
+  ExpectNoCastSession(sink, missing_app_id, "missing app id");
+
+  std::string missing_display_name = R"({
+      "applications": [{
+        "appId": "ABCDEFGH",
+        "namespaces": [
+          {"name": "urn:x-cast:com.google.cast.media"},
+          {"name": "urn:x-cast:com.google.foo"}
+        ],
+        "sessionId": "sessionId",
+        "statusText":"App status",
+        "transportId":"transportId"
+      }]
+  })";
+  ExpectNoCastSession(sink, missing_display_name, "missing display name");
+
+  std::string missing_namespaces = R"({
+      "applications": [{
+        "appId": "ABCDEFGH",
+        "displayName": "App display name",
+        "namespaces": [],
+        "sessionId": "sessionId",
+        "statusText":"App status",
+        "transportId":"transportId"
+      }]
+  })";
+  ExpectNoCastSession(sink, missing_namespaces, "missing namespaces");
+
+  std::string missing_session_id = R"({
+      "applications": [{
+        "appId": "ABCDEFGH",
+        "displayName": "App display name",
+        "namespaces": [
+          {"name": "urn:x-cast:com.google.cast.media"},
+          {"name": "urn:x-cast:com.google.foo"}
+        ],
+        "statusText":"App status",
+        "transportId":"transportId"
+      }]
+  })";
+  ExpectNoCastSession(sink, missing_session_id, "missing session id");
+
+  std::string missing_transport_id = R"({
+      "applications": [{
+        "appId": "ABCDEFGH",
+        "displayName": "App display name",
+        "namespaces": [
+          {"name": "urn:x-cast:com.google.cast.media"},
+          {"name": "urn:x-cast:com.google.foo"}
+        ],
+        "sessionId": "sessionId",
+        "statusText":"App status"
+      }]
+  })";
+  ExpectNoCastSession(sink, missing_transport_id, "missing transport id");
+}
+
+TEST(CastInternalMessageUtilTest, CreateReceiverActionCastMessage) {
+  std::string client_id = "clientId";
+  MediaSinkInternal sink = CreateCastSink(1);
+  std::string expected_message = R"({
+     "clientId": "clientId",
+     "message": {
+        "action": "cast",
+        "receiver": {
+           "capabilities": [ "video_out", "audio_out" ],
+           "displayStatus": null,
+           "friendlyName": "friendly name 1",
+           "isActiveInput": null,
+           "label": "yYH_HCL9CKJFmvKJ9m3Une2cS8s",
+           "receiverType": "cast",
+           "volume": null
+        }
+     },
+     "sequenceNumber": -1,
+     "timeoutMillis": 0,
+     "type": "receiver_action"
+  })";
+
+  auto message =
+      CreateReceiverActionCastMessage(client_id, sink, kReceiverIdToken);
+  ExpectJSONMessagesEqual(expected_message, message->get_message());
+}
+
+TEST(CastInternalMessageUtilTest, CreateReceiverActionStopMessage) {
+  std::string client_id = "clientId";
+  MediaSinkInternal sink = CreateCastSink(1);
+  std::string expected_message = R"({
+     "clientId": "clientId",
+     "message": {
+        "action": "stop",
+        "receiver": {
+           "capabilities": [ "video_out", "audio_out" ],
+           "displayStatus": null,
+           "friendlyName": "friendly name 1",
+           "isActiveInput": null,
+           "label": "yYH_HCL9CKJFmvKJ9m3Une2cS8s",
+           "receiverType": "cast",
+           "volume": null
+        }
+     },
+     "sequenceNumber": -1,
+     "timeoutMillis": 0,
+     "type": "receiver_action"
+  })";
+
+  auto message =
+      CreateReceiverActionStopMessage(client_id, sink, kReceiverIdToken);
+  ExpectJSONMessagesEqual(expected_message, message->get_message());
+}
+
+TEST(CastInternalMessageUtilTest, CreateNewSessionMessage) {
+  MediaSinkInternal sink = CreateCastSink(1);
+  std::string client_id = "clientId";
+  auto receiver_status = ReceiverStatus();
+  ASSERT_TRUE(receiver_status);
+  auto session = CastSession::From(sink, kReceiverIdToken, *receiver_status);
+  ASSERT_TRUE(session);
+
+  std::string expected_message = R"({
+   "clientId": "clientId",
+   "message": {
+      "appId": "ABCDEFGH",
+      "appImages": [  ],
+      "displayName": "App display name",
+      "namespaces": [ {
+         "name": "urn:x-cast:com.google.cast.media"
+      }, {
+         "name": "urn:x-cast:com.google.foo"
+      } ],
+      "receiver": {
+         "capabilities": [ "video_out", "audio_out" ],
+         "displayStatus": null,
+         "friendlyName": "friendly name 1",
+         "isActiveInput": null,
+         "label": "yYH_HCL9CKJFmvKJ9m3Une2cS8s",
+         "receiverType": "cast",
+         "volume": null
+      },
+      "senderApps": [  ],
+      "sessionId": "sessionId",
+      "statusText": "App status",
+      "transportId": "transportId"
+   },
+   "sequenceNumber": -1,
+   "timeoutMillis": 0,
+   "type": "new_session"
+  })";
+
+  auto message = CreateNewSessionMessage(*session, client_id);
+  ExpectJSONMessagesEqual(expected_message, message->get_message());
+}
+
+TEST(CastInternalMessageUtilTest, CreateAppMessageAck) {
+  std::string client_id = "clientId";
+  int sequence_number = 12345;
+
+  std::string expected_message = R"({
+   "clientId": "clientId",
+   "message": null,
+   "sequenceNumber": 12345,
+   "timeoutMillis": 0,
+   "type": "app_message"
+  })";
+
+  auto message = CreateAppMessageAck(client_id, sequence_number);
+  ExpectJSONMessagesEqual(expected_message, message->get_message());
+}
+
+TEST(CastInternalMessageUtilTest, CreateAppMessage) {
+  std::string session_id = "sessionId";
+  std::string client_id = "clientId";
+  base::Value message_body(base::Value::Type::DICTIONARY);
+  message_body.SetKey("foo", base::Value("bar"));
+  cast_channel::CastMessage cast_message = cast_channel::CreateCastMessage(
+      "urn:x-cast:com.google.foo", message_body, "sourceId", "destinationId");
+
+  std::string expected_message = R"({
+   "clientId": "clientId",
+   "message": {
+      "message": "{\"foo\":\"bar\"}",
+      "namespaceName": "urn:x-cast:com.google.foo",
+      "sessionId": "sessionId"
+   },
+   "sequenceNumber": -1,
+   "timeoutMillis": 0,
+   "type": "app_message"
+  })";
+
+  auto message = CreateAppMessage(session_id, client_id, cast_message);
+  ExpectJSONMessagesEqual(expected_message, message->get_message());
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/cast_media_route_provider_unittest.cc b/chrome/browser/media/router/providers/cast/cast_media_route_provider_unittest.cc
index b32a575..28ee791e 100644
--- a/chrome/browser/media/router/providers/cast/cast_media_route_provider_unittest.cc
+++ b/chrome/browser/media/router/providers/cast/cast_media_route_provider_unittest.cc
@@ -64,7 +64,7 @@
   EXPECT_CALL(app_discovery_service_, DoStartObservingMediaSinks(_)).Times(0);
   provider_->StartObservingMediaSinks(non_cast_source);
 
-  MediaSource::Id cast_source("cast:ABCDEFGH");
+  MediaSource::Id cast_source("cast:ABCDEFGH?clientId=123");
   EXPECT_CALL(app_discovery_service_, DoStartObservingMediaSinks(_));
   provider_->StartObservingMediaSinks(cast_source);
   EXPECT_FALSE(app_discovery_service_.callbacks().empty());
@@ -78,6 +78,7 @@
   media_sink_service_.AddOrUpdateSink(CreateCastSink(2));
   MediaSource::Id source_id(
       "cast:ABCDEFAB?capabilities=video_out,audio_out"
+      "&clientId=123"
       "&broadcastNamespace=namespace"
       "&broadcastMessage=message");
 
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.cc
index bcb86de..581135e 100644
--- a/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.cc
+++ b/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.cc
@@ -162,9 +162,17 @@
   // while destruction took place, thereby avoiding endless attempts to upload
   // the same file.
 
-  // |network_connection_tracker_| might already have posted a task back to us,
-  // but it will not run, because |task_runner_| has already been stopped.
-  network_connection_tracker_->RemoveNetworkConnectionObserver(this);
+  if (network_connection_tracker_) {
+    // * |network_connection_tracker_| might already have posted a task back
+    //   to us, but it will not run, because |task_runner_| has already been
+    //   stopped.
+    // * RemoveNetworkConnectionObserver() should generally be called on the
+    //   same thread as AddNetworkConnectionObserver(), but in this case it's
+    //   okay to remove on a separate thread, because this only happens during
+    //   Chrome shutdown, when no others tasks are running; there can be no
+    //   concurrently executing notification from the tracker.
+    network_connection_tracker_->RemoveNetworkConnectionObserver(this);
+  }
 }
 
 void WebRtcRemoteEventLogManager::SetNetworkConnectionTracker(
diff --git a/chrome/browser/metrics/subprocess_metrics_provider_unittest.cc b/chrome/browser/metrics/subprocess_metrics_provider_unittest.cc
index 7330132..9bb0117 100644
--- a/chrome/browser/metrics/subprocess_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/subprocess_metrics_provider_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/metrics/histogram.h"
 #include "base/metrics/histogram_flattener.h"
@@ -14,8 +15,12 @@
 #include "base/metrics/persistent_memory_allocator.h"
 #include "base/metrics/statistics_recorder.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using ::testing::UnorderedElementsAre;
+using ::testing::IsEmpty;
+
 namespace {
 
 const uint32_t TEST_MEMORY_SIZE = 64 << 10;  // 64 KiB
@@ -74,7 +79,7 @@
             std::string(), false));
   }
 
-  size_t GetSnapshotHistogramCount() {
+  std::vector<std::string> GetSnapshotHistogramNames() {
     // Merge the data from the allocator into the StatisticsRecorder.
     provider_.MergeHistogramDeltas();
 
@@ -85,7 +90,7 @@
     base::StatisticsRecorder::PrepareDeltas(true, base::Histogram::kNoFlags,
                                             base::Histogram::kNoFlags,
                                             &snapshot_manager);
-    return flattener.GetRecordedDeltaHistogramNames().size();
+    return flattener.GetRecordedDeltaHistogramNames();
   }
 
   void EnableRecording() { provider_.OnRecordingEnabled(); }
@@ -113,8 +118,7 @@
   DISALLOW_COPY_AND_ASSIGN(SubprocessMetricsProviderTest);
 };
 
-// Temporarily disabled until someone can troubleshoot http://crbug.com/863262
-TEST_F(SubprocessMetricsProviderTest, DISABLED_SnapshotMetrics) {
+TEST_F(SubprocessMetricsProviderTest, SnapshotMetrics) {
   base::HistogramBase* foo = base::Histogram::FactoryGet("foo", 1, 100, 10, 0);
   base::HistogramBase* bar = base::Histogram::FactoryGet("bar", 1, 100, 10, 0);
   base::HistogramBase* baz = base::Histogram::FactoryGet("baz", 1, 100, 10, 0);
@@ -130,25 +134,26 @@
                               CreateDuplicateAllocator(global_allocator.get()));
 
   // Recording should find the two histograms created in persistent memory.
-  EXPECT_EQ(2U, GetSnapshotHistogramCount());
+  EXPECT_THAT(GetSnapshotHistogramNames(), UnorderedElementsAre("foo", "bar"));
 
   // A second run should have nothing to produce.
-  EXPECT_EQ(0U, GetSnapshotHistogramCount());
+  EXPECT_THAT(GetSnapshotHistogramNames(), IsEmpty());
 
   // Create a new histogram and update existing ones. Should now report 3 items.
   baz->Add(1969);
   foo->Add(10);
   bar->Add(20);
-  EXPECT_EQ(3U, GetSnapshotHistogramCount());
+  EXPECT_THAT(GetSnapshotHistogramNames(),
+              UnorderedElementsAre("foo", "bar", "baz"));
 
   // Ensure that deregistering does a final merge of the data.
   foo->Add(10);
   bar->Add(20);
   DeregisterSubprocessAllocator(123);
-  EXPECT_EQ(2U, GetSnapshotHistogramCount());
+  EXPECT_THAT(GetSnapshotHistogramNames(), UnorderedElementsAre("foo", "bar"));
 
   // Further snapshots should be empty even if things have changed.
   foo->Add(10);
   bar->Add(20);
-  EXPECT_EQ(0U, GetSnapshotHistogramCount());
+  EXPECT_THAT(GetSnapshotHistogramNames(), IsEmpty());
 }
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc
index 86696fb..6f62c20 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -1084,7 +1084,10 @@
       PasswordAccessoryController::FromWebContents(web_contents());
   if (!accessory)
     return;  // No accessory needs change here.
-  accessory->RefreshSuggestionsForField(is_fillable, is_password_field);
+  accessory->RefreshSuggestionsForField(
+      password_manager_driver_bindings_.GetCurrentTargetFrame()
+          ->GetLastCommittedOrigin(),
+      is_fillable, is_password_field);
 #endif  // defined(OS_ANDROID)
 }
 
diff --git a/chrome/browser/password_manager/password_accessory_controller.cc b/chrome/browser/password_manager/password_accessory_controller.cc
index 6f5c332..11d7906 100644
--- a/chrome/browser/password_manager/password_accessory_controller.cc
+++ b/chrome/browser/password_manager/password_accessory_controller.cc
@@ -8,7 +8,6 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/android/preferences/preferences_launcher.h"
-#include "chrome/browser/password_manager/password_accessory_view_interface.h"
 #include "chrome/browser/password_manager/password_generation_dialog_view_interface.h"
 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
 #include "chrome/grit/generated_resources.h"
@@ -22,8 +21,6 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
 
-#include "chrome/browser/android/preferences/preferences_launcher.h"
-
 using autofill::PasswordForm;
 using Item = PasswordAccessoryViewInterface::AccessoryItem;
 
@@ -210,10 +207,15 @@
 }
 
 void PasswordAccessoryController::RefreshSuggestionsForField(
+    const url::Origin& origin,
     bool is_fillable,
     bool is_password_field) {
   // TODO(crbug/853766): Record CTR metric.
-  SendViewItems(is_password_field);
+  view_->OnItemsAvailable(
+      CreateViewItems(origin,
+                      is_fillable ? origin_suggestions_[origin]
+                                  : std::vector<SuggestionElementData>(),
+                      is_password_field));
 }
 
 gfx::NativeView PasswordAccessoryController::container_view() const {
@@ -224,13 +226,11 @@
   return web_contents_->GetTopLevelNativeWindow();
 }
 
-void PasswordAccessoryController::SendViewItems(bool is_password_field) {
-  DCHECK(view_);
-  last_focused_field_was_for_passwords_ = is_password_field;
-  const url::Origin& origin =
-      web_contents_->GetFocusedFrame()->GetLastCommittedOrigin();
-  const std::vector<SuggestionElementData>& suggestions =
-      origin_suggestions_[origin];
+// static
+std::vector<Item> PasswordAccessoryController::CreateViewItems(
+    const url::Origin& origin,
+    const std::vector<SuggestionElementData>& suggestions,
+    bool is_password_field) {
   std::vector<Item> items;
   base::string16 passwords_title_str;
 
@@ -266,7 +266,5 @@
       IDS_PASSWORD_MANAGER_ACCESSORY_ALL_PASSWORDS_LINK);
   items.emplace_back(manage_passwords_title, manage_passwords_title, false,
                      Item::Type::OPTION);
-
-  // Notify the view about all just created elements.
-  view_->OnItemsAvailable(items);
+  return items;
 }
diff --git a/chrome/browser/password_manager/password_accessory_controller.h b/chrome/browser/password_manager/password_accessory_controller.h
index 9830285..2231d353 100644
--- a/chrome/browser/password_manager/password_accessory_controller.h
+++ b/chrome/browser/password_manager/password_accessory_controller.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/password_manager/password_accessory_view_interface.h"
 #include "components/autofill/core/common/filling_status.h"
 #include "components/autofill/core/common/password_generation_util.h"
 #include "content/public/browser/web_contents_user_data.h"
@@ -28,7 +29,6 @@
 class PasswordManagerDriver;
 }  // namespace password_manager
 
-class PasswordAccessoryViewInterface;
 class PasswordGenerationDialogViewInterface;
 
 // The controller for the view located below the keyboard accessory.
@@ -91,8 +91,11 @@
   void OnFilledIntoFocusedField(autofill::FillingStatus status);
 
   // Makes sure, that all shown suggestions are appropriate for the currently
-  // focused field.
-  void RefreshSuggestionsForField(bool is_fillable, bool is_password_field);
+  // focused field and for fields that lost the focus. If a field lost focus,
+  // |is_fillable| will be false.
+  void RefreshSuggestionsForField(const url::Origin& origin,
+                                  bool is_fillable,
+                                  bool is_password_field);
 
   // The web page view containing the focused field.
   gfx::NativeView container_view() const;
@@ -129,10 +132,12 @@
       std::unique_ptr<PasswordAccessoryViewInterface> view,
       CreateDialogFactory create_dialog_callback);
 
-  // Creates the view items based on the |origin_suggestions_| and sends them to
-  // the view. If |is_password_field| is false, password suggestions won't be
-  // interactive.
-  void SendViewItems(bool is_password_field);
+  // Creates the view items based on the given |suggestions|.
+  // If |is_password_field| is false, password suggestions won't be interactive.
+  static std::vector<PasswordAccessoryViewInterface::AccessoryItem>
+  CreateViewItems(const url::Origin& origin,
+                  const std::vector<SuggestionElementData>& suggestions,
+                  bool is_password_field);
 
   // Contains the last set of credentials by origin.
   std::map<url::Origin, std::vector<SuggestionElementData>> origin_suggestions_;
diff --git a/chrome/browser/password_manager/password_accessory_controller_unittest.cc b/chrome/browser/password_manager/password_accessory_controller_unittest.cc
index 4d7ee08..c5603a5 100644
--- a/chrome/browser/password_manager/password_accessory_controller_unittest.cc
+++ b/chrome/browser/password_manager/password_accessory_controller_unittest.cc
@@ -245,7 +245,6 @@
         std::make_unique<StrictMock<MockPasswordAccessoryView>>(),
         mock_dialog_factory_.Get());
     NavigateAndCommit(GURL("https://example.com"));
-    FocusWebContentsOnMainFrame();
   }
 
   PasswordAccessoryController* controller() {
@@ -287,8 +286,10 @@
 
   controller()->SavePasswordsForOrigin({CreateEntry("Ben", "S3cur3").first},
                                        url::Origin::Create(GURL(kExampleSite)));
-  controller()->RefreshSuggestionsForField(/*is_fillable=*/true,
-                                           /*is_password_field=*/false);
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/true,
+      /*is_password_field=*/false);
 }
 
 TEST_F(PasswordAccessoryControllerTest, HintsToEmptyUserNames) {
@@ -304,8 +305,10 @@
 
   controller()->SavePasswordsForOrigin({CreateEntry("", "S3cur3").first},
                                        url::Origin::Create(GURL(kExampleSite)));
-  controller()->RefreshSuggestionsForField(/*is_fillable=*/true,
-                                           /*is_password_field=*/false);
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/true,
+      /*is_password_field=*/false);
 }
 
 TEST_F(PasswordAccessoryControllerTest, SortsAlphabeticalDuringTransform) {
@@ -338,8 +341,10 @@
       {CreateEntry("Ben", "S3cur3").first, CreateEntry("Zebra", "M3h").first,
        CreateEntry("Alf", "PWD").first, CreateEntry("Cat", "M1@u").first},
       url::Origin::Create(GURL(kExampleSite)));
-  controller()->RefreshSuggestionsForField(/*is_fillable=*/true,
-                                           /*is_password_field=*/false);
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/true,
+      /*is_password_field=*/false);
 }
 
 TEST_F(PasswordAccessoryControllerTest, RepeatsSuggestionsForSameFrame) {
@@ -357,8 +362,10 @@
                                        url::Origin::Create(GURL(kExampleSite)));
 
   // Pretend that any input in the same frame was focused.
-  controller()->RefreshSuggestionsForField(/*is_fillable=*/true,
-                                           /*is_fillable=*/false);
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/true,
+      /*is_fillable=*/false);
 }
 
 TEST_F(PasswordAccessoryControllerTest, ProvidesEmptySuggestionsMessage) {
@@ -370,8 +377,10 @@
 
   controller()->SavePasswordsForOrigin({},
                                        url::Origin::Create(GURL(kExampleSite)));
-  controller()->RefreshSuggestionsForField(/*is_fillable=*/true,
-                                           /*is_password_field=*/false);
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/true,
+      /*is_password_field=*/false);
 }
 
 TEST_F(PasswordAccessoryControllerTest, RelaysAutomaticGenerationAvailable) {
@@ -439,8 +448,10 @@
   // This should result in the non-interactive suggestion expected above.
   controller()->SavePasswordsForOrigin({CreateEntry("Ben", "S3cur3").first},
                                        url::Origin::Create(GURL(kExampleSite)));
-  controller()->RefreshSuggestionsForField(/*is_fillable=*/true,
-                                           /*is_password_field=*/false);
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/true,
+      /*is_password_field=*/false);
 
   // Pretend that we focus a password field now: By triggering a refresh with
   // |is_password_field| set to true, all suggestions should become interactive.
@@ -452,8 +463,10 @@
                   MatchesItem(ASCIIToUTF16("S3cur3"), password_for_str("Ben"),
                               true, ItemType::SUGGESTION),
                   IsDivider(), MatchesOption(manage_passwords_str()))));
-  controller()->RefreshSuggestionsForField(/*is_fillable=*/true,
-                                           /*is_password_field=*/true);
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/true,
+      /*is_password_field=*/true);
 }
 
 TEST_F(PasswordAccessoryControllerTest, CachesIsReplacedByNewPasswords) {
@@ -467,8 +480,10 @@
                   IsDivider(), MatchesOption(manage_passwords_str()))));
   controller()->SavePasswordsForOrigin({CreateEntry("Ben", "S3cur3").first},
                                        url::Origin::Create(GURL(kExampleSite)));
-  controller()->RefreshSuggestionsForField(/*is_fillable=*/true,
-                                           /*is_password_field=*/false);
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/true,
+      /*is_password_field=*/false);
 
   EXPECT_CALL(*view(),
               OnItemsAvailable(ElementsAre(
@@ -480,6 +495,38 @@
                   IsDivider(), MatchesOption(manage_passwords_str()))));
   controller()->SavePasswordsForOrigin({CreateEntry("Alf", "M3lm4k").first},
                                        url::Origin::Create(GURL(kExampleSite)));
-  controller()->RefreshSuggestionsForField(/*is_fillable=*/true,
-                                           /*is_password_field=*/false);
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/true,
+      /*is_password_field=*/false);
+}
+
+TEST_F(PasswordAccessoryControllerTest, UnfillableFieldClearsSuggestions) {
+  EXPECT_CALL(*view(),
+              OnItemsAvailable(ElementsAre(
+                  MatchesLabel(passwords_title_str(kExampleDomain)),
+                  MatchesItem(ASCIIToUTF16("Ben"), ASCIIToUTF16("Ben"), false,
+                              ItemType::SUGGESTION),
+                  MatchesItem(ASCIIToUTF16("S3cur3"), password_for_str("Ben"),
+                              true, ItemType::NON_INTERACTIVE_SUGGESTION),
+                  IsDivider(), MatchesOption(manage_passwords_str()))));
+  // Set any, non-empty password list and pretend a username field was focused.
+  // This should result in the non-emtpy suggestions expected above.
+  controller()->SavePasswordsForOrigin({CreateEntry("Ben", "S3cur3").first},
+                                       url::Origin::Create(GURL(kExampleSite)));
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/true,
+      /*is_password_field=*/false);
+
+  // Pretend that the focus was lost or moved to an unfillable field. Now, only
+  // the empty state message should be sent.
+  EXPECT_CALL(*view(),
+              OnItemsAvailable(ElementsAre(
+                  MatchesLabel(passwords_empty_str(kExampleDomain)),
+                  IsDivider(), MatchesOption(manage_passwords_str()))));
+  controller()->RefreshSuggestionsForField(
+      url::Origin::Create(GURL(kExampleSite)),
+      /*is_fillable=*/false,
+      /*is_password_field=*/false);  // Unused.
 }
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
index 8b46523..5ad7d13e 100644
--- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
+++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -916,4 +916,27 @@
 
 #endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
 
+// Tests that the Picture-in-Picture state is properly updated when the window
+// is closed at a system level.
+IN_PROC_BROWSER_TEST_F(PictureInPictureWindowControllerBrowserTest,
+                       CloseWindowNotifiesController) {
+  LoadTabAndEnterPictureInPicture(browser());
+
+  content::WebContents* active_web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  OverlayWindowViews* overlay_window = static_cast<OverlayWindowViews*>(
+      window_controller()->GetWindowForTesting());
+  ASSERT_TRUE(overlay_window);
+  ASSERT_TRUE(overlay_window->IsVisible());
+
+  // Simulate closing from the system.
+  overlay_window->OnNativeWidgetDestroyed();
+
+  bool in_picture_in_picture = false;
+  ASSERT_TRUE(ExecuteScriptAndExtractBool(
+      active_web_contents, "isInPictureInPicture();", &in_picture_in_picture));
+  EXPECT_FALSE(in_picture_in_picture);
+}
+
 #endif  // !defined(OS_ANDROID)
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 18f059e..2d0e643 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -794,11 +794,9 @@
 #endif
 
 #if !defined(OS_ANDROID)
-#if !defined(OS_CHROMEOS)
   { key::kRelaunchNotification,
     prefs::kRelaunchNotification,
     base::Value::Type::INTEGER },
-#endif  // !defined(OS_CHROMEOS)
   { key::kRelaunchNotificationPeriod,
     prefs::kRelaunchNotificationPeriod,
     base::Value::Type::INTEGER },
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 083de60..29745cd 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/media/media_device_id_salt.h"
 #include "chrome/browser/media/media_engagement_service.h"
 #include "chrome/browser/media/media_storage_id_salt.h"
+#include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/webrtc/media_stream_devices_controller.h"
 #include "chrome/browser/metrics/chrome_metrics_service_client.h"
@@ -651,6 +652,7 @@
   InstantService::RegisterProfilePrefs(registry);
   gcm::GCMChannelStatusSyncer::RegisterProfilePrefs(registry);
   gcm::RegisterProfilePrefs(registry);
+  media_router::RegisterProfilePrefs(registry);
   ntp_tiles::CustomLinksManagerImpl::RegisterProfilePrefs(registry);
   StartupBrowserCreator::RegisterProfilePrefs(registry);
 #endif
diff --git a/chrome/browser/profiles/gaia_info_update_service.cc b/chrome/browser/profiles/gaia_info_update_service.cc
index c15d673..ec2e2e2 100644
--- a/chrome/browser/profiles/gaia_info_update_service.cc
+++ b/chrome/browser/profiles/gaia_info_update_service.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_metrics.h"
 #include "chrome/browser/profiles/profiles_state.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/account_tracker_service.h"
@@ -39,9 +39,9 @@
 
 GAIAInfoUpdateService::GAIAInfoUpdateService(Profile* profile)
     : profile_(profile) {
-  SigninManagerBase* signin_manager =
-      SigninManagerFactory::GetForProfile(profile_);
-  signin_manager->AddObserver(this);
+  identity::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile_);
+  identity_manager->AddObserver(this);
 
   PrefService* prefs = profile_->GetPrefs();
   last_updated_ = base::Time::FromInternalValue(
@@ -55,9 +55,9 @@
 
 void GAIAInfoUpdateService::Update() {
   // The user must be logged in.
-  SigninManagerBase* signin_manager =
-      SigninManagerFactory::GetForProfile(profile_);
-  if (!signin_manager->IsAuthenticated())
+  identity::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile_);
+  if (!identity_manager->HasPrimaryAccount())
     return;
 
   if (profile_image_downloader_)
@@ -173,9 +173,9 @@
 void GAIAInfoUpdateService::Shutdown() {
   timer_.Stop();
   profile_image_downloader_.reset();
-  SigninManagerBase* signin_manager =
-      SigninManagerFactory::GetForProfile(profile_);
-  signin_manager->RemoveObserver(this);
+  identity::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile_);
+  identity_manager->RemoveObserver(this);
 
   // OK to reset |profile_| pointer here because GAIAInfoUpdateService will not
   // access it again.  This pointer is also used to implement the delegate for
@@ -208,12 +208,12 @@
   timer_.Start(FROM_HERE, delta, this, &GAIAInfoUpdateService::Update);
 }
 
-void GAIAInfoUpdateService::GoogleSigninSucceeded(const std::string& account_id,
-                                                  const std::string& username) {
-  OnUsernameChanged(username);
+void GAIAInfoUpdateService::OnPrimaryAccountSet(
+    const AccountInfo& primary_account_info) {
+  OnUsernameChanged(primary_account_info.gaia);
 }
 
-void GAIAInfoUpdateService::GoogleSignedOut(const std::string& account_id,
-                                            const std::string& username) {
+void GAIAInfoUpdateService::OnPrimaryAccountCleared(
+    const AccountInfo& previous_primary_account_info) {
   OnUsernameChanged(std::string());
 }
diff --git a/chrome/browser/profiles/gaia_info_update_service.h b/chrome/browser/profiles/gaia_info_update_service.h
index 5c84e89d..4128577 100644
--- a/chrome/browser/profiles/gaia_info_update_service.h
+++ b/chrome/browser/profiles/gaia_info_update_service.h
@@ -14,7 +14,7 @@
 #include "chrome/browser/profiles/profile_downloader.h"
 #include "chrome/browser/profiles/profile_downloader_delegate.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/browser/signin_manager.h"
+#include "services/identity/public/cpp/identity_manager.h"
 
 class Profile;
 class ProfileDownloader;
@@ -23,7 +23,7 @@
 // The results are saved in the profile info cache.
 class GAIAInfoUpdateService : public KeyedService,
                               public ProfileDownloaderDelegate,
-                              public SigninManagerBase::Observer {
+                              public identity::IdentityManager::Observer {
  public:
   explicit GAIAInfoUpdateService(Profile* profile);
   ~GAIAInfoUpdateService() override;
@@ -54,11 +54,10 @@
   void OnUsernameChanged(const std::string& username);
   void ScheduleNextUpdate();
 
-  // Overridden from SigninManagerBase::Observer:
-  void GoogleSigninSucceeded(const std::string& account_id,
-                             const std::string& username) override;
-  void GoogleSignedOut(const std::string& account_id,
-                       const std::string& username) override;
+  // Overridden from identity::IdentityManager::Observer:
+  void OnPrimaryAccountSet(const AccountInfo& primary_account_info) override;
+  void OnPrimaryAccountCleared(
+      const AccountInfo& previous_primary_account_info) override;
 
   Profile* profile_;
   std::unique_ptr<ProfileDownloader> profile_image_downloader_;
diff --git a/chrome/browser/profiles/gaia_info_update_service_factory.cc b/chrome/browser/profiles/gaia_info_update_service_factory.cc
index 9edd14cd..b607b97 100644
--- a/chrome/browser/profiles/gaia_info_update_service_factory.cc
+++ b/chrome/browser/profiles/gaia_info_update_service_factory.cc
@@ -6,7 +6,7 @@
 
 #include "chrome/browser/profiles/gaia_info_update_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/common/pref_names.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -15,7 +15,7 @@
     : BrowserContextKeyedServiceFactory(
         "GAIAInfoUpdateService",
         BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(SigninManagerFactory::GetInstance());
+  DependsOn(IdentityManagerFactory::GetInstance());
 }
 
 GAIAInfoUpdateServiceFactory::~GAIAInfoUpdateServiceFactory() {}
diff --git a/chrome/browser/profiles/gaia_info_update_service_unittest.cc b/chrome/browser/profiles/gaia_info_update_service_unittest.cc
index c4bda264..ed21e6c5 100644
--- a/chrome/browser/profiles/gaia_info_update_service_unittest.cc
+++ b/chrome/browser/profiles/gaia_info_update_service_unittest.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/signin/test_signin_client_builder.h"
 #include "chrome/common/pref_names.h"
@@ -29,6 +30,7 @@
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/signin_pref_names.h"
 #include "components/sync_preferences/pref_service_syncable.h"
+#include "services/identity/public/cpp/identity_test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_unittest_util.h"
@@ -87,9 +89,9 @@
 
   Profile* CreateProfile(const std::string& name) {
     TestingProfile::TestingFactories testing_factories;
-    testing_factories.push_back(std::make_pair(
-        ChromeSigninClientFactory::GetInstance(),
-        signin::BuildTestSigninClient));
+    testing_factories.push_back(
+        std::make_pair(ChromeSigninClientFactory::GetInstance(),
+                       signin::BuildTestSigninClient));
     Profile* profile = testing_profile_manager_.CreateTestingProfile(
         name, std::unique_ptr<sync_preferences::PrefServiceSyncable>(),
         base::UTF8ToUTF16(name), 0, std::string(), testing_factories);
@@ -301,9 +303,9 @@
 #if !defined(OS_CHROMEOS)
 
 TEST_F(GAIAInfoUpdateServiceTest, LogOut) {
-  SigninManager* signin_manager =
-      SigninManagerFactory::GetForProfile(profile());
-  signin_manager->SetAuthenticatedAccountInfo("gaia_id", "pat@example.com");
+  identity::SetPrimaryAccount(SigninManagerFactory::GetForProfile(profile()),
+                              IdentityManagerFactory::GetForProfile(profile()),
+                              "pat@example.com");
   base::string16 gaia_name = base::UTF8ToUTF16("Pat Foo");
 
   ASSERT_EQ(1u, storage()->GetNumberOfProfiles());
@@ -319,8 +321,9 @@
   EXPECT_FALSE(service()->GetCachedPictureURL().empty());
 
   // Log out.
-  signin_manager->SignOut(signin_metrics::SIGNOUT_TEST,
-                          signin_metrics::SignoutDelete::IGNORE_METRIC);
+  identity::ClearPrimaryAccount(
+      SigninManagerFactory::GetForProfile(profile()),
+      IdentityManagerFactory::GetForProfile(profile()));
   // Verify that the GAIA name and picture, and picture URL are unset.
   EXPECT_TRUE(entry->GetGAIAName().empty());
   EXPECT_EQ(nullptr, entry->GetGAIAPicture());
@@ -330,11 +333,9 @@
 TEST_F(GAIAInfoUpdateServiceTest, LogIn) {
   // Log in.
   EXPECT_CALL(*service(), Update());
-  AccountTrackerServiceFactory::GetForProfile(profile())
-      ->SeedAccountInfo("gaia_id", "pat@example.com");
-  SigninManager* signin_manager =
-      SigninManagerFactory::GetForProfile(profile());
-  signin_manager->OnExternalSigninCompleted("pat@example.com");
+  identity::SetPrimaryAccount(SigninManagerFactory::GetForProfile(profile()),
+                              IdentityManagerFactory::GetForProfile(profile()),
+                              "pat@example.com");
 }
 
 #endif
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc
index e8f837f..5e93376 100644
--- a/chrome/browser/profiles/profile.cc
+++ b/chrome/browser/profiles/profile.cc
@@ -273,7 +273,12 @@
 
 bool Profile::IsSyncAllowed() {
   if (ProfileSyncServiceFactory::HasProfileSyncService(this)) {
-    return ProfileSyncServiceFactory::GetForProfile(this)->IsSyncAllowed();
+    browser_sync::ProfileSyncService* sync_service =
+        ProfileSyncServiceFactory::GetForProfile(this);
+    return !sync_service->HasDisableReason(
+               syncer::SyncService::DISABLE_REASON_PLATFORM_OVERRIDE) &&
+           !sync_service->HasDisableReason(
+               syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY);
   }
 
   // No ProfileSyncService created yet - we don't want to create one, so just
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index 69270d03..deec95b 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -9,6 +9,8 @@
 #include <memory>
 
 #include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_path_watcher.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/json/json_reader.h"
@@ -20,6 +22,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task_scheduler/task_scheduler.h"
+#include "base/test/bind_test_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
@@ -35,6 +38,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_features.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -846,3 +850,157 @@
       net::LOAD_ONLY_FROM_CACHE);
   url_fetcher_delegate3.WaitForCompletion();
 }
+
+namespace {
+
+// Watches for the destruction of the specified path (Which, in the tests that
+// use it, is typically a directory), and expects the parent directory not to be
+// deleted.
+//
+// This is used the the media cache deletion tests, so handles all the possible
+// orderings of events that could happen:
+//
+// * In PRE_* tests, the media cache could deleted before the test completes, by
+// the task posted on Profile / isolated app URLRequestContext creation.
+//
+// * In the followup test, the media cache could be deleted by the off-thread
+// delete media cache task before the FileDestructionWatcher starts watching for
+// deletion, or even before it's created.
+//
+// * In the followup test, the media cache could be deleted after the
+// FileDestructionWatcher starts watching.
+//
+// It also may be possible to get a notification of the media cache being
+// created from the the previous test, so this allows multiple watch events to
+// happen, before the path is actually deleted.
+//
+// The public methods are called on the UI thread, the private ones called on a
+// separate SequencedTaskRunner.
+class FileDestructionWatcher {
+ public:
+  explicit FileDestructionWatcher(const base::FilePath& watched_file_path)
+      : watched_file_path_(watched_file_path) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  }
+
+  void WaitForDestruction() {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    DCHECK(!watcher_);
+    base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})
+        ->PostTask(FROM_HERE,
+                   base::BindOnce(&FileDestructionWatcher::StartWatchingPath,
+                                  base::Unretained(this)));
+    run_loop_.Run();
+    // The watcher should be destroyed before quitting the run loop, once the
+    // file has been destroyed.
+    DCHECK(!watcher_);
+
+    // Double check that the file was destroyed, and that the parent directory
+    // was not.
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    EXPECT_FALSE(base::PathExists(watched_file_path_));
+    EXPECT_TRUE(base::PathExists(watched_file_path_.DirName()));
+  }
+
+ private:
+  void StartWatchingPath() {
+    DCHECK(!watcher_);
+    watcher_ = std::make_unique<base::FilePathWatcher>();
+    // Start watching before checking if the file exists, as the file could be
+    // destroyed between the existence check and when we start watching, if the
+    // order were reversed.
+    EXPECT_TRUE(watcher_->Watch(
+        watched_file_path_, false /* recursive */,
+        base::BindRepeating(&FileDestructionWatcher::OnPathChanged,
+                            base::Unretained(this))));
+    CheckIfPathExists();
+  }
+
+  void OnPathChanged(const base::FilePath& path, bool error) {
+    EXPECT_EQ(watched_file_path_, path);
+    EXPECT_FALSE(error);
+    CheckIfPathExists();
+  }
+
+  // Checks if the path exists, and if so, destroys the watcher and quits
+  // |run_loop_|.
+  void CheckIfPathExists() {
+    if (!base::PathExists(watched_file_path_)) {
+      watcher_.reset();
+      run_loop_.Quit();
+      return;
+    }
+  }
+
+  base::RunLoop run_loop_;
+  const base::FilePath watched_file_path_;
+
+  // Created and destroyed off of the UI thread, on the sequence used to watch
+  // for changes.
+  std::unique_ptr<base::FilePathWatcher> watcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileDestructionWatcher);
+};
+
+}  // namespace
+
+// Create a media cache file, and make sure it's deleted by the time the next
+// test runs.
+IN_PROC_BROWSER_TEST_F(ProfileWithoutMediaCacheBrowserTest,
+                       PRE_DeleteMediaCache) {
+  base::FilePath media_cache_path =
+      browser()->profile()->GetPath().Append(chrome::kMediaCacheDirname);
+
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  EXPECT_TRUE(base::CreateDirectory(media_cache_path));
+  std::string data = "foo";
+  base::WriteFile(media_cache_path.AppendASCII("foo"), data.c_str(),
+                  data.size());
+}
+
+IN_PROC_BROWSER_TEST_F(ProfileWithoutMediaCacheBrowserTest, DeleteMediaCache) {
+  base::FilePath media_cache_path =
+      browser()->profile()->GetPath().Append(chrome::kMediaCacheDirname);
+
+  base::ScopedAllowBlockingForTesting allow_blocking;
+
+  FileDestructionWatcher destruction_watcher(media_cache_path);
+  destruction_watcher.WaitForDestruction();
+}
+
+// Create a media cache file, and make sure it's deleted by initializing an
+// extension browser context.
+IN_PROC_BROWSER_TEST_F(ProfileWithoutMediaCacheBrowserTest,
+                       PRE_DeleteIsolatedAppMediaCache) {
+  scoped_refptr<const extensions::Extension> app =
+      BuildTestApp(browser()->profile());
+  content::StoragePartition* extension_partition =
+      content::BrowserContext::GetStoragePartitionForSite(
+          browser()->profile(),
+          extensions::Extension::GetBaseURLFromExtensionId(app->id()));
+
+  base::FilePath extension_media_cache_path =
+      extension_partition->GetPath().Append(chrome::kMediaCacheDirname);
+
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  EXPECT_TRUE(base::CreateDirectory(extension_media_cache_path));
+  std::string data = "foo";
+  base::WriteFile(extension_media_cache_path.AppendASCII("foo"), data.c_str(),
+                  data.size());
+}
+
+IN_PROC_BROWSER_TEST_F(ProfileWithoutMediaCacheBrowserTest,
+                       DeleteIsolatedAppMediaCache) {
+  scoped_refptr<const extensions::Extension> app =
+      BuildTestApp(browser()->profile());
+  content::StoragePartition* extension_partition =
+      content::BrowserContext::GetStoragePartitionForSite(
+          browser()->profile(),
+          extensions::Extension::GetBaseURLFromExtensionId(app->id()));
+
+  base::FilePath extension_media_cache_path =
+      extension_partition->GetPath().Append(chrome::kMediaCacheDirname);
+
+  FileDestructionWatcher destruction_watcher(extension_media_cache_path);
+  destruction_watcher.WaitForDestruction();
+}
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index 6dd54b7..b8c9017 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -12,6 +12,8 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/metrics/field_trial.h"
@@ -19,6 +21,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/task_traits.h"
 #include "base/time/default_clock.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
@@ -113,6 +116,19 @@
   return net::CACHE_BACKEND_DEFAULT;
 }
 
+void MaybeDeleteMediaCache(const base::FilePath& media_cache_path) {
+  if (!base::FeatureList::IsEnabled(features::kUseSameCacheForMedia) ||
+      media_cache_path.empty()) {
+    return;
+  }
+  base::PostTaskWithTraits(
+      FROM_HERE,
+      {base::TaskPriority::BACKGROUND, base::MayBlock(),
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+      base::BindOnce(base::IgnoreResult(&base::DeleteFile), media_cache_path,
+                     true /* recursive */));
+}
+
 }  // namespace
 
 using content::BrowserThread;
@@ -522,6 +538,8 @@
   InitializeExtensionsRequestContext(profile_params);
 #endif
 
+  MaybeDeleteMediaCache(lazy_params_->media_cache_path);
+
   // Create a media request context based on the main context, but using a
   // media cache.  It shares the same job factory as the main context.
   StoragePartitionDescriptor details(profile_path_, false);
@@ -555,6 +573,11 @@
         protocol_handler_interceptor,
     content::ProtocolHandlerMap* protocol_handlers,
     content::URLRequestInterceptorScopedVector request_interceptors) const {
+  if (!partition_descriptor.in_memory) {
+    MaybeDeleteMediaCache(
+        partition_descriptor.path.Append(chrome::kMediaCacheDirname));
+  }
+
   // Copy most state from the main context.
   AppRequestContext* context = new AppRequestContext();
   context->CopyFrom(main_context);
diff --git a/chrome/browser/resources/print_preview/new/destination_dialog.html b/chrome/browser/resources/print_preview/new/destination_dialog.html
index 02ea28f..eaf8b76 100644
--- a/chrome/browser/resources/print_preview/new/destination_dialog.html
+++ b/chrome/browser/resources/print_preview/new/destination_dialog.html
@@ -85,29 +85,35 @@
         width: 24px;
       }
 
-      :host #cloudprintPromo .close-button {
+      :host #cloudprintPromo button {
         -webkit-margin-start: 12px;
+        background-color: #f5f5f5;
         background-image: -webkit-image-set(
           url(chrome://theme/IDR_CLOSE_DIALOG) 1x,
           url(chrome://theme/IDR_CLOSE_DIALOG@2x) 2x);
         background-repeat: no-repeat;
         background-size: 14px;
-        height: 14px;
-        width: 14px;
+        border: none;
+        box-shadow: none;
+        min-height: 14px;
+        min-width: 14px;
+        outline: none;
+        padding: 0;
       }
 
-      :host #cloudprintPromo .close-button:hover {
-        background-image: -webkit-image-set(
-          url(chrome://theme/IDR_CLOSE_DIALOG_H) 1x,
-          url(chrome://theme/IDR_CLOSE_DIALOG_H@2x) 2x);
-      }
-
-      :host #cloudprintPromo .close-button:active {
+      :host #cloudprintPromo button:active {
         background-image: -webkit-image-set(
           url(chrome://theme/IDR_CLOSE_DIALOG_P) 1x,
           url(chrome://theme/IDR_CLOSE_DIALOG_P@2x) 2x);
       }
 
+      :host #cloudprintPromo button:focus,
+      :host #cloudprintPromo button:hover {
+        background-image: -webkit-image-set(
+          url(chrome://theme/IDR_CLOSE_DIALOG_H) 1x,
+          url(chrome://theme/IDR_CLOSE_DIALOG_H@2x) 2x);
+      }
+
       :host #invitationPromo {
         flex-direction: column;
       }
@@ -176,7 +182,7 @@
             hidden$="[[!showCloudPrintPromo]]">
           <img src="../images/cloud.png" class="icon" alt="">
           <div class="promo-text"></div>
-          <div class="close-button"></div>
+          <button on-click="onCloudPrintPromoDismissed_"></button>
         </div>
         <div class="promo" id="invitationPromo" hidden="[[!invitation_]]">
           <div inner-h-t-m-l="[[getInvitationText_(invitation_)]]"></div>
diff --git a/chrome/browser/resources/print_preview/new/destination_dialog.js b/chrome/browser/resources/print_preview/new/destination_dialog.js
index 3a526c5..4cf257b 100644
--- a/chrome/browser/resources/print_preview/new/destination_dialog.js
+++ b/chrome/browser/resources/print_preview/new/destination_dialog.js
@@ -100,9 +100,6 @@
   attached: function() {
     this.tracker_.add(
         assert(this.$$('.sign-in')), 'click', this.onSignInClick_.bind(this));
-    this.tracker_.add(
-        assert(this.$$('#cloudprintPromo > .close-button')), 'click',
-        this.onCloudPrintPromoDismissed_.bind(this));
   },
 
   /**
diff --git a/chrome/browser/resources/ukm/BUILD.gn b/chrome/browser/resources/ukm/BUILD.gn
deleted file mode 100644
index 4fe10b1..0000000
--- a/chrome/browser/resources/ukm/BUILD.gn
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
-  deps = [
-    ":ukm_internals",
-  ]
-}
-
-js_library("ukm_internals") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-    "//ui/webui/resources/js:util",
-  ]
-}
diff --git a/chrome/browser/resources/ukm/ukm_internals.js b/chrome/browser/resources/ukm/ukm_internals.js
deleted file mode 100644
index 9449c73..0000000
--- a/chrome/browser/resources/ukm/ukm_internals.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * Fetches data from the Ukm service and updates the DOM to display it as a
- * list.
- */
-function updateUkmData() {
-  cr.sendWithPromise('requestUkmData').then((ukmData) => {
-    $('state').innerText = ukmData.state ? 'True' : 'False';
-    $('clientid').innerText = ukmData.client_id;
-    $('sessionid').innerText = ukmData.session_id;
-
-    sourceDiv = $('sources');
-    for (const source of ukmData.sources) {
-      const sourceElement = document.createElement('h3');
-      if (source.url !== undefined)
-        sourceElement.innerText = `Id: ${source.id} Url: ${source.url}`;
-      else
-        sourceElement.innerText = `Id: ${source.id}`;
-      sourceDiv.appendChild(sourceElement);
-
-      for (const entry of source.entries) {
-        const entryElement = document.createElement('h4');
-        entryElement.innerText = `Entry: ${entry.name}`;
-        sourceDiv.appendChild(entryElement);
-
-        if (entry.metrics === undefined)
-          continue;
-        for (const metric of entry.metrics) {
-          const metricElement = document.createElement('h5');
-          metricElement.innerText =
-              `Metric: ${metric.name} Value: ${metric.value}`;
-          sourceDiv.appendChild(metricElement);
-        }
-      }
-    }
-  });
-}
-
-updateUkmData();
diff --git a/chrome/browser/search/ntp_icon_source.cc b/chrome/browser/search/ntp_icon_source.cc
index e013f4f..15f5e59 100644
--- a/chrome/browser/search/ntp_icon_source.cc
+++ b/chrome/browser/search/ntp_icon_source.cc
@@ -14,6 +14,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "cc/paint/skia_paint_canvas.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
+#include "chrome/browser/history/top_sites_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/instant_io_context.h"
 #include "chrome/browser/search/suggestions/image_decoder_impl.h"
@@ -24,6 +25,7 @@
 #include "components/favicon/core/fallback_url_util.h"
 #include "components/favicon/core/favicon_service.h"
 #include "components/favicon_base/favicon_types.h"
+#include "components/history/core/browser/top_sites.h"
 #include "components/image_fetcher/core/image_fetcher_impl.h"
 #include "components/suggestions/proto/suggestions.pb.h"
 #include "components/suggestions/suggestions_service.h"
@@ -34,6 +36,7 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "ui/base/webui/web_ui_util.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/codec/png_codec.h"
@@ -255,18 +258,35 @@
   const ParsedNtpIconPath parsed = ParseNtpIconPath(path);
 
   if (parsed.url.is_valid()) {
+    int icon_size_in_pixels =
+        std::ceil(parsed.size_in_dip * parsed.device_scale_factor);
+    NtpIconRequest request(callback, parsed.url, icon_size_in_pixels,
+                           parsed.device_scale_factor);
+
+    // Check if the requested URL is part of the prepopulated pages (currently,
+    // only the Web Store).
+    scoped_refptr<history::TopSites> top_sites =
+        TopSitesFactory::GetForProfile(profile_);
+    if (top_sites) {
+      for (const auto& prepopulated_page : top_sites->GetPrepopulatedPages()) {
+        if (parsed.url == prepopulated_page.most_visited.url) {
+          gfx::Image& image =
+              ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+                  prepopulated_page.favicon_id);
+          ReturnRenderedIconForRequest(request, image.AsBitmap());
+          return;
+        }
+      }
+    }
+
     // This will query for a local favicon. If not found, will take alternative
     // action in OnLocalFaviconAvailable.
     const bool fallback_to_host = true;
-    int icon_size_in_pixels =
-        std::ceil(parsed.size_in_dip * parsed.device_scale_factor);
     favicon_service->GetRawFaviconForPageURL(
         parsed.url, {favicon_base::IconType::kFavicon}, icon_size_in_pixels,
         fallback_to_host,
         base::Bind(&NtpIconSource::OnLocalFaviconAvailable,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   NtpIconRequest(callback, parsed.url, icon_size_in_pixels,
-                                  parsed.device_scale_factor)),
+                   weak_ptr_factory_.GetWeakPtr(), request),
         &cancelable_task_tracker_);
   } else {
     callback.Run(nullptr);
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 62fa3cb..60b26cfa 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -48,6 +48,7 @@
 #include "components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h"
 #include "components/autofill/core/browser/webdata/autofill_profile_syncable_service.h"
 #include "components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h"
+#include "components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h"
 #include "components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/autofill_features.h"
@@ -597,6 +598,17 @@
                  profile_web_data_service_.get())
           ->change_processor()
           ->GetControllerDelegateOnUIThread();
+    case syncer::AUTOFILL_WALLET_DATA: {
+      // TODO(feuunk): This doesn't allow switching which database to use at
+      // runtime. This should be fixed as part of the USS migration for
+      // payments.
+      auto service = account_web_data_service_ ? account_web_data_service_
+                                               : profile_web_data_service_;
+      return autofill::AutofillWalletSyncBridge::FromWebDataService(
+                 service.get())
+          ->change_processor()
+          ->GetControllerDelegateOnUIThread();
+    }
 #if defined(OS_CHROMEOS)
     case syncer::PRINTERS:
       return chromeos::SyncedPrintersManagerFactory::GetForBrowserContext(
diff --git a/chrome/browser/themes/increased_contrast_theme_supplier.cc b/chrome/browser/themes/increased_contrast_theme_supplier.cc
index 700cbe0a..b403cab6 100644
--- a/chrome/browser/themes/increased_contrast_theme_supplier.cc
+++ b/chrome/browser/themes/increased_contrast_theme_supplier.cc
@@ -22,11 +22,10 @@
       *color = SK_ColorWHITE;
       return true;
     case ThemeProperties::COLOR_FRAME_INACTIVE:
+    case ThemeProperties::COLOR_FRAME_INCOGNITO_INACTIVE:
       *color = SK_ColorGRAY;
       return true;
     case ThemeProperties::COLOR_FRAME:
-      *color = SK_ColorDKGRAY;
-      return true;
     case ThemeProperties::COLOR_FRAME_INCOGNITO:
       *color = SK_ColorDKGRAY;
       return true;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 2e5deaba4..82df345 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -425,14 +425,6 @@
       "cocoa/one_click_signin_dialog_controller.mm",
       "cocoa/one_click_signin_view_controller.h",
       "cocoa/one_click_signin_view_controller.mm",
-      "cocoa/page_info/page_info_bubble_controller.h",
-      "cocoa/page_info/page_info_bubble_controller.mm",
-      "cocoa/page_info/page_info_utils_cocoa.h",
-      "cocoa/page_info/page_info_utils_cocoa.mm",
-      "cocoa/page_info/permission_selector_button.h",
-      "cocoa/page_info/permission_selector_button.mm",
-      "cocoa/page_info/split_block_button.h",
-      "cocoa/page_info/split_block_button.mm",
       "cocoa/password_reuse_warning_dialog_cocoa.h",
       "cocoa/password_reuse_warning_dialog_cocoa.mm",
       "cocoa/password_reuse_warning_view_controller.h",
@@ -551,8 +543,6 @@
       "cocoa/touchbar/web_textfield_touch_bar_controller.mm",
       "cocoa/translate/translate_bubble_bridge_views.h",
       "cocoa/translate/translate_bubble_bridge_views.mm",
-      "cocoa/translate/translate_bubble_controller.h",
-      "cocoa/translate/translate_bubble_controller.mm",
       "cocoa/url_drop_target.h",
       "cocoa/url_drop_target.mm",
       "cocoa/vertical_gradient_view.h",
@@ -2622,8 +2612,6 @@
         "cocoa/importer/import_lock_dialog_cocoa.mm",
         "cocoa/login_handler_cocoa.h",
         "cocoa/login_handler_cocoa.mm",
-        "cocoa/page_info/page_info_bubble_controller.h",
-        "cocoa/page_info/page_info_bubble_controller.mm",
         "cocoa/password_reuse_warning_dialog_cocoa.h",
         "cocoa/password_reuse_warning_dialog_cocoa.mm",
         "cocoa/password_reuse_warning_view_controller.h",
@@ -3046,6 +3034,12 @@
       "views/permission_bubble/chooser_bubble_ui.h",
       "views/permission_bubble/permission_prompt_impl.cc",
       "views/permission_bubble/permission_prompt_impl.h",
+      "views/relaunch_notification/relaunch_notification_controller.cc",
+      "views/relaunch_notification/relaunch_notification_controller.h",
+      "views/relaunch_notification/relaunch_recommended_bubble_view.cc",
+      "views/relaunch_notification/relaunch_recommended_bubble_view.h",
+      "views/relaunch_notification/relaunch_required_dialog_view.cc",
+      "views/relaunch_notification/relaunch_required_dialog_view.h",
       "views/safe_browsing/password_reuse_modal_warning_dialog.cc",
       "views/safe_browsing/password_reuse_modal_warning_dialog.h",
       "views/session_crashed_bubble_view.cc",
@@ -3498,22 +3492,17 @@
 
     if (!is_chromeos) {
       sources += [
-        "views/relaunch_notification/relaunch_notification_controller.cc",
-        "views/relaunch_notification/relaunch_notification_controller.h",
-        "views/relaunch_notification/relaunch_recommended_bubble_view.cc",
-        "views/relaunch_notification/relaunch_recommended_bubble_view.h",
-        "views/relaunch_notification/relaunch_required_dialog_view.cc",
-        "views/relaunch_notification/relaunch_required_dialog_view.h",
         "views/screen_capture_notification_ui_views.cc",
       ]
-      if (is_mac) {
-        sources += [
-          "views/policy/enterprise_startup_dialog_mac_util.h",
-          "views/policy/enterprise_startup_dialog_mac_util.mm",
-          "views/relaunch_notification/get_app_menu_anchor_point.h",
-          "views/relaunch_notification/get_app_menu_anchor_point.mm",
-        ]
-      }
+    }
+
+    if (is_mac) {
+      sources += [
+        "views/policy/enterprise_startup_dialog_mac_util.h",
+        "views/policy/enterprise_startup_dialog_mac_util.mm",
+        "views/relaunch_notification/get_app_menu_anchor_point.h",
+        "views/relaunch_notification/get_app_menu_anchor_point.mm",
+      ]
     }
 
     if (is_chrome_branded) {
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc
index a6bf7f2..edb6476 100644
--- a/chrome/browser/ui/browser_ui_prefs.cc
+++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -39,9 +39,7 @@
   registry->RegisterBooleanPref(prefs::kAllowFileSelectionDialogs, true);
 
 #if !defined(OS_ANDROID)
-#if !defined(OS_CHROMEOS)
   registry->RegisterIntegerPref(prefs::kRelaunchNotification, 0);
-#endif  // !defined(OS_CHROMEOS)
   registry->RegisterIntegerPref(
       prefs::kRelaunchNotificationPeriod,
       base::saturated_cast<int>(
diff --git a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
index c50f112..e5ed7c24 100644
--- a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
+++ b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
@@ -367,6 +367,9 @@
     return;
 
   // Remove and re-add menu item so menu gets the correct size.
+  // |removeItemAtIndex:| can trigger an eager dealloc, so retain it
+  // in the meantime.
+  base::scoped_nsobject<NSMenuItem> menuItem([browserActionsMenuItem_ retain]);
   NSInteger index = [[self menu] indexOfItem:browserActionsMenuItem_];
   [[self menu] removeItemAtIndex:index];
   [[self menu] insertItem:browserActionsMenuItem_ atIndex:index];
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h
index 1662cbf..5bf172eb 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -57,7 +57,6 @@
 @class TabStripControllerCocoa;
 @class TabStripView;
 @class ToolbarController;
-@class TranslateBubbleController;
 
 namespace content {
 class WebContents;
@@ -109,8 +108,6 @@
   BOOL initializing_;  // YES while we are currently in initWithBrowser:
   BOOL ownsBrowser_;  // Only ever NO when testing
 
-  TranslateBubbleController* translateBubbleController_;  // Weak.
-
   // The total amount by which we've grown the window up or down (to display a
   // bookmark bar and/or download shelf), respectively; reset to 0 when moved
   // away from the bottom/top or resized (or zoomed).
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 6739d09..534764a 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -79,7 +79,6 @@
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #import "chrome/browser/ui/cocoa/touchbar/browser_window_touch_bar_controller.h"
 #include "chrome/browser/ui/cocoa/translate/translate_bubble_bridge_views.h"
-#import "chrome/browser/ui/cocoa/translate/translate_bubble_controller.h"
 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -1599,54 +1598,8 @@
                                      step:(translate::TranslateStep)step
                                 errorType:(translate::TranslateErrors::Type)
                                 errorType {
-  if (chrome::ShowAllDialogsWithViewsToolkit()) {
-    ShowTranslateBubbleViews([self window], [self locationBarBridge], contents,
-                             step, errorType, true);
-    return;
-  }
-  // TODO(hajimehoshi): The similar logic exists at TranslateBubbleView::
-  // ShowBubble. This should be unified.
-  if (translateBubbleController_) {
-    // When the user reads the advanced setting panel, the bubble should not be
-    // changed because they are focusing on the bubble.
-    if (translateBubbleController_.webContents == contents &&
-        translateBubbleController_.model->GetViewState() ==
-        TranslateBubbleModel::VIEW_STATE_ADVANCED) {
-      return;
-    }
-    if (step != translate::TRANSLATE_STEP_TRANSLATE_ERROR) {
-      TranslateBubbleModel::ViewState viewState =
-          TranslateBubbleModelImpl::TranslateStepToViewState(step);
-      [translateBubbleController_ switchView:viewState];
-    } else {
-      [translateBubbleController_ switchToErrorView:errorType];
-    }
-    return;
-  }
-
-  std::string sourceLanguage;
-  std::string targetLanguage;
-  ChromeTranslateClient::GetTranslateLanguages(
-      contents, &sourceLanguage, &targetLanguage);
-
-  std::unique_ptr<translate::TranslateUIDelegate> uiDelegate(
-      new translate::TranslateUIDelegate(
-          ChromeTranslateClient::GetManagerFromWebContents(contents)
-              ->GetWeakPtr(),
-          sourceLanguage, targetLanguage));
-  std::unique_ptr<TranslateBubbleModel> model(
-      new TranslateBubbleModelImpl(step, std::move(uiDelegate)));
-  translateBubbleController_ =
-      [[TranslateBubbleController alloc] initWithParentWindow:self
-                                                        model:std::move(model)
-                                                  webContents:contents];
-  [translateBubbleController_ showWindow:nil];
-
-  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
-  [center addObserver:self
-             selector:@selector(translateBubbleWindowWillClose:)
-                 name:NSWindowWillCloseNotification
-               object:[translateBubbleController_ window]];
+  ShowTranslateBubbleViews([self window], [self locationBarBridge], contents,
+                           step, errorType, true);
 }
 
 - (void)dismissPermissionBubble {
@@ -1655,17 +1608,6 @@
     delegate->Closing();
 }
 
-// Nil out the weak translate bubble controller reference.
-- (void)translateBubbleWindowWillClose:(NSNotification*)notification {
-  DCHECK_EQ([notification object], [translateBubbleController_ window]);
-
-  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
-  [center removeObserver:self
-                    name:NSWindowWillCloseNotification
-                  object:[translateBubbleController_ window]];
-  translateBubbleController_ = nil;
-}
-
 // If the browser is in incognito mode or has multi-profiles, install the image
 // view to decorate the window at the upper right. Use the same base y
 // coordinate as the tab strip.
diff --git a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.h b/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.h
deleted file mode 100644
index 3abc77d..0000000
--- a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_PAGE_INFO_PAGE_INFO_BUBBLE_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_PAGE_INFO_PAGE_INFO_BUBBLE_CONTROLLER_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include <memory>
-
-#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
-#import "chrome/browser/ui/cocoa/base_bubble_controller.h"
-#include "chrome/browser/ui/page_info/page_info_ui.h"
-#include "content/public/browser/web_contents_observer.h"
-
-class LocationBarDecoration;
-class PageInfoUIBridge;
-@class InspectLinkView;
-
-namespace content {
-class WebContents;
-}
-
-namespace net {
-class X509Certificate;
-}
-
-// This NSWindowController subclass manages the InfoBubbleWindow and view that
-// are displayed when the user clicks the omnibox security indicator icon.
-@interface PageInfoBubbleController : BaseBubbleController {
- @private
-  content::WebContents* webContents_;
-
-  base::scoped_nsobject<NSView> contentView_;
-
-  // The main content view for the Permissions tab.
-  NSView* securitySectionView_;
-
-  // Displays the short security summary for the page
-  // (private/not private/etc.).
-  NSTextField* securitySummaryField_;
-
-  // Displays a longer explanation of the page's security state, and how the
-  // user should treat it.
-  NSTextField* securityDetailsField_;
-
-  // The link button for opening a Chrome Help Center page explaining connection
-  // security.
-  NSButton* connectionHelpButton_;
-
-  // URL of the page for which the bubble is shown.
-  GURL url_;
-
-  // Displays a paragraph to accompany the reset decisions button, explaining
-  // that the user has made a decision to trust an invalid security certificate
-  // for the current site.
-  // This field only shows when there is an acrive certificate exception.
-  NSTextField* resetDecisionsField_;
-
-  // The link button for revoking certificate decisions.
-  // This link only shows when there is an active certificate exception.
-  NSButton* resetDecisionsButton_;
-
-  // The server certificate from the identity info. This should always be
-  // non-null on a cryptographic connection, and null otherwise.
-  scoped_refptr<net::X509Certificate> certificate_;
-
-  // Separator line.
-  NSView* separatorAfterSecuritySection_;
-
-  // Container for the site settings section.
-  NSView* siteSettingsSectionView_;
-
-  // Container for certificate info in the site settings section.
-  InspectLinkView* certificateView_;
-
-  // Container for cookies info in the site settings section.
-  InspectLinkView* cookiesView_;
-
-  // Container for permission info in the site settings section.
-  NSView* permissionsView_;
-
-  // The link button for showing site settings.
-  NSButton* siteSettingsButton_;
-
-  // The UI translates user actions to specific events and forwards them to the
-  // |presenter_|. The |presenter_| handles these events and updates the UI.
-  std::unique_ptr<PageInfo> presenter_;
-
-  // Bridge which implements the PageInfoUI interface and forwards
-  // methods on to this class.
-  std::unique_ptr<PageInfoUIBridge> bridge_;
-
-  // The omnibox icon the bubble is anchored to. The icon is set as active
-  // when the bubble is opened, and inactive when the bubble is closed.
-  // Usually we would override OmniboxDecorationBubbleController but the page
-  // info icon has a race condition where it might switch between
-  // LocationIconDecoration and SecurityStateBubbleDecoration.
-  LocationBarDecoration* decoration_;  // Weak.
-
-  // The button for changing password decisions.
-  // This button only shows when there is an password reuse event.
-  NSButton* changePasswordButton_;
-
-  // The button for whitelisting password reuse decisions.
-  // This button only shows when there is an password reuse event.
-  NSButton* whitelistPasswordReuseButton_;
-}
-
-// Designated initializer. The controller will release itself when the bubble
-// is closed. |parentWindow| cannot be nil. |webContents| may be nil for
-// testing purposes.
-- (id)initWithParentWindow:(NSWindow*)parentWindow
-          pageInfoUIBridge:(PageInfoUIBridge*)bridge
-               webContents:(content::WebContents*)webContents
-                       url:(const GURL&)url;
-
-// Return the default width of the window. It may be wider to fit the content.
-// This may be overriden by a subclass for testing purposes.
-- (CGFloat)defaultWindowWidth;
-
-@end
-
-// Provides a bridge between the PageInfoUI C++ interface and the Cocoa
-// implementation in PageInfoBubbleController.
-class PageInfoUIBridge : public content::WebContentsObserver,
-                         public PageInfoUI {
- public:
-  explicit PageInfoUIBridge(content::WebContents* web_contents);
-  ~PageInfoUIBridge() override;
-
-  void set_bubble_controller(PageInfoBubbleController* bubble_controller);
-
-  // WebContentsObserver implementation.
-  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
-
-  // PageInfoUI implementations.
-  void SetCookieInfo(const CookieInfoList& cookie_info_list) override;
-  void SetPermissionInfo(const PermissionInfoList& permission_info_list,
-                         ChosenObjectInfoList chosen_object_info_list) override;
-  void SetIdentityInfo(const IdentityInfo& identity_info) override;
-
- protected:
-  // WebContentsObserver implementation.
-  void DidFinishNavigation(
-      content::NavigationHandle* navigation_handle) override;
-
- private:
-  // The WebContents the bubble UI is attached to.
-  content::WebContents* web_contents_;
-
-  // The Cocoa controller for the bubble UI.
-  PageInfoBubbleController* bubble_controller_;
-
-  DISALLOW_COPY_AND_ASSIGN(PageInfoUIBridge);
-};
-
-#endif  // CHROME_BROWSER_UI_COCOA_PAGE_INFO_PAGE_INFO_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm b/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm
deleted file mode 100644
index 87f5d3f..0000000
--- a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm
+++ /dev/null
@@ -1,1540 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.h"
-
-#import <AppKit/AppKit.h>
-
-#include <cmath>
-
-#include "base/bind.h"
-#include "base/i18n/rtl.h"
-#include "base/mac/foundation_util.h"
-#include "base/mac/mac_util.h"
-#include "base/strings/sys_string_conversions.h"
-#import "chrome/browser/certificate_viewer.h"
-#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/cocoa/browser_dialogs_views_mac.h"
-#import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "chrome/browser/ui/cocoa/bubble_anchor_helper.h"
-#import "chrome/browser/ui/cocoa/info_bubble_view.h"
-#import "chrome/browser/ui/cocoa/info_bubble_window.h"
-#include "chrome/browser/ui/cocoa/key_equivalent_constants.h"
-#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
-#import "chrome/browser/ui/cocoa/location_bar/page_info_bubble_decoration.h"
-#import "chrome/browser/ui/cocoa/page_info/permission_selector_button.h"
-#include "chrome/browser/ui/page_info/page_info_dialog.h"
-#include "chrome/browser/ui/page_info/permission_menu_model.h"
-#import "chrome/browser/ui/tab_dialogs.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/grit/theme_resources.h"
-#include "components/content_settings/core/browser/content_settings_registry.h"
-#include "components/strings/grit/components_chromium_strings.h"
-#include "components/strings/grit/components_strings.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/page_navigator.h"
-#include "content/public/browser/ssl_host_state_delegate.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/url_constants.h"
-#include "extensions/common/constants.h"
-#include "skia/ext/skia_utils_mac.h"
-#import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
-#import "ui/base/cocoa/a11y_util.h"
-#include "ui/base/cocoa/cocoa_base_utils.h"
-#import "ui/base/cocoa/controls/button_utils.h"
-#import "ui/base/cocoa/controls/hyperlink_button_cell.h"
-#import "ui/base/cocoa/flipped_view.h"
-#import "ui/base/cocoa/hover_image_button.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/color_palette.h"
-#include "ui/gfx/image/image_skia_util_mac.h"
-#import "ui/gfx/mac/coordinate_conversion.h"
-#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
-#include "ui/resources/grit/ui_resources.h"
-
-using ChosenObjectInfoPtr = std::unique_ptr<PageInfoUI::ChosenObjectInfo>;
-using ChosenObjectDeleteCallback =
-    base::Callback<void(const PageInfoUI::ChosenObjectInfo&)>;
-
-namespace {
-
-// General ---------------------------------------------------------------------
-
-// The default width of the window, in view coordinates. It may be larger to
-// fit the content.
-constexpr CGFloat kDefaultWindowWidth = 320;
-
-// Padding around each section
-constexpr CGFloat kSectionVerticalPadding = 20;
-constexpr CGFloat kSectionHorizontalPadding = 16;
-
-// Links are buttons with invisible padding, so we need to move them back to
-// align with other text.
-constexpr CGFloat kLinkButtonXAdjustment = 1;
-
-// Built-in margin for NSButton to take into account.
-constexpr CGFloat kNSButtonBuiltinMargin = 4;
-
-// Security Section ------------------------------------------------------------
-
-// Spacing between security summary, security details, and cert decisions text.
-constexpr CGFloat kSecurityParagraphSpacing = 12;
-
-// Site Settings Section -------------------------------------------------------
-
-// Square size of the permission images.
-constexpr CGFloat kPermissionImageSize = 16;
-
-// Spacing between a permission image and the text.
-constexpr CGFloat kPermissionImageSpacing = 6;
-
-// Minimum distance between the label and its corresponding menu.
-constexpr CGFloat kMinSeparationBetweenLabelAndMenu = 16;
-
-// Square size of the permission delete button image.
-constexpr CGFloat kPermissionDeleteImageSize = 16;
-
-// The spacing between individual permissions.
-constexpr CGFloat kPermissionsVerticalSpacing = 16;
-
-// Spacing to add after a permission label, either directly on top of
-// kPermissionsVerticalSpacing, or before additional text (e.g. "X in use" for
-// cookies).
-constexpr CGFloat kPermissionLabelBottomPadding = 4;
-
-// Amount to lower each permission icon to align the icon baseline with the
-// label text.
-constexpr CGFloat kPermissionIconYAdjustment = 1;
-
-// Amount to lower each permission popup button to make its text align with the
-// permission label.
-constexpr CGFloat kPermissionPopupButtonYAdjustment = 3;
-
-// Internal Page Bubble --------------------------------------------------------
-
-// Padding between the window frame and content for the internal page bubble.
-constexpr CGFloat kInternalPageFramePadding = 10;
-
-// Spacing between the image and text for internal pages.
-constexpr CGFloat kInternalPageImageSpacing = 10;
-
-// -----------------------------------------------------------------------------
-
-// A unique tag given to chosen object views (e.g. to show a site has access to
-// a USB/Bluetooth device) in order to repopulate them on permissions updates.
-// This number must not be the same as any permission in ContentSettingsType.
-constexpr int kChosenObjectTag = CONTENT_SETTINGS_NUM_TYPES;
-
-// NOTE: This assumes that there will never be more than one page info
-// bubble shown, and that the one that is shown is associated with the current
-// window. This matches the behaviour in Views: see PageInfoBubbleView.
-PageInfoBubbleController* g_page_info_bubble = nullptr;
-
-// Takes in the parent window, which should be a BrowserWindow, and gets the
-// proper anchor point for the bubble. The returned point is in screen
-// coordinates.
-NSPoint AnchorPointForWindow(NSWindow* parent) {
-  Browser* browser = chrome::FindBrowserWithWindow(parent);
-  DCHECK(browser);
-  return GetPageInfoAnchorPointForBrowser(browser);
-}
-
-NSImage* GetNSImageFromImageSkia(const gfx::ImageSkia& image) {
-  return NSImageFromImageSkiaWithColorSpace(image,
-                                            base::mac::GetSRGBColorSpace());
-}
-
-SkColor GetRelatedTextColor() {
-  return skia::NSDeviceColorToSkColor(
-      [[NSColor textColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
-}
-
-}  // namespace
-
-// The |InspectLinkView| objects are used to show the Cookie and Certificate
-// status and a link to inspect the underlying data.
-@interface InspectLinkView : FlippedView
-@end
-
-@implementation InspectLinkView {
-  NSButton* actionLink_;
-}
-
-- (id)initWithFrame:(NSRect)frame {
-  if (self = [super initWithFrame:frame]) {
-    [self setAutoresizingMask:NSViewWidthSizable];
-  }
-  return self;
-}
-
-- (void)setActionLink:(NSButton*)actionLink {
-  actionLink_ = actionLink;
-}
-
-- (void)setLinkText:(NSString*)linkText {
-  [actionLink_ setTitle:linkText];
-  [GTMUILocalizerAndLayoutTweaker sizeToFitView:actionLink_];
-}
-
-- (void)setLinkToolTip:(NSString*)linkToolTip {
-  [actionLink_ setToolTip:linkToolTip];
-}
-
-- (void)setLinkTarget:(NSObject*)target withAction:(SEL)action {
-  [actionLink_ setTarget:target];
-  [actionLink_ setAction:action];
-}
-@end
-
-@interface ChosenObjectDeleteButton : HoverImageButton {
- @private
-  ChosenObjectInfoPtr objectInfo_;
-  ChosenObjectDeleteCallback callback_;
-}
-
-// Designated initializer. Takes ownership of |objectInfo|.
-- (instancetype)initWithChosenObject:(ChosenObjectInfoPtr)objectInfo
-                             atPoint:(NSPoint)point
-                        withCallback:(ChosenObjectDeleteCallback)callback;
-
-// Action when the button is clicked.
-- (void)deleteClicked:(id)sender;
-
-@end
-
-@implementation ChosenObjectDeleteButton
-
-- (instancetype)initWithChosenObject:(ChosenObjectInfoPtr)objectInfo
-                             atPoint:(NSPoint)point
-                        withCallback:(ChosenObjectDeleteCallback)callback {
-  NSRect frame = NSMakeRect(point.x, point.y, kPermissionDeleteImageSize,
-                            kPermissionDeleteImageSize);
-  if (self = [super initWithFrame:frame]) {
-    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-    [self setDefaultImage:rb.GetNativeImageNamed(IDR_CLOSE_2).ToNSImage()];
-    [self setHoverImage:rb.GetNativeImageNamed(IDR_CLOSE_2_H).ToNSImage()];
-    [self setPressedImage:rb.GetNativeImageNamed(IDR_CLOSE_2_P).ToNSImage()];
-    [self setBordered:NO];
-    [self setToolTip:l10n_util::GetNSString(
-                         objectInfo->ui_info.delete_tooltip_string_id)];
-    [self setTarget:self];
-    [self setAction:@selector(deleteClicked:)];
-    objectInfo_ = std::move(objectInfo);
-    callback_ = callback;
-  }
-  return self;
-}
-
-- (void)deleteClicked:(id)sender {
-  callback_.Run(*objectInfo_);
-}
-
-@end
-
-@implementation PageInfoBubbleController
-
-+ (PageInfoBubbleController*)getPageInfoBubbleForTest {
-  return g_page_info_bubble;
-}
-
-- (CGFloat)defaultWindowWidth {
-  return kDefaultWindowWidth;
-}
-
-bool IsInternalURL(const GURL& url) {
-  return url.SchemeIs(content::kChromeUIScheme) ||
-         url.SchemeIs(content::kChromeDevToolsScheme) ||
-         url.SchemeIs(extensions::kExtensionScheme) ||
-         url.SchemeIs(content::kViewSourceScheme);
-}
-
-- (id)initWithParentWindow:(NSWindow*)parentWindow
-          pageInfoUIBridge:(PageInfoUIBridge*)bridge
-               webContents:(content::WebContents*)webContents
-                       url:(const GURL&)url {
-  DCHECK(parentWindow);
-
-  webContents_ = webContents;
-  url_ = url;
-
-  // Use an arbitrary height; it will be changed in performLayout.
-  NSRect contentRect = NSMakeRect(0, 0, [self defaultWindowWidth], 1);
-  // Create an empty window into which content is placed.
-  base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc]
-      initWithContentRect:contentRect
-                styleMask:NSBorderlessWindowMask
-                  backing:NSBackingStoreBuffered
-                    defer:NO]);
-
-  if ((self = [super initWithWindow:window.get()
-                       parentWindow:parentWindow
-                         anchoredAt:NSZeroPoint])) {
-    [[self bubble] setArrowLocation:info_bubble::kTopLeading];
-
-    // Create the container view that uses flipped coordinates.
-    NSRect contentFrame = NSMakeRect(0, 0, [self defaultWindowWidth], 300);
-    contentView_.reset([[FlippedView alloc] initWithFrame:contentFrame]);
-
-    // Replace the window's content.
-    [[[self window] contentView]
-        setSubviews:[NSArray arrayWithObject:contentView_.get()]];
-
-    if (IsInternalURL(url_)) {
-      [self initializeContentsForInternalPage:url_];
-    } else {
-      [self initializeContents];
-    }
-
-    bridge_.reset(bridge);
-    bridge_->set_bubble_controller(self);
-  }
-  return self;
-}
-
-- (void)showWindow:(id)sender {
-  BrowserWindowController* controller = [BrowserWindowController
-      browserWindowControllerForWindow:[self parentWindow]];
-  LocationBarViewMac* locationBar = [controller locationBarBridge];
-  if (locationBar) {
-    decoration_ = locationBar->page_info_decoration();
-    decoration_->SetActive(true);
-  }
-
-  [super showWindow:sender];
-}
-
-- (void)close {
-  if (decoration_) {
-    decoration_->SetActive(false);
-    decoration_ = nullptr;
-  }
-
-  [super close];
-}
-
-- (Profile*)profile {
-  return Profile::FromBrowserContext(webContents_->GetBrowserContext());
-}
-
-- (void)windowWillClose:(NSNotification*)notification {
-  if (presenter_.get())
-    presenter_->OnUIClosing();
-  presenter_.reset();
-  [super windowWillClose:notification];
-}
-
-- (void)setPresenter:(PageInfo*)presenter {
-  presenter_.reset(presenter);
-}
-
-// Create the subviews for the bubble for internal Chrome pages.
-- (void)initializeContentsForInternalPage:(const GURL&)url {
-  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-
-  int text = IDS_PAGE_INFO_INTERNAL_PAGE;
-  int icon = IDR_PRODUCT_LOGO_16;
-  if (url.SchemeIs(extensions::kExtensionScheme)) {
-    text = IDS_PAGE_INFO_EXTENSION_PAGE;
-    icon = IDR_PLUGINS_FAVICON;
-  } else if (url.SchemeIs(content::kViewSourceScheme)) {
-    text = IDS_PAGE_INFO_VIEW_SOURCE_PAGE;
-    // view-source scheme uses the same icon as chrome:// pages.
-    icon = IDR_PRODUCT_LOGO_16;
-  } else if (!url.SchemeIs(content::kChromeUIScheme) &&
-             !url.SchemeIs(content::kChromeDevToolsScheme)) {
-    NOTREACHED();
-  }
-
-  NSPoint controlOrigin =
-      NSMakePoint(kInternalPageFramePadding,
-                  kInternalPageFramePadding + info_bubble::kBubbleArrowHeight);
-  NSImage* productLogoImage = rb.GetNativeImageNamed(icon).ToNSImage();
-  NSImageView* imageView = [self addImageWithSize:[productLogoImage size]
-                                           toView:contentView_
-                                          atPoint:controlOrigin];
-  [imageView setImage:productLogoImage];
-
-  NSRect imageFrame = [imageView frame];
-  controlOrigin.x += NSWidth(imageFrame) + kInternalPageImageSpacing;
-  NSTextField* textField = [self addText:l10n_util::GetStringUTF16(text)
-                                withSize:[NSFont smallSystemFontSize]
-                                    bold:NO
-                                  toView:contentView_
-                                 atPoint:controlOrigin];
-  // Center the image vertically with the text. Previously this code centered
-  // the text vertically while holding the image in place. That produced correct
-  // results when the image, at 26x26, was taller than (or just slightly
-  // shorter) than the text, but produced incorrect results once the icon
-  // shrank to 16x16. The icon should now always be shorter than the text.
-  // See crbug.com/572044 .
-  NSRect textFrame = [textField frame];
-  imageFrame.origin.y += (NSHeight(textFrame) - NSHeight(imageFrame)) / 2;
-  [imageView setFrame:imageFrame];
-
-  // Adjust the contentView to fit everything.
-  CGFloat maxY = std::max(NSMaxY(imageFrame), NSMaxY(textFrame));
-  [contentView_ setFrame:NSMakeRect(0, 0, [self defaultWindowWidth],
-                                    maxY + kInternalPageFramePadding)];
-
-  [self sizeAndPositionWindow];
-}
-
-// Create the subviews for the page info bubble.
-- (void)initializeContents {
-  securitySectionView_ = [self addSecuritySectionToView:contentView_];
-  separatorAfterSecuritySection_ = [self addSeparatorToView:contentView_];
-  siteSettingsSectionView_ = [self addSiteSettingsSectionToView:contentView_];
-
-  [self performLayout];
-}
-
-// Create and return a subview for the security section and add it to the given
-// |superview|. |superview| retains the new view.
-- (NSView*)addSecuritySectionToView:(NSView*)superview {
-  base::scoped_nsobject<NSView> securitySectionView(
-      [[FlippedView alloc] initWithFrame:[superview frame]]);
-  [superview addSubview:securitySectionView];
-
-  // Create a controlOrigin to place the text fields. The y value doesn't
-  // matter, because the correct value is calculated in -performLayout.
-  NSPoint controlOrigin = NSMakePoint(kSectionHorizontalPadding, 0);
-
-  // Create a text field for the security summary (private/not private/etc.).
-  securitySummaryField_ = [self addText:base::string16()
-                               withSize:[NSFont systemFontSize]
-                                   bold:NO
-                                 toView:securitySectionView
-                                atPoint:controlOrigin];
-
-  securityDetailsField_ = [self addText:base::string16()
-                               withSize:[NSFont smallSystemFontSize]
-                                   bold:NO
-                                 toView:securitySectionView
-                                atPoint:controlOrigin];
-
-  // These will be created only if necessary.
-  resetDecisionsField_ = nil;
-  resetDecisionsButton_ = nil;
-  changePasswordButton_ = nil;
-  whitelistPasswordReuseButton_ = nil;
-
-  NSString* connectionHelpButtonText = l10n_util::GetNSString(IDS_LEARN_MORE);
-  connectionHelpButton_ = [self addLinkButtonWithText:connectionHelpButtonText
-                                               toView:securitySectionView];
-  [connectionHelpButton_ setTarget:self];
-  [connectionHelpButton_ setAction:@selector(openConnectionHelp:)];
-
-  if (base::i18n::IsRTL()) {
-    securitySummaryField_.alignment = NSRightTextAlignment;
-    securityDetailsField_.alignment = NSRightTextAlignment;
-  }
-
-  return securitySectionView.get();
-}
-
-// Create and return a subview for the site settings and add it to the given
-// |superview|. |superview| retains the new view.
-- (NSView*)addSiteSettingsSectionToView:(NSView*)superview {
-  base::scoped_nsobject<NSView> siteSettingsSectionView(
-      [[FlippedView alloc] initWithFrame:[superview frame]]);
-  [superview addSubview:siteSettingsSectionView];
-
-  permissionsView_ =
-      [[[FlippedView alloc] initWithFrame:[superview frame]] autorelease];
-  [siteSettingsSectionView addSubview:permissionsView_];
-
-  // The certificate section is created on demand.
-  certificateView_ = nil;
-
-  // Initialize the two containers that hold the controls. The initial frames
-  // are arbitrary, and will be adjusted after the controls are laid out.
-  PageInfoUI::PermissionInfo info;
-  info.type = CONTENT_SETTINGS_TYPE_COOKIES;
-  info.setting = CONTENT_SETTING_ALLOW;
-  cookiesView_ = [self
-      addInspectLinkToView:siteSettingsSectionView
-               sectionIcon:GetNSImageFromImageSkia(
-                               PageInfoUI::GetPermissionIcon(
-                                   info, GetRelatedTextColor()))
-              sectionTitle:l10n_util::GetStringUTF16(IDS_PAGE_INFO_COOKIES)
-                  linkText:l10n_util::GetPluralNSStringF(
-                               IDS_PAGE_INFO_NUM_COOKIES, 0)];
-  [cookiesView_ setLinkTarget:self
-                   withAction:@selector(showCookiesAndSiteData:)];
-
-  // Create the link button to view site settings. Its position will be set in
-  // performLayout.
-  NSString* siteSettingsButtonText =
-      l10n_util::GetNSString(IDS_PAGE_INFO_SITE_SETTINGS_LINK);
-  siteSettingsButton_ = [self addButtonWithText:siteSettingsButtonText
-                                         toView:siteSettingsSectionView];
-  [GTMUILocalizerAndLayoutTweaker sizeToFitView:siteSettingsButton_];
-
-  [siteSettingsButton_ setTarget:self];
-  [siteSettingsButton_ setAction:@selector(showSiteSettingsData:)];
-
-  return siteSettingsSectionView.get();
-}
-
-- (InspectLinkView*)addInspectLinkToView:(NSView*)superview
-                             sectionIcon:(NSImage*)imageIcon
-                            sectionTitle:(const base::string16&)titleText
-                                linkText:(NSString*)linkText {
-  // Create the subview.
-  base::scoped_nsobject<InspectLinkView> newView(
-      [[InspectLinkView alloc] initWithFrame:[superview frame]]);
-  [superview addSubview:newView];
-
-  bool isRTL = base::i18n::IsRTL();
-  NSPoint controlOrigin = NSMakePoint(kSectionHorizontalPadding, 0);
-
-  CGFloat viewWidth = NSWidth([newView frame]);
-
-  // Reset X for the icon.
-  if (isRTL) {
-    controlOrigin.x =
-        viewWidth - kPermissionImageSize - kSectionHorizontalPadding;
-  }
-
-  NSImageView* imageView = [self addImageWithSize:[imageIcon size]
-                                           toView:newView
-                                          atPoint:controlOrigin];
-  [imageView setImage:imageIcon];
-
-  NSButton* actionLink = [self addLinkButtonWithText:linkText toView:newView];
-  [newView setActionLink:actionLink];
-
-  if (isRTL) {
-    controlOrigin.x -= kPermissionImageSpacing;
-    NSTextField* sectionTitle = [self addText:titleText
-                                     withSize:[NSFont systemFontSize]
-                                         bold:NO
-                                       toView:newView
-                                      atPoint:controlOrigin];
-    [sectionTitle sizeToFit];
-
-    NSPoint sectionTitleOrigin = [sectionTitle frame].origin;
-    sectionTitleOrigin.x -= NSWidth([sectionTitle frame]);
-    [sectionTitle setFrameOrigin:sectionTitleOrigin];
-
-    // Align the icon with the text.
-    [self alignPermissionIcon:imageView withTextField:sectionTitle];
-
-    controlOrigin.y +=
-        NSHeight([sectionTitle frame]) + kPermissionLabelBottomPadding;
-    controlOrigin.x -= NSWidth([actionLink frame]) - kLinkButtonXAdjustment;
-    [actionLink setFrameOrigin:controlOrigin];
-  } else {
-    controlOrigin.x += kPermissionImageSize + kPermissionImageSpacing;
-    NSTextField* sectionTitle = [self addText:titleText
-                                     withSize:[NSFont systemFontSize]
-                                         bold:NO
-                                       toView:newView
-                                      atPoint:controlOrigin];
-    [sectionTitle sizeToFit];
-
-    // Align the icon with the text.
-    [self alignPermissionIcon:imageView withTextField:sectionTitle];
-
-    controlOrigin.y +=
-        NSHeight([sectionTitle frame]) + kPermissionLabelBottomPadding;
-    controlOrigin.x -= kLinkButtonXAdjustment;
-    [actionLink setFrameOrigin:controlOrigin];
-  }
-
-  controlOrigin.y += NSHeight([actionLink frame]);
-  [newView setFrameSize:NSMakeSize(NSWidth([newView frame]), controlOrigin.y)];
-
-  return newView.get();
-}
-
-// Handler for the link button below the list of cookies.
-- (void)showCookiesAndSiteData:(id)sender {
-  DCHECK(webContents_);
-  DCHECK(presenter_);
-  presenter_->RecordPageInfoAction(PageInfo::PAGE_INFO_COOKIES_DIALOG_OPENED);
-  TabDialogs::FromWebContents(webContents_)->ShowCollectedCookies();
-}
-
-// Handler for the site settings button below the list of permissions.
-- (void)showSiteSettingsData:(id)sender {
-  DCHECK(webContents_);
-  DCHECK(presenter_);
-  presenter_->OpenSiteSettingsView();
-}
-
-- (void)openConnectionHelp:(id)sender {
-  DCHECK(webContents_);
-  DCHECK(presenter_);
-  presenter_->RecordPageInfoAction(PageInfo::PAGE_INFO_CONNECTION_HELP_OPENED);
-  webContents_->OpenURL(content::OpenURLParams(
-      GURL(chrome::kPageInfoHelpCenterURL), content::Referrer(),
-      WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK,
-      false));
-}
-
-// Handler for the link button to show certificate information.
-- (void)showCertificateInfo:(id)sender {
-  DCHECK(certificate_.get());
-  DCHECK(presenter_);
-  presenter_->RecordPageInfoAction(
-      PageInfo::PAGE_INFO_CERTIFICATE_DIALOG_OPENED);
-  ShowCertificateViewer(webContents_, [self parentWindow], certificate_.get());
-}
-
-// Handler for the link button to revoke user certificate decisions.
-- (void)resetCertificateDecisions:(id)sender {
-  DCHECK(resetDecisionsButton_);
-  presenter_->OnRevokeSSLErrorBypassButtonPressed();
-  [self close];
-}
-
-// Handler for the button to change password decisions.
-- (void)changePasswordDecisions:(id)sender {
-  DCHECK(changePasswordButton_);
-  presenter_->OnChangePasswordButtonPressed(webContents_);
-  [self close];
-}
-
-// Handler for the button to whitelist password reuse decisions.
-- (void)whitelistPasswordReuseDecisions:(id)sender {
-  DCHECK(whitelistPasswordReuseButton_);
-  presenter_->OnWhitelistPasswordReuseButtonPressed(webContents_);
-  [self close];
-}
-
-- (CGFloat)layoutViewAtRTLStart:(NSView*)view withYPosition:(CGFloat)yPos {
-  CGFloat xPos;
-  if (base::i18n::IsRTL()) {
-    xPos = kDefaultWindowWidth - kSectionHorizontalPadding -
-           NSWidth([view frame]) + kNSButtonBuiltinMargin;
-  } else {
-    xPos = kSectionHorizontalPadding - kNSButtonBuiltinMargin;
-  }
-  [view setFrameOrigin:NSMakePoint(xPos, yPos - kNSButtonBuiltinMargin)];
-  return yPos + NSHeight([view frame]) - kNSButtonBuiltinMargin;
-}
-
-// Set the Y position of |view| to the given position, and return the position
-// of its bottom edge.
-- (CGFloat)setYPositionOfView:(NSView*)view to:(CGFloat)position {
-  NSRect frame = [view frame];
-  frame.origin.y = position;
-  [view setFrame:frame];
-  return position + NSHeight(frame);
-}
-
-- (void)setWidthOfView:(NSView*)view to:(CGFloat)width {
-  [view setFrameSize:NSMakeSize(width, NSHeight([view frame]))];
-}
-
-- (void)setHeightOfView:(NSView*)view to:(CGFloat)height {
-  [view setFrameSize:NSMakeSize(NSWidth([view frame]), height)];
-}
-
-// Layout all of the controls in the window. This should be called whenever
-// the content has changed.
-- (void)performLayout {
-  // Skip layout if the bubble is closing.
-  InfoBubbleWindow* bubbleWindow =
-      base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]);
-  if ([bubbleWindow isClosing])
-    return;
-
-  // Make the content at least as wide as the permissions view.
-  CGFloat contentWidth =
-      std::max([self defaultWindowWidth], NSWidth([permissionsView_ frame]));
-
-  // Set the width of the content view now, so that all the text fields will
-  // be sized to fit before their heights and vertical positions are adjusted.
-  [self setWidthOfView:contentView_ to:contentWidth];
-  [self setWidthOfView:securitySectionView_ to:contentWidth];
-  [self setWidthOfView:siteSettingsSectionView_ to:contentWidth];
-
-  CGFloat yPos = 0;
-
-  [self layoutSecuritySection];
-  yPos = [self setYPositionOfView:securitySectionView_ to:yPos];
-
-  yPos = [self setYPositionOfView:separatorAfterSecuritySection_ to:yPos];
-
-  [self layoutSiteSettingsSection];
-  yPos = [self setYPositionOfView:siteSettingsSectionView_ to:yPos];
-
-  [contentView_ setFrame:NSMakeRect(0, 0, NSWidth([contentView_ frame]), yPos)];
-
-  [self sizeAndPositionWindow];
-}
-
-- (void)layoutSecuritySection {
-  // Margins are handled by the caller.
-  CGFloat yPos = 0;
-
-  [self sizeTextFieldHeightToFit:securitySummaryField_];
-  yPos = [self setYPositionOfView:securitySummaryField_
-                               to:yPos + kSectionVerticalPadding];
-
-  [self sizeTextFieldHeightToFit:securityDetailsField_];
-  yPos = [self setYPositionOfView:securityDetailsField_
-                               to:yPos + kSecurityParagraphSpacing];
-
-  // A common anchor point for link elements
-  CGFloat linkY = kSectionHorizontalPadding - kLinkButtonXAdjustment;
-
-  NSPoint helpOrigin = NSMakePoint(linkY, yPos);
-  if (base::i18n::IsRTL()) {
-    helpOrigin.x = NSWidth([contentView_ frame]) - helpOrigin.x -
-                   NSWidth(connectionHelpButton_.frame);
-  }
-  [connectionHelpButton_ setFrameOrigin:helpOrigin];
-  yPos = NSMaxY([connectionHelpButton_ frame]);
-
-  if (resetDecisionsButton_) {
-    DCHECK(resetDecisionsField_);
-    yPos = [self setYPositionOfView:resetDecisionsField_
-                                 to:yPos + kSecurityParagraphSpacing];
-
-    NSPoint resetOrigin = NSMakePoint(linkY, yPos);
-    if (base::i18n::IsRTL()) {
-      resetOrigin.x = NSWidth([contentView_ frame]) - resetOrigin.x -
-                      NSWidth(resetDecisionsButton_.frame);
-    }
-    [resetDecisionsButton_ setFrameOrigin:resetOrigin];
-    yPos = NSMaxY([resetDecisionsButton_ frame]);
-  }
-
-  if (changePasswordButton_) {
-    NSPoint changePasswordButtonOrigin;
-    NSPoint whitelistReuseButtonOrigin;
-    CGFloat viewWidth = NSWidth([contentView_ frame]);
-    CGFloat changePasswordButtonWidth = NSWidth([changePasswordButton_ frame]);
-    CGFloat whitelistReuseButtonWidth =
-        NSWidth([whitelistPasswordReuseButton_ frame]);
-    CGFloat horizontalPadding =
-        kSectionHorizontalPadding - kNSButtonBuiltinMargin;
-    bool canFitInOneLine = changePasswordButtonWidth +
-                               whitelistReuseButtonWidth +
-                               2 * horizontalPadding <=
-                           viewWidth;
-    bool isRTL = base::i18n::IsRTL();
-    // Buttons are left-aligned for LTR languages, and are right aligned for
-    // RTL languages. Button order follows OSX convention.
-    if (canFitInOneLine) {
-      whitelistReuseButtonOrigin.y = changePasswordButtonOrigin.y =
-          yPos + kSecurityParagraphSpacing;
-      if (isRTL) {
-        whitelistReuseButtonOrigin.x =
-            viewWidth - whitelistReuseButtonWidth - horizontalPadding;
-        changePasswordButtonOrigin.x =
-            whitelistReuseButtonOrigin.x - changePasswordButtonWidth;
-      } else {
-        whitelistReuseButtonOrigin.x = horizontalPadding;
-        changePasswordButtonOrigin.x =
-            whitelistReuseButtonOrigin.x + whitelistReuseButtonWidth;
-      }
-    } else {
-      // If these buttons cannot fit in one line, stack them vertically.
-      CGFloat buttonWidth = viewWidth - 2 * horizontalPadding;
-      whitelistReuseButtonOrigin.x = horizontalPadding;
-      whitelistReuseButtonOrigin.y = yPos + kSecurityParagraphSpacing;
-      [whitelistPasswordReuseButton_
-          setFrameSize:NSMakeSize(
-                           buttonWidth,
-                           NSHeight([whitelistPasswordReuseButton_ frame]))];
-      changePasswordButtonOrigin.x = horizontalPadding;
-      changePasswordButtonOrigin.y =
-          yPos + kSecurityParagraphSpacing +
-          NSHeight([whitelistPasswordReuseButton_ frame]);
-      [changePasswordButton_
-          setFrameSize:NSMakeSize(buttonWidth,
-                                  NSHeight([changePasswordButton_ frame]))];
-    }
-    [changePasswordButton_ setFrameOrigin:changePasswordButtonOrigin];
-    [whitelistPasswordReuseButton_ setFrameOrigin:whitelistReuseButtonOrigin];
-    yPos = NSMaxY([changePasswordButton_ frame]) - kNSButtonBuiltinMargin;
-  }
-
-  // Resize the height based on contents.
-  [self setHeightOfView:securitySectionView_ to:yPos + kSectionVerticalPadding];
-}
-
-- (void)layoutSiteSettingsSection {
-  // Margins are handled by the caller.
-  CGFloat yPos = 0;
-
-  yPos = [self setYPositionOfView:permissionsView_ to:yPos] +
-         kPermissionsVerticalSpacing;
-
-  if (certificateView_) {
-    yPos = [self setYPositionOfView:certificateView_ to:yPos] +
-           kPermissionsVerticalSpacing;
-  }
-
-  yPos =
-      [self setYPositionOfView:cookiesView_ to:yPos] + kSectionVerticalPadding;
-
-  yPos = [self layoutViewAtRTLStart:siteSettingsButton_ withYPosition:yPos] +
-         kSectionVerticalPadding;
-
-  // Resize the height based on contents.
-  [self setHeightOfView:siteSettingsSectionView_ to:yPos];
-}
-
-// Adjust the size of the window to match the size of the content, and position
-// the bubble anchor appropriately.
-- (void)sizeAndPositionWindow {
-  NSRect windowFrame = [contentView_ frame];
-  windowFrame.size =
-      [[[self window] contentView] convertSize:windowFrame.size toView:nil];
-  // Adjust the origin by the difference in height.
-  windowFrame.origin = [[self window] frame].origin;
-  windowFrame.origin.y -=
-      NSHeight(windowFrame) - NSHeight([[self window] frame]);
-
-  // Resize the window. Only animate if the window is visible, otherwise it
-  // could be "growing" while it's opening, looking awkward.
-  [[self window] setFrame:windowFrame
-                  display:YES
-                  animate:[[self window] isVisible]];
-
-  // Adjust the anchor for the bubble.
-  [self setAnchorPoint:AnchorPointForWindow([self parentWindow])];
-}
-
-// Sets properties on the given |field| to act as the title or description
-// labels in the bubble.
-- (void)configureTextFieldAsLabel:(NSTextField*)textField {
-  [textField setEditable:NO];
-  [textField setSelectable:YES];
-  [textField setDrawsBackground:NO];
-  [textField setBezeled:NO];
-}
-
-// Adjust the height of the given text field to match its text.
-- (void)sizeTextFieldHeightToFit:(NSTextField*)textField {
-  NSRect frame = [textField frame];
-  frame.size.height +=
-      [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:textField];
-  [textField setFrame:frame];
-}
-
-// Create a new text field and add it to the given array of subviews.
-// The array will retain a reference to the object.
-- (NSTextField*)addText:(const base::string16&)text
-               withSize:(CGFloat)fontSize
-                   bold:(BOOL)bold
-                 toView:(NSView*)view
-                atPoint:(NSPoint)point {
-  // Size the text to take up the full available width, with some padding.
-  // The height is arbitrary as it will be adjusted later.
-  CGFloat width = NSWidth([view frame]) - point.x - kSectionHorizontalPadding;
-  NSRect frame = NSMakeRect(point.x, point.y, width, 100);
-  base::scoped_nsobject<NSTextField> textField(
-      [[NSTextField alloc] initWithFrame:frame]);
-  [self configureTextFieldAsLabel:textField.get()];
-  [textField setStringValue:base::SysUTF16ToNSString(text)];
-  NSFont* font = bold ? [NSFont boldSystemFontOfSize:fontSize]
-                      : [NSFont systemFontOfSize:fontSize];
-  [textField setFont:font];
-  [self sizeTextFieldHeightToFit:textField];
-  [textField setAutoresizingMask:NSViewWidthSizable];
-  [view addSubview:textField.get()];
-  return textField.get();
-}
-
-// Add an image as a subview of the given view, placed at a pre-determined x
-// position and the given y position. The image is not in the accessibility
-// order, since the image is always accompanied by text in this bubble. Return
-// the new NSImageView.
-- (NSImageView*)addImageWithSize:(NSSize)size
-                          toView:(NSView*)view
-                         atPoint:(NSPoint)point {
-  NSRect frame = NSMakeRect(point.x, point.y, size.width, size.height);
-  base::scoped_nsobject<NSImageView> imageView(
-      [[NSImageView alloc] initWithFrame:frame]);
-  ui::a11y_util::HideImageFromAccessibilityOrder(imageView);
-  [imageView setImageFrameStyle:NSImageFrameNone];
-  [view addSubview:imageView.get()];
-  return imageView.get();
-}
-
-// Add a separator as a subview of the given view. Return the new view.
-- (NSView*)addSeparatorToView:(NSView*)view {
-  // Use an arbitrary position; it will be adjusted in performLayout.
-  NSBox* spacer = [self
-      horizontalSeparatorWithFrame:NSMakeRect(0, 0, NSWidth([view frame]), 0)];
-  [view addSubview:spacer];
-  return spacer;
-}
-
-// Add a link button with the given text to |view|.
-- (NSButton*)addLinkButtonWithText:(NSString*)text toView:(NSView*)view {
-  // Frame size is arbitrary; it will be adjusted by the layout tweaker.
-  NSRect frame = NSMakeRect(kSectionHorizontalPadding, 0, 100, 10);
-  base::scoped_nsobject<NSButton> button(
-      [[NSButton alloc] initWithFrame:frame]);
-  base::scoped_nsobject<HyperlinkButtonCell> cell(
-      [[HyperlinkButtonCell alloc] initTextCell:text]);
-  [cell setControlSize:NSSmallControlSize];
-  [button setCell:cell.get()];
-  [button setButtonType:NSMomentaryPushInButton];
-  [button setBezelStyle:NSRegularSquareBezelStyle];
-  [view addSubview:button.get()];
-
-  [GTMUILocalizerAndLayoutTweaker sizeToFitView:button.get()];
-  return button.get();
-}
-
-// Create and return a button with the specified text and add it to the given
-// |view|. |view| retains the new button.
-- (NSButton*)addButtonWithText:(NSString*)text toView:(NSView*)view {
-  NSRect containerFrame = [view frame];
-  // Frame size is arbitrary; it will be adjusted by the layout tweaker.
-  NSRect frame = NSMakeRect(kSectionHorizontalPadding, 0, 100, 10);
-  base::scoped_nsobject<NSButton> button(
-      [[NSButton alloc] initWithFrame:frame]);
-
-  // Determine the largest possible size for this button. The size is the width
-  // of the connection section minus the padding on both sides minus the
-  // connection image size and spacing.
-  CGFloat maxTitleWidth =
-      containerFrame.size.width - kSectionHorizontalPadding * 2;
-
-  base::scoped_nsobject<NSButtonCell> cell(
-      [[NSButtonCell alloc] initTextCell:text]);
-  [button setCell:cell.get()];
-  [GTMUILocalizerAndLayoutTweaker sizeToFitView:button.get()];
-
-  // Ensure the containing view is large enough to contain the button with its
-  // widest possible title.
-  NSRect buttonFrame = [button frame];
-  buttonFrame.size.width = maxTitleWidth;
-
-  [button setFrame:buttonFrame];
-  [button setButtonType:NSMomentaryPushInButton];
-  [button setBezelStyle:NSRegularSquareBezelStyle];
-  [view addSubview:button.get()];
-
-  return button.get();
-}
-
-// Set the content of the identity and identity status fields, and add the
-// Certificate view or password reuse buttons if applicable.
-- (void)setIdentityInfo:(const PageInfoUI::IdentityInfo&)identityInfo {
-  std::unique_ptr<PageInfoUI::SecurityDescription> security_description =
-      identityInfo.GetSecurityDescription();
-  [securitySummaryField_
-      setStringValue:base::SysUTF16ToNSString(security_description->summary)];
-
-  [securityDetailsField_
-      setStringValue:base::SysUTF16ToNSString(security_description->details)];
-
-  certificate_ = identityInfo.certificate;
-
-  if (certificate_) {
-    if (identityInfo.show_ssl_decision_revoke_button) {
-      resetDecisionsField_ =
-          [self addText:base::string16()
-               withSize:[NSFont smallSystemFontSize]
-                   bold:NO
-                 toView:securitySectionView_
-                atPoint:NSMakePoint(kSectionHorizontalPadding, 0)];
-      [resetDecisionsField_
-          setStringValue:l10n_util::GetNSString(
-                             IDS_PAGE_INFO_INVALID_CERTIFICATE_DESCRIPTION)];
-      [self sizeTextFieldHeightToFit:resetDecisionsField_];
-
-      resetDecisionsButton_ = [self
-          addLinkButtonWithText:
-              l10n_util::GetNSString(
-                  IDS_PAGE_INFO_RESET_INVALID_CERTIFICATE_DECISIONS_BUTTON)
-                         toView:securitySectionView_];
-      [resetDecisionsButton_ setTarget:self];
-      [resetDecisionsButton_ setAction:@selector(resetCertificateDecisions:)];
-
-      if (base::i18n::IsRTL()) {
-        resetDecisionsField_.alignment = NSRightTextAlignment;
-      }
-    }
-
-    // Show information about the page's certificate.
-    bool isValid =
-        (identityInfo.identity_status != PageInfo::SITE_IDENTITY_STATUS_ERROR);
-    NSString* linkText = l10n_util::GetNSString(
-        isValid ? IDS_PAGE_INFO_CERTIFICATE_VALID_LINK
-                : IDS_PAGE_INFO_CERTIFICATE_INVALID_LINK);
-
-    certificateView_ =
-        [self addInspectLinkToView:siteSettingsSectionView_
-                       sectionIcon:NSImageFromImageSkia(
-                                       PageInfoUI::GetCertificateIcon(
-                                           GetRelatedTextColor()))
-                      sectionTitle:l10n_util::GetStringUTF16(
-                                       IDS_PAGE_INFO_CERTIFICATE)
-                          linkText:linkText];
-    if (isValid) {
-      [certificateView_
-          setLinkToolTip:l10n_util::GetNSStringF(
-                             IDS_PAGE_INFO_CERTIFICATE_VALID_LINK_TOOLTIP,
-                             base::UTF8ToUTF16(
-                                 certificate_->issuer().GetDisplayName()))];
-    } else {
-      [certificateView_
-          setLinkToolTip:l10n_util::GetNSString(
-                             IDS_PAGE_INFO_CERTIFICATE_INVALID_LINK_TOOLTIP)];
-    }
-
-    [certificateView_ setLinkTarget:self
-                         withAction:@selector(showCertificateInfo:)];
-  }
-  if (identityInfo.show_change_password_buttons) {
-    whitelistPasswordReuseButton_ = [ButtonUtils
-        buttonWithTitle:l10n_util::GetNSString(
-                            IDS_PAGE_INFO_WHITELIST_PASSWORD_REUSE_BUTTON)
-                 action:@selector(whitelistPasswordReuseDecisions:)
-                 target:self];
-    [whitelistPasswordReuseButton_ sizeToFit];
-    [whitelistPasswordReuseButton_ setKeyEquivalent:kKeyEquivalentEscape];
-    [securitySectionView_ addSubview:whitelistPasswordReuseButton_];
-    changePasswordButton_ =
-        [ButtonUtils buttonWithTitle:l10n_util::GetNSString(
-                                         IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON)
-                              action:@selector(changePasswordDecisions:)
-                              target:self];
-    [changePasswordButton_ sizeToFit];
-    [changePasswordButton_ setKeyEquivalent:kKeyEquivalentReturn];
-    [securitySectionView_ addSubview:changePasswordButton_];
-  }
-
-  [self performLayout];
-}
-
-// Add a pop-up button for |permissionInfo| to the given view.
-- (NSPopUpButton*)addPopUpButtonForPermission:
-                      (const PageInfoUI::PermissionInfo&)permissionInfo
-                                       toView:(NSView*)view
-                                      atPoint:(NSPoint)point {
-  GURL url = webContents_ ? webContents_->GetURL() : GURL();
-  __block PageInfoBubbleController* weakSelf = self;
-  PermissionMenuModel::ChangeCallback callback = base::BindRepeating(
-      base::RetainBlock(^(const PageInfoUI::PermissionInfo& permission) {
-        [weakSelf onPermissionChanged:permission.type to:permission.setting];
-      }));
-  base::scoped_nsobject<PermissionSelectorButton> button(
-      [[PermissionSelectorButton alloc] initWithPermissionInfo:permissionInfo
-                                                        forURL:url
-                                                  withCallback:callback
-                                                       profile:[self profile]]);
-
-  // Determine the largest possible size for this button.
-  CGFloat maxTitleWidth =
-      [button maxTitleWidthForContentSettingsType:permissionInfo.type
-                               withDefaultSetting:permissionInfo.default_setting
-                                          profile:[self profile]];
-
-  // Ensure the containing view is large enough to contain the button with its
-  // widest possible title.
-  NSRect containerFrame = [view frame];
-  containerFrame.size.width =
-      std::max(NSWidth(containerFrame),
-               point.x + maxTitleWidth + kSectionHorizontalPadding);
-  [view setFrame:containerFrame];
-  [view addSubview:button.get()];
-
-  // Tag the button with the permission type so it can be updated later.
-  [button setTag:permissionInfo.type];
-  return button.get();
-}
-
-// Add a delete button for |objectInfo| to the given view.
-- (NSButton*)addDeleteButtonForChosenObject:(ChosenObjectInfoPtr)objectInfo
-                                     toView:(NSView*)view
-                                    atPoint:(NSPoint)point {
-  __block PageInfoBubbleController* weakSelf = self;
-  auto callback = base::BindRepeating(
-      base::RetainBlock(^(const PageInfoUI::ChosenObjectInfo& objectInfo) {
-        [weakSelf onChosenObjectDeleted:objectInfo];
-      }));
-  base::scoped_nsobject<ChosenObjectDeleteButton> button(
-      [[ChosenObjectDeleteButton alloc]
-          initWithChosenObject:std::move(objectInfo)
-                       atPoint:point
-                  withCallback:callback]);
-
-  // Ensure the containing view is large enough to contain the button.
-  NSRect containerFrame = [view frame];
-  containerFrame.size.width =
-      std::max(NSWidth(containerFrame), point.x + kPermissionDeleteImageSize +
-                                            kSectionHorizontalPadding);
-  [view setFrame:containerFrame];
-  [view addSubview:button.get()];
-  [button setTag:kChosenObjectTag];
-  return button.get();
-}
-
-// Called when the user changes the setting of a permission.
-- (void)onPermissionChanged:(ContentSettingsType)permissionType
-                         to:(ContentSetting)newSetting {
-  if (presenter_)
-    presenter_->OnSitePermissionChanged(permissionType, newSetting);
-}
-
-// Called when the user revokes permission for a previously chosen object.
-- (void)onChosenObjectDeleted:(const PageInfoUI::ChosenObjectInfo&)info {
-  if (presenter_)
-    presenter_->OnSiteChosenObjectDeleted(info.ui_info, *info.object);
-}
-
-// Adds a new row to the UI listing the permissions. Returns the NSPoint of the
-// last UI element added (either the permission button, in LTR, or the text
-// label, in RTL).
-- (NSPoint)addPermission:(const PageInfoUI::PermissionInfo&)permissionInfo
-                  toView:(NSView*)view
-                 atPoint:(NSPoint)point {
-  base::string16 labelText =
-      PageInfoUI::PermissionTypeToUIString(permissionInfo.type);
-  bool isRTL = base::i18n::IsRTL();
-  base::scoped_nsobject<NSImage> image(
-      [GetNSImageFromImageSkia(PageInfoUI::GetPermissionIcon(
-          permissionInfo, GetRelatedTextColor())) retain]);
-
-  NSPoint position;
-  NSImageView* imageView;
-  NSPopUpButton* button;
-  NSTextField* label;
-
-  CGFloat viewWidth = NSWidth([view frame]);
-
-  if (isRTL) {
-    point.x = NSWidth([view frame]) - kPermissionImageSize -
-              kSectionHorizontalPadding;
-    imageView = [self addImageWithSize:[image size] toView:view atPoint:point];
-    [imageView setImage:image];
-    point.x -= kPermissionImageSpacing;
-
-    label = [self addText:labelText
-                 withSize:[NSFont systemFontSize]
-                     bold:NO
-                   toView:view
-                  atPoint:point];
-    [label sizeToFit];
-    point.x -= NSWidth([label frame]);
-    [label setFrameOrigin:point];
-
-    position =
-        NSMakePoint(point.x, point.y + kPermissionPopupButtonYAdjustment);
-    button = [self addPopUpButtonForPermission:permissionInfo
-                                        toView:view
-                                       atPoint:position];
-    position.x -= NSWidth([button frame]);
-    [button setFrameOrigin:position];
-  } else {
-    imageView = [self addImageWithSize:[image size] toView:view atPoint:point];
-    [imageView setImage:image];
-    point.x += kPermissionImageSize + kPermissionImageSpacing;
-
-    label = [self addText:labelText
-                 withSize:[NSFont systemFontSize]
-                     bold:NO
-                   toView:view
-                  atPoint:point];
-    [label sizeToFit];
-
-    position = NSMakePoint(NSMaxX([label frame]),
-                           point.y + kPermissionPopupButtonYAdjustment);
-
-    button = [self addPopUpButtonForPermission:permissionInfo
-                                        toView:view
-                                       atPoint:position];
-  }
-  [label setToolTip:base::SysUTF16ToNSString(labelText)];
-
-  [view setFrameSize:NSMakeSize(viewWidth, NSHeight([view frame]))];
-
-  // Adjust the vertical position of the button so that its title text is
-  // aligned with the label. Assumes that the text is the same size in both.
-  // Also adjust the horizontal position to remove excess space due to the
-  // invisible bezel.
-  NSRect titleRect = [[button cell] titleRectForBounds:[button bounds]];
-  if (isRTL) {
-    position.x = kSectionHorizontalPadding;
-  } else {
-    position.x = kDefaultWindowWidth - kSectionHorizontalPadding -
-                 [button frame].size.width;
-  }
-  position.y -= titleRect.origin.y;
-  [button setFrameOrigin:position];
-
-  // Truncate the label if it's too wide.
-  // This is a workaround for https://crbug.com/654268 until MacViews ships.
-  NSRect labelFrame = [label frame];
-  if (isRTL) {
-    CGFloat maxLabelWidth = NSMaxX(labelFrame) - NSMaxX([button frame]) -
-                            kMinSeparationBetweenLabelAndMenu;
-    if (NSWidth(labelFrame) > maxLabelWidth) {
-      labelFrame.origin.x = NSMaxX(labelFrame) - maxLabelWidth;
-      labelFrame.size.width = maxLabelWidth;
-      [label setFrame:labelFrame];
-      [[label cell] setLineBreakMode:NSLineBreakByTruncatingTail];
-    }
-  } else {
-    CGFloat maxLabelWidth = NSMinX([button frame]) - NSMinX(labelFrame) -
-                            kMinSeparationBetweenLabelAndMenu;
-    if (NSWidth(labelFrame) > maxLabelWidth) {
-      labelFrame.size.width = maxLabelWidth;
-      [label setFrame:labelFrame];
-      [[label cell] setLineBreakMode:NSLineBreakByTruncatingTail];
-    }
-  }
-
-  // Align the icon with the text.
-  [self alignPermissionIcon:imageView withTextField:label];
-
-  // Permissions specified by policy or an extension cannot be changed.
-  if (permissionInfo.source == content_settings::SETTING_SOURCE_EXTENSION ||
-      permissionInfo.source == content_settings::SETTING_SOURCE_POLICY) {
-    [button setEnabled:NO];
-  }
-
-  // Update |point| to match the y of the bottomost UI element added (|button|).
-  NSRect buttonFrame = [button frame];
-  point.y = NSMaxY(labelFrame) + kPermissionLabelBottomPadding;
-
-  // Show the reason for the permission decision in a new row if it did not come
-  // from the user.
-  base::string16 reason = PageInfoUI::PermissionDecisionReasonToUIString(
-      [self profile], permissionInfo, url_);
-  if (!reason.empty()) {
-    // Do this even in RTL to make sure -addText sets the right width for the
-    // permission decision reason label.
-    point.x = kSectionHorizontalPadding + kPermissionImageSize +
-              kPermissionImageSpacing;
-
-    label = [self addText:reason
-                 withSize:[NSFont smallSystemFontSize]
-                     bold:NO
-                   toView:view
-                  atPoint:point];
-    if (isRTL) {
-      [label setAlignment:NSRightTextAlignment];
-      // Shift the reason left to align the permission label and the permission
-      // decision reason's right edges.
-      point.x -= (kPermissionImageSize + kPermissionImageSpacing);
-      [label setFrameOrigin:point];
-    }
-
-    label.textColor =
-        skia::SkColorToSRGBNSColor(PageInfoUI::GetSecondaryTextColor());
-    point.y += NSHeight(label.frame);
-  }
-
-  return NSMakePoint(NSMaxX(buttonFrame), point.y);
-}
-
-// Adds a new row to the UI listing the permissions. Returns the NSPoint of the
-// last UI element added (either the permission button, in LTR, or the text
-// label, in RTL).
-- (NSPoint)addChosenObject:(ChosenObjectInfoPtr)objectInfo
-                    toView:(NSView*)view
-                   atPoint:(NSPoint)point {
-  base::string16 labelText = l10n_util::GetStringFUTF16(
-      objectInfo->ui_info.label_string_id,
-      PageInfoUI::ChosenObjectToUIString(*objectInfo));
-  bool isRTL = base::i18n::IsRTL();
-  base::scoped_nsobject<NSImage> image(
-      [GetNSImageFromImageSkia(PageInfoUI::GetChosenObjectIcon(
-          *objectInfo, false, GetRelatedTextColor())) retain]);
-
-  NSPoint position;
-  NSImageView* imageView;
-  NSButton* button;
-  NSTextField* label;
-
-  CGFloat viewWidth = NSWidth([view frame]);
-
-  if (isRTL) {
-    point.x = NSWidth([view frame]) - kPermissionImageSize -
-              kPermissionImageSpacing - kSectionHorizontalPadding;
-    imageView = [self addImageWithSize:[image size] toView:view atPoint:point];
-    [imageView setImage:image];
-    point.x -= kPermissionImageSpacing;
-
-    label = [self addText:labelText
-                 withSize:[NSFont systemFontSize]
-                     bold:NO
-                   toView:view
-                  atPoint:point];
-    [label sizeToFit];
-    point.x -= NSWidth([label frame]);
-    [label setFrameOrigin:point];
-
-    position = NSMakePoint(point.x, point.y);
-    button = [self addDeleteButtonForChosenObject:std::move(objectInfo)
-                                           toView:view
-                                          atPoint:position];
-    position.x -= NSWidth([button frame]);
-    [button setFrameOrigin:position];
-  } else {
-    imageView = [self addImageWithSize:[image size] toView:view atPoint:point];
-    [imageView setImage:image];
-    point.x += kPermissionImageSize + kPermissionImageSpacing;
-
-    label = [self addText:labelText
-                 withSize:[NSFont systemFontSize]
-                     bold:NO
-                   toView:view
-                  atPoint:point];
-    [label sizeToFit];
-
-    position = NSMakePoint(NSMaxX([label frame]), point.y);
-    button = [self addDeleteButtonForChosenObject:std::move(objectInfo)
-                                           toView:view
-                                          atPoint:position];
-  }
-  [imageView setTag:kChosenObjectTag];
-  [label setTag:kChosenObjectTag];
-
-  [view setFrameSize:NSMakeSize(viewWidth, NSHeight([view frame]))];
-
-  // Adjust the vertical position of the button so that its title text is
-  // aligned with the label. Assumes that the text is the same size in both.
-  // Also adjust the horizontal position to remove excess space due to the
-  // invisible bezel.
-  NSRect titleRect = [[button cell] titleRectForBounds:[button bounds]];
-  position.y -= titleRect.origin.y;
-  [button setFrameOrigin:position];
-
-  // Align the icon with the text.
-  [self alignPermissionIcon:imageView withTextField:label];
-
-  NSRect buttonFrame = [button frame];
-  return NSMakePoint(NSMaxX(buttonFrame), NSMaxY(buttonFrame));
-}
-
-// Align an image with a text field by vertically centering the image on
-// the cap height of the first line of text.
-- (void)alignPermissionIcon:(NSImageView*)imageView
-              withTextField:(NSTextField*)textField {
-  NSRect frame = [imageView frame];
-  frame.origin.y += kPermissionIconYAdjustment;
-  [imageView setFrame:frame];
-}
-
-- (void)setCookieInfo:(const CookieInfoList&)cookieInfoList {
-  // |cookieInfoList| should only ever have 2 items: first- and third-party
-  // cookies.
-  DCHECK_EQ(cookieInfoList.size(), 2u);
-
-  int totalAllowed = 0;
-  for (const auto& i : cookieInfoList) {
-    totalAllowed += i.allowed;
-  }
-
-  [cookiesView_ setLinkText:l10n_util::GetPluralNSStringF(
-                                IDS_PAGE_INFO_NUM_COOKIES, totalAllowed)];
-  [self performLayout];
-}
-
-- (void)setPermissionInfo:(const PermissionInfoList&)permissionInfoList
-         andChosenObjects:(ChosenObjectInfoList)chosenObjectInfoList {
-  NSPoint controlOrigin = NSMakePoint(kSectionHorizontalPadding, 0);
-
-  // If |permissionsView_| is already populated, just handle updates to
-  // permissions made by the user here. This will avoid removing/adding new
-  // views (and thus breaking the responder chain), and also avoid immediately
-  // removing permissions set back to the default, which could be user error.
-  // Note that "update" means setPermissionInfo will only change the title of
-  // the permission |PermissionSelectorButton|. This is OK because it is not
-  // possible for the following to occur without closing the Page Info bubble:
-  //   - a permission gets changed away from the factory default (and thus needs
-  //     to be shown in Page Info)
-  //   - a permission's source changes (and becomes disabled / needs to show a
-  //     reason).
-  if ([permissionsView_ subviews].count != 0) {
-    NSView* view = nil;
-    // Remove all the chosen object views. They will be repopulated if the site
-    // still has access to them.
-    while ((view = [permissionsView_ viewWithTag:kChosenObjectTag]))
-      [view removeFromSuperview];
-
-    for (view in [permissionsView_ subviews]) {
-      // Skip views that don't need to be modified (default tags are -1 or 0).
-      if ([view tag] <= 0)
-        continue;
-
-      ContentSettingsType permissionType =
-          static_cast<ContentSettingsType>([view tag]);
-
-      PermissionSelectorButton* button =
-          base::mac::ObjCCastStrict<PermissionSelectorButton>(view);
-      const int yOrigin = [button frame].origin.y;
-      // Permissions set back to the factory default setting will disappear from
-      // |permissionInfoList|, so use |updated| to keep track of whether
-      // |button| has been updated with its new permission value yet.
-      bool updated = false;
-      for (const auto& permission : permissionInfoList) {
-        if (permissionType != permission.type)
-          continue;
-
-        updated = true;
-        [button setButtonTitle:permission profile:[self profile]];
-        break;
-      }
-
-      if (!updated) {
-        // Permissions that are no longer in |permissionInfoList| have been set
-        // back to factory default settings.
-        PageInfoUI::PermissionInfo default_info;
-        default_info.type = permissionType;
-        default_info.setting = CONTENT_SETTING_DEFAULT;
-        default_info.default_setting =
-            content_settings::ContentSettingsRegistry::GetInstance()
-                ->Get(permissionType)
-                ->GetInitialDefaultSetting();
-        default_info.source = content_settings::SETTING_SOURCE_USER;
-        default_info.is_incognito = [self profile]->IsOffTheRecord();
-        [button setButtonTitle:default_info profile:[self profile]];
-      }
-
-      // Updating the text might have changed the width of the
-      // |PermissionSelectorRow|, so reposition here.
-      if (base::i18n::IsRTL()) {
-        [button setFrameOrigin:NSMakePoint(kSectionHorizontalPadding, yOrigin)];
-      } else {
-        [button setFrameOrigin:NSMakePoint(NSWidth([permissionsView_ frame]) -
-                                               kSectionHorizontalPadding -
-                                               NSWidth([button frame]),
-                                           yOrigin)];
-      }
-    }
-    if ([[permissionsView_ subviews] count] != 0) {
-      controlOrigin.y =
-          NSMaxY([[[permissionsView_ subviews] lastObject] frame]);
-    }
-  } else {
-    // Creates permissions views (if any) for the first time.
-    for (const auto& permission : permissionInfoList) {
-      controlOrigin.y += kPermissionsVerticalSpacing;
-      NSPoint rowBottomRight = [self addPermission:permission
-                                            toView:permissionsView_
-                                           atPoint:controlOrigin];
-      controlOrigin.y = rowBottomRight.y;
-    }
-  }
-
-  for (auto& object : chosenObjectInfoList) {
-    controlOrigin.y += kPermissionsVerticalSpacing;
-    NSPoint rowBottomRight = [self addChosenObject:std::move(object)
-                                            toView:permissionsView_
-                                           atPoint:controlOrigin];
-    controlOrigin.y = rowBottomRight.y;
-  }
-
-  // |permissionsView_| was updated here, so make sure keyboard access still
-  // works by updating the responder chain.
-  [[self window] recalculateKeyViewLoop];
-
-  [permissionsView_ setFrameSize:NSMakeSize(NSWidth([permissionsView_ frame]),
-                                            controlOrigin.y)];
-  [self performLayout];
-}
-
-@end
-
-PageInfoUIBridge::PageInfoUIBridge(content::WebContents* web_contents)
-    : content::WebContentsObserver(web_contents),
-      web_contents_(web_contents),
-      bubble_controller_(nil) {
-  DCHECK(!g_page_info_bubble);
-}
-
-PageInfoUIBridge::~PageInfoUIBridge() {
-  DCHECK(g_page_info_bubble);
-  g_page_info_bubble = nullptr;
-}
-
-void PageInfoUIBridge::set_bubble_controller(
-    PageInfoBubbleController* controller) {
-  bubble_controller_ = controller;
-  g_page_info_bubble = controller;
-}
-
-void PageInfoUIBridge::SetIdentityInfo(
-    const PageInfoUI::IdentityInfo& identity_info) {
-  [bubble_controller_ setIdentityInfo:identity_info];
-}
-
-void PageInfoUIBridge::RenderFrameDeleted(
-    content::RenderFrameHost* render_frame_host) {
-  if (render_frame_host == web_contents_->GetMainFrame()) {
-    [bubble_controller_ close];
-  }
-}
-
-void PageInfoUIBridge::SetCookieInfo(const CookieInfoList& cookie_info_list) {
-  [bubble_controller_ setCookieInfo:cookie_info_list];
-}
-
-void PageInfoUIBridge::SetPermissionInfo(
-    const PermissionInfoList& permission_info_list,
-    ChosenObjectInfoList chosen_object_info_list) {
-  [bubble_controller_ setPermissionInfo:permission_info_list
-                       andChosenObjects:std::move(chosen_object_info_list)];
-}
-
-void PageInfoUIBridge::DidFinishNavigation(
-    content::NavigationHandle* navigation_handle) {
-  if (!navigation_handle->IsInMainFrame() ||
-      !navigation_handle->HasCommitted()) {
-    return;
-  }
-  // If the browser navigates to another page, close the bubble.
-  [bubble_controller_ close];
-}
-
-void ShowPageInfoDialogImpl(Browser* browser,
-                            content::WebContents* web_contents,
-                            const GURL& virtual_url,
-                            const security_state::SecurityInfo& security_info,
-                            bubble_anchor_util::Anchor anchor) {
-  if (chrome::ShowAllDialogsWithViewsToolkit()) {
-    chrome::ShowPageInfoBubbleViews(browser, web_contents, virtual_url,
-                                    security_info, anchor);
-    return;
-  }
-
-  // Don't show the bubble if it's already being shown. Since this method is
-  // called each time the location icon is clicked, each click toggles the
-  // bubble in and out.
-  if (g_page_info_bubble)
-    return;
-
-  // Create the bridge. This will be owned by the bubble controller.
-  PageInfoUIBridge* bridge = new PageInfoUIBridge(web_contents);
-  NSWindow* parent = browser->window()->GetNativeWindow();
-
-  // Create the bubble controller. It will dealloc itself when it closes,
-  // resetting |g_page_info_bubble|.
-  PageInfoBubbleController* bubble_controller =
-      [[PageInfoBubbleController alloc] initWithParentWindow:parent
-                                            pageInfoUIBridge:bridge
-                                                 webContents:web_contents
-                                                         url:virtual_url];
-
-  if (!IsInternalURL(virtual_url)) {
-    // Initialize the presenter, which holds the model and controls the UI.
-    // This is also owned by the bubble controller.
-    PageInfo* presenter =
-        new PageInfo(bridge, browser->profile(),
-                     TabSpecificContentSettings::FromWebContents(web_contents),
-                     web_contents, virtual_url, security_info);
-    [bubble_controller setPresenter:presenter];
-  }
-
-  [bubble_controller showWindow:nil];
-}
diff --git a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller_unittest.mm
deleted file mode 100644
index ef88c91..0000000
--- a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller_unittest.mm
+++ /dev/null
@@ -1,369 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.h"
-
-#include <stddef.h>
-
-#include "base/i18n/rtl.h"
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
-#import "chrome/browser/ui/cocoa/location_bar/page_info_bubble_decoration.h"
-#import "chrome/browser/ui/cocoa/test/cocoa_profile_test.h"
-#include "content/public/test/test_web_contents_factory.h"
-#include "net/test/test_certificate_data.h"
-#include "testing/gtest_mac.h"
-
-@interface PageInfoBubbleController (ExposedForTesting)
-- (NSView*)permissionsView;
-- (NSButton*)resetDecisionsButton;
-- (NSButton*)connectionHelpButton;
-@end
-
-@implementation PageInfoBubbleController (ExposedForTesting)
-- (NSView*)permissionsView {
-  return permissionsView_;
-}
-- (NSButton*)resetDecisionsButton {
-  return resetDecisionsButton_;
-}
-- (NSButton*)connectionHelpButton {
-  return connectionHelpButton_;
-}
-- (NSButton*)changePasswordButton {
-  return changePasswordButton_;
-}
-- (NSButton*)whitelistPasswordReuseButton {
-  return whitelistPasswordReuseButton_;
-}
-@end
-
-@interface PageInfoBubbleControllerForTesting : PageInfoBubbleController {
- @private
-  CGFloat defaultWindowWidth_;
-}
-@end
-
-@implementation PageInfoBubbleControllerForTesting
-- (void)setDefaultWindowWidth:(CGFloat)width {
-  defaultWindowWidth_ = width;
-}
-- (CGFloat)defaultWindowWidth {
-  // If |defaultWindowWidth_| is 0, use the superclass implementation.
-  return defaultWindowWidth_ ? defaultWindowWidth_ : [super defaultWindowWidth];
-}
-@end
-
-namespace {
-
-// Indices of the menu items in the permission menu.
-enum PermissionMenuIndices {
-  kMenuIndexContentSettingAllow = 0,
-  kMenuIndexContentSettingBlock,
-  kMenuIndexContentSettingDefault
-};
-
-const ContentSettingsType kTestPermissionTypes[] = {
-    CONTENT_SETTINGS_TYPE_IMAGES,
-    CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
-    CONTENT_SETTINGS_TYPE_JAVASCRIPT,
-    CONTENT_SETTINGS_TYPE_PLUGINS,
-    CONTENT_SETTINGS_TYPE_POPUPS,
-    CONTENT_SETTINGS_TYPE_GEOLOCATION,
-    CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
-    CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC};
-
-const ContentSetting kTestSettings[] = {
-    CONTENT_SETTING_DEFAULT, CONTENT_SETTING_DEFAULT, CONTENT_SETTING_DEFAULT,
-    CONTENT_SETTING_ALLOW,   CONTENT_SETTING_BLOCK,   CONTENT_SETTING_ALLOW,
-    CONTENT_SETTING_BLOCK,   CONTENT_SETTING_BLOCK};
-
-const ContentSetting kTestDefaultSettings[] = {
-    CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ASK};
-
-const content_settings::SettingSource kTestSettingSources[] = {
-    content_settings::SETTING_SOURCE_USER,
-    content_settings::SETTING_SOURCE_USER,
-    content_settings::SETTING_SOURCE_USER,
-    content_settings::SETTING_SOURCE_USER,
-    content_settings::SETTING_SOURCE_USER,
-    content_settings::SETTING_SOURCE_POLICY,
-    content_settings::SETTING_SOURCE_POLICY,
-    content_settings::SETTING_SOURCE_EXTENSION};
-
-class PageInfoBubbleControllerTest : public CocoaProfileTest {
- public:
-  PageInfoBubbleControllerTest() { controller_ = nil; }
-
-  void TearDown() override {
-    [controller_ close];
-    CocoaProfileTest::TearDown();
-  }
-
- protected:
-  PageInfoUIBridge* bridge_;  // Weak, owned by controller.
-
-  enum MatchType { TEXT_EQUAL = 0, TEXT_NOT_EQUAL };
-
-  // Creates a new page info bubble, with the given default width.
-  // If |default_width| is 0, the *default* default width will be used.
-  void CreateBubbleWithWidth(CGFloat default_width) {
-    bridge_ = new PageInfoUIBridge(nullptr);
-
-    // The controller cleans up after itself when the window closes.
-    controller_ = [PageInfoBubbleControllerForTesting alloc];
-    [controller_ setDefaultWindowWidth:default_width];
-    [controller_ initWithParentWindow:browser()->window()->GetNativeWindow()
-                     pageInfoUIBridge:bridge_
-                          webContents:web_contents_factory_.CreateWebContents(
-                                          browser()->profile())
-                                  url:GURL("https://www.google.com")];
-    window_ = [controller_ window];
-    [controller_ showWindow:nil];
-  }
-
-  void CreateBubble() { CreateBubbleWithWidth(0.0); }
-
-  // Return a pointer to the first NSTextField found that either matches, or
-  // doesn't match, the given text.
-  NSTextField* FindTextField(MatchType match_type, NSString* text) {
-    // The window's only immediate child is an invisible view that has a flipped
-    // coordinate origin. It is into this that all views get placed.
-    NSArray* window_subviews = [[window_ contentView] subviews];
-    EXPECT_EQ(1U, [window_subviews count]);
-    NSArray* bubble_subviews = [[window_subviews lastObject] subviews];
-    NSArray* security_section_subviews =
-        [[bubble_subviews firstObject] subviews];
-
-    /**
-     *Expect 3 views:
-     * - the identity
-     * - identity status
-     * - security details link
-     */
-    EXPECT_EQ(3U, [security_section_subviews count]);
-
-    bool desired_result = match_type == TEXT_EQUAL;
-    for (NSView* view in security_section_subviews) {
-      if ([view isKindOfClass:[NSTextField class]]) {
-        NSTextField* text_field = static_cast<NSTextField*>(view);
-        if ([[text_field stringValue] isEqual:text] == desired_result)
-          return text_field;
-      }
-    }
-    return nil;
-  }
-
-  NSMutableArray* FindAllSubviewsOfClass(NSView* parent_view, Class a_class) {
-    NSMutableArray* views = [NSMutableArray array];
-    for (NSView* view in [parent_view subviews]) {
-      if ([view isKindOfClass:a_class])
-        [views addObject:view];
-    }
-    return views;
-  }
-
-  // Sets up the dialog with some test permission settings.
-  void SetTestPermissions() {
-    // Create a list of 5 different permissions, corresponding to all the
-    // possible settings:
-    // - [allow, block, ask] by default
-    // - [block, allow] * by user
-    PermissionInfoList permission_info_list;
-    PageInfoUI::PermissionInfo info;
-    for (size_t i = 0; i < arraysize(kTestPermissionTypes); ++i) {
-      info.type = kTestPermissionTypes[i];
-      info.setting = kTestSettings[i];
-      if (info.setting == CONTENT_SETTING_DEFAULT)
-        info.default_setting = kTestDefaultSettings[i];
-      info.source = kTestSettingSources[i];
-      info.is_incognito = false;
-      permission_info_list.push_back(info);
-    }
-    ChosenObjectInfoList chosen_object_info_list;
-    bridge_->SetPermissionInfo(permission_info_list,
-                               std::move(chosen_object_info_list));
-  }
-
-  int NumSettingsNotSetByUser() const {
-    int num_non_user_settings = 0;
-    for (size_t i = 0; i < arraysize(kTestSettingSources); ++i) {
-      num_non_user_settings +=
-          (kTestSettingSources[i] != content_settings::SETTING_SOURCE_USER) ? 1
-                                                                            : 0;
-    }
-    return num_non_user_settings;
-  }
-
-  content::TestWebContentsFactory web_contents_factory_;
-
-  PageInfoBubbleControllerForTesting* controller_;  // Weak, owns self.
-  NSWindow* window_;  // Weak, owned by controller.
-};
-
-TEST_F(PageInfoBubbleControllerTest, ConnectionHelpButton) {
-  PageInfoUI::IdentityInfo info;
-  info.site_identity = std::string("example.com");
-  info.identity_status = PageInfo::SITE_IDENTITY_STATUS_UNKNOWN;
-
-  CreateBubble();
-
-  bridge_->SetIdentityInfo(const_cast<PageInfoUI::IdentityInfo&>(info));
-
-  EXPECT_EQ([[controller_ connectionHelpButton] action],
-            @selector(openConnectionHelp:));
-}
-
-TEST_F(PageInfoBubbleControllerTest, ResetDecisionsButton) {
-  PageInfoUI::IdentityInfo info;
-  info.site_identity = std::string("example.com");
-  info.identity_status = PageInfo::SITE_IDENTITY_STATUS_UNKNOWN;
-
-  CreateBubble();
-
-  // Set identity info, specifying that the button should not be shown.
-  info.show_ssl_decision_revoke_button = false;
-  bridge_->SetIdentityInfo(const_cast<PageInfoUI::IdentityInfo&>(info));
-  EXPECT_EQ([controller_ resetDecisionsButton], nil);
-
-  // Set identity info, specifying that the button should be shown.
-  info.certificate = net::X509Certificate::CreateFromBytes(
-      reinterpret_cast<const char*>(google_der), sizeof(google_der));
-  ASSERT_TRUE(info.certificate);
-  info.show_ssl_decision_revoke_button = true;
-  bridge_->SetIdentityInfo(const_cast<PageInfoUI::IdentityInfo&>(info));
-  EXPECT_NE([controller_ resetDecisionsButton], nil);
-
-  // Check that clicking the button calls the right selector.
-  EXPECT_EQ([[controller_ resetDecisionsButton] action],
-            @selector(resetCertificateDecisions:));
-
-  // Since the bubble is only created once per identity, we only need to check
-  // the button is *added* when needed. So we don't check that it's removed
-  // when we set an identity with `show_ssl_decision_revoke_button == false`
-  // again.
-}
-
-TEST_F(PageInfoBubbleControllerTest, SetPermissionInfo) {
-  CreateBubble();
-  SetTestPermissions();
-
-  // There should be three subviews per permission.
-  NSArray* subviews = [[controller_ permissionsView] subviews];
-  EXPECT_EQ(arraysize(kTestPermissionTypes) * 3,
-            [subviews count] - NumSettingsNotSetByUser());
-
-  // Ensure that there is a label for each permission.
-  NSMutableArray* permission_labels = [NSMutableArray array];
-  for (NSView* view in subviews) {
-    if ([view isKindOfClass:[NSTextField class]])
-      [permission_labels
-          addObject:[static_cast<NSTextField*>(view) stringValue]];
-  }
-  EXPECT_EQ(arraysize(kTestPermissionTypes),
-            [permission_labels count] - NumSettingsNotSetByUser());
-
-  // Ensure that the button labels are distinct, and look for the correct
-  // number of disabled buttons.
-  int disabled_count = 0;
-  NSMutableSet* button_labels = [NSMutableSet set];
-  for (NSView* view in subviews) {
-    if ([view isKindOfClass:[NSPopUpButton class]]) {
-      NSPopUpButton* button = static_cast<NSPopUpButton*>(view);
-      [button_labels addObject:[[button selectedCell] title]];
-
-      if (![button isEnabled])
-        ++disabled_count;
-    }
-  }
-  EXPECT_EQ(5UL, [button_labels count]);
-
-  // Permissions with a setting source of SETTING_SOURCE_POLICY or
-  // SETTING_SOURCE_EXTENSION should have their buttons disabled.
-  EXPECT_EQ(NumSettingsNotSetByUser(), disabled_count);
-}
-
-TEST_F(PageInfoBubbleControllerTest, WindowWidth) {
-  const CGFloat kBigEnoughBubbleWidth = 310;
-  // Creating a window that should fit everything.
-  CreateBubbleWithWidth(kBigEnoughBubbleWidth);
-  SetTestPermissions();
-
-  CGFloat window_width = NSWidth([[controller_ window] frame]);
-
-  // Check the window was made bigger to fit the content.
-  EXPECT_EQ(kBigEnoughBubbleWidth, window_width);
-
-  // Check that the window is wider than the right edge of all the permission
-  // popup buttons (LTR locales) or wider than the left edge (RTL locales).
-  bool is_rtl = base::i18n::IsRTL();
-  for (NSView* view in [[controller_ permissionsView] subviews]) {
-    if (is_rtl) {
-      if ([view isKindOfClass:[NSPopUpButton class]]) {
-        NSPopUpButton* button = static_cast<NSPopUpButton*>(view);
-        EXPECT_GT(NSMinX([button frame]), 0);
-      }
-      if ([view isKindOfClass:[NSImageView class]]) {
-        NSImageView* icon = static_cast<NSImageView*>(view);
-        EXPECT_LT(NSMaxX([icon frame]), window_width);
-      }
-    } else {
-      if ([view isKindOfClass:[NSImageView class]]) {
-        NSImageView* icon = static_cast<NSImageView*>(view);
-        EXPECT_GT(NSMinX([icon frame]), 0);
-      }
-      if ([view isKindOfClass:[NSPopUpButton class]]) {
-        NSPopUpButton* button = static_cast<NSPopUpButton*>(view);
-        EXPECT_LT(NSMaxX([button frame]), window_width);
-      }
-    }
-  }
-}
-
-// Tests the page icon decoration's active state.
-TEST_F(PageInfoBubbleControllerTest, PageIconDecorationActiveState) {
-  NSWindow* window = browser()->window()->GetNativeWindow();
-  BrowserWindowController* controller =
-      [BrowserWindowController browserWindowControllerForWindow:window];
-  LocationBarDecoration* decoration =
-      [controller locationBarBridge]->page_info_decoration();
-
-  CreateBubble();
-  EXPECT_TRUE([[controller_ window] isVisible]);
-  EXPECT_TRUE(decoration->active());
-
-  [controller_ close];
-  EXPECT_FALSE(decoration->active());
-}
-
-TEST_F(PageInfoBubbleControllerTest, PasswordReuseButtons) {
-  PageInfoUI::IdentityInfo info;
-  info.site_identity = std::string("example.com");
-  info.identity_status = PageInfo::SITE_IDENTITY_STATUS_UNKNOWN;
-
-  CreateBubble();
-
-  // Set identity info, specifying that buttons should not be shown.
-  info.show_change_password_buttons = false;
-  bridge_->SetIdentityInfo(const_cast<PageInfoUI::IdentityInfo&>(info));
-  EXPECT_EQ([controller_ changePasswordButton], nil);
-  EXPECT_EQ([controller_ whitelistPasswordReuseButton], nil);
-
-  // Set identity info, specifying that buttons should be shown.
-  info.show_change_password_buttons = true;
-  bridge_->SetIdentityInfo(const_cast<PageInfoUI::IdentityInfo&>(info));
-  EXPECT_NE([controller_ changePasswordButton], nil);
-  EXPECT_NE([controller_ whitelistPasswordReuseButton], nil);
-
-  // Check that clicking the button calls the right selector.
-  EXPECT_EQ([[controller_ changePasswordButton] action],
-            @selector(changePasswordDecisions:));
-  EXPECT_EQ([[controller_ whitelistPasswordReuseButton] action],
-            @selector(whitelistPasswordReuseDecisions:));
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/page_info/page_info_bubble_views_mac_browsertest.mm b/chrome/browser/ui/cocoa/page_info/page_info_bubble_views_mac_browsertest.mm
index 83921dac..212a2ae 100644
--- a/chrome/browser/ui/cocoa/page_info/page_info_bubble_views_mac_browsertest.mm
+++ b/chrome/browser/ui/cocoa/page_info/page_info_bubble_views_mac_browsertest.mm
@@ -66,19 +66,13 @@
       access_manager->fullscreen_controller();
 
   fullscreen_controller->ToggleBrowserFullscreenMode();
-  if (ui::MaterialDesignController::IsSecondaryUiMaterial()) {
-    views::BubbleDialogDelegateView* page_info =
-        PageInfoBubbleView::GetPageInfoBubble();
-    EXPECT_TRUE(page_info);
-    views::Widget* page_info_bubble = page_info->GetWidget();
-    EXPECT_TRUE(page_info_bubble);
-    EXPECT_EQ(GetParam().bubble_type, PageInfoBubbleView::GetShownBubbleType());
-    EXPECT_TRUE(page_info_bubble->IsVisible());
-  } else {
-    EXPECT_TRUE([PageInfoBubbleController getPageInfoBubbleForTest]);
-    // In Cocoa, the crash occurs when the bubble tries to re-layout.
-    [[PageInfoBubbleController getPageInfoBubbleForTest] performLayout];
-  }
+  views::BubbleDialogDelegateView* page_info =
+      PageInfoBubbleView::GetPageInfoBubble();
+  EXPECT_TRUE(page_info);
+  views::Widget* page_info_bubble = page_info->GetWidget();
+  EXPECT_TRUE(page_info_bubble);
+  EXPECT_EQ(GetParam().bubble_type, PageInfoBubbleView::GetShownBubbleType());
+  EXPECT_TRUE(page_info_bubble->IsVisible());
 
   // There should be no crash here from re-anchoring the Page Info bubble while
   // transitioning into full screen.
diff --git a/chrome/browser/ui/cocoa/page_info/page_info_utils_cocoa.h b/chrome/browser/ui/cocoa/page_info/page_info_utils_cocoa.h
deleted file mode 100644
index 4b09b80..0000000
--- a/chrome/browser/ui/cocoa/page_info/page_info_utils_cocoa.h
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_PAGE_INFO_PAGE_INFO_UTILS_COCOA_H_
-#define CHROME_BROWSER_UI_COCOA_PAGE_INFO_PAGE_INFO_UTILS_COCOA_H_
-
-#import <Cocoa/Cocoa.h>
-
-NSSize SizeForPageInfoButtonTitle(NSPopUpButton* button, NSString* title);
-
-#endif  // CHROME_BROWSER_UI_COCOA_PAGE_INFO_PAGE_INFO_UTILS_COCOA_H_
diff --git a/chrome/browser/ui/cocoa/page_info/page_info_utils_cocoa.mm b/chrome/browser/ui/cocoa/page_info/page_info_utils_cocoa.mm
deleted file mode 100644
index 1dbf9567..0000000
--- a/chrome/browser/ui/cocoa/page_info/page_info_utils_cocoa.mm
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/page_info/page_info_utils_cocoa.h"
-
-namespace {
-// The amount of horizontal space between the button's title and its arrow icon.
-const CGFloat kButtonTitleRightPadding = 4.0f;
-}
-
-// Determine the size of a popup button with the given title.
-NSSize SizeForPageInfoButtonTitle(NSPopUpButton* button, NSString* title) {
-  NSDictionary* textAttributes =
-      [[button attributedTitle] attributesAtIndex:0 effectiveRange:NULL];
-  NSSize titleSize = [title sizeWithAttributes:textAttributes];
-
-  NSRect frame = [button frame];
-  NSRect titleRect = [[button cell] titleRectForBounds:frame];
-  CGFloat width = titleSize.width + NSWidth(frame) - NSWidth(titleRect);
-
-  return NSMakeSize(width + kButtonTitleRightPadding, NSHeight(frame));
-}
diff --git a/chrome/browser/ui/cocoa/page_info/permission_selector_button.h b/chrome/browser/ui/cocoa/page_info/permission_selector_button.h
deleted file mode 100644
index a613e0a..0000000
--- a/chrome/browser/ui/cocoa/page_info/permission_selector_button.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_PAGE_INFO_PERMISSION_SELECTOR_BUTTON_H_
-#define CHROME_BROWSER_UI_COCOA_PAGE_INFO_PERMISSION_SELECTOR_BUTTON_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include <memory>
-
-#include "base/mac/scoped_nsobject.h"
-#include "chrome/browser/ui/page_info/permission_menu_model.h"
-#include "components/content_settings/core/common/content_settings.h"
-
-@class MenuControllerCocoa;
-
-class Profile;
-
-@interface PermissionSelectorButton : NSPopUpButton {
- @private
-  std::unique_ptr<PermissionMenuModel> menuModel_;
-  base::scoped_nsobject<MenuControllerCocoa> menuController_;
-}
-
-// Designated initializer.
-- (id)initWithPermissionInfo:(const PageInfoUI::PermissionInfo&)permissionInfo
-                      forURL:(const GURL&)url
-                withCallback:(PermissionMenuModel::ChangeCallback)callback
-                     profile:(Profile*)profile;
-
-// Returns the largest possible size given all of the items in the menu.
-- (CGFloat)maxTitleWidthForContentSettingsType:(ContentSettingsType)type
-                            withDefaultSetting:(ContentSetting)defaultSetting
-                                       profile:(Profile*)profile;
-
-// Updates the title of the NSPopUpButton and resizes it to fit the new text.
-- (void)setButtonTitle:(const PageInfoUI::PermissionInfo&)permissionInfo
-               profile:(Profile*)profile;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_PAGE_INFO_PERMISSION_SELECTOR_BUTTON_H_
diff --git a/chrome/browser/ui/cocoa/page_info/permission_selector_button.mm b/chrome/browser/ui/cocoa/page_info/permission_selector_button.mm
deleted file mode 100644
index 0ec3193..0000000
--- a/chrome/browser/ui/cocoa/page_info/permission_selector_button.mm
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/page_info/permission_selector_button.h"
-
-#include "base/strings/sys_string_conversions.h"
-#include "chrome/browser/ui/cocoa/page_info/page_info_utils_cocoa.h"
-#include "chrome/browser/ui/page_info/page_info_ui.h"
-#import "ui/base/cocoa/menu_controller.h"
-
-@implementation PermissionSelectorButton
-
-- (id)initWithPermissionInfo:(const PageInfoUI::PermissionInfo&)permissionInfo
-                      forURL:(const GURL&)url
-                withCallback:(PermissionMenuModel::ChangeCallback)callback
-                     profile:(Profile*)profile {
-  if (self = [super initWithFrame:NSMakeRect(0, 0, 1, 1) pullsDown:NO]) {
-    [self setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
-    [self setBordered:NO];
-    [[self cell] setControlSize:NSSmallControlSize];
-
-    menuModel_.reset(
-        new PermissionMenuModel(profile, url, permissionInfo, callback));
-
-    menuController_.reset([[MenuControllerCocoa alloc]
-                 initWithModel:menuModel_.get()
-        useWithPopUpButtonCell:NO]);
-    [self setMenu:[menuController_ menu]];
-    [self selectItemWithTag:permissionInfo.setting];
-
-    [self setButtonTitle:permissionInfo profile:profile];
-
-    NSString* description = base::SysUTF16ToNSString(
-        PageInfoUI::PermissionTypeToUIString(permissionInfo.type));
-    [[self cell]
-        accessibilitySetOverrideValue:description
-                         forAttribute:NSAccessibilityDescriptionAttribute];
-  }
-  return self;
-}
-
-- (CGFloat)maxTitleWidthForContentSettingsType:(ContentSettingsType)type
-                            withDefaultSetting:(ContentSetting)defaultSetting
-                                       profile:(Profile*)profile {
-  // Determine the largest possible size for this button.
-  CGFloat maxTitleWidth = 0;
-  for (NSMenuItem* item in [self itemArray]) {
-    NSString* title =
-        base::SysUTF16ToNSString(PageInfoUI::PermissionActionToUIString(
-            profile, type, static_cast<ContentSetting>([item tag]),
-            defaultSetting, content_settings::SETTING_SOURCE_USER));
-    NSSize size = SizeForPageInfoButtonTitle(self, title);
-    maxTitleWidth = std::max(maxTitleWidth, size.width);
-  }
-  return maxTitleWidth;
-}
-
-// Accessor function for testing only.
-- (NSMenu*)permissionMenu {
-  return [menuController_ menu];
-}
-
-- (void)setButtonTitle:(const PageInfoUI::PermissionInfo&)permissionInfo
-               profile:(Profile*)profile {
-  // Set the button title.
-  base::scoped_nsobject<NSMenuItem> titleItem([[NSMenuItem alloc] init]);
-  base::string16 buttonTitle = PageInfoUI::PermissionActionToUIString(
-      profile, permissionInfo.type, permissionInfo.setting,
-      permissionInfo.default_setting, permissionInfo.source);
-  [titleItem setTitle:base::SysUTF16ToNSString(buttonTitle)];
-  [[self cell] setUsesItemFromMenu:NO];
-  [[self cell] setMenuItem:titleItem];
-  // Although the frame is reset, below, this sizes the cell properly.
-  [self sizeToFit];
-
-  // Size the button to just fit the visible title - not all of its items.
-  [self setFrameSize:SizeForPageInfoButtonTitle(self, [self title])];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/page_info/permission_selector_button_unittest.mm b/chrome/browser/ui/cocoa/page_info/permission_selector_button_unittest.mm
deleted file mode 100644
index 63188c3..0000000
--- a/chrome/browser/ui/cocoa/page_info/permission_selector_button_unittest.mm
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/page_info/permission_selector_button.h"
-
-#include "base/mac/scoped_nsobject.h"
-#include "base/test/scoped_feature_list.h"
-#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
-#include "chrome/browser/ui/page_info/page_info_ui.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "ui/base/ui_base_features.h"
-
-@interface PermissionSelectorButton (Testing)
-- (NSMenu*)permissionMenu;
-@end
-
-namespace {
-
-const ContentSettingsType kTestPermissionType =
-    CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC;
-
-class PermissionSelectorButtonTest : public CocoaTest {
- public:
-  PermissionSelectorButtonTest() {
-    // This file only tests Cocoa UI and can be deleted when kSecondaryUiMd is
-    // default.
-    scoped_feature_list_.InitAndDisableFeature(features::kSecondaryUiMd);
-
-    got_callback_ = false;
-    PageInfoUI::PermissionInfo test_info;
-    test_info.type = kTestPermissionType;
-    test_info.setting = CONTENT_SETTING_BLOCK;
-    test_info.source = content_settings::SETTING_SOURCE_USER;
-    test_info.is_incognito = false;
-    GURL test_url("http://www.google.com");
-    PermissionMenuModel::ChangeCallback callback = base::Bind(
-        &PermissionSelectorButtonTest::Callback, base::Unretained(this));
-    view_.reset([[PermissionSelectorButton alloc]
-        initWithPermissionInfo:test_info
-                        forURL:test_url
-                  withCallback:callback
-                       profile:&profile_]);
-    [[test_window() contentView] addSubview:view_];
-  }
-
-  void Callback(const PageInfoUI::PermissionInfo& permission) {
-    EXPECT_TRUE(permission.type == kTestPermissionType);
-    got_callback_ = true;
-  }
-
-  content::TestBrowserThreadBundle thread_bundle_;
-  TestingProfile profile_;
-
-  bool got_callback_;
-  base::scoped_nsobject<PermissionSelectorButton> view_;
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(PermissionSelectorButtonTest);
-};
-
-TEST_VIEW(PermissionSelectorButtonTest, view_);
-
-TEST_F(PermissionSelectorButtonTest, Callback) {
-  NSMenu* menu = [view_ permissionMenu];
-  NSMenuItem* item = [menu itemAtIndex:0];
-  [[item target] performSelector:[item action] withObject:item];
-  EXPECT_TRUE(got_callback_);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/cocoa/page_info/split_block_button.h b/chrome/browser/ui/cocoa/page_info/split_block_button.h
deleted file mode 100644
index 689ae1a..0000000
--- a/chrome/browser/ui/cocoa/page_info/split_block_button.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_PAGE_INFO_SPLIT_BLOCK_BUTTON_H_
-#define CHROME_BROWSER_UI_COCOA_PAGE_INFO_SPLIT_BLOCK_BUTTON_H_
-
-#import <Cocoa/Cocoa.h>
-
-#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
-#include "ui/base/models/simple_menu_model.h"
-
-@class SplitButtonPopUpCell;
-@class SplitButtonTitleCell;
-
-// Block ('deny') button for the permissions bubble.  Subclassed from
-// ConstrainedWindowButton, so that it shares styling, but contains two cells
-// instead of just one.  The left cell behaves as a normal button, and when
-// clicked, calls the button's |action| on its |target|.  The right cell behaves
-// as a NSPopUpButtonCell, and implements a single-item menu.
-@interface SplitBlockButton : ConstrainedWindowButton {
- @private
-  base::scoped_nsobject<SplitButtonTitleCell> leftCell_;
-  base::scoped_nsobject<SplitButtonPopUpCell> rightCell_;
-
-  ui::ScopedCrTrackingArea leftTrackingArea_;
-  ui::ScopedCrTrackingArea rightTrackingArea_;
-}
-
-// Designated initializer.
-- (id)initWithMenuDelegate:(ui::SimpleMenuModel::Delegate*)menuDelegate;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_PAGE_INFO_SPLIT_BLOCK_BUTTON_H_
diff --git a/chrome/browser/ui/cocoa/page_info/split_block_button.mm b/chrome/browser/ui/cocoa/page_info/split_block_button.mm
deleted file mode 100644
index de71ab0..0000000
--- a/chrome/browser/ui/cocoa/page_info/split_block_button.mm
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/page_info/split_block_button.h"
-
-#include <cmath>
-
-#include "base/logging.h"
-#include "base/mac/scoped_nsobject.h"
-#include "chrome/grit/generated_resources.h"
-#include "skia/ext/skia_utils_mac.h"
-#import "ui/base/cocoa/menu_controller.h"
-#include "ui/base/l10n/l10n_util_mac.h"
-#include "ui/base/models/simple_menu_model.h"
-
-namespace {
-
-enum MouseLocation {
-  kInsideLeftCell,
-  kInsideRightCell,
-  kNotInside,
-};
-
-enum CornerType {
-  kRounded,
-  kAngled,
-};
-
-NSBezierPath* PathWithCornerStyles(NSRect frame,
-                                   CornerType leftCornerStyle,
-                                   CornerType rightCornerStyle) {
-  base::scoped_nsobject<NSBezierPath> path([[NSBezierPath bezierPath] retain]);
-  const CGFloat x0 = NSMinX(frame);
-  const CGFloat x1 = NSMaxX(frame);
-  const CGFloat y0 = NSMinY(frame);
-  const CGFloat y1 = NSMaxY(frame);
-  const CGFloat radius = 2;
-
-  // Start at the center bottom.  Draw left and up, including both left corners.
-  [path moveToPoint:NSMakePoint(std::floor((x1 - x0) * .5), y0)];
-  if (leftCornerStyle == kAngled) {
-    [path lineToPoint:NSMakePoint(x0, y0)];
-    [path lineToPoint:NSMakePoint(x0, y1)];
-  } else {
-    [path appendBezierPathWithArcFromPoint:NSMakePoint(x0, y0)
-                                   toPoint:NSMakePoint(x0, y0 + radius)
-                                    radius:radius];
-    [path appendBezierPathWithArcFromPoint:NSMakePoint(x0, y1)
-                                   toPoint:NSMakePoint(x0 + radius, y1)
-                                    radius:radius];
-  }
-  // Draw through the upper right-hand and lower-right-hand corners.
-  if (rightCornerStyle == kAngled) {
-    [path lineToPoint:NSMakePoint(x1, y1)];
-    [path lineToPoint:NSMakePoint(x1, y0)];
-  } else {
-    [path appendBezierPathWithArcFromPoint:NSMakePoint(x1, y1)
-                                   toPoint:NSMakePoint(x1, y1 - radius)
-                                    radius:radius];
-    [path appendBezierPathWithArcFromPoint:NSMakePoint(x1, y0)
-                                   toPoint:NSMakePoint(x1 - radius, y0)
-                                    radius:radius];
-  }
-  return path.autorelease();
-}
-
-void DrawBezel(id<ConstrainedWindowButtonDrawableCell> cell,
-               CornerType leftCorners,
-               CornerType rightCorners,
-               NSRect frame,
-               NSView* view) {
-  if ([cell isMouseInside]) {
-    base::scoped_nsobject<NSBezierPath> path(
-        [PathWithCornerStyles(frame, leftCorners, rightCorners) retain]);
-    [ConstrainedWindowButton DrawBackgroundAndShadowForPath:path
-                                                   withCell:cell
-                                                     inView:view];
-    [ConstrainedWindowButton DrawInnerHighlightForPath:path
-                                              withCell:cell
-                                                inView:view];
-  }
-}
-
-}  // namespace
-
-// A button cell used by SplitBlockButton, containing the title.
-@interface SplitButtonTitleCell : ConstrainedWindowButtonCell
-- (NSRect)rect;
-@end
-
-// A button cell used by SplitBlockButton, containing the popup menu.
-@interface SplitButtonPopUpCell
-    : NSPopUpButtonCell<ConstrainedWindowButtonDrawableCell> {
- @private
-  BOOL isMouseInside_;
-  base::scoped_nsobject<MenuControllerCocoa> menuController_;
-  std::unique_ptr<ui::SimpleMenuModel> menuModel_;
-}
-
-// Designated initializer.
-- (id)initWithMenuDelegate:(ui::SimpleMenuModel::Delegate*)menuDelegate;
-
-- (NSRect)rect;
-
-@end
-
-@implementation SplitBlockButton
-
-- (id)initWithMenuDelegate:(ui::SimpleMenuModel::Delegate*)menuDelegate {
-  if (self = [super initWithFrame:NSZeroRect]) {
-    leftCell_.reset([[SplitButtonTitleCell alloc] init]);
-    rightCell_.reset(
-        [[SplitButtonPopUpCell alloc] initWithMenuDelegate:menuDelegate]);
-    [leftCell_ setTitle:l10n_util::GetNSString(IDS_PERMISSION_DENY)];
-    [leftCell_ setEnabled:YES];
-    [rightCell_ setEnabled:YES];
-  }
-  return self;
-}
-
-+ (Class)cellClass {
-  return nil;
-}
-
-- (NSString*)title {
-  return [leftCell_ title];
-}
-
-- (void)setAction:(SEL)action {
-  [leftCell_ setAction:action];
-}
-
-- (void)setTarget:(id)target {
-  [leftCell_ setTarget:target];
-}
-
-- (void)drawRect:(NSRect)rect {
-  // Copy the base class:  inset to leave room for the shadow.
-  --rect.size.height;
-
-  // This function assumes that |rect| is always the same as [self frame].
-  // If that changes, the drawing functions will need to be adjusted.
-  const CGFloat radius = 2;
-  NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:rect
-                                                       xRadius:radius
-                                                       yRadius:radius];
-  [ConstrainedWindowButton DrawBackgroundAndShadowForPath:path
-                                                 withCell:nil
-                                                   inView:self];
-
-  // Use intersection rects for the cell drawing, to ensure the height
-  // adjustment is honored.
-  [leftCell_ setControlView:self];
-  [leftCell_ drawWithFrame:NSIntersectionRect(rect, [self leftCellRect])
-                    inView:self];
-
-  [rightCell_ setControlView:self];
-  [rightCell_ drawWithFrame:NSIntersectionRect(rect, [self rightCellRect])
-                     inView:self];
-
-  // Draw the border.
-  path = [NSBezierPath bezierPathWithRoundedRect:NSInsetRect(rect, 0.5, 0.5)
-                                         xRadius:radius
-                                         yRadius:radius];
-  [ConstrainedWindowButton DrawBorderForPath:path withCell:nil inView:self];
-}
-
-- (void)updateTrackingAreas {
-  [self updateTrackingArea:&leftTrackingArea_
-                   forCell:leftCell_
-                  withRect:[self leftCellRect]];
-
-  [self updateTrackingArea:&rightTrackingArea_
-                   forCell:rightCell_
-                  withRect:[self rightCellRect]];
-}
-
-- (void)updateTrackingArea:(ui::ScopedCrTrackingArea*)trackingArea
-                   forCell:(id<ConstrainedWindowButtonDrawableCell>)cell
-                  withRect:(NSRect)rect {
-  DCHECK(trackingArea);
-  NSTrackingAreaOptions options =
-      NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp;
-  [self removeTrackingArea:trackingArea->get()];
-  trackingArea->reset([[CrTrackingArea alloc] initWithRect:rect
-                                                   options:options
-                                                     owner:self
-                                                  userInfo:nil]);
-  [self addTrackingArea:trackingArea->get()];
-}
-
-- (void)mouseEntered:(NSEvent*)theEvent {
-  [self mouseMoved:theEvent];
-}
-
-- (void)mouseExited:(NSEvent*)theEvent {
-  [self mouseMoved:theEvent];
-}
-
-- (void)mouseMoved:(NSEvent*)theEvent {
-  MouseLocation location = [self mouseLocationForEvent:theEvent];
-  [rightCell_ setIsMouseInside:NO];
-  [leftCell_ setIsMouseInside:NO];
-  if (location == kInsideLeftCell)
-    [leftCell_ setIsMouseInside:YES];
-  else if (location == kInsideRightCell)
-    [rightCell_ setIsMouseInside:YES];
-  [self setNeedsDisplay:YES];
-}
-
-- (void)mouseDown:(NSEvent*)theEvent {
-  MouseLocation downLocation = [self mouseLocationForEvent:theEvent];
-  NSCell* focusCell = nil;
-  NSRect rect;
-  if (downLocation == kInsideLeftCell) {
-    focusCell = leftCell_.get();
-    rect = [self leftCellRect];
-  } else if (downLocation == kInsideRightCell) {
-    focusCell = rightCell_.get();
-    rect = [self rightCellRect];
-  }
-
-  do {
-    MouseLocation location = [self mouseLocationForEvent:theEvent];
-    if (location != kNotInside) {
-      [focusCell setHighlighted:YES];
-      [self setNeedsDisplay:YES];
-
-      if ([focusCell trackMouse:theEvent
-                         inRect:rect
-                         ofView:self
-                   untilMouseUp:NO]) {
-        [focusCell setState:![focusCell state]];
-        [self setNeedsDisplay:YES];
-        break;
-      } else {
-        // The above -trackMouse call returned NO, so we know that
-        // the mouse left the cell before a mouse up event occurred.
-        [focusCell setHighlighted:NO];
-        [self setNeedsDisplay:YES];
-      }
-    }
-    const NSUInteger mask = NSLeftMouseUpMask | NSLeftMouseDraggedMask;
-    theEvent = [[self window] nextEventMatchingMask:mask];
-  } while ([theEvent type] != NSLeftMouseUp);
-}
-
-- (MouseLocation)mouseLocationForEvent:(NSEvent*)theEvent {
-  MouseLocation location = kNotInside;
-  NSPoint mousePoint =
-      [self convertPoint:[theEvent locationInWindow] fromView:nil];
-  if ([self mouse:mousePoint inRect:[leftCell_ rect]])
-    location = kInsideLeftCell;
-  else if ([self mouse:mousePoint inRect:[self rightCellRect]])
-    location = kInsideRightCell;
-  return location;
-}
-
-- (void)sizeToFit {
-  NSSize leftSize = [leftCell_ cellSize];
-  NSSize rightSize = [rightCell_ cellSize];
-  NSSize size = NSMakeSize(
-      std::ceil(std::max(leftSize.width + rightSize.width,
-                         constrained_window_button::kButtonMinWidth)),
-      std::ceil(std::max(leftSize.height, rightSize.height)));
-  [self setFrameSize:size];
-}
-
-- (NSRect)leftCellRect {
-  return [leftCell_ rect];
-}
-
-- (NSRect)rightCellRect {
-  NSRect leftFrame, rightFrame;
-  NSDivideRect([self bounds], &leftFrame, &rightFrame,
-               NSWidth([self leftCellRect]), NSMinXEdge);
-  return rightFrame;
-}
-
-// Accessor for Testing.
-- (NSMenu*)menu {
-  return [rightCell_ menu];
-}
-
-@end
-
-@implementation SplitButtonTitleCell
-
-- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView {
-  DrawBezel(self, kRounded, kAngled, frame, controlView);
-}
-
-- (NSRect)rect {
-  NSSize size = [self cellSize];
-  return NSMakeRect(0, 0, std::ceil(size.width), std::ceil(size.height));
-}
-
-@end
-
-@implementation SplitButtonPopUpCell
-
-@synthesize isMouseInside = isMouseInside_;
-
-- (id)initWithMenuDelegate:(ui::SimpleMenuModel::Delegate*)menuDelegate {
-  if (self = [super initTextCell:@"" pullsDown:YES]) {
-    [self setControlSize:NSSmallControlSize];
-    [self setArrowPosition:NSPopUpArrowAtCenter];
-    [self setBordered:NO];
-    [self setBackgroundColor:[NSColor clearColor]];
-    menuModel_.reset(new ui::SimpleMenuModel(menuDelegate));
-    menuModel_->AddItemWithStringId(0, IDS_PERMISSION_CUSTOMIZE);
-    menuController_.reset([[MenuControllerCocoa alloc]
-                 initWithModel:menuModel_.get()
-        useWithPopUpButtonCell:NO]);
-    [self setMenu:[menuController_ menu]];
-    [self setUsesItemFromMenu:NO];
-  }
-  return self;
-}
-
-- (void)drawBorderAndBackgroundWithFrame:(NSRect)frame
-                                  inView:(NSView*)controlView {
-  // The arrow, which is what should be drawn by the base class, is drawn
-  // during -drawBezelWithFrame.  The only way to draw our own border with
-  // the default arrow is to make the cell unbordered, and draw the border
-  // from -drawBorderAndBackgroundWithFrame, rather than simply overriding
-  // -drawBezelWithFrame.
-  DrawBezel(self, kAngled, kRounded, frame, controlView);
-  [super drawBorderAndBackgroundWithFrame:NSOffsetRect(frame, -4, 0)
-                                   inView:controlView];
-}
-
-- (NSRect)rect {
-  NSSize size = [self cellSize];
-  return NSMakeRect(0, 0, std::ceil(size.width), std::ceil(size.height));
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/translate/translate_bubble_controller.h b/chrome/browser/ui/cocoa/translate/translate_bubble_controller.h
deleted file mode 100644
index be74fa2..0000000
--- a/chrome/browser/ui/cocoa/translate/translate_bubble_controller.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_TRANSLATE_TRANSLATE_BUBBLE_CONTROLLER_H_
-#define CHROME_BROWSER_UI_COCOA_TRANSLATE_TRANSLATE_BUBBLE_CONTROLLER_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include <memory>
-
-#include "base/mac/scoped_nsobject.h"
-#include "chrome/browser/translate/chrome_translate_client.h"
-#import "chrome/browser/ui/cocoa/omnibox_decoration_bubble_controller.h"
-#include "components/translate/core/common/translate_errors.h"
-
-@class BrowserWindowController;
-
-class TranslateBubbleModel;
-
-namespace content {
-class WebContents;
-}
-
-// Displays the Translate bubble. The Translate bubble is a bubble which
-// pops up when clicking the Translate icon on Omnibox. This bubble
-// allows us to translate a foreign page into user-selected language,
-// revert this, and configure the translate setting.
-@interface TranslateBubbleController
-    : OmniboxDecorationBubbleController<NSTextViewDelegate> {
-  // The views of each state. The keys are TranslateBubbleModel::ViewState,
-  // and the values are NSView*.
-  base::scoped_nsobject<NSDictionary<NSNumber*, NSView*>> views_;
-
-  // The 'Try again' button on the error panel.
-  NSButton* tryAgainButton_;
-}
-
-@property(readonly, nonatomic) const content::WebContents* webContents;
-@property(readonly, nonatomic) const TranslateBubbleModel* model;
-
-- (id)initWithParentWindow:(BrowserWindowController*)controller
-                     model:(std::unique_ptr<TranslateBubbleModel>)model
-               webContents:(content::WebContents*)webContents;
-- (void)switchView:(TranslateBubbleModel::ViewState)viewState;
-- (void)switchToErrorView:(translate::TranslateErrors::Type)errorType;
-
-@end
-
-// The methods on this category are used internally by the controller and are
-// only exposed for testing purposes. DO NOT USE OTHERWISE.
-@interface TranslateBubbleController (ExposedForTesting)
-- (IBAction)handleCloseButtonPressed:(id)sender;
-- (IBAction)handleTranslateButtonPressed:(id)sender;
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_TRANSLATE_TRANSLATE_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/translate/translate_bubble_controller.mm b/chrome/browser/ui/cocoa/translate/translate_bubble_controller.mm
deleted file mode 100644
index 1ecb0ae..0000000
--- a/chrome/browser/ui/cocoa/translate/translate_bubble_controller.mm
+++ /dev/null
@@ -1,962 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/translate/translate_bubble_controller.h"
-
-#include <utility>
-
-#include "base/mac/foundation_util.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/sys_string_conversions.h"
-#include "chrome/browser/ui/chrome_pages.h"
-#import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#import "chrome/browser/ui/cocoa/bubble_combobox.h"
-#include "chrome/browser/ui/cocoa/chrome_style.h"
-#import "chrome/browser/ui/cocoa/hover_close_button.h"
-#import "chrome/browser/ui/cocoa/info_bubble_view.h"
-#import "chrome/browser/ui/cocoa/info_bubble_window.h"
-#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
-#import "chrome/browser/ui/cocoa/location_bar/translate_decoration.h"
-#include "chrome/browser/ui/translate/language_combobox_model.h"
-#include "chrome/browser/ui/translate/translate_bubble_model.h"
-#include "chrome/browser/ui/translate/translate_bubble_view_state_transition.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
-#include "components/strings/grit/components_strings.h"
-#include "components/translate/core/browser/translate_ui_delegate.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/common/referrer.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "ui/base/cocoa/cocoa_base_utils.h"
-#import "ui/base/cocoa/controls/hyperlink_button_cell.h"
-#include "ui/base/cocoa/controls/hyperlink_text_view.h"
-#import "ui/base/cocoa/window_size_constants.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/models/combobox_model.h"
-
-// TODO(hajimehoshi): This class is almost same as that of views. Refactor them.
-class TranslateDenialComboboxModel : public ui::ComboboxModel {
- public:
-  explicit TranslateDenialComboboxModel(
-      const base::string16& original_language_name) {
-    // Dummy menu item, which is shown on the top of a NSPopUpButton. The top
-    // text of the denial pop up menu should be IDS_TRANSLATE_BUBBLE_DENY, while
-    // it is impossible to use it here because NSPopUpButtons' addItemWithTitle
-    // removes a duplicated menu item. Instead, the title will be set later by
-    // NSMenuItem's setTitle.
-    items_.push_back(base::string16());
-
-    // Menu items in the drop down menu.
-    items_.push_back(l10n_util::GetStringFUTF16(
-        IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_LANG,
-        original_language_name));
-    items_.push_back(l10n_util::GetStringUTF16(
-        IDS_TRANSLATE_BUBBLE_NEVER_TRANSLATE_SITE));
-  }
-  ~TranslateDenialComboboxModel() override {}
-
- private:
-  // ComboboxModel:
-  int GetItemCount() const override { return items_.size(); }
-  base::string16 GetItemAt(int index) override { return items_[index]; }
-  bool IsItemSeparatorAt(int index) override { return false; }
-  int GetDefaultIndex() const override { return 0; }
-
-  std::vector<base::string16> items_;
-
-  DISALLOW_COPY_AND_ASSIGN(TranslateDenialComboboxModel);
-};
-
-const CGFloat kTranslateBubbleIconWidth = 30;
-const CGFloat kTranslateBubbleIconHeight = 30;
-const CGFloat kTranslateBubbleIconPadding = 12;
-
-const CGFloat kTranslateBubbleWindowWidth = 320;
-
-// Padding between the window frame and content.
-const CGFloat kTranslateBubbleFramePadding = 16;
-
-const CGFloat kTranslateBubbleRelatedControlHorizontalSpacing = -2;
-
-const CGFloat kTranslateBubbleRelatedControlVerticalSpacing = 8;
-const CGFloat kTranslateBubbleUnrelatedControlVerticalSpacing = 20;
-
-const CGFloat kTranslateBubbleContentWidth =
-    kTranslateBubbleWindowWidth - 2 * kTranslateBubbleFramePadding;
-
-@interface TranslateBubbleController()
-
-- (void)performLayout;
-- (NSView*)newBeforeTranslateView;
-- (NSView*)newTranslatingView;
-- (NSView*)newAfterTranslateView;
-- (NSView*)newErrorView;
-- (NSView*)newAdvancedView;
-- (void)updateAdvancedView;
-- (void)updateAlwaysCheckboxes;
-- (NSImageView*)addIcon:(NSView*)view;
-- (NSTextView*)addStyledTextView:(NSString*)message
-                          toView:(NSView*)view
-                      withRanges:(std::vector<NSRange>)ranges
-                        delegate:(id<NSTextViewDelegate>)delegate;
-- (NSTextField*)addText:(NSString*)text
-                 toView:(NSView*)view;
-- (NSButton*)addLinkButtonWithText:(NSString*)text
-                            action:(SEL)action
-                            toView:(NSView*)view;
-- (NSButton*)addButton:(NSString*)title
-                action:(SEL)action
-                toView:(NSView*)view;
-- (NSButton*)addCheckbox:(NSString*)title
-                  action:(SEL)action
-                  toView:(NSView*)view;
-- (NSButton*)addCloseButton:(NSView*)view action:(SEL)action;
-- (NSPopUpButton*)addPopUpButton:(ui::ComboboxModel*)model
-                          action:(SEL)action
-                          toView:(NSView*)view;
-- (IBAction)handleAlwaysTranslateCheckboxPressed:(id)sender;
-- (IBAction)handleDoneButtonPressed:(id)sender;
-- (IBAction)handleCancelButtonPressed:(id)sender;
-- (IBAction)handleCloseButtonPressed:(id)sender;
-- (IBAction)handleShowOriginalButtonPressed:(id)sender;
-- (IBAction)handleTryAgainButtonPressed:(id)sender;
-- (IBAction)handleAdvancedLinkButtonPressed:(id)sender;
-- (IBAction)handleLanguageSettingsLinkButtonPressed:(id)sender;
-- (IBAction)handleDenialPopUpButtonNeverTranslateLanguageSelected:(id)sender;
-- (IBAction)handleDenialPopUpButtonNeverTranslateSiteSelected:(id)sender;
-- (IBAction)handleSourceLanguagePopUpButtonSelectedItemChanged:(id)sender;
-- (IBAction)handleTargetLanguagePopUpButtonSelectedItemChanged:(id)sender;
-- (BOOL)textView:(NSTextView*)aTextView
-    clickedOnLink:(id)link
-          atIndex:(NSUInteger)charIndex;
-@end
-
-@implementation TranslateBubbleController {
- @private
-  content::WebContents* webContents_;
-  std::unique_ptr<TranslateBubbleModel> model_;
-
-  // The 'Done' or 'Translate' button on the advanced (option) panel.
-  NSButton* advancedDoneButton_;
-
-  // The 'Cancel' button on the advanced (option) panel.
-  NSButton* advancedCancelButton_;
-
-  // The 'Always translate' checkbox on the before panel.
-  // This is nil when the current WebContents is in an incognito window.
-  NSButton* beforeAlwaysTranslateCheckbox_;
-
-  // The 'Always translate' checkbox on the advanced (option) panel.
-  // This is nil when the current WebContents is in an incognito window.
-  NSButton* advancedAlwaysTranslateCheckbox_;
-
-  // The '[x]' close button on the upper right side of the before panel.
-  NSButton* closeButton_;
-
-  // The combobox model which is used to deny translation at the view before
-  // translate.
-  std::unique_ptr<TranslateDenialComboboxModel> translateDenialComboboxModel_;
-
-  // The combobox model for source languages on the advanced (option) panel.
-  std::unique_ptr<LanguageComboboxModel> sourceLanguageComboboxModel_;
-
-  // The combobox model for target languages on the advanced (option) panel.
-  std::unique_ptr<LanguageComboboxModel> targetLanguageComboboxModel_;
-
-  // Whether the translation is actually executed once at least.
-  BOOL translateExecuted_;
-
-  // The state of the 'Always ...' checkboxes.
-  BOOL shouldAlwaysTranslate_;
-}
-
-@synthesize webContents = webContents_;
-
-- (id)initWithParentWindow:(BrowserWindowController*)controller
-                     model:(std::unique_ptr<TranslateBubbleModel>)model
-               webContents:(content::WebContents*)webContents {
-  NSWindow* parentWindow = [controller window];
-
-  // Use an arbitrary size; it will be changed in performLayout.
-  NSRect contentRect = ui::kWindowSizeDeterminedLater;
-  base::scoped_nsobject<InfoBubbleWindow> window(
-      [[InfoBubbleWindow alloc] initWithContentRect:contentRect
-                                          styleMask:NSBorderlessWindowMask
-                                            backing:NSBackingStoreBuffered
-                                              defer:NO]);
-
-  // Disable animations - otherwise, the window/controller will outlive the web
-  // contents it's associated with.
-  [window setAllowedAnimations:info_bubble::kAnimateNone];
-
-  if ((self = [super initWithWindow:window
-                       parentWindow:parentWindow
-                         anchoredAt:NSZeroPoint])) {
-    webContents_ = webContents;
-    model_ = std::move(model);
-
-    shouldAlwaysTranslate_ = model_->ShouldAlwaysTranslate();
-    if (!webContents_->GetBrowserContext()->IsOffTheRecord()) {
-      shouldAlwaysTranslate_ =
-          model_->ShouldAlwaysTranslateBeCheckedByDefault();
-    }
-
-    if (model_->GetViewState() !=
-        TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE) {
-      translateExecuted_ = YES;
-    }
-
-    views_.reset([@{
-        @(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE):
-            [self newBeforeTranslateView],
-        @(TranslateBubbleModel::VIEW_STATE_TRANSLATING):
-            [self newTranslatingView],
-        @(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE):
-            [self newAfterTranslateView],
-        @(TranslateBubbleModel::VIEW_STATE_ERROR):
-            [self newErrorView],
-        @(TranslateBubbleModel::VIEW_STATE_ADVANCED):
-            [self newAdvancedView],
-    } retain]);
-
-    // The [X] Close Button.
-    closeButton_ = [self addCloseButton:[[self window] contentView]
-                                 action:@selector(handleCloseButtonPressed:)];
-
-    [self performLayout];
-    translate::ReportUiAction(translate::BUBBLE_SHOWN);
-  }
-  return self;
-}
-
-- (void)windowWillClose:(NSNotification*)notification {
-  model_->OnBubbleClosing();
-  [super windowWillClose:notification];
-}
-
-- (NSView*)currentView {
-  NSNumber* key = @(model_->GetViewState());
-  NSView* view = [views_ objectForKey:key];
-  DCHECK(view);
-  return view;
-}
-
-- (const TranslateBubbleModel*)model {
-  return model_.get();
-}
-
-- (void)showWindow:(id)sender {
-  BrowserWindowController* browserWindowController = [BrowserWindowController
-      browserWindowControllerForWindow:self.parentWindow];
-  LocationBarViewMac* locationBar = [browserWindowController locationBarBridge];
-  if (locationBar) {
-    NSPoint anchorPoint =
-        locationBar->GetBubblePointForDecoration([self decorationForBubble]);
-    anchorPoint =
-        ui::ConvertPointFromWindowToScreen([self parentWindow], anchorPoint);
-    [self setAnchorPoint:anchorPoint];
-  }
-  [super showWindow:sender];
-}
-
-- (LocationBarDecoration*)decorationForBubble {
-  BrowserWindowController* browserWindowController = [BrowserWindowController
-      browserWindowControllerForWindow:self.parentWindow];
-  LocationBarViewMac* locationBar = [browserWindowController locationBarBridge];
-  return locationBar ? locationBar->translate_decoration() : nullptr;
-}
-
-- (void)switchView:(TranslateBubbleModel::ViewState)viewState {
-  if (model_->GetViewState() == viewState)
-    return;
-
-  model_->SetViewState(viewState);
-  [self performLayout];
-}
-
-- (void)switchToErrorView:(translate::TranslateErrors::Type)errorType {
-  [self switchView:TranslateBubbleModel::VIEW_STATE_ERROR];
-  model_->ShowError(errorType);
-}
-
-- (void)performLayout {
-  [self updateAlwaysCheckboxes];
-  NSWindow* window = [self window];
-  [[window contentView] setSubviews:@[ [self currentView], closeButton_ ]];
-
-  CGFloat height = NSHeight([[self currentView] frame]) +
-                   2 * kTranslateBubbleFramePadding +
-                   info_bubble::kBubbleArrowHeight;
-
-  NSRect windowFrame = [window contentRectForFrameRect:[[self window] frame]];
-  NSRect newWindowFrame = [window
-      frameRectForContentRect:NSMakeRect(NSMinX(windowFrame),
-                                         NSMaxY(windowFrame) - height,
-                                         kTranslateBubbleWindowWidth, height)];
-
-  // Adjust the origin of closeButton.
-  CGFloat closeX = kTranslateBubbleWindowWidth -
-                   chrome_style::kCloseButtonPadding -
-                   chrome_style::GetCloseButtonSize();
-  CGFloat closeY = height - kTranslateBubbleFramePadding -
-                   chrome_style::kCloseButtonPadding -
-                   info_bubble::kBubbleArrowHeight;
-  [closeButton_ setFrameOrigin:NSMakePoint(closeX, closeY)];
-
-  [window setFrame:newWindowFrame
-           display:YES
-           animate:[[self window] isVisible]];
-}
-
-- (NSView*)newBeforeTranslateView {
-  NSRect contentFrame =
-      NSMakeRect(kTranslateBubbleFramePadding, kTranslateBubbleFramePadding,
-                 kTranslateBubbleContentWidth, 0);
-  NSView* view = [[NSView alloc] initWithFrame:contentFrame];
-
-  base::string16 originalLanguageName =
-      model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
-  base::string16 targetLanguageName =
-      model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
-
-  std::vector<size_t> offsets;
-  NSString* message = l10n_util::GetNSStringF(
-      IDS_TRANSLATE_BUBBLE_BEFORE_TRANSLATE_NEW, originalLanguageName,
-      targetLanguageName, &offsets);
-  std::vector<NSRange> ranges;
-  ranges.push_back(NSMakeRange(offsets[0], originalLanguageName.length()));
-  ranges.push_back(NSMakeRange(offsets[1], targetLanguageName.length()));
-
-  NSTextView* textLabel = [self addStyledTextView:message
-                                           toView:view
-                                       withRanges:ranges
-                                         delegate:self];
-
-  NSString* title =
-      l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ACCEPT);
-  NSButton* translateButton =
-      [self addButton:title
-               action:@selector(handleTranslateButtonPressed:)
-               toView:view];
-  [translateButton setKeyEquivalent:@"\r"];
-
-  // TODO(hajimehoshi): When TranslateDenialComboboxModel is factored out as a
-  // common model, ui::MenuModel will be used here.
-  translateDenialComboboxModel_.reset(
-      new TranslateDenialComboboxModel(originalLanguageName));
-  NSPopUpButton* denyPopUpButton =
-      [self addPopUpButton:translateDenialComboboxModel_.get()
-                    action:nil
-                    toView:view];
-  [denyPopUpButton setPullsDown:YES];
-  [[denyPopUpButton itemAtIndex:1] setTarget:self];
-  [[denyPopUpButton itemAtIndex:1]
-      setAction:@selector(
-                    handleDenialPopUpButtonNeverTranslateLanguageSelected:)];
-  [[denyPopUpButton itemAtIndex:2] setTarget:self];
-  [[denyPopUpButton itemAtIndex:2]
-      setAction:@selector(handleDenialPopUpButtonNeverTranslateSiteSelected:)];
-
-  title = base::SysUTF16ToNSString(
-      l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_OPTIONS_MENU_BUTTON));
-  [[denyPopUpButton itemAtIndex:0] setTitle:title];
-
-  // Adjust width for the first item.
-  base::scoped_nsobject<NSMenu> originalMenu([[denyPopUpButton menu] copy]);
-  [denyPopUpButton removeAllItems];
-  [denyPopUpButton addItemWithTitle:[[originalMenu itemAtIndex:0] title]];
-  [denyPopUpButton sizeToFit];
-  [denyPopUpButton setMenu:originalMenu];
-
-  // 'Always translate' checkbox
-  if (!webContents_->GetBrowserContext()->IsOffTheRecord()) {
-    title =
-        l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ALWAYS_DO_THIS);
-    SEL action = @selector(handleAlwaysTranslateCheckboxPressed:);
-    beforeAlwaysTranslateCheckbox_ =
-        [self addCheckbox:title action:action toView:view];
-  }
-
-  NSImageView* icon = [self addIcon:view];
-
-  // Layout
-  CGFloat yPos = 0;
-
-  [translateButton
-      setFrameOrigin:NSMakePoint(kTranslateBubbleContentWidth -
-                                     NSWidth([translateButton frame]),
-                                 yPos)];
-
-  NSRect denyPopUpButtonFrame = [denyPopUpButton frame];
-  CGFloat diffY = [[denyPopUpButton cell]
-    titleRectForBounds:[denyPopUpButton bounds]].origin.y;
-  [denyPopUpButton
-      setFrameOrigin:NSMakePoint(
-                         NSMinX([translateButton frame]) -
-                             denyPopUpButtonFrame.size.width -
-                             kTranslateBubbleRelatedControlHorizontalSpacing,
-                         yPos + diffY)];
-
-  yPos += NSHeight([translateButton frame]) +
-          kTranslateBubbleUnrelatedControlVerticalSpacing;
-
-  if (beforeAlwaysTranslateCheckbox_) {
-    [beforeAlwaysTranslateCheckbox_
-        setFrameOrigin:NSMakePoint(kTranslateBubbleIconWidth +
-                                       kTranslateBubbleIconPadding,
-                                   yPos)];
-
-    yPos += NSHeight([beforeAlwaysTranslateCheckbox_ frame]) +
-            kTranslateBubbleRelatedControlVerticalSpacing;
-  }
-
-  [textLabel setFrameOrigin:NSMakePoint(kTranslateBubbleIconWidth +
-                                            kTranslateBubbleIconPadding,
-                                        yPos)];
-
-  yPos = NSMaxY([textLabel frame]);
-  [icon setFrameOrigin:NSMakePoint(0, yPos - kTranslateBubbleIconHeight)];
-  [view setFrameSize:NSMakeSize(kTranslateBubbleContentWidth, yPos)];
-
-  return view;
-}
-
-- (NSView*)newTranslatingView {
-  NSRect contentFrame =
-      NSMakeRect(kTranslateBubbleFramePadding, kTranslateBubbleFramePadding,
-                 kTranslateBubbleContentWidth, 0);
-  NSView* view = [[NSView alloc] initWithFrame:contentFrame];
-
-  NSString* message =
-      l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_TRANSLATING);
-  NSTextField* textLabel = [self addText:message
-                                  toView:view];
-  NSString* title =
-      l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_REVERT);
-  NSButton* showOriginalButton =
-      [self addButton:title
-               action:@selector(handleShowOriginalButtonPressed:)
-               toView:view];
-  [showOriginalButton setEnabled:NO];
-  NSImageView* icon = [self addIcon:view];
-
-  // Layout
-  // TODO(hajimehoshi): Use l10n_util::VerticallyReflowGroup.
-  CGFloat yPos = 0;
-
-  [showOriginalButton
-      setFrameOrigin:NSMakePoint(kTranslateBubbleContentWidth -
-                                     NSWidth([showOriginalButton frame]),
-                                 yPos)];
-
-  yPos += NSHeight([showOriginalButton frame]) +
-          kTranslateBubbleUnrelatedControlVerticalSpacing;
-
-  [textLabel setFrameOrigin:NSMakePoint(kTranslateBubbleIconWidth +
-                                            kTranslateBubbleIconPadding,
-                                        yPos)];
-
-  yPos = NSMaxY([textLabel frame]);
-  [icon setFrameOrigin:NSMakePoint(0, yPos - kTranslateBubbleIconHeight)];
-  [view setFrameSize:NSMakeSize(kTranslateBubbleContentWidth, yPos)];
-
-  return view;
-}
-
-- (NSView*)newAfterTranslateView {
-  NSRect contentFrame =
-      NSMakeRect(kTranslateBubbleFramePadding, kTranslateBubbleFramePadding,
-                 kTranslateBubbleContentWidth, 0);
-  NSView* view = [[NSView alloc] initWithFrame:contentFrame];
-
-  NSString* message =
-      l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_TRANSLATED);
-  NSTextField* textLabel = [self addText:message
-                                  toView:view];
-  message = l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ADVANCED_LINK);
-  NSButton* advancedLinkButton =
-      [self addLinkButtonWithText:message
-                           action:@selector(handleAdvancedLinkButtonPressed:)
-                           toView:view];
-  NSString* title =
-      l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_REVERT);
-  NSButton* showOriginalButton =
-      [self addButton:title
-               action:@selector(handleShowOriginalButtonPressed:)
-               toView:view];
-
-  NSImageView* icon = [self addIcon:view];
-
-  // Layout
-  CGFloat yPos = 0;
-
-  [showOriginalButton
-      setFrameOrigin:NSMakePoint(kTranslateBubbleContentWidth -
-                                     NSWidth([showOriginalButton frame]),
-                                 yPos)];
-
-  yPos += NSHeight([showOriginalButton frame]) +
-          kTranslateBubbleUnrelatedControlVerticalSpacing;
-
-  [textLabel setFrameOrigin:NSMakePoint(kTranslateBubbleIconWidth +
-                                            kTranslateBubbleIconPadding,
-                                        yPos)];
-  [advancedLinkButton setFrameOrigin:NSMakePoint(
-      NSMaxX([textLabel frame]), yPos)];
-
-  yPos = NSMaxY([textLabel frame]);
-  [icon setFrameOrigin:NSMakePoint(0, yPos - kTranslateBubbleIconHeight)];
-  [view setFrameSize:NSMakeSize(kTranslateBubbleContentWidth, yPos)];
-
-  return view;
-}
-
-- (NSView*)newErrorView {
-  NSRect contentFrame =
-      NSMakeRect(kTranslateBubbleFramePadding, kTranslateBubbleFramePadding,
-                 kTranslateBubbleContentWidth, 0);
-  NSView* view = [[NSView alloc] initWithFrame:contentFrame];
-
-  NSString* message =
-      l10n_util::GetNSString(IDS_TRANSLATE_BUBBLE_COULD_NOT_TRANSLATE);
-  NSTextField* textLabel = [self addText:message toView:view];
-  message = l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ADVANCED_LINK);
-  NSButton* advancedLinkButton =
-      [self addLinkButtonWithText:message
-                           action:@selector(handleAdvancedLinkButtonPressed:)
-                           toView:view];
-  NSString* title =
-      l10n_util::GetNSString(IDS_TRANSLATE_BUBBLE_TRY_AGAIN);
-  tryAgainButton_ = [self addButton:title
-                             action:@selector(handleTryAgainButtonPressed:)
-                             toView:view];
-
-  NSImageView* icon = [self addIcon:view];
-
-  // Layout
-  CGFloat yPos = 0;
-
-  [tryAgainButton_
-      setFrameOrigin:NSMakePoint(kTranslateBubbleContentWidth -
-                                     NSWidth([tryAgainButton_ frame]),
-                                 yPos)];
-
-  yPos += NSHeight([tryAgainButton_ frame]) +
-          kTranslateBubbleUnrelatedControlVerticalSpacing;
-
-  [textLabel setFrameOrigin:NSMakePoint(kTranslateBubbleIconWidth +
-                                            kTranslateBubbleIconPadding,
-                                        yPos)];
-  [advancedLinkButton
-      setFrameOrigin:NSMakePoint(NSMaxX([textLabel frame]), yPos)];
-
-  yPos = NSMaxY([textLabel frame]);
-  [icon setFrameOrigin:NSMakePoint(0, yPos - kTranslateBubbleIconHeight)];
-  [view setFrameSize:NSMakeSize(kTranslateBubbleContentWidth, yPos)];
-
-  return view;
-}
-
-- (NSView*)newAdvancedView {
-  NSRect contentFrame =
-      NSMakeRect(kTranslateBubbleFramePadding, kTranslateBubbleFramePadding,
-                 kTranslateBubbleContentWidth, 0);
-  NSView* view = [[NSView alloc] initWithFrame:contentFrame];
-
-  NSString* title = l10n_util::GetNSStringWithFixup(
-      IDS_TRANSLATE_BUBBLE_PAGE_LANGUAGE);
-  NSTextField* sourceLanguageLabel = [self addText:title
-                                            toView:view];
-  title = l10n_util::GetNSStringWithFixup(
-      IDS_TRANSLATE_BUBBLE_TRANSLATION_LANGUAGE);
-  NSTextField* targetLanguageLabel = [self addText:title
-                                            toView:view];
-
-  // combobox
-  int sourceDefaultIndex = model_->GetOriginalLanguageIndex();
-  int targetDefaultIndex = model_->GetTargetLanguageIndex();
-  sourceLanguageComboboxModel_.reset(
-      new LanguageComboboxModel(sourceDefaultIndex, model_.get()));
-  targetLanguageComboboxModel_.reset(
-      new LanguageComboboxModel(targetDefaultIndex, model_.get()));
-  SEL action = @selector(handleSourceLanguagePopUpButtonSelectedItemChanged:);
-  NSPopUpButton* sourcePopUpButton =
-      [self addPopUpButton:sourceLanguageComboboxModel_.get()
-                    action:action
-                    toView:view];
-  action = @selector(handleTargetLanguagePopUpButtonSelectedItemChanged:);
-  NSPopUpButton* targetPopUpButton =
-      [self addPopUpButton:targetLanguageComboboxModel_.get()
-                    action:action
-                    toView:view];
-
-  // 'Always translate' checkbox
-  if (!webContents_->GetBrowserContext()->IsOffTheRecord()) {
-    NSString* title =
-        l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ALWAYS);
-    action = @selector(handleAlwaysTranslateCheckboxPressed:);
-    advancedAlwaysTranslateCheckbox_ =
-        [self addCheckbox:title action:action toView:view];
-  }
-
-  // Buttons
-  advancedDoneButton_ =
-      [self addButton:l10n_util::GetNSStringWithFixup(IDS_DONE)
-               action:@selector(handleDoneButtonPressed:)
-               toView:view];
-  [advancedDoneButton_ setKeyEquivalent:@"\r"];
-  advancedCancelButton_ =
-      [self addButton:l10n_util::GetNSStringWithFixup(IDS_CANCEL)
-               action:@selector(handleCancelButtonPressed:)
-               toView:view];
-
-  NSString* message = l10n_util::GetNSStringWithFixup(
-        IDS_TRANSLATE_BUBBLE_LANGUAGE_SETTINGS);
-  action = @selector(handleLanguageSettingsLinkButtonPressed:);
-  NSButton* languageSettingsLinkButton =
-      [self addLinkButtonWithText:message
-                           action:action
-                           toView:view];
-
-  // Layout
-  CGFloat textLabelWidth = NSWidth([sourceLanguageLabel frame]);
-  if (textLabelWidth < NSWidth([targetLanguageLabel frame]))
-    textLabelWidth = NSWidth([targetLanguageLabel frame]);
-
-  CGFloat yPos = 0;
-
-  [advancedDoneButton_ setFrameOrigin:NSMakePoint(0, yPos)];
-  [advancedCancelButton_ setFrameOrigin:NSMakePoint(0, yPos)];
-
-  [languageSettingsLinkButton setFrameOrigin:NSMakePoint(0, yPos)];
-
-  // Vertical center the languageSettingsLinkButton with the
-  // advancedDoneButton_. Move the link position by 1px to make the baseline of
-  // the text inside the link vertically align with the text inside the buttons.
-  yPos = 1 + floor((NSHeight([advancedDoneButton_ frame]) -
-         NSHeight([languageSettingsLinkButton frame])) / 2);
-  [languageSettingsLinkButton setFrameOrigin:NSMakePoint(0, yPos)];
-
-  yPos = NSHeight([advancedDoneButton_ frame]) +
-         kTranslateBubbleUnrelatedControlVerticalSpacing;
-
-  if (advancedAlwaysTranslateCheckbox_) {
-    [advancedAlwaysTranslateCheckbox_
-        setFrameOrigin:NSMakePoint(textLabelWidth, yPos)];
-
-    yPos += NSHeight([advancedAlwaysTranslateCheckbox_ frame]) +
-            kTranslateBubbleRelatedControlVerticalSpacing;
-  }
-
-  CGFloat diffY = [[sourcePopUpButton cell]
-                   titleRectForBounds:[sourcePopUpButton bounds]].origin.y;
-
-  [targetLanguageLabel setFrameOrigin:NSMakePoint(
-      textLabelWidth - NSWidth([targetLanguageLabel frame]), yPos + diffY)];
-
-  NSRect frame = [targetPopUpButton frame];
-  frame.origin = NSMakePoint(textLabelWidth, yPos);
-  frame.size.width =
-      (kTranslateBubbleWindowWidth - 2 * kTranslateBubbleFramePadding) -
-      textLabelWidth;
-  [targetPopUpButton setFrame:frame];
-
-  yPos += NSHeight([targetPopUpButton frame]) +
-          kTranslateBubbleRelatedControlVerticalSpacing;
-
-  [sourceLanguageLabel setFrameOrigin:NSMakePoint(
-      textLabelWidth - NSWidth([sourceLanguageLabel frame]), yPos + diffY)];
-
-  frame = [sourcePopUpButton frame];
-  frame.origin = NSMakePoint(textLabelWidth, yPos);
-  frame.size.width = NSWidth([targetPopUpButton frame]);
-  [sourcePopUpButton setFrame:frame];
-
-  [view setFrameSize:NSMakeSize(kTranslateBubbleContentWidth,
-                                NSMaxY([sourcePopUpButton frame]) +
-                                    kTranslateBubbleIconPadding)];
-
-  [self updateAdvancedView];
-
-  return view;
-}
-
-- (void)updateAdvancedView {
-  NSString* title;
-  if (model_->IsPageTranslatedInCurrentLanguages())
-    title = l10n_util::GetNSStringWithFixup(IDS_DONE);
-  else
-    title = l10n_util::GetNSStringWithFixup(IDS_TRANSLATE_BUBBLE_ACCEPT);
-  [advancedDoneButton_ setTitle:title];
-  [advancedDoneButton_ sizeToFit];
-
-  NSRect frame = [advancedDoneButton_ frame];
-  frame.origin.x =
-      (kTranslateBubbleWindowWidth - 2 * kTranslateBubbleFramePadding) -
-      NSWidth(frame);
-  [advancedDoneButton_ setFrameOrigin:frame.origin];
-
-  frame = [advancedCancelButton_ frame];
-  frame.origin.x = NSMinX([advancedDoneButton_ frame]) - NSWidth(frame) -
-                   kTranslateBubbleRelatedControlHorizontalSpacing;
-  [advancedCancelButton_ setFrameOrigin:frame.origin];
-}
-
-- (void)updateAlwaysCheckboxes {
-  NSInteger state = shouldAlwaysTranslate_ ? NSOnState : NSOffState;
-  [beforeAlwaysTranslateCheckbox_ setState:state];
-  [advancedAlwaysTranslateCheckbox_ setState:state];
-}
-
-- (NSImageView*)addIcon:(NSView*)view {
-  NSRect imageFrame =
-      NSMakeRect(0, 0, kTranslateBubbleIconWidth, kTranslateBubbleIconHeight);
-  base::scoped_nsobject<NSImageView> image(
-      [[NSImageView alloc] initWithFrame:imageFrame]);
-  [image setImage:(ui::ResourceBundle::GetSharedInstance()
-                       .GetImageNamed(IDR_TRANSLATE_BUBBLE_ICON)
-                       .ToNSImage())];
-  [view addSubview:image];
-  return image.get();
-}
-
-- (NSTextView*)addStyledTextView:(NSString*)message
-                          toView:(NSView*)view
-                      withRanges:(std::vector<NSRange>)ranges
-                        delegate:(id<NSTextViewDelegate>)delegate {
-  NSRect frame =
-      NSMakeRect(kTranslateBubbleFramePadding + kTranslateBubbleIconWidth +
-                     kTranslateBubbleIconPadding,
-                 kTranslateBubbleFramePadding,
-                 kTranslateBubbleContentWidth - kTranslateBubbleIconWidth -
-                     kTranslateBubbleIconPadding,
-                 0);
-  base::scoped_nsobject<HyperlinkTextView> styledText(
-      [[HyperlinkTextView alloc] initWithFrame:frame]);
-  [styledText setMessage:message
-                withFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]
-            messageColor:(skia::SkColorToCalibratedNSColor(SK_ColorBLACK))];
-  [styledText setDelegate:delegate];
-
-  NSColor* linkColor =
-      skia::SkColorToCalibratedNSColor(chrome_style::GetLinkColor());
-  // Create the link with no underlining.
-  [styledText setLinkTextAttributes:nil];
-  NSTextStorage* storage = [styledText textStorage];
-  for (const auto& range : ranges) {
-    [styledText addLinkRange:range withURL:nil linkColor:linkColor];
-    [storage addAttribute:NSUnderlineStyleAttributeName
-                    value:@(NSUnderlineStyleNone)
-                    range:range];
-  }
-
-  [view addSubview:styledText];
-  [styledText setVerticallyResizable:YES];
-  [styledText sizeToFit];
-  return styledText.get();
-}
-
-- (NSTextField*)addText:(NSString*)text
-                 toView:(NSView*)view {
-  base::scoped_nsobject<NSTextField> textField(
-      [[NSTextField alloc] initWithFrame:NSZeroRect]);
-  [textField setEditable:NO];
-  [textField setSelectable:YES];
-  [textField setDrawsBackground:NO];
-  [textField setBezeled:NO];
-  [textField setStringValue:text];
-  NSFont* font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
-  [textField setFont:font];
-  [textField setAutoresizingMask:NSViewWidthSizable];
-  [view addSubview:textField.get()];
-
-  [textField sizeToFit];
-  return textField.get();
-}
-
-- (NSButton*)addLinkButtonWithText:(NSString*)text
-                            action:(SEL)action
-                            toView:(NSView*)view {
-  base::scoped_nsobject<NSButton> button(
-      [[HyperlinkButtonCell buttonWithString:text] retain]);
-
-  [button setButtonType:NSMomentaryPushInButton];
-  [button setBezelStyle:NSRegularSquareBezelStyle];
-  [button setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
-  [button sizeToFit];
-  [button setTarget:self];
-  [button setAction:action];
-
-  [view addSubview:button.get()];
-
-  return button.get();
-}
-
-- (NSButton*)addButton:(NSString*)title
-                action:(SEL)action
-                toView:(NSView*)view {
-  base::scoped_nsobject<NSButton> button(
-      [[NSButton alloc] initWithFrame:NSZeroRect]);
-  [button setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
-  [button setTitle:title];
-  [button setBezelStyle:NSRoundedBezelStyle];
-  [[button cell] setControlSize:NSSmallControlSize];
-  [button sizeToFit];
-  [button setTarget:self];
-  [button setAction:action];
-
-  [view addSubview:button.get()];
-
-  return button.get();
-}
-
-- (NSButton*)addCheckbox:(NSString*)title
-                  action:(SEL)action
-                  toView:(NSView*)view {
-  base::scoped_nsobject<NSButton> button(
-      [[NSButton alloc] initWithFrame:NSZeroRect]);
-  [button setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
-  [button setTitle:title];
-  [[button cell] setControlSize:NSSmallControlSize];
-  [button setButtonType:NSSwitchButton];
-  [button sizeToFit];
-  [button setTarget:self];
-  [button setAction:action];
-
-  [view addSubview:button.get()];
-
-  return button.get();
-}
-
-- (NSButton*)addCloseButton:(NSView*)view action:(SEL)action {
-  const int extent = chrome_style::GetCloseButtonSize();
-  NSRect frame = NSMakeRect(0, 0, extent, extent);
-  base::scoped_nsobject<NSButton> button(
-      [[WebUIHoverCloseButton alloc] initWithFrame:frame]);
-  [button setTarget:self];
-  [button setAction:action];
-  [view addSubview:button.get()];
-  return button.get();
-}
-
-- (NSPopUpButton*)addPopUpButton:(ui::ComboboxModel*)model
-                          action:(SEL)action
-                          toView:(NSView*)view {
-  base::scoped_nsobject<NSPopUpButton> button(
-      [[BubbleCombobox alloc] initWithFrame:NSZeroRect
-                                  pullsDown:NO
-                                      model:model]);
-  [button setTarget:self];
-  [button setAction:action];
-  [button sizeToFit];
-  [view addSubview:button.get()];
-  return button.get();
-}
-
-- (IBAction)handleTranslateButtonPressed:(id)sender {
-  model_->SetAlwaysTranslate(shouldAlwaysTranslate_);
-  translate::ReportUiAction(translate::TRANSLATE_BUTTON_CLICKED);
-  translateExecuted_ = YES;
-  model_->Translate();
-}
-
-- (IBAction)handleAlwaysTranslateCheckboxPressed:(NSButton*)sender {
-  shouldAlwaysTranslate_ = [sender state] == NSOnState;
-  translate::ReportUiAction(shouldAlwaysTranslate_
-                                ? translate::ALWAYS_TRANSLATE_CHECKED
-                                : translate::ALWAYS_TRANSLATE_UNCHECKED);
-}
-
-- (IBAction)handleDoneButtonPressed:(id)sender {
-  translate::ReportUiAction(translate::DONE_BUTTON_CLICKED);
-  model_->SetAlwaysTranslate(shouldAlwaysTranslate_);
-  if (model_->IsPageTranslatedInCurrentLanguages()) {
-    model_->GoBackFromAdvanced();
-    [self performLayout];
-  } else {
-    translateExecuted_ = true;
-    model_->Translate();
-    [self switchView:TranslateBubbleModel::VIEW_STATE_TRANSLATING];
-  }
-}
-
-- (IBAction)handleCancelButtonPressed:(id)sender {
-  translate::ReportUiAction(translate::CANCEL_BUTTON_CLICKED);
-  model_->GoBackFromAdvanced();
-  [self performLayout];
-}
-
-- (IBAction)handleCloseButtonPressed:(id)sender {
-  model_->DeclineTranslation();
-  translate::ReportUiAction(translate::CLOSE_BUTTON_CLICKED);
-  [self close];
-}
-
-- (IBAction)handleShowOriginalButtonPressed:(id)sender {
-  translate::ReportUiAction(translate::SHOW_ORIGINAL_BUTTON_CLICKED);
-  model_->RevertTranslation();
-  [self close];
-}
-
-- (IBAction)handleTryAgainButtonPressed:(id)sender {
-  model_->Translate();
-  translate::ReportUiAction(translate::TRY_AGAIN_BUTTON_CLICKED);
-}
-
-- (IBAction)handleAdvancedLinkButtonPressed:(id)sender {
-  translate::ReportUiAction(translate::ADVANCED_LINK_CLICKED);
-  [self switchView:TranslateBubbleModel::VIEW_STATE_ADVANCED];
-}
-
-- (IBAction)handleLanguageSettingsLinkButtonPressed:(id)sender {
-  GURL url = chrome::GetSettingsUrl(chrome::kLanguageOptionsSubPage);
-  webContents_->OpenURL(content::OpenURLParams(
-      url, content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB,
-      ui::PAGE_TRANSITION_LINK, false));
-  translate::ReportUiAction(translate::SETTINGS_LINK_CLICKED);
-  [self close];
-}
-
-- (IBAction)handleDenialPopUpButtonNeverTranslateLanguageSelected:(id)sender {
-  translate::ReportUiAction(translate::NEVER_TRANSLATE_LANGUAGE_MENU_CLICKED);
-  model_->DeclineTranslation();
-  model_->SetNeverTranslateLanguage(true);
-  [self close];
-}
-
-- (IBAction)handleDenialPopUpButtonNeverTranslateSiteSelected:(id)sender {
-  translate::ReportUiAction(translate::NEVER_TRANSLATE_SITE_MENU_CLICKED);
-  model_->DeclineTranslation();
-  model_->SetNeverTranslateSite(true);
-  [self close];
-}
-
-- (IBAction)handleSourceLanguagePopUpButtonSelectedItemChanged:(id)sender {
-  translate::ReportUiAction(translate::SOURCE_LANGUAGE_MENU_CLICKED);
-  NSPopUpButton* button = base::mac::ObjCCastStrict<NSPopUpButton>(sender);
-  model_->UpdateOriginalLanguageIndex([button indexOfSelectedItem]);
-  [self updateAdvancedView];
-}
-
-- (IBAction)handleTargetLanguagePopUpButtonSelectedItemChanged:(id)sender {
-  translate::ReportUiAction(translate::TARGET_LANGUAGE_MENU_CLICKED);
-  NSPopUpButton* button = base::mac::ObjCCastStrict<NSPopUpButton>(sender);
-  model_->UpdateTargetLanguageIndex([button indexOfSelectedItem]);
-  [self updateAdvancedView];
-}
-
-// The NSTextViewDelegate method which called when user click on the
-// source or target language on the before translate view.
-- (BOOL)textView:(NSTextView*)aTextView
-    clickedOnLink:(id)link
-          atIndex:(NSUInteger)charIndex {
-  translate::ReportUiAction(translate::ADVANCED_LINK_CLICKED);
-  [self switchView:TranslateBubbleModel::VIEW_STATE_ADVANCED];
-  return YES;
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/translate/translate_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/translate/translate_bubble_controller_unittest.mm
deleted file mode 100644
index e8b97e0b..0000000
--- a/chrome/browser/ui/cocoa/translate/translate_bubble_controller_unittest.mm
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/translate/translate_bubble_controller.h"
-
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
-#import "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#import "chrome/browser/ui/cocoa/browser_window_controller.h"
-#import "chrome/browser/ui/cocoa/info_bubble_window.h"
-#import "chrome/browser/ui/cocoa/test/cocoa_profile_test.h"
-#include "chrome/browser/ui/cocoa/test/run_loop_testing.h"
-#include "chrome/browser/ui/translate/translate_bubble_model.h"
-#include "chrome/common/url_constants.h"
-#include "content/public/browser/site_instance.h"
-#include "ui/base/ui_base_features.h"
-
-@implementation BrowserWindowController (ForTesting)
-
-- (TranslateBubbleController*)translateBubbleController{
-  return translateBubbleController_;
-}
-
-@end
-
-@implementation TranslateBubbleController (ForTesting)
-
-- (NSView*)errorView {
-  NSNumber* key = @(TranslateBubbleModel::VIEW_STATE_ERROR);
-  return [views_ objectForKey:key];
-}
-- (NSButton*)tryAgainButton {
-  return tryAgainButton_;
-}
-
-@end
-
-class TranslateBubbleControllerTest : public CocoaProfileTest {
- public:
-  TranslateBubbleControllerTest() {}
-
-  // CocoaProfileTest:
-  void SetUp() override {
-    // This file only tests Cocoa UI and can be deleted when kSecondaryUiMd is
-    // default.
-    scoped_feature_list_.InitAndDisableFeature(features::kSecondaryUiMd);
-
-    CocoaProfileTest::SetUp();
-
-    site_instance_ = content::SiteInstance::Create(profile());
-
-    NSWindow* nativeWindow = browser()->window()->GetNativeWindow();
-    bwc_ =
-        [BrowserWindowController browserWindowControllerForWindow:nativeWindow];
-    web_contents_ = AppendToTabStrip();
-  }
-
-  content::WebContents* AppendToTabStrip() {
-    std::unique_ptr<content::WebContents> web_contents =
-        content::WebContents::Create(content::WebContents::CreateParams(
-            profile(), site_instance_.get()));
-    content::WebContents* raw_web_contents = web_contents.get();
-    browser()->tab_strip_model()->AppendWebContents(std::move(web_contents),
-                                                    /*foreground=*/true);
-    return raw_web_contents;
-  }
-
-  BrowserWindowController* bwc() { return bwc_; }
-
-  TranslateBubbleController* bubble() {
-    return [bwc() translateBubbleController];
-  }
-
-  void ShowBubble() {
-    ASSERT_FALSE(bubble());
-    translate::TranslateStep step = translate::TRANSLATE_STEP_BEFORE_TRANSLATE;
-
-    [bwc_ showTranslateBubbleForWebContents:web_contents_
-                                       step:step
-                                  errorType:translate::TranslateErrors::NONE];
-
-    // Ensure that there are no closing animations.
-    InfoBubbleWindow* window = (InfoBubbleWindow*)[bubble() window];
-    [window setAllowedAnimations:info_bubble::kAnimateNone];
-  }
-
-  void SwitchToErrorView() {
-    translate::TranslateStep step = translate::TRANSLATE_STEP_TRANSLATE_ERROR;
-    [bwc_
-        showTranslateBubbleForWebContents:web_contents_
-                                     step:step
-                                errorType:translate::TranslateErrors::NETWORK];
-  }
-
-  void CloseBubble() {
-    [bubble() close];
-    chrome::testing::NSRunLoopRunAllPending();
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-  scoped_refptr<content::SiteInstance> site_instance_;
-  BrowserWindowController* bwc_;
-  content::WebContents* web_contents_;
-
-  DISALLOW_COPY_AND_ASSIGN(TranslateBubbleControllerTest);
-};
-
-TEST_F(TranslateBubbleControllerTest, ShowAndClose) {
-  EXPECT_FALSE(bubble());
-
-  ShowBubble();
-  EXPECT_TRUE(bubble());
-
-  CloseBubble();
-  EXPECT_FALSE(bubble());
-}
-
-TEST_F(TranslateBubbleControllerTest, SwitchToErrorView) {
-  EXPECT_FALSE(bubble());
-  ShowBubble();
-  const TranslateBubbleModel* model = [bubble() model];
-
-  EXPECT_TRUE(bubble());
-  EXPECT_EQ(TranslateBubbleModel::ViewState::VIEW_STATE_BEFORE_TRANSLATE,
-            model->GetViewState());
-
-  SwitchToErrorView();
-
-  NSView* errorView = [bubble() errorView];
-  // We should have 4 subview inside the error view:
-  // A NSTextField, a NSImageView and two NSButton.
-  EXPECT_EQ(4UL, [[errorView subviews] count]);
-
-  // one of the subview should be "Try again" button.
-  EXPECT_TRUE([[errorView subviews] containsObject:[bubble() tryAgainButton]]);
-  EXPECT_EQ(TranslateBubbleModel::ViewState::VIEW_STATE_ERROR,
-            model->GetViewState());
-  EXPECT_TRUE(bubble());
-  CloseBubble();
-}
-
-TEST_F(TranslateBubbleControllerTest, SwitchViews) {
-  // A basic test which just switch between views to make sure no crash.
-  EXPECT_FALSE(bubble());
-
-  ShowBubble();
-  EXPECT_TRUE(bubble());
-
-  // Switch to during translating view.
-  [bubble()
-      switchView:(TranslateBubbleModel::ViewState::VIEW_STATE_TRANSLATING)];
-
-  EXPECT_TRUE(bubble());
-
-  // Switch to after translating view.
-  [bubble()
-      switchView:(TranslateBubbleModel::ViewState::VIEW_STATE_AFTER_TRANSLATE)];
-
-  EXPECT_TRUE(bubble());
-
-  // Switch to advanced view.
-  [bubble() switchView:(TranslateBubbleModel::ViewState::VIEW_STATE_ADVANCED)];
-
-  EXPECT_TRUE(bubble());
-
-  // Switch to before translating view.
-  [bubble() switchView:
-                (TranslateBubbleModel::ViewState::VIEW_STATE_BEFORE_TRANSLATE)];
-
-  EXPECT_TRUE(bubble());
-
-  CloseBubble();
-  EXPECT_FALSE(bubble());
-}
-
-TEST_F(TranslateBubbleControllerTest, CloseRegistersDecline) {
-  const char kDeclineTranslateDismissUI[] =
-      "Translate.DeclineTranslateDismissUI";
-  const char kDeclineTranslate[] = "Translate.DeclineTranslate";
-
-  // A simple close without any interactions registers as a dismissal.
-  {
-    base::HistogramTester histogram_tester;
-    ShowBubble();
-    CloseBubble();
-    histogram_tester.ExpectTotalCount(kDeclineTranslateDismissUI, 1);
-    histogram_tester.ExpectTotalCount(kDeclineTranslate, 0);
-  }
-
-  // A close while pressing e.g. 'x', registers as decline.
-  {
-    base::HistogramTester histogram_tester;
-    ShowBubble();
-    [bubble() handleCloseButtonPressed:nil];
-
-    CloseBubble();
-    histogram_tester.ExpectTotalCount(kDeclineTranslateDismissUI, 0);
-    histogram_tester.ExpectTotalCount(kDeclineTranslate, 1);
-  }
-}
diff --git a/chrome/browser/ui/cocoa/translate/translate_bubble_test_utils_views_cocoa.mm b/chrome/browser/ui/cocoa/translate/translate_bubble_test_utils_views_cocoa.mm
deleted file mode 100644
index 0574cd8..0000000
--- a/chrome/browser/ui/cocoa/translate/translate_bubble_test_utils_views_cocoa.mm
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/translate/translate_bubble_test_utils.h"
-
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/cocoa/browser_dialogs_views_mac.h"
-#include "chrome/browser/ui/cocoa/browser_window_controller.h"
-#include "chrome/browser/ui/cocoa/translate/translate_bubble_controller.h"
-#include "chrome/browser/ui/translate/translate_bubble_model.h"
-#include "chrome/browser/ui/views/translate/translate_bubble_view.h"
-#include "ui/events/keycodes/dom/dom_code.h"
-#include "ui/views/controls/button/label_button.h"
-
-// TODO(groby): Share with translate_bubble_controller_unittest.mm
-@implementation BrowserWindowController (ForTesting)
-
-- (TranslateBubbleController*)translateBubbleController {
-  return translateBubbleController_;
-}
-
-@end
-
-namespace translate {
-
-namespace test_utils {
-
-const TranslateBubbleModel* GetCurrentModel(Browser* browser) {
-  DCHECK(browser);
-  if (chrome::ShowAllDialogsWithViewsToolkit()) {
-    TranslateBubbleView* view = TranslateBubbleView::GetCurrentBubble();
-    return view ? view->model() : nullptr;
-  }
-
-  NSWindow* native_window = browser->window()->GetNativeWindow();
-  BrowserWindowController* controller =
-      [BrowserWindowController browserWindowControllerForWindow:native_window];
-  return [[controller translateBubbleController] model];
-}
-
-void PressTranslate(Browser* browser) {
-  DCHECK(browser);
-
-  if (chrome::ShowAllDialogsWithViewsToolkit()) {
-    TranslateBubbleView* bubble = TranslateBubbleView::GetCurrentBubble();
-    DCHECK(bubble);
-
-    views::LabelButton button(nullptr, base::string16());
-    button.set_id(TranslateBubbleView::BUTTON_ID_TRANSLATE);
-
-    bubble->ButtonPressed(&button,
-                          ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN,
-                                       ui::DomCode::ENTER, ui::EF_NONE));
-    return;
-  }
-
-  NSWindow* native_window = browser->window()->GetNativeWindow();
-  BrowserWindowController* controller =
-      [BrowserWindowController browserWindowControllerForWindow:native_window];
-  [[controller translateBubbleController] handleTranslateButtonPressed:nil];
-}
-
-}  // namespace test_utils
-
-}  // namespace translate
diff --git a/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.cc b/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.cc
index 5e41940f..63e7925 100644
--- a/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.cc
+++ b/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.cc
@@ -14,12 +14,10 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profiles_state.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/browser_sync/profile_sync_service.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
@@ -93,16 +91,15 @@
   if (signin_error_controller && signin_error_controller->HasError())
     return false;
 
-  const browser_sync::ProfileSyncService* sync_service =
-      ProfileSyncServiceFactory::GetForProfile(profile);
   // Promotion should only show for english locale.
   PrefService* local_state = g_browser_process->local_state();
   std::string locale = base::i18n::GetConfiguredLocale();
   if (locale != "en-US" && locale != "en-CA")
     return false;
   if (!base::FeatureList::IsEnabled(features::kDesktopIOSPromotion) ||
-      !sync_service || !sync_service->IsSyncAllowed())
+      !profile->IsSyncAllowed()) {
     return false;
+  }
 
   // Check if the specific entrypoint is enabled by Finch.
   std::string targeted_entry_point = base::GetFieldTrialParamValueByFeature(
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
index 73f9d37..5d731de 100644
--- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
+++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/ui/views/chrome_constrained_window_views_client.h"
 #include "chrome/browser/ui/views/chrome_views_delegate.h"
 #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
+#include "chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "services/service_manager/sandbox/switches.h"
 
@@ -53,8 +54,6 @@
 #include "ash/public/interfaces/constants.mojom.h"
 #include "content/public/common/content_switches.h"
 #include "ui/base/ui_base_features.h"
-#else  // defined(OS_CHROMEOS)
-#include "chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller.h"
 #endif  // defined(OS_CHROMEOS)
 
 ChromeBrowserMainExtraPartsViews::ChromeBrowserMainExtraPartsViews() {
@@ -173,18 +172,14 @@
 }
 
 void ChromeBrowserMainExtraPartsViews::PostBrowserStart() {
-#if !defined(OS_CHROMEOS)
   relaunch_notification_controller_ =
       std::make_unique<RelaunchNotificationController>(
           UpgradeDetector::GetInstance());
-#endif
 }
 
 void ChromeBrowserMainExtraPartsViews::PostMainMessageLoopRun() {
-#if !defined(OS_CHROMEOS)
   // The relaunch notification controller acts on timer-based events. Tear it
   // down explicitly here to avoid a case where such an event arrives during
   // shutdown.
   relaunch_notification_controller_.reset();
-#endif
 }
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h
index 434a1f0..697ac4d 100644
--- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h
+++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h
@@ -27,9 +27,7 @@
 }
 #endif
 
-#if !defined(OS_CHROMEOS)
 class RelaunchNotificationController;
-#endif
 
 class ChromeBrowserMainExtraPartsViews : public ChromeBrowserMainExtraParts {
  public:
@@ -60,11 +58,9 @@
   std::unique_ptr<views::MusClient> mus_client_;
 #endif
 
-#if !defined(OS_CHROMEOS)
   // Manages the relaunch notification prompts.
   std::unique_ptr<RelaunchNotificationController>
       relaunch_notification_controller_;
-#endif
 
   DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainExtraPartsViews);
 };
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
index bc1ff473..69c5df8c 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
@@ -73,6 +73,18 @@
   // calling through private APIs.
   DCHECK(tabstrip);
 
+  const bool restored = !frame()->IsMaximized() && !frame()->IsFullscreen();
+  gfx::Rect bounds = gfx::Rect(0, GetTopInset(restored), width(),
+                               tabstrip->GetPreferredSize().height());
+  bounds.Inset(GetTabStripLeftInset(), 0,
+               GetAfterTabstripItemWidth() + GetTabstripPadding(), 0);
+  return bounds;
+}
+
+int BrowserNonClientFrameViewMac::GetTopInset(bool restored) const {
+  if (!browser_view()->IsTabStripVisible())
+    return 0;
+
   // Calculate the y offset for the tab strip because in fullscreen mode the tab
   // strip may need to move under the slide down menu bar.
   CGFloat y_offset = kTabstripTopInset;
@@ -99,15 +111,7 @@
     }
   }
 
-  gfx::Rect bounds =
-      gfx::Rect(0, y_offset, width(), tabstrip->GetPreferredSize().height());
-  bounds.Inset(GetTabStripLeftInset(), 0,
-               GetAfterTabstripItemWidth() + GetTabstripPadding(), 0);
-  return bounds;
-}
-
-int BrowserNonClientFrameViewMac::GetTopInset(bool restored) const {
-  return browser_view()->IsTabStripVisible() ? kTabstripTopInset : 0;
+  return y_offset;
 }
 
 int BrowserNonClientFrameViewMac::GetAfterTabstripItemWidth() const {
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc
index 0e5d086..19f3694 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout.cc
+++ b/chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -323,15 +323,7 @@
   vertical_layout_rect_ = browser_view->GetLocalBounds();
   int top_inset = delegate_->GetTopInsetInBrowserView(false);
   int top = LayoutTabStripRegion(top_inset);
-  int possible_fullscreen_tab_strip_offset = 0;
   if (delegate_->IsTabStripVisible()) {
-#if defined(OS_MACOSX)
-    // Tab strip should always start from the top inset unless it is under the
-    // system menu bar during full screen mode on Mac. In this case, the tab
-    // strip and other top UI will move under the menu bar while the content
-    // should stay put.
-    possible_fullscreen_tab_strip_offset = tab_strip_->bounds().y() - top_inset;
-#endif
     // By passing true to GetTopInsetInBrowserView(), we position the tab
     // background to vertically align with the frame background image of a
     // restored-mode frame, even in a maximized window.  Then in the frame code,
@@ -354,7 +346,6 @@
   UpdateTopContainerBounds();
 
   int bottom = LayoutDownloadShelf(browser_view->height());
-  top -= possible_fullscreen_tab_strip_offset;
   // Treat a detached bookmark bar as if the web contents container is shifted
   // upwards and overlaps it.
   int active_top_margin = GetContentsOffsetForBookmarkBar();
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
index 914e1fa1..3240412 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -50,6 +50,9 @@
 IconLabelBubbleView::SeparatorView::SeparatorView(IconLabelBubbleView* owner) {
   DCHECK(owner);
   owner_ = owner;
+
+  SetPaintToLayer();
+  layer()->SetFillsBoundsOpaquely(false);
 }
 
 void IconLabelBubbleView::SeparatorView::OnPaint(gfx::Canvas* canvas) {
@@ -63,15 +66,18 @@
                    gfx::PointF(x, GetLocalBounds().bottom()), separator_color);
 }
 
-void IconLabelBubbleView::SeparatorView::OnImplicitAnimationsCompleted() {
-  if (layer() && layer()->opacity() == 1.0f)
-    DestroyLayer();
-}
-
 void IconLabelBubbleView::SeparatorView::UpdateOpacity() {
   if (!visible())
     return;
 
+  // When using focus rings are visible we should hide the separator instantly
+  // when the IconLabelBubbleView is focused. Otherwise we should follow the
+  // inkdrop.
+  if (views::PlatformStyle::kPreferFocusRings && owner_->HasFocus()) {
+    layer()->SetOpacity(0.0f);
+    return;
+  }
+
   views::InkDrop* ink_drop = owner_->GetInkDrop();
   DCHECK(ink_drop);
 
@@ -88,10 +94,6 @@
     duration = kIconLabelBubbleFadeInDurationMs;
   }
 
-  if (!layer())
-    SetPaintToLayer();
-  layer()->SetFillsBoundsOpaquely(false);
-
   if (disable_animation_for_test_) {
     layer()->SetOpacity(opacity);
   } else {
@@ -99,7 +101,6 @@
     animation.SetTransitionDuration(
         base::TimeDelta::FromMilliseconds(duration));
     animation.SetTweenType(gfx::Tween::Type::EASE_IN);
-    animation.AddObserver(this);
     layer()->SetOpacity(opacity);
   }
 }
@@ -377,6 +378,16 @@
   OnActivate(event);
 }
 
+void IconLabelBubbleView::OnFocus() {
+  separator_view_->UpdateOpacity();
+  Button::OnFocus();
+}
+
+void IconLabelBubbleView::OnBlur() {
+  separator_view_->UpdateOpacity();
+  Button::OnBlur();
+}
+
 void IconLabelBubbleView::OnWidgetDestroying(views::Widget* widget) {
   widget->RemoveObserver(this);
 }
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
index 4d3254d..e45806a 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
@@ -9,7 +9,6 @@
 
 #include "base/macros.h"
 #include "base/strings/string16.h"
-#include "ui/compositor/layer_animation_observer.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/animation/ink_drop_host_view.h"
@@ -38,17 +37,13 @@
   static constexpr int kTrailingPaddingPreMd = 2;
 
   // A view that draws the separator.
-  class SeparatorView : public views::View,
-                        public ui::ImplicitAnimationObserver {
+  class SeparatorView : public views::View {
    public:
     explicit SeparatorView(IconLabelBubbleView* owner);
 
     // views::View:
     void OnPaint(gfx::Canvas* canvas) override;
 
-    // ui::ImplicitAnimationObserver:
-    void OnImplicitAnimationsCompleted() override;
-
     // Updates the opacity based on the ink drop's state.
     void UpdateOpacity();
 
@@ -154,6 +149,8 @@
   bool IsTriggerableEvent(const ui::Event& event) override;
   bool ShouldUpdateInkDropOnClickCanceled() const override;
   void NotifyClick(const ui::Event& event) override;
+  void OnFocus() override;
+  void OnBlur() override;
 
   // views::WidgetObserver:
   void OnWidgetDestroying(views::Widget* widget) override;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index 677eb81..60b6e2f 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -178,12 +178,14 @@
                                          match_.contents_class);
     suggestion_view_->description()->SetText(match_.description,
                                              match_.description_class);
-    // Explicitly re-apply default styling - high contrast modes use different
-    // text colors depending on selection state.
-    suggestion_view_->content()->ApplyTextColor(
-        OmniboxPart::RESULTS_TEXT_DEFAULT);
-    suggestion_view_->description()->ApplyTextColor(
-        OmniboxPart::RESULTS_TEXT_DEFAULT);
+
+    // Normally, OmniboxTextView caches its appearance, but in high contrast
+    // selected-ness changes the text colors, so the styling of the text part of
+    // the results needs to be recomputed.
+    if (high_contrast) {
+      suggestion_view_->content()->ReapplyStyling();
+      suggestion_view_->description()->ReapplyStyling();
+    }
   }
 
   AutocompleteMatch* keyword_match = match_.associated_keyword.get();
diff --git a/chrome/browser/ui/views/omnibox/omnibox_text_view.cc b/chrome/browser/ui/views/omnibox/omnibox_text_view.cc
index 4d0cb05..5d87db9 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_text_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_text_view.cc
@@ -224,36 +224,7 @@
       std::make_unique<ACMatchClassifications>(classifications);
   render_text_ = CreateRenderText(text);
 
-  const size_t text_length = render_text_->text().length();
-  for (size_t i = 0; i < classifications.size(); ++i) {
-    const size_t text_start = classifications[i].offset;
-    if (text_start >= text_length)
-      break;
-
-    const size_t text_end =
-        (i < (classifications.size() - 1))
-            ? std::min(classifications[i + 1].offset, text_length)
-            : text_length;
-    const gfx::Range current_range(text_start, text_end);
-
-    // Calculate style-related data.
-    if (classifications[i].style & ACMatchClassification::MATCH)
-      render_text_->ApplyWeight(gfx::Font::Weight::BOLD, current_range);
-
-    OmniboxPart part = OmniboxPart::RESULTS_TEXT_DEFAULT;
-    if (classifications[i].style & ACMatchClassification::URL) {
-      part = OmniboxPart::RESULTS_TEXT_URL;
-      render_text_->SetDirectionalityMode(gfx::DIRECTIONALITY_AS_URL);
-    } else if (classifications[i].style & ACMatchClassification::DIM) {
-      part = OmniboxPart::RESULTS_TEXT_DIMMED;
-    } else if (classifications[i].style & ACMatchClassification::INVISIBLE) {
-      part = OmniboxPart::RESULTS_TEXT_INVISIBLE;
-    }
-    render_text_->ApplyColor(result_view_->GetColor(part), current_range);
-  }
-
-  UpdateLineHeight();
-  SetPreferredSize(CalculatePreferredSize());
+  ReapplyStyling();
 }
 
 void OmniboxTextView::SetText(const SuggestionAnswer::ImageLine& line,
@@ -309,6 +280,40 @@
   return font_height_;
 }
 
+void OmniboxTextView::ReapplyStyling() {
+  const ACMatchClassifications& classifications = *cached_classifications_;
+  const size_t text_length = render_text_->text().length();
+  for (size_t i = 0; i < classifications.size(); ++i) {
+    const size_t text_start = classifications[i].offset;
+    if (text_start >= text_length)
+      break;
+
+    const size_t text_end =
+        (i < (classifications.size() - 1))
+            ? std::min(classifications[i + 1].offset, text_length)
+            : text_length;
+    const gfx::Range current_range(text_start, text_end);
+
+    // Calculate style-related data.
+    if (classifications[i].style & ACMatchClassification::MATCH)
+      render_text_->ApplyWeight(gfx::Font::Weight::BOLD, current_range);
+
+    OmniboxPart part = OmniboxPart::RESULTS_TEXT_DEFAULT;
+    if (classifications[i].style & ACMatchClassification::URL) {
+      part = OmniboxPart::RESULTS_TEXT_URL;
+      render_text_->SetDirectionalityMode(gfx::DIRECTIONALITY_AS_URL);
+    } else if (classifications[i].style & ACMatchClassification::DIM) {
+      part = OmniboxPart::RESULTS_TEXT_DIMMED;
+    } else if (classifications[i].style & ACMatchClassification::INVISIBLE) {
+      part = OmniboxPart::RESULTS_TEXT_INVISIBLE;
+    }
+    render_text_->ApplyColor(result_view_->GetColor(part), current_range);
+  }
+
+  UpdateLineHeight();
+  SetPreferredSize(CalculatePreferredSize());
+}
+
 std::unique_ptr<gfx::RenderText> OmniboxTextView::CreateRenderText(
     const base::string16& text) const {
   auto render_text = gfx::RenderText::CreateHarfBuzzInstance();
diff --git a/chrome/browser/ui/views/omnibox/omnibox_text_view.h b/chrome/browser/ui/views/omnibox/omnibox_text_view.h
index 4a5bc29..01ccc0b 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_text_view.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_text_view.h
@@ -63,6 +63,10 @@
   // multiple lines.
   int GetLineHeight() const;
 
+  // Reapplies text styling to the results text, based on the types of the match
+  // parts.
+  void ReapplyStyling();
+
  private:
   std::unique_ptr<gfx::RenderText> CreateRenderText(
       const base::string16& text) const;
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc
index 546f9af..d5845ef 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -604,6 +604,10 @@
   views::Widget::OnNativeWidgetSizeChanged(new_size);
 }
 
+void OverlayWindowViews::OnNativeWidgetDestroyed() {
+  controller_->OnWindowDestroyed();
+}
+
 void OverlayWindowViews::TogglePlayPause() {
   // Retrieve expected active state based on what command was sent in
   // TogglePlayPause() since the IPC message may not have been propogated
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.h b/chrome/browser/ui/views/overlay/overlay_window_views.h
index ca28d91..da9e1f3 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.h
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.h
@@ -51,6 +51,7 @@
   void OnNativeBlur() override;
   void OnNativeWidgetMove() override;
   void OnNativeWidgetSizeChanged(const gfx::Size& new_size) override;
+  void OnNativeWidgetDestroyed() override;
 
   // Gets the bounds of the controls.
   gfx::Rect GetCloseControlsBounds();
diff --git a/chrome/browser/ui/views/payments/order_summary_view_controller.cc b/chrome/browser/ui/views/payments/order_summary_view_controller.cc
index f718d1d6d..0f421b4 100644
--- a/chrome/browser/ui/views/payments/order_summary_view_controller.cc
+++ b/chrome/browser/ui/views/payments/order_summary_view_controller.cc
@@ -151,6 +151,10 @@
   return button;
 }
 
+bool OrderSummaryViewController::ShouldShowSecondaryButton() {
+  return false;
+}
+
 base::string16 OrderSummaryViewController::GetSheetTitle() {
   return l10n_util::GetStringUTF16(IDS_PAYMENTS_ORDER_SUMMARY_LABEL);
 }
diff --git a/chrome/browser/ui/views/payments/order_summary_view_controller.h b/chrome/browser/ui/views/payments/order_summary_view_controller.h
index 9f25d33..e085fa3 100644
--- a/chrome/browser/ui/views/payments/order_summary_view_controller.h
+++ b/chrome/browser/ui/views/payments/order_summary_view_controller.h
@@ -40,6 +40,7 @@
  private:
   // PaymentRequestSheetController:
   std::unique_ptr<views::Button> CreatePrimaryButton() override;
+  bool ShouldShowSecondaryButton() override;
   base::string16 GetSheetTitle() override;
   void FillContentView(views::View* content_view) override;
   void UpdatePayButtonState(bool enabled);
diff --git a/chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller.cc b/chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller.cc
index 3696241e..d52ea1ed 100644
--- a/chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller.cc
+++ b/chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller.cc
@@ -360,7 +360,7 @@
 
   widget_ = RelaunchRecommendedBubbleView::ShowBubble(
       browser, upgrade_detector_->upgrade_detected_time(),
-      base::BindRepeating(&chrome::AttemptRestart));
+      base::BindRepeating(&chrome::AttemptRelaunch));
 
   // Monitor the widget so that |widget_| can be cleared on close.
   widget_->AddObserver(this);
@@ -384,7 +384,7 @@
 
   widget_ = RelaunchRequiredDialogView::Show(
       browser, timer_.desired_run_time(),
-      base::BindRepeating(&chrome::AttemptRestart));
+      base::BindRepeating(&chrome::AttemptRelaunch));
 
   // Monitor the widget so that |widget_| can be cleared on close.
   widget_->AddObserver(this);
@@ -396,5 +396,5 @@
 }
 
 void RelaunchNotificationController::OnRelaunchDeadlineExpired() {
-  chrome::AttemptRestart();
+  chrome::AttemptRelaunch();
 }
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc
index ceefd28..401ae5a 100644
--- a/chrome/browser/ui/views/tabs/new_tab_button.cc
+++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -465,13 +465,13 @@
       // The new tab background is mirrored in RTL mode, but the theme
       // background should never be mirrored. Mirror it here to compensate.
       float x_scale = 1.0f;
-      int x = GetMirroredX() + background_offset_.x();
-      const gfx::Size size = GetContentsBounds().size();
+      const gfx::Rect& contents_bounds = GetContentsBounds();
+      int x = GetMirroredX() + contents_bounds.x() + background_offset_.x();
       if (base::i18n::IsRTL()) {
         x_scale = -1.0f;
         // Offset by |width| such that the same region is painted as if there
         // was no flip.
-        x += size.width();
+        x += contents_bounds.width();
       }
 
       const bool succeeded = canvas->InitPaintFlagsForTiling(
diff --git a/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc b/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc
index 1f25b7d..0b69b7b 100644
--- a/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc
+++ b/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc
@@ -85,6 +85,8 @@
 
 }  // namespace
 
+// Changes to this class should be in sync with its iOS equivalent
+// ios/chrome/browser/ui/webui/ukm_internals_ui.cc
 UkmInternalsUI::UkmInternalsUI(content::WebUI* web_ui)
     : content::WebUIController(web_ui) {
   ukm::UkmService* ukm_service =
diff --git a/chrome/browser/vr/service/browser_xr_device.cc b/chrome/browser/vr/service/browser_xr_device.cc
index 6fd9c9c..e32daa766 100644
--- a/chrome/browser/vr/service/browser_xr_device.cc
+++ b/chrome/browser/vr/service/browser_xr_device.cc
@@ -113,21 +113,19 @@
     base::WeakPtr<VRDisplayHost> display,
     device::mojom::XRDeviceRuntimeSessionOptionsPtr options,
     device::mojom::VRDisplayHost::RequestSessionCallback callback,
-    device::mojom::XRPresentationConnectionPtr connection,
+    device::mojom::XRSessionPtr session,
     device::mojom::XRSessionControllerPtr immersive_session_controller) {
-  if (connection && display) {
+  if (session && display) {
     if (options->immersive) {
       presenting_display_host_ = display.get();
       immersive_session_controller_ = std::move(immersive_session_controller);
     }
 
-    device::mojom::XRSessionPtr xr_session = device::mojom::XRSession::New();
-    xr_session->connection = std::move(connection);
-    std::move(callback).Run(std::move(xr_session));
+    std::move(callback).Run(std::move(session));
   } else {
     std::move(callback).Run(nullptr);
-    if (connection) {
-      // The device has been removed, but we still got a connection, so make
+    if (session) {
+      // The device has been removed, but we still got a session, so make
       // sure to clean up this weird state.
       immersive_session_controller_ = std::move(immersive_session_controller);
       StopImmersiveSession();
diff --git a/chrome/browser/vr/service/browser_xr_device.h b/chrome/browser/vr/service/browser_xr_device.h
index de78a5a..242ee26 100644
--- a/chrome/browser/vr/service/browser_xr_device.h
+++ b/chrome/browser/vr/service/browser_xr_device.h
@@ -57,7 +57,7 @@
       base::WeakPtr<VRDisplayHost> display,
       device::mojom::XRDeviceRuntimeSessionOptionsPtr options,
       device::mojom::VRDisplayHost::RequestSessionCallback callback,
-      device::mojom::XRPresentationConnectionPtr connection,
+      device::mojom::XRSessionPtr session,
       device::mojom::XRSessionControllerPtr immersive_session_controller);
 
   device::mojom::XRRuntimePtr device_;
diff --git a/chrome/browser/vr/service/vr_display_host.cc b/chrome/browser/vr/service/vr_display_host.cc
index b22645ba7..f2937a3 100644
--- a/chrome/browser/vr/service/vr_display_host.cc
+++ b/chrome/browser/vr/service/vr_display_host.cc
@@ -124,25 +124,11 @@
                                      std::move(display_info));
 }
 
-void VRDisplayHost::OnARSessionCreated(
-    vr::BrowserXrDevice* device,
-    device::mojom::VRDisplayHost::RequestSessionCallback callback,
-    device::mojom::XRSessionPtr session) {
-  if (!session) {
-    std::move(callback).Run(nullptr);
-    return;
-  }
-
-  device->GetRuntime()->RequestMagicWindowSession(
-      base::BindOnce(&VRDisplayHost::OnMagicWindowSessionCreated,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
-}
-
 void VRDisplayHost::OnMagicWindowSessionCreated(
     device::mojom::VRDisplayHost::RequestSessionCallback callback,
-    device::mojom::VRMagicWindowProviderPtr magic_window_provider,
+    device::mojom::XRSessionPtr session,
     device::mojom::XRSessionControllerPtr controller) {
-  if (!magic_window_provider) {
+  if (!session) {
     std::move(callback).Run(nullptr);
     return;
   }
@@ -152,10 +138,7 @@
 
   magic_window_controllers_.AddPtr(std::move(controller));
 
-  device::mojom::XRSessionPtr xr_session = device::mojom::XRSession::New();
-  xr_session->magic_window_provider = magic_window_provider.PassInterface();
-
-  std::move(callback).Run(std::move(xr_session));
+  std::move(callback).Run(std::move(session));
 }
 
 VRDisplayHost::~VRDisplayHost() {
@@ -214,28 +197,16 @@
       ReportRequestPresent();
     }
 
-    // Ensure we will notify the immersive device when we are destroyed, so
-    // lingering presentation state will be cleaned up.
-    DCHECK(device == immersive_device_);
-
     device->RequestSession(this, std::move(runtime_options),
                            std::move(callback));
-  } else if (runtime_options->provide_passthrough_camera) {
-    // WebXrHitTest enabled means we are requesting an AR session.  This means
-    // we make two requests to the device - one to request permissions and start
-    // the runtime, then a followup to actually get the magic window provider.
-    // TODO(offenwanger): Clean this up and make only one request.
-    // base::Unretained(device) is safe because either device is alive when we
-    // are called back, or we are called back with failure.
-    device->RequestSession(
-        this, std::move(runtime_options),
-        base::BindOnce(&VRDisplayHost::OnARSessionCreated,
-                       weak_ptr_factory_.GetWeakPtr(), base::Unretained(device),
-                       std::move(callback)));
   } else {
-    device->GetRuntime()->RequestMagicWindowSession(
-        base::BindOnce(&VRDisplayHost::OnMagicWindowSessionCreated,
-                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+    base::OnceCallback<void(device::mojom::XRSessionPtr,
+                            device::mojom::XRSessionControllerPtr)>
+        magic_window_callback =
+            base::BindOnce(&VRDisplayHost::OnMagicWindowSessionCreated,
+                           weak_ptr_factory_.GetWeakPtr(), std::move(callback));
+    device->GetRuntime()->RequestSession(std::move(runtime_options),
+                                         std::move(magic_window_callback));
   }
 }
 
diff --git a/chrome/browser/vr/service/vr_display_host.h b/chrome/browser/vr/service/vr_display_host.h
index 2e8e9e6..e8b673e3 100644
--- a/chrome/browser/vr/service/vr_display_host.h
+++ b/chrome/browser/vr/service/vr_display_host.h
@@ -73,12 +73,8 @@
   bool InternalSupportsSession(device::mojom::XRSessionOptions* options);
   void OnMagicWindowSessionCreated(
       device::mojom::VRDisplayHost::RequestSessionCallback callback,
-      device::mojom::VRMagicWindowProviderPtr session,
+      device::mojom::XRSessionPtr session,
       device::mojom::XRSessionControllerPtr controller);
-  void OnARSessionCreated(
-      vr::BrowserXrDevice* device,
-      device::mojom::VRDisplayHost::RequestSessionCallback callback,
-      device::mojom::XRSessionPtr session);
 
   // TODO(https://crbug.com/837538): Instead, check before returning this
   // object.
diff --git a/chrome/browser/vr/ui_unittest.cc b/chrome/browser/vr/ui_unittest.cc
index 1664f6d55..d0a4eeeb 100644
--- a/chrome/browser/vr/ui_unittest.cc
+++ b/chrome/browser/vr/ui_unittest.cc
@@ -467,17 +467,15 @@
   EXPECT_EQ(initial_position, content_group->LocalTransform());
 }
 
-TEST_F(UiTest, SecurityIconClickTriggersUnsupportedMode) {
+TEST_F(UiTest, SecurityIconClickShouldShowPageInfo) {
   CreateScene(kNotInWebVr);
 
   // Initial state.
   VerifyOnlyElementsVisible("Initial", kElementsVisibleInBrowsing);
 
-  // Clicking on security icon should trigger unsupported mode.
-  EXPECT_CALL(*browser_,
-              OnUnsupportedMode(UiUnsupportedMode::kUnhandledPageInfo));
-  browser_->OnUnsupportedMode(UiUnsupportedMode::kUnhandledPageInfo);
-  VerifyOnlyElementsVisible("Prompt invisible", kElementsVisibleInBrowsing);
+  EXPECT_CALL(*browser_, ShowPageInfo);
+  auto* security_icon = scene_->GetUiElementByName(kUrlBarSecurityButton);
+  ClickElement(security_icon);
 }
 
 TEST_F(UiTest, ClickingOmniboxTriggersUnsupportedMode) {
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.cc b/chrome/common/media_router/providers/cast/cast_media_source.cc
index 06f0047..8f97a0d 100644
--- a/chrome/common/media_router/providers/cast/cast_media_source.cc
+++ b/chrome/common/media_router/providers/cast/cast_media_source.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/common/media_router/providers/cast/cast_media_source.h"
 
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -18,18 +19,19 @@
 
 namespace {
 
-constexpr char kMirroringAppId[] = "0F5096E8";
-constexpr char kAudioMirroringAppId[] = "85CDB22F";
-
 // Parameter keys used by new Cast URLs.
 constexpr char kCapabilitiesKey[] = "capabilities";
 constexpr char kBroadcastNamespaceKey[] = "broadcastNamespace";
 constexpr char kBroadcastMessageKey[] = "broadcastMessage";
+constexpr char kClientIdKey[] = "clientId";
+constexpr char kLaunchTimeoutKey[] = "launchTimeout";
 
 // Parameter keys used by legacy Cast URLs.
 constexpr char kLegacyAppIdKey[] = "__castAppId__";
 constexpr char kLegacyBroadcastNamespaceKey[] = "__castBroadcastNamespace__";
 constexpr char kLegacyBroadcastMessageKey[] = "__castBroadcastMessage__";
+constexpr char kLegacyClientIdKey[] = "__castClientId__";
+constexpr char kLegacyLaunchTimeoutKey[] = "__castLaunchTimeout__";
 
 // TODO(imcheng): Move to common utils?
 std::string DecodeURLComponent(const std::string& encoded) {
@@ -61,8 +63,9 @@
 std::unique_ptr<CastMediaSource> CastMediaSourceForTabMirroring(
     const MediaSource::Id& source_id) {
   return std::make_unique<CastMediaSource>(
-      source_id, std::vector<CastAppInfo>({CastAppInfo(kMirroringAppId),
-                                           CastAppInfo(kAudioMirroringAppId)}));
+      source_id,
+      std::vector<CastAppInfo>({CastAppInfo(kCastStreamingAppId),
+                                CastAppInfo(kCastStreamingAudioAppId)}));
 }
 
 std::unique_ptr<CastMediaSource> CastMediaSourceForDesktopMirroring(
@@ -70,28 +73,33 @@
 // Desktop audio mirroring is only supported on some platforms.
 #if defined(OS_WIN) || defined(OS_CHROMEOS)
   return std::make_unique<CastMediaSource>(
-      source_id, std::vector<CastAppInfo>({CastAppInfo(kMirroringAppId),
-                                           CastAppInfo(kAudioMirroringAppId)}));
+      source_id,
+      std::vector<CastAppInfo>({CastAppInfo(kCastStreamingAppId),
+                                CastAppInfo(kCastStreamingAudioAppId)}));
 #else
   return std::make_unique<CastMediaSource>(
-      source_id, std::vector<CastAppInfo>({CastAppInfo(kMirroringAppId)}));
+      source_id, std::vector<CastAppInfo>({CastAppInfo(kCastStreamingAppId)}));
 #endif
 }
 
 std::unique_ptr<CastMediaSource> CreateFromURLParams(
     const MediaSource::Id& source_id,
     const std::vector<CastAppInfo>& app_infos,
+    const std::string& client_id,
     const std::string& broadcast_namespace,
-    const std::string& broadcast_message) {
+    const std::string& broadcast_message,
+    base::TimeDelta launch_timeout) {
   if (app_infos.empty())
     return nullptr;
 
   auto cast_source = std::make_unique<CastMediaSource>(source_id, app_infos);
+  cast_source->set_client_id(client_id);
   if (!broadcast_namespace.empty() && !broadcast_message.empty()) {
     cast_source->set_broadcast_request(
         BroadcastRequest(broadcast_namespace, broadcast_message));
   }
-
+  if (launch_timeout > base::TimeDelta())
+    cast_source->set_launch_timeout(launch_timeout);
   return cast_source;
 }
 
@@ -103,6 +111,8 @@
     return nullptr;
 
   std::string broadcast_namespace, broadcast_message, capabilities;
+  std::string client_id;
+  int launch_timeout_millis = 0;
   for (net::QueryIterator query_it(url); !query_it.IsAtEnd();
        query_it.Advance()) {
     std::string key = query_it.GetKey();
@@ -116,6 +126,12 @@
       broadcast_message = DecodeURLComponent(value);
     } else if (key == kCapabilitiesKey) {
       capabilities = value;
+    } else if (key == kClientIdKey) {
+      client_id = value;
+    } else if (key == kLaunchTimeoutKey) {
+      if (!base::StringToInt(value, &launch_timeout_millis) ||
+          launch_timeout_millis < 0)
+        launch_timeout_millis = 0;
     }
   }
 
@@ -129,8 +145,9 @@
     }
   }
 
-  return CreateFromURLParams(source_id, {app_info}, broadcast_namespace,
-                             broadcast_message);
+  return CreateFromURLParams(
+      source_id, {app_info}, client_id, broadcast_namespace, broadcast_message,
+      base::TimeDelta::FromMilliseconds(launch_timeout_millis));
 }
 
 std::unique_ptr<CastMediaSource> ParseLegacyCastUrl(
@@ -141,6 +158,8 @@
   // Legacy URLs can specify multiple apps.
   std::vector<std::string> app_id_params;
   std::string broadcast_namespace, broadcast_message;
+  std::string client_id;
+  int launch_timeout_millis = 0;
   for (const auto& key_value : parameters) {
     const auto& key = key_value.first;
     const auto& value = key_value.second;
@@ -151,6 +170,12 @@
     } else if (key == kLegacyBroadcastMessageKey) {
       // The broadcast message is URL-encoded.
       broadcast_message = DecodeURLComponent(value);
+    } else if (key == kLegacyClientIdKey) {
+      client_id = value;
+    } else if (key == kLegacyLaunchTimeoutKey) {
+      if (!base::StringToInt(value, &launch_timeout_millis) ||
+          launch_timeout_millis < 0)
+        launch_timeout_millis = 0;
     }
   }
 
@@ -187,8 +212,9 @@
   if (app_infos.empty())
     return nullptr;
 
-  return CreateFromURLParams(source_id, app_infos, broadcast_namespace,
-                             broadcast_message);
+  return CreateFromURLParams(
+      source_id, app_infos, client_id, broadcast_namespace, broadcast_message,
+      base::TimeDelta::FromMilliseconds(launch_timeout_millis));
 }
 
 }  // namespace
@@ -226,9 +252,6 @@
 }
 
 CastMediaSource::CastMediaSource(const MediaSource::Id& source_id,
-                                 const CastAppInfo& app_info)
-    : source_id_(source_id), app_infos_({app_info}) {}
-CastMediaSource::CastMediaSource(const MediaSource::Id& source_id,
                                  const std::vector<CastAppInfo>& app_infos)
     : source_id_(source_id), app_infos_(app_infos) {}
 CastMediaSource::CastMediaSource(const CastMediaSource& other) = default;
diff --git a/chrome/common/media_router/providers/cast/cast_media_source.h b/chrome/common/media_router/providers/cast/cast_media_source.h
index ae090b5e2..e46b725 100644
--- a/chrome/common/media_router/providers/cast/cast_media_source.h
+++ b/chrome/common/media_router/providers/cast/cast_media_source.h
@@ -16,6 +16,16 @@
 
 namespace media_router {
 
+static constexpr char kCastStreamingAppId[] = "0F5096E8";
+static constexpr char kCastStreamingAudioAppId[] = "85CDB22F";
+
+// Placeholder app ID advertised by the multizone leader in a receiver status
+// message.
+static constexpr char kMultizoneLeaderAppId[] = "MultizoneLeader";
+
+static constexpr base::TimeDelta kDefaultLaunchTimeout =
+    base::TimeDelta::FromSeconds(60);
+
 // Represents a Cast app and its capabilitity requirements.
 struct CastAppInfo {
   explicit CastAppInfo(const std::string& app_id);
@@ -39,10 +49,8 @@
   // Returns the parsed form of |source|, or nullptr if it cannot be parsed.
   static std::unique_ptr<CastMediaSource> From(const MediaSource::Id& source);
 
-  explicit CastMediaSource(const MediaSource::Id& source_id,
-                           const CastAppInfo& app_info);
-  explicit CastMediaSource(const MediaSource::Id& source_id,
-                           const std::vector<CastAppInfo>& app_infos);
+  CastMediaSource(const MediaSource::Id& source_id,
+                  const std::vector<CastAppInfo>& app_infos);
   CastMediaSource(const CastMediaSource& other);
   ~CastMediaSource();
 
@@ -55,6 +63,12 @@
 
   const MediaSource::Id& source_id() const { return source_id_; }
   const std::vector<CastAppInfo>& app_infos() const { return app_infos_; }
+  const std::string& client_id() const { return client_id_; }
+  void set_client_id(const std::string& client_id) { client_id_ = client_id; }
+  base::TimeDelta launch_timeout() const { return launch_timeout_; }
+  void set_launch_timeout(base::TimeDelta launch_timeout) {
+    launch_timeout_ = launch_timeout;
+  }
   const base::Optional<cast_channel::BroadcastRequest>& broadcast_request()
       const {
     return broadcast_request_;
@@ -68,6 +82,9 @@
   // TODO(imcheng): Fill in other parameters.
   MediaSource::Id source_id_;
   std::vector<CastAppInfo> app_infos_;
+  base::TimeDelta launch_timeout_ = kDefaultLaunchTimeout;
+  // Empty if not set.
+  std::string client_id_;
   base::Optional<cast_channel::BroadcastRequest> broadcast_request_;
 };
 
diff --git a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
index 94a9204..54181fdc 100644
--- a/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
+++ b/chrome/common/media_router/providers/cast/cast_media_source_unittest.cc
@@ -13,7 +13,9 @@
   MediaSource::Id source_id(
       "cast:ABCDEFAB?capabilities=video_out,audio_out"
       "&broadcastNamespace=namespace"
-      "&broadcastMessage=message");
+      "&broadcastMessage=message"
+      "&clientId=12345"
+      "&launchTimeout=30000");
   std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id);
   ASSERT_TRUE(source);
   EXPECT_EQ(source_id, source->source_id());
@@ -27,13 +29,17 @@
   ASSERT_TRUE(broadcast_request);
   EXPECT_EQ("namespace", broadcast_request->broadcast_namespace);
   EXPECT_EQ("message", broadcast_request->message);
+  EXPECT_EQ("12345", source->client_id());
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(30000), source->launch_timeout());
 }
 
 TEST(CastMediaSourceTest, FromLegacyCastURL) {
   MediaSource::Id source_id(
       "https://google.com/cast#__castAppId__=ABCDEFAB(video_out,audio_out)"
       "/__castBroadcastNamespace__=namespace"
-      "/__castBroadcastMessage__=message");
+      "/__castBroadcastMessage__=message"
+      "/__castClientId__=12345"
+      "/__castLaunchTimeout__=30000");
   std::unique_ptr<CastMediaSource> source = CastMediaSource::From(source_id);
   ASSERT_TRUE(source);
   EXPECT_EQ(source_id, source->source_id());
@@ -47,6 +53,8 @@
   ASSERT_TRUE(broadcast_request);
   EXPECT_EQ("namespace", broadcast_request->broadcast_namespace);
   EXPECT_EQ("message", broadcast_request->message);
+  EXPECT_EQ("12345", source->client_id());
+  EXPECT_EQ(base::TimeDelta::FromMilliseconds(30000), source->launch_timeout());
 }
 
 TEST(CastMediaSourceTest, FromPresentationURL) {
@@ -57,6 +65,8 @@
   ASSERT_EQ(2u, source->app_infos().size());
   EXPECT_EQ("0F5096E8", source->app_infos()[0].app_id);
   EXPECT_EQ("85CDB22F", source->app_infos()[1].app_id);
+  EXPECT_TRUE(source->client_id().empty());
+  EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout());
 }
 
 TEST(CastMediaSourceTest, FromMirroringURN) {
@@ -67,6 +77,8 @@
   ASSERT_EQ(2u, source->app_infos().size());
   EXPECT_EQ("0F5096E8", source->app_infos()[0].app_id);
   EXPECT_EQ("85CDB22F", source->app_infos()[1].app_id);
+  EXPECT_TRUE(source->client_id().empty());
+  EXPECT_EQ(kDefaultLaunchTimeout, source->launch_timeout());
 }
 
 TEST(CastMediaSourceTest, FromInvalidSource) {
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 70fddd7..d56dc0ba 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1997,11 +1997,9 @@
 #endif  // !defined(OS_ANDROID)
 
 #if !defined(OS_ANDROID)
-#if !defined(OS_CHROMEOS)
 // Pref name for the policy controlling the way in which users are notified of
 // the need to relaunch the browser for a pending update.
 const char kRelaunchNotification[] = "browser.relaunch_notification";
-#endif  // !defined(OS_CHROMEOS)
 // Pref name for the policy controlling the time period over which users are
 // notified of the need to relaunch the browser for a pending update. Values
 // are in milliseconds.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index c41685c..d2184936b 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -728,9 +728,7 @@
 #endif  // !defined(OS_ANDROID)
 
 #if !defined(OS_ANDROID)
-#if !defined(OS_CHROMEOS)
 extern const char kRelaunchNotification[];
-#endif  // !defined(OS_CHROMEOS)
 extern const char kRelaunchNotificationPeriod[];
 #endif  // !defined(OS_ANDROID)
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index db3480c6..2f8e1bf 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1474,6 +1474,8 @@
         "../browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc",
         "../browser/ui/views/payments/shipping_option_view_controller_browsertest.cc",
         "../browser/ui/views/profiles/profile_chooser_view_browsertest.cc",
+        "../browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view_browsertest.cc",
+        "../browser/ui/views/relaunch_notification/relaunch_required_dialog_view_browsertest.cc",
         "../browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog_browsertest.cc",
         "../browser/ui/views/select_file_dialog_extension_browsertest.cc",
         "../browser/ui/views/sync/profile_signin_confirmation_dialog_views_browsertest.cc",
@@ -1527,12 +1529,6 @@
           "../browser/ui/views/web_dialog_view_browsertest.cc",
         ]
       }
-      if (!is_chromeos) {
-        sources += [
-          "../browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view_browsertest.cc",
-          "../browser/ui/views/relaunch_notification/relaunch_required_dialog_view_browsertest.cc",
-        ]
-      }
     }
 
     if (is_linux && !is_component_build) {
@@ -3205,6 +3201,7 @@
       "../browser/media/router/mojo/media_sink_service_status_unittest.cc",
       "../browser/media/router/providers/cast/cast_app_availability_tracker_unittest.cc",
       "../browser/media/router/providers/cast/cast_app_discovery_service_unittest.cc",
+      "../browser/media/router/providers/cast/cast_internal_message_util_unittest.cc",
       "../browser/media/router/providers/cast/cast_media_route_provider_metrics_unittest.cc",
       "../browser/media/router/providers/cast/cast_media_route_provider_unittest.cc",
       "../browser/media/router/providers/cast/dual_media_sink_service_unittest.cc",
@@ -3472,7 +3469,6 @@
       "../browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc",
       "../browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc",
       "../browser/extensions/api/signed_in_devices/signed_in_devices_manager_unittest.cc",
-      "../browser/extensions/api/socket/combined_socket_unittest.cc",
       "../browser/extensions/api/socket/socket_api_unittest.cc",
       "../browser/extensions/api/socket/tcp_socket_unittest.cc",
       "../browser/extensions/api/socket/tls_socket_unittest.cc",
@@ -4168,7 +4164,6 @@
         "../browser/ui/cocoa/omnibox/omnibox_popup_view_mac_unittest.mm",
         "../browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm",
         "../browser/ui/cocoa/page_info/page_info_bubble_controller_unittest.mm",
-        "../browser/ui/cocoa/page_info/permission_selector_button_unittest.mm",
         "../browser/ui/cocoa/profiles/avatar_button_controller_unittest.mm",
         "../browser/ui/cocoa/profiles/avatar_button_unittest.mm",
         "../browser/ui/cocoa/profiles/avatar_icon_controller_unittest.mm",
@@ -4202,7 +4197,6 @@
         "../browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm",
         "../browser/ui/cocoa/touchbar/credit_card_autofill_touch_bar_controller_unittest.mm",
         "../browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller_unittest.mm",
-        "../browser/ui/cocoa/translate/translate_bubble_controller_unittest.mm",
         "../browser/ui/cocoa/url_drop_target_unittest.mm",
         "../browser/ui/cocoa/vertical_gradient_view_unittest.mm",
         "../browser/ui/cocoa/view_resizer_pong.h",
@@ -4362,14 +4356,11 @@
       "../browser/ui/views/payments/payment_request_item_list_unittest.cc",
       "../browser/ui/views/payments/validating_textfield_unittest.cc",
       "../browser/ui/views/payments/view_stack_unittest.cc",
+      "../browser/ui/views/relaunch_notification/relaunch_notification_controller_unittest.cc",
+      "../browser/ui/views/relaunch_notification/relaunch_required_dialog_view_unittest.cc",
     ]
     if (is_chromeos) {
       sources += [ "../browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc" ]
-    } else {
-      sources += [
-        "../browser/ui/views/relaunch_notification/relaunch_notification_controller_unittest.cc",
-        "../browser/ui/views/relaunch_notification/relaunch_required_dialog_view_unittest.cc",
-      ]
     }
     if (!is_chromeos && (!is_mac || mac_views_browser)) {
       sources += [
@@ -5108,10 +5099,6 @@
         # toolkit-views secondary UI. It should not be deleted with the Cocoa
         # bubble (but it can be deleted with the Cocoa browser window).
         "../browser/ui/cocoa/permission_bubble/permission_bubble_cocoa_interactive_uitest.mm",
-
-        # The translate bubble tests only obsolete Cocoa UI and doesn't link.
-        # Ensure the corresponding file is deleted when removing the next line.
-        # "../browser/ui/cocoa/translate/translate_bubble_test_utils_views_cocoa.mm",
       ]
     }
 
diff --git a/chrome/test/base/dialog_test_browser_window.cc b/chrome/test/base/dialog_test_browser_window.cc
index bf88d63..d1110de3 100644
--- a/chrome/test/base/dialog_test_browser_window.cc
+++ b/chrome/test/base/dialog_test_browser_window.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/test/base/dialog_test_browser_window.h"
 
+#include "build/build_config.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -52,6 +53,10 @@
 }
 
 gfx::Size DialogTestBrowserWindow::GetMaximumDialogSize() {
+#if defined(OS_MACOSX)
+  // Zero-size windows aren't allowed on Mac.
+  return gfx::Size(1, 1);
+#endif
   return gfx::Size();
 }
 
diff --git a/chrome/test/data/extensions/api_test/socket/api/background.js b/chrome/test/data/extensions/api_test/socket/api/background.js
index d093aa0..4e675fa8 100644
--- a/chrome/test/data/extensions/api_test/socket/api/background.js
+++ b/chrome/test/data/extensions/api_test/socket/api/background.js
@@ -200,16 +200,16 @@
     socket.read(acceptedSocketId, function(readInfo) {
       arrayBuffer2String(readInfo.data, function (s) {
         assertDataMatch(request, s);
-        succeeded = true;
-        // Test whether socket.getInfo correctly reflects the connection status
-        // if the peer has closed the connection.
-        setTimeout(function() {
+        // Rather than using a timeout, use another read to detect the peer
+        // termination.
+        socket.read(acceptedSocketId, function(readInfo2) {
+          chrome.test.assertEq(-2, readInfo2.resultCode);
           socket.getInfo(acceptedSocketId, function(info) {
             chrome.test.assertFalse(info.connected);
             socket.destroy(socketId);
             chrome.test.succeed();
           });
-        }, 500);
+        });
       });
     });
   }
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 0383715..9dbacec 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -2453,7 +2453,7 @@
   },
 
   "RelaunchNotification": {
-    "os": ["win", "linux", "mac"],
+    "os": ["win", "linux", "mac", "chromeos"],
     "test_policy": { "RelaunchNotification": 1 },
     "pref_mappings": [
       { "pref": "browser.relaunch_notification",
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 9753eec..16621e5 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -183,6 +183,8 @@
     "webdata/autofill_table_encryptor_factory.h",
     "webdata/autofill_wallet_metadata_syncable_service.cc",
     "webdata/autofill_wallet_metadata_syncable_service.h",
+    "webdata/autofill_wallet_sync_bridge.cc",
+    "webdata/autofill_wallet_sync_bridge.h",
     "webdata/autofill_wallet_syncable_service.cc",
     "webdata/autofill_wallet_syncable_service.h",
     "webdata/autofill_webdata.h",
diff --git a/components/autofill/core/browser/webdata/OWNERS b/components/autofill/core/browser/webdata/OWNERS
new file mode 100644
index 0000000..7385936a
--- /dev/null
+++ b/components/autofill/core/browser/webdata/OWNERS
@@ -0,0 +1 @@
+per-file *sync_bridge*=jkrcal@chromium.org
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
new file mode 100644
index 0000000..3296c81
--- /dev/null
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -0,0 +1,90 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/sync/model_impl/client_tag_based_model_type_processor.h"
+
+namespace autofill {
+
+namespace {
+
+// Address to this variable used as the user data key.
+static int kAutofillWalletSyncBridgeUserDataKey = 0;
+
+}  // namespace
+
+// static
+void AutofillWalletSyncBridge::CreateForWebDataServiceAndBackend(
+    const std::string& app_locale,
+    AutofillWebDataBackend* web_data_backend,
+    AutofillWebDataService* web_data_service) {
+  web_data_service->GetDBUserData()->SetUserData(
+      &kAutofillWalletSyncBridgeUserDataKey,
+      std::make_unique<AutofillWalletSyncBridge>(
+          std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
+              syncer::AUTOFILL_WALLET_DATA,
+              /*dump_stack=*/base::RepeatingClosure())));
+}
+
+// static
+syncer::ModelTypeSyncBridge* AutofillWalletSyncBridge::FromWebDataService(
+    AutofillWebDataService* web_data_service) {
+  return static_cast<AutofillWalletSyncBridge*>(
+      web_data_service->GetDBUserData()->GetUserData(
+          &kAutofillWalletSyncBridgeUserDataKey));
+}
+
+AutofillWalletSyncBridge::AutofillWalletSyncBridge(
+    std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor)
+    : ModelTypeSyncBridge(std::move(change_processor)) {}
+
+AutofillWalletSyncBridge::~AutofillWalletSyncBridge() {}
+
+std::unique_ptr<syncer::MetadataChangeList>
+AutofillWalletSyncBridge::CreateMetadataChangeList() {
+  NOTIMPLEMENTED();
+  return nullptr;
+}
+
+base::Optional<syncer::ModelError> AutofillWalletSyncBridge::MergeSyncData(
+    std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+    syncer::EntityChangeList entity_data) {
+  return ApplySyncChanges(std::move(metadata_change_list),
+                          std::move(entity_data));
+}
+
+base::Optional<syncer::ModelError> AutofillWalletSyncBridge::ApplySyncChanges(
+    std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+    syncer::EntityChangeList entity_data) {
+  NOTIMPLEMENTED();
+  return base::nullopt;
+}
+
+void AutofillWalletSyncBridge::GetData(StorageKeyList storage_keys,
+                                       DataCallback callback) {
+  NOTIMPLEMENTED();
+}
+
+void AutofillWalletSyncBridge::GetAllDataForDebugging(DataCallback callback) {
+  NOTIMPLEMENTED();
+}
+
+std::string AutofillWalletSyncBridge::GetClientTag(
+    const syncer::EntityData& entity_data) {
+  NOTIMPLEMENTED();
+  return "";
+}
+
+std::string AutofillWalletSyncBridge::GetStorageKey(
+    const syncer::EntityData& entity_data) {
+  NOTIMPLEMENTED();
+  return "";
+}
+
+}  // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
new file mode 100644
index 0000000..6037895
--- /dev/null
+++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
@@ -0,0 +1,63 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_SYNC_BRIDGE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_SYNC_BRIDGE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/supports_user_data.h"
+#include "components/sync/model/metadata_change_list.h"
+#include "components/sync/model/model_error.h"
+#include "components/sync/model/model_type_change_processor.h"
+#include "components/sync/model/model_type_sync_bridge.h"
+
+namespace autofill {
+
+class AutofillWebDataBackend;
+class AutofillWebDataService;
+
+// Sync bridge responsible for propagating local changes to the processor and
+// applying remote changes to the local database.
+class AutofillWalletSyncBridge : public base::SupportsUserData::Data,
+                                 public syncer::ModelTypeSyncBridge {
+ public:
+  // Factory method that hides dealing with change_processor and also stores the
+  // created bridge within |web_data_service|. This method should only be
+  // called on |web_data_service|'s DB thread.
+  static void CreateForWebDataServiceAndBackend(
+      const std::string& app_locale,
+      AutofillWebDataBackend* webdata_backend,
+      AutofillWebDataService* web_data_service);
+
+  static syncer::ModelTypeSyncBridge* FromWebDataService(
+      AutofillWebDataService* web_data_service);
+
+  explicit AutofillWalletSyncBridge(
+      std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor);
+  ~AutofillWalletSyncBridge() override;
+
+  // ModelTypeSyncBridge implementation.
+  std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
+      override;
+  base::Optional<syncer::ModelError> MergeSyncData(
+      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+      syncer::EntityChangeList entity_data) override;
+  base::Optional<syncer::ModelError> ApplySyncChanges(
+      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+      syncer::EntityChangeList entity_changes) override;
+  void GetData(StorageKeyList storage_keys, DataCallback callback) override;
+  void GetAllDataForDebugging(DataCallback callback) override;
+  std::string GetClientTag(const syncer::EntityData& entity_data) override;
+  std::string GetStorageKey(const syncer::EntityData& entity_data) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AutofillWalletSyncBridge);
+};
+
+}  // namespace autofill
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_SYNC_BRIDGE_H_
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc
index 0cec2e2..713f268 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -14,6 +14,7 @@
 #include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h"
 #include "components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h"
 #include "components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h"
+#include "components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/browser/webdata/web_data_model_type_controller.h"
 #include "components/browser_sync/browser_sync_switches.h"
@@ -151,9 +152,18 @@
     // enforced by the datatype controller. Register unless explicitly disabled.
     bool wallet_disabled = disabled_types.Has(syncer::AUTOFILL_WALLET_DATA);
     if (!wallet_disabled) {
-      controllers.push_back(std::make_unique<AutofillWalletDataTypeController>(
-          syncer::AUTOFILL_WALLET_DATA, db_thread_, error_callback,
-          sync_client_, web_data_service_));
+      if (base::FeatureList::IsEnabled(switches::kSyncUSSAutofillWalletData)) {
+        controllers.push_back(
+            std::make_unique<autofill::WebDataModelTypeController>(
+                syncer::AUTOFILL_WALLET_DATA, sync_client_, db_thread_,
+                web_data_service_,
+                base::BindRepeating(&AutofillProfileDelegateFromDataService)));
+      } else {
+        controllers.push_back(
+            std::make_unique<AutofillWalletDataTypeController>(
+                syncer::AUTOFILL_WALLET_DATA, db_thread_, error_callback,
+                sync_client_, web_data_service_));
+      }
     }
 
     // Wallet metadata sync depends on Wallet data sync. Register if Wallet data
diff --git a/components/cast_channel/cast_message_util.cc b/components/cast_channel/cast_message_util.cc
index 011ec8e..790c73c 100644
--- a/components/cast_channel/cast_message_util.cc
+++ b/components/cast_channel/cast_message_util.cc
@@ -34,13 +34,14 @@
 constexpr char kTypeNodeId[] = "type";
 constexpr char kRequestIdNodeId[] = "requestId";
 
-// Cast application protocol message types.
+// Cast application protocol message types. Keep in sync with CastMessageType.
 constexpr char kKeepAlivePingType[] = "PING";
 constexpr char kKeepAlivePongType[] = "PONG";
 constexpr char kGetAppAvailabilityRequestType[] = "GET_APP_AVAILABILITY";
 constexpr char kConnectionRequestType[] = "CONNECT";
 constexpr char kBroadcastRequestType[] = "APPLICATION_BROADCAST";
 constexpr char kLaunchRequestType[] = "LAUNCH";
+constexpr char kStopRequestType[] = "STOP";
 constexpr char kReceiverStatusType[] = "RECEIVER_STATUS";
 constexpr char kLaunchErrorType[] = "LAUNCH_ERROR";
 
@@ -107,6 +108,7 @@
   if (!message.has_payload_utf8())
     return nullptr;
 
+  // TODO(https://crbug.com/809249): Parse JSON using data_decoder service.
   return base::DictionaryValue::From(
       base::JSONReader::Read(message.payload_utf8()));
 }
@@ -146,6 +148,8 @@
       return kBroadcastRequestType;
     case CastMessageType::kLaunch:
       return kLaunchRequestType;
+    case CastMessageType::kStop:
+      return kStopRequestType;
     case CastMessageType::kReceiverStatus:
       return kReceiverStatusType;
     case CastMessageType::kLaunchError:
@@ -170,6 +174,8 @@
     return CastMessageType::kBroadcast;
   if (type == kLaunchRequestType)
     return CastMessageType::kLaunch;
+  if (type == kStopRequestType)
+    return CastMessageType::kStop;
   if (type == kReceiverStatusType)
     return CastMessageType::kReceiverStatus;
   if (type == kLaunchErrorType)
@@ -347,6 +353,17 @@
                            kPlatformReceiverId);
 }
 
+CastMessage CreateStopRequest(const std::string& source_id,
+                              int request_id,
+                              const std::string& session_id) {
+  Value dict(Value::Type::DICTIONARY);
+  dict.SetKey(kTypeNodeId, Value(kStopRequestType));
+  dict.SetKey(kRequestIdNodeId, Value(request_id));
+  dict.SetKey("sessionId", Value(session_id));
+  return CreateCastMessage(kReceiverNamespace, dict, source_id,
+                           kPlatformReceiverId);
+}
+
 CastMessage CreateCastMessage(const std::string& message_namespace,
                               const base::Value& message,
                               const std::string& source_id,
@@ -406,8 +423,7 @@
     default;
 LaunchSessionResponse::~LaunchSessionResponse() = default;
 
-LaunchSessionResponse GetLaunchSessionResponse(
-    const base::DictionaryValue& payload) {
+LaunchSessionResponse GetLaunchSessionResponse(const base::Value& payload) {
   const Value* type_value =
       payload.FindKeyOfType(kTypeNodeId, Value::Type::STRING);
   if (!type_value)
diff --git a/components/cast_channel/cast_message_util.h b/components/cast_channel/cast_message_util.h
index aedf0bc..c854352 100644
--- a/components/cast_channel/cast_message_util.h
+++ b/components/cast_channel/cast_message_util.h
@@ -27,6 +27,7 @@
   kConnect,    // Virtual connection request
   kBroadcast,  // Application broadcast / precache
   kLaunch,     // Session launch request
+  kStop,       // Session stop request
   kReceiverStatus,
   kLaunchError,
   kOther  // Add new types above |kOther|.
@@ -132,6 +133,10 @@
                                 const std::string& app_id,
                                 const std::string& locale);
 
+CastMessage CreateStopRequest(const std::string& source_id,
+                              int request_id,
+                              const std::string& session_id);
+
 // Creates a generic CastMessage with |message| as the string payload. Used for
 // app messages.
 CastMessage CreateCastMessage(const std::string& message_namespace,
@@ -168,16 +173,15 @@
   ~LaunchSessionResponse();
 
   Result result = Result::kUnknown;
-
   // Populated if |result| is |kOk|.
   base::Optional<base::Value> receiver_status;
 };
 
 // Parses |payload| into a LaunchSessionResponse. Returns an empty
 // LaunchSessionResponse if |payload| is not a properly formatted launch
-// response. |payload| must be from the string payload of a CastMessage.
-LaunchSessionResponse GetLaunchSessionResponse(
-    const base::DictionaryValue& payload);
+// response. |payload| must be a dictionary from the string payload of a
+// CastMessage.
+LaunchSessionResponse GetLaunchSessionResponse(const base::Value& payload);
 
 }  // namespace cast_channel
 
diff --git a/components/cast_channel/cast_message_util_unittest.cc b/components/cast_channel/cast_message_util_unittest.cc
index 9fdbfa8..8e629cfd 100644
--- a/components/cast_channel/cast_message_util_unittest.cc
+++ b/components/cast_channel/cast_message_util_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/json/json_reader.h"
 #include "base/values.h"
+#include "components/cast_channel/proto/cast_channel.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cast_channel {
@@ -34,8 +35,7 @@
     }
   )";
 
-  std::unique_ptr<base::DictionaryValue> value =
-      base::DictionaryValue::From(base::JSONReader::Read(payload));
+  std::unique_ptr<base::Value> value = base::JSONReader::Read(payload);
   ASSERT_TRUE(value);
 
   LaunchSessionResponse response = GetLaunchSessionResponse(*value);
@@ -51,8 +51,7 @@
     }
   )";
 
-  std::unique_ptr<base::DictionaryValue> value =
-      base::DictionaryValue::From(base::JSONReader::Read(payload));
+  std::unique_ptr<base::Value> value = base::JSONReader::Read(payload);
   ASSERT_TRUE(value);
 
   LaunchSessionResponse response = GetLaunchSessionResponse(*value);
@@ -70,8 +69,7 @@
     }
   )";
 
-  std::unique_ptr<base::DictionaryValue> value =
-      base::DictionaryValue::From(base::JSONReader::Read(payload));
+  std::unique_ptr<base::Value> value = base::JSONReader::Read(payload);
   ASSERT_TRUE(value);
 
   LaunchSessionResponse response = GetLaunchSessionResponse(*value);
@@ -79,4 +77,26 @@
   EXPECT_FALSE(response.receiver_status);
 }
 
+TEST(CastMessageUtilTest, CreateStopRequest) {
+  std::string expected_message = R"(
+    {
+      "type": "STOP",
+      "requestId": 123,
+      "sessionId": "sessionId"
+    }
+  )";
+
+  std::unique_ptr<base::Value> expected_value =
+      base::JSONReader::Read(expected_message);
+  ASSERT_TRUE(expected_value);
+
+  CastMessage message = CreateStopRequest("sourceId", 123, "sessionId");
+  ASSERT_TRUE(IsCastMessageValid(message));
+
+  std::unique_ptr<base::Value> actual_value =
+      base::JSONReader::Read(message.payload_utf8());
+  ASSERT_TRUE(actual_value);
+  EXPECT_EQ(*expected_value, *actual_value);
+}
+
 }  // namespace cast_channel
diff --git a/components/consent_auditor/consent_auditor.h b/components/consent_auditor/consent_auditor.h
index 30e61ac..fa62710d 100644
--- a/components/consent_auditor/consent_auditor.h
+++ b/components/consent_auditor/consent_auditor.h
@@ -31,7 +31,7 @@
   GOOGLE_LOCATION_SERVICE = 3,
   CHROME_UNIFIED_CONSENT = 4,
 
-  FEATURE_LAST = GOOGLE_LOCATION_SERVICE
+  FEATURE_LAST = CHROME_UNIFIED_CONSENT
 };
 
 // Whether a consent is given or not given.
diff --git a/components/consent_auditor/consent_sync_bridge_impl.cc b/components/consent_auditor/consent_sync_bridge_impl.cc
index 05c60ed..264f32cb 100644
--- a/components/consent_auditor/consent_sync_bridge_impl.cc
+++ b/components/consent_auditor/consent_sync_bridge_impl.cc
@@ -51,16 +51,6 @@
   return entity_data;
 }
 
-// TODO(vitaliii): Delete this function both here and in UserEventSyncBridge.
-std::unique_ptr<EntityData> CopyToEntityData(
-    const UserConsentSpecifics specifics) {
-  auto entity_data = std::make_unique<EntityData>();
-  entity_data->non_unique_name =
-      base::Int64ToString(specifics.client_consent_time_usec());
-  *entity_data->specifics.mutable_user_consent() = specifics;
-  return entity_data;
-}
-
 }  // namespace
 
 ConsentSyncBridgeImpl::ConsentSyncBridgeImpl(
@@ -296,11 +286,12 @@
   }
 
   auto batch = std::make_unique<MutableDataBatch>();
-  UserConsentSpecifics specifics;
   for (const Record& r : *data_records) {
-    if (specifics.ParseFromString(r.value)) {
-      DCHECK_EQ(r.id, GetStorageKeyFromSpecifics(specifics));
-      batch->Put(r.id, CopyToEntityData(specifics));
+    auto specifics = std::make_unique<UserConsentSpecifics>();
+
+    if (specifics->ParseFromString(r.value)) {
+      DCHECK_EQ(r.id, GetStorageKeyFromSpecifics(*specifics));
+      batch->Put(r.id, MoveToEntityData(std::move(specifics)));
     } else {
       change_processor()->ReportError(
           {FROM_HERE, "Failed deserializing user events."});
diff --git a/components/password_manager/core/browser/password_bubble_experiment.cc b/components/password_manager/core/browser/password_bubble_experiment.cc
index 3c446d4..27022f7a 100644
--- a/components/password_manager/core/browser/password_bubble_experiment.cc
+++ b/components/password_manager/core/browser/password_bubble_experiment.cc
@@ -60,9 +60,14 @@
 bool ShouldShowChromeSignInPasswordPromo(
     PrefService* prefs,
     const syncer::SyncService* sync_service) {
-  if (!sync_service || !sync_service->IsSyncAllowed() ||
-      sync_service->IsFirstSetupComplete())
+  if (!sync_service ||
+      sync_service->HasDisableReason(
+          syncer::SyncService::DISABLE_REASON_PLATFORM_OVERRIDE) ||
+      sync_service->HasDisableReason(
+          syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY) ||
+      sync_service->IsFirstSetupComplete()) {
     return false;
+  }
   // Don't show the promo more than 3 times.
   constexpr int kThreshold = 3;
   return !prefs->GetBoolean(
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 3482396..8f58dadd 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -150,8 +150,7 @@
                              true /* should_migrate_http_passwords */,
                              true /* should_query_suppressed_https_forms */)),
       form_fetcher_(form_fetcher ? form_fetcher : owned_form_fetcher_.get()),
-      votes_uploader_(client, observed_form.IsPossibleChangePasswordForm()),
-      is_main_frame_secure_(client->IsMainFrameSecure()) {
+      votes_uploader_(client, observed_form.IsPossibleChangePasswordForm()) {
   // Non-HTML forms should not need any interaction with the renderer, and hence
   // no driver. Note that cloned PasswordFormManager instances can have HTML
   // forms without drivers as well.
@@ -625,17 +624,14 @@
 
   // Look for the actually submitted credentials in the list of previously saved
   // credentials that were available to autofilling.
-  // This first match via FindBestSavedMatch focuses on matches by username and
-  // falls back to password based matches if |submitted_form_| has no username
-  // filled.
   const PasswordForm* saved_form = FindBestSavedMatch(submitted_form_.get());
-  if (saved_form != nullptr) {
+  if (saved_form) {
     // The user signed in with a login we autofilled.
     pending_credentials_ = *saved_form;
     SetPasswordOverridden(pending_credentials_.password_value !=
                           password_to_save.first);
 
-    if (IsPendingCredentialsPublicSuffixMatch()) {
+    if (pending_credentials_.is_public_suffix_match) {
       // If the autofilled credentials were a PSL match or credentials stored
       // from Android apps, store a copy with the current origin and signon
       // realm. This ensures that on the next visit, a precise match is found.
@@ -647,10 +643,6 @@
       // If this isn't updated, then password generation uploads are off for
       // sites where PSL matching is required to fill the login form, as two
       // PASSWORD votes are uploaded per saved password instead of one.
-      //
-      // TODO(gcasto): It would be nice if other state were shared such that if
-      // say a password was updated on one match it would update on all related
-      // passwords. This is a much larger change.
       UpdateMetadataForUsage(&pending_credentials_);
 
       // Update |pending_credentials_| in order to be able correctly save it.
@@ -667,8 +659,7 @@
       // actually correspond to two different accounts (see
       // http://crbug.com/385619). In that case the user should be asked again
       // before saving the password. This is ensured by setting
-      // |password_overriden_| on |pending_credentials_| to false and setting
-      // |origin| and |signon_realm| to correct values.
+      // |password_overriden_| on |pending_credentials_| to false.
       //
       // There is still the edge case when the autofilled credentials represent
       // the same account as |submitted_form_| but the stored password
@@ -746,14 +737,8 @@
     }
   }
 
-  if (!IsValidAndroidFacetURI(pending_credentials_.signon_realm)) {
+  if (!IsValidAndroidFacetURI(pending_credentials_.signon_realm))
     pending_credentials_.action = submitted_form_->action;
-    // If the user selected credentials we autofilled from a PasswordForm
-    // that contained no action URL (IE6/7 imported passwords, for example),
-    // bless it with the action URL from the observed form. See b/1107719.
-    if (pending_credentials_.action.is_empty())
-      pending_credentials_.action = observed_form_.action;
-  }
 
   pending_credentials_.password_value = password_to_save.first;
   pending_credentials_.preferred = submitted_form_->preferred;
@@ -771,7 +756,9 @@
     pending_credentials_.display_name = submitted_form_->display_name;
     pending_credentials_.federation_origin = submitted_form_->federation_origin;
     pending_credentials_.icon_url = submitted_form_->icon_url;
-    // Take the correct signon_realm for federated credentials.
+    // It's important to override |signon_realm| for federated credentials
+    // because it has format "federation://" + origin_host + "/" +
+    // federation_host
     pending_credentials_.signon_realm = submitted_form_->signon_realm;
   }
 
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h
index 547c462..339b764 100644
--- a/components/password_manager/core/browser/password_form_manager.h
+++ b/components/password_manager/core/browser/password_form_manager.h
@@ -437,10 +437,6 @@
 
   VotesUploader votes_uploader_;
 
-  // True if the main frame's visible URL, at the time this PasswordFormManager
-  // was created, is secure.
-  bool is_main_frame_secure_ = false;
-
   // Takes care of recording metrics and events for this PasswordFormManager.
   // Make sure to call Init before using |*this|, to ensure it is not null.
   scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder_;
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc
index 437840a..7322313 100644
--- a/components/password_manager/core/common/password_manager_features.cc
+++ b/components/password_manager/core/common/password_manager_features.cc
@@ -71,11 +71,17 @@
 // selection, rather than autofilling on page load, with highlighting of fields.
 const base::Feature kFillOnAccountSelect = {"fill-on-account-select",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
-// Enables new password form parsing mechanism, details in
-// go/new-cpm-design-refactoring.
+
+// Enables new password form parsing mechanism for filling passwords, details in
+// https://goo.gl/QodPH1
 const base::Feature kNewPasswordFormParsing = {
     "new-password-form-parsing", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables new password form parsing mechanism for saving passwords, details in
+// https://goo.gl/QodPH1
+const base::Feature kNewPasswordFormParsingForSaving = {
+    "new-password-form-parsing-for-saving", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Field trial identifier for password generation requirements.
 const char* kGenerationRequirementsFieldTrial =
     "PasswordGenerationRequirements";
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h
index cc59717..7eb1bf2 100644
--- a/components/password_manager/core/common/password_manager_features.h
+++ b/components/password_manager/core/common/password_manager_features.h
@@ -26,6 +26,7 @@
 extern const base::Feature kShowAllSavedPasswordsContextMenu;
 extern const base::Feature kFillOnAccountSelect;
 extern const base::Feature kNewPasswordFormParsing;
+extern const base::Feature kNewPasswordFormParsingForSaving;
 extern const base::Feature kPasswordExport;
 extern const base::Feature kPasswordImport;
 extern const base::Feature kPasswordSearchMobile;
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index c147691..b31014e6 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -11651,7 +11651,7 @@
         'dynamic_refresh': True,
         'per_profile': False,
       },
-      'supported_on': ['chrome.*:66-'],
+      'supported_on': ['chrome.*:66-', 'chrome_os:70-'],
       'type': 'int-enum',
       'schema': {
         'type': 'integer',
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index 24152e3..1766d58 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -858,6 +858,7 @@
     "engine/ui_model_worker_unittest.cc",
     "engine_impl/apply_control_data_updates_unittest.cc",
     "engine_impl/backoff_delay_provider_unittest.cc",
+    "engine_impl/cycle/data_type_debug_info_emitter_unittest.cc",
     "engine_impl/cycle/nudge_tracker_unittest.cc",
     "engine_impl/cycle/status_controller_unittest.cc",
     "engine_impl/debug_info_event_listener_unittest.cc",
diff --git a/components/sync/PRESUBMIT.py b/components/sync/PRESUBMIT.py
index bca86cb..0d138565 100644
--- a/components/sync/PRESUBMIT.py
+++ b/components/sync/PRESUBMIT.py
@@ -48,7 +48,7 @@
 
 # Start and end regexes for finding the EntitySpecifics definition in
 # sync.proto.
-PROTO_DEFINITION_START_PATTERN = '^message EntitySpecifics'
+PROTO_DEFINITION_START_PATTERN = '^  oneof specifics_variant \{'
 PROTO_DEFINITION_END_PATTERN = '^\}'
 
 # Start and end regexes for finding the ModelTypeInfoMap definition
@@ -60,6 +60,7 @@
 # model_type.cc is where the ModelTypeInfoMap is
 # sync.proto is where the proto definitions for ModelTypes are.
 PROTO_FILE_PATH = './protocol/sync.proto'
+PROTO_FILE_NAME = 'sync.proto'
 MODEL_TYPE_FILE_NAME = 'model_type.cc'
 
 SYNC_SOURCE_FILES = (r'^components[\\/]sync[\\/].*\.(cc|h)$',)
@@ -214,12 +215,11 @@
       if '//' in line or len(split_proto_line) < 3:
         continue
 
-      field_typename = split_proto_line[1]
-      field_identifier = split_proto_line[2]
+      field_typename = split_proto_line[0]
+      field_identifier = split_proto_line[1]
       proto_field_definitions[field_typename] = field_identifier
   return proto_field_definitions
 
-
 def StripTrailingS(string):
   return string.rstrip('sS')
 
@@ -384,8 +384,9 @@
   results = []
   results += CheckChangeLintsClean(input_api, output_api)
   for f in input_api.AffectedFiles():
-    if f.LocalPath().endswith(MODEL_TYPE_FILE_NAME):
-      return CheckModelTypeInfoMap(input_api, output_api, f)
+    if (f.LocalPath().endswith(MODEL_TYPE_FILE_NAME) or
+        f.LocalPath().endswith(PROTO_FILE_NAME)):
+      results += CheckModelTypeInfoMap(input_api, output_api, f)
   return results
 
 def CheckChangeOnUpload(input_api, output_api):
diff --git a/components/sync/PRESUBMIT_test.py b/components/sync/PRESUBMIT_test.py
index 6164a18a..df563a0 100755
--- a/components/sync/PRESUBMIT_test.py
+++ b/components/sync/PRESUBMIT_test.py
@@ -70,16 +70,19 @@
 # test presubmit parsing of EntitySpecifics definition in that file.
 MOCK_PROTOFILE_CONTENTS = ('\n'
   'message EntitySpecifics {\n'
-  '//comment\n'
+  '  //comment\n'
   '\n'
-  'optional AutofillSpecifics autofill = 123;\n'
-  'optional AppSpecifics app = 456;\n'
-  'optional AppSettingSpecifics app_setting = 789;\n'
-  'optional ExtensionSettingSpecifics extension_setting = 910;\n'
-  'optional ManagedUserSharedSettingSpecifics managed_user_shared_setting'
+  '  oneof specifics_variant {\n'
+  '    AutofillSpecifics autofill = 123;\n'
+  '    AppSpecifics app = 456;\n'
+  '    AppSettingSpecifics app_setting = 789;\n'
+  '    ExtensionSettingSpecifics extension_setting = 910;\n'
+  '    ManagedUserSharedSettingSpecifics managed_user_shared_setting'
                                                                     ' = 915;\n'
-  '//comment\n'
-  '}\n')
+  '    //comment\n'
+  '  }\n'
+  '}\n'
+  )
 
 
 # Format string used as the contents of a mock model_type.cc
diff --git a/components/sync/base/data_type_histogram.cc b/components/sync/base/data_type_histogram.cc
index 18546e4..42b8b34a 100644
--- a/components/sync/base/data_type_histogram.cc
+++ b/components/sync/base/data_type_histogram.cc
@@ -11,9 +11,7 @@
 void SyncRecordMemoryKbHistogram(const std::string& histogram_name_prefix,
                                  syncer::ModelType model_type,
                                  size_t value) {
-  std::string type_string;
-  if (RealModelTypeToNotificationType(model_type, &type_string)) {
-    std::string full_histogram_name = histogram_name_prefix + type_string;
-    base::UmaHistogramCounts1M(full_histogram_name, value / 1024);
-  }
+  std::string type_string = ModelTypeToHistogramSuffix(model_type);
+  std::string full_histogram_name = histogram_name_prefix + type_string;
+  base::UmaHistogramCounts1M(full_histogram_name, value / 1024);
 }
diff --git a/components/sync/base/model_type.h b/components/sync/base/model_type.h
index 7903bba9..ea9a153 100644
--- a/components/sync/base/model_type.h
+++ b/components/sync/base/model_type.h
@@ -331,10 +331,14 @@
 
 // TODO(sync): The functions below badly need some cleanup.
 
-// Returns a pointer to a string with application lifetime that represents
-// the name of |model_type|.
+// Returns a string with application lifetime that represents the name of
+// |model_type|.
 const char* ModelTypeToString(ModelType model_type);
 
+// Returns a string with application lifetime that is used as the histogram
+// suffix for |model_type|.
+const char* ModelTypeToHistogramSuffix(ModelType model_type);
+
 // Some histograms take an integer parameter that represents a model type.
 // The mapping from ModelType to integer is defined here. It should match the
 // mapping from integer to labels defined in histograms.xml.
diff --git a/components/sync/driver/sync_driver_switches.cc b/components/sync/driver/sync_driver_switches.cc
index e409510..697cd0f 100644
--- a/components/sync/driver/sync_driver_switches.cc
+++ b/components/sync/driver/sync_driver_switches.cc
@@ -74,4 +74,8 @@
 const base::Feature kSyncUSSAutofillProfile{"SyncUSSAutofillProfile",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enable USS implementation of autofill wallet datatype.
+const base::Feature kSyncUSSAutofillWalletData{
+    "SyncUSSAutofillWalletData", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace switches
diff --git a/components/sync/driver/sync_driver_switches.h b/components/sync/driver/sync_driver_switches.h
index 77c3e17..b01df2b2 100644
--- a/components/sync/driver/sync_driver_switches.h
+++ b/components/sync/driver/sync_driver_switches.h
@@ -29,6 +29,7 @@
 extern const base::Feature kSyncUSSBookmarks;
 extern const base::Feature kSyncUSSSessions;
 extern const base::Feature kSyncUSSAutofillProfile;
+extern const base::Feature kSyncUSSAutofillWalletData;
 
 }  // namespace switches
 
diff --git a/components/sync/driver/sync_service.cc b/components/sync/driver/sync_service.cc
index 2ec82a3..e04efc7 100644
--- a/components/sync/driver/sync_service.cc
+++ b/components/sync/driver/sync_service.cc
@@ -17,11 +17,6 @@
   return GetDisableReasons() == DISABLE_REASON_NONE;
 }
 
-bool SyncService::IsSyncAllowed() const {
-  return !HasDisableReason(DISABLE_REASON_PLATFORM_OVERRIDE) &&
-         !HasDisableReason(DISABLE_REASON_ENTERPRISE_POLICY);
-}
-
 bool SyncService::IsEngineInitialized() const {
   switch (GetState()) {
     case State::DISABLED:
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h
index d7922988..3d270305 100644
--- a/components/sync/driver/sync_service.h
+++ b/components/sync/driver/sync_service.h
@@ -187,11 +187,6 @@
   bool IsEngineInitialized() const;
 
   // DEPRECATED! Use GetDisableReasons/HasDisableReason instead.
-  // Equivalent to "!HasDisableReason(DISABLE_REASON_PLATFORM_OVERRIDE) &&
-  // !HasDisableReason(DISABLE_REASON_ENTERPRISE_POLICY)".
-  bool IsSyncAllowed() const;
-
-  // DEPRECATED! Use GetDisableReasons/HasDisableReason instead.
   // Equivalent to having no disable reasons, i.e.
   // "GetDisableReasons() == DISABLE_REASON_NONE".
   bool CanSyncStart() const;
diff --git a/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc b/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc
index 68c3a17..93bc48b 100644
--- a/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc
+++ b/components/sync/engine_impl/cycle/data_type_debug_info_emitter.cc
@@ -4,14 +4,64 @@
 
 #include "components/sync/engine_impl/cycle/data_type_debug_info_emitter.h"
 
+#include <string>
+
+#include "base/metrics/histogram.h"
 #include "components/sync/engine/cycle/type_debug_info_observer.h"
 
 namespace syncer {
 
+namespace {
+
+const char kModelTypeEntityChangeHistogramPrefix[] =
+    "Sync.ModelTypeEntityChange.";
+
+// Values corrospond to a UMA histogram, do not modify, or delete any values.
+// Add new values only directly before COUNT.
+enum ModelTypeEntityChange {
+  LOCAL_DELETION = 0,
+  LOCAL_CREATION = 1,
+  LOCAL_UPDATE = 2,
+  REMOTE_DELETION = 3,
+  REMOTE_UPDATE = 4,
+  MODEL_TYPE_ENTITY_CHANGE_COUNT = 5
+};
+
+void EmitNewChangesToUma(int count,
+                         ModelTypeEntityChange bucket,
+                         base::HistogramBase* histogram) {
+  DCHECK_GE(count, 0);
+  if (count > 0) {
+    histogram->AddCount(bucket, count);
+  }
+}
+
+// We'll add many values in this histogram. Since the name of the histogram is
+// not static here, we cannot use the (efficient) macros that use caching of the
+// histogram object. The helper functions like UmaHistogramEnumeration are not
+// efficient and thus we need re-implement the code here, caching the resulting
+// histogram object.
+base::HistogramBase* GetModelTypeEntityChangeHistogram(ModelType type) {
+  std::string type_string = ModelTypeToHistogramSuffix(type);
+  std::string full_histogram_name =
+      kModelTypeEntityChangeHistogramPrefix + type_string;
+  return base::LinearHistogram::FactoryGet(
+      /*name=*/full_histogram_name, /*minimum=*/1,
+      /*maximum=*/MODEL_TYPE_ENTITY_CHANGE_COUNT,
+      /*bucket_count=*/MODEL_TYPE_ENTITY_CHANGE_COUNT + 1,
+      /*flagz=*/base::HistogramBase::kUmaTargetedHistogramFlag);
+}
+
+}  // namespace
+
 DataTypeDebugInfoEmitter::DataTypeDebugInfoEmitter(
     ModelType type,
     base::ObserverList<TypeDebugInfoObserver>* observers)
-    : type_(type), type_debug_info_observers_(observers) {}
+    : type_(type),
+      type_debug_info_observers_(observers),
+      histogram_(GetModelTypeEntityChangeHistogram(type)) {
+  DCHECK(histogram_);
+}
 
 DataTypeDebugInfoEmitter::~DataTypeDebugInfoEmitter() {}
 
@@ -26,6 +76,23 @@
 void DataTypeDebugInfoEmitter::EmitCommitCountersUpdate() {
   for (auto& observer : *type_debug_info_observers_)
     observer.OnCommitCountersUpdated(type_, commit_counters_);
+
+  // Emit the newly added counts to UMA.
+  EmitNewChangesToUma(
+      /*count=*/commit_counters_.num_creation_commits_attempted -
+          emitted_commit_counters_.num_creation_commits_attempted,
+      /*bucket=*/LOCAL_CREATION, histogram_);
+  EmitNewChangesToUma(
+      /*count=*/commit_counters_.num_deletion_commits_attempted -
+          emitted_commit_counters_.num_deletion_commits_attempted,
+      /*bucket=*/LOCAL_DELETION, histogram_);
+  EmitNewChangesToUma(
+      /*count=*/commit_counters_.num_update_commits_attempted -
+          emitted_commit_counters_.num_update_commits_attempted,
+      /*bucket=*/LOCAL_UPDATE, histogram_);
+
+  // Mark the current state of the counters as uploaded to UMA.
+  emitted_commit_counters_ = commit_counters_;
 }
 
 const UpdateCounters& DataTypeDebugInfoEmitter::GetUpdateCounters() const {
@@ -39,6 +106,27 @@
 void DataTypeDebugInfoEmitter::EmitUpdateCountersUpdate() {
   for (auto& observer : *type_debug_info_observers_)
     observer.OnUpdateCountersUpdated(type_, update_counters_);
+
+  // Emit the newly added counts to UMA.
+  EmitNewChangesToUma(
+      /*count=*/update_counters_.num_tombstone_updates_received -
+          emitted_update_counters_.num_tombstone_updates_received,
+      /*bucket=*/REMOTE_DELETION, histogram_);
+  // The REMOTE_UPDATE type is not explicitly stored, we need to compute it as a
+  // diff of (all - deletions).
+  int emitted_remote_updates_count =
+      emitted_update_counters_.num_updates_received -
+      emitted_update_counters_.num_tombstone_updates_received;
+  int remote_updates_count = update_counters_.num_updates_received -
+                             update_counters_.num_tombstone_updates_received;
+  EmitNewChangesToUma(
+      /*count=*/remote_updates_count - emitted_remote_updates_count,
+      /*bucket=*/REMOTE_UPDATE, histogram_);
+
+  // Mark the current state of the counters as uploaded to UMA.
+  emitted_update_counters_ = update_counters_;
 }
 
+void DataTypeDebugInfoEmitter::EmitStatusCountersUpdate() {}
+
 }  // namespace syncer
diff --git a/components/sync/engine_impl/cycle/data_type_debug_info_emitter.h b/components/sync/engine_impl/cycle/data_type_debug_info_emitter.h
index e49be1b6..2aac422 100644
--- a/components/sync/engine_impl/cycle/data_type_debug_info_emitter.h
+++ b/components/sync/engine_impl/cycle/data_type_debug_info_emitter.h
@@ -13,6 +13,10 @@
 #include "components/sync/engine/cycle/commit_counters.h"
 #include "components/sync/engine/cycle/update_counters.h"
 
+namespace base {
+class HistogramBase;
+}
+
 namespace syncer {
 
 class TypeDebugInfoObserver;
@@ -55,8 +59,10 @@
   // Triggers an update counters update to registered observers.
   void EmitUpdateCountersUpdate();
 
-  // Triggers a status counters update to registered observers.
-  virtual void EmitStatusCountersUpdate() = 0;
+  // Triggers a status counters update to registered observers. The default
+  // implementation does nothing and is present only to make this class
+  // non-abstract and thus unit-testable.
+  virtual void EmitStatusCountersUpdate();
 
  protected:
   const ModelType type_;
@@ -68,9 +74,20 @@
   base::ObserverList<TypeDebugInfoObserver>* type_debug_info_observers_;
 
  private:
+  // The actual up-to-date counters.
   CommitCounters commit_counters_;
   UpdateCounters update_counters_;
 
+  // The last state of the counters emitted to UMA. In the next round of
+  // emitting to UMA, we only need to upload the diff between the actual
+  // counters and the counts here.
+  CommitCounters emitted_commit_counters_;
+  UpdateCounters emitted_update_counters_;
+
+  // The histogram to record to; cached for efficiency because many histogram
+  // entries are recorded in this object during run-time.
+  base::HistogramBase* const histogram_;
+
   DISALLOW_COPY_AND_ASSIGN(DataTypeDebugInfoEmitter);
 };
 
diff --git a/components/sync/engine_impl/cycle/data_type_debug_info_emitter_unittest.cc b/components/sync/engine_impl/cycle/data_type_debug_info_emitter_unittest.cc
new file mode 100644
index 0000000..68cc6f7
--- /dev/null
+++ b/components/sync/engine_impl/cycle/data_type_debug_info_emitter_unittest.cc
@@ -0,0 +1,131 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync/engine_impl/cycle/data_type_debug_info_emitter.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace syncer {
+namespace {
+
+TEST(DataTypeDebugInfoEmitterTest, ShouldEmitCommitsToUMAIfChanged) {
+  base::ObserverList<TypeDebugInfoObserver> observers;
+  DataTypeDebugInfoEmitter emitter(BOOKMARKS, &observers);
+
+  CommitCounters* counters = emitter.GetMutableCommitCounters();
+  counters->num_deletion_commits_attempted += 3;
+  counters->num_creation_commits_attempted += 2;
+  counters->num_update_commits_attempted += 1;
+
+  base::HistogramTester histogram_tester;
+  emitter.EmitCommitCountersUpdate();
+  EXPECT_EQ(
+      3, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange.BOOKMARK",
+                                         /*LOCAL_DELETION=*/0));
+  EXPECT_EQ(
+      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange.BOOKMARK",
+                                         /*LOCAL_CREATION=*/1));
+  EXPECT_EQ(1, histogram_tester.GetBucketCount(
+                   "Sync.ModelTypeEntityChange.BOOKMARK", /*LOCAL_UPDATE=*/2));
+}
+
+TEST(DataTypeDebugInfoEmitterTest, ShouldNotEmitCommitsToUMAIfNotChanged) {
+  base::ObserverList<TypeDebugInfoObserver> observers;
+  DataTypeDebugInfoEmitter emitter(BOOKMARKS, &observers);
+
+  base::HistogramTester histogram_tester;
+  emitter.EmitCommitCountersUpdate();
+  histogram_tester.ExpectTotalCount("Sync.ModelTypeEntityChange.BOOKMARK", 0);
+}
+
+// Tests that at each EmitCommitCountersUpdate() call, only the changes since
+// the last call to EmitCommitCountersUpdate() are reported to UMA.
+TEST(DataTypeDebugInfoEmitterTest, ShouldEmitCommitsToUMAIncrementally) {
+  base::ObserverList<TypeDebugInfoObserver> observers;
+  DataTypeDebugInfoEmitter emitter(BOOKMARKS, &observers);
+
+  CommitCounters* counters = emitter.GetMutableCommitCounters();
+  counters->num_deletion_commits_attempted += 3;
+  counters->num_creation_commits_attempted += 2;
+  counters->num_update_commits_attempted += 1;
+
+  // First emission - tested in the test above.
+  emitter.EmitCommitCountersUpdate();
+
+  counters = emitter.GetMutableCommitCounters();
+  counters->num_deletion_commits_attempted += 1;
+  counters->num_creation_commits_attempted += 2;
+  counters->num_update_commits_attempted += 3;
+
+  // Test the second emission that it only reports the increment in counters.
+  base::HistogramTester histogram_tester;
+  emitter.EmitCommitCountersUpdate();
+  EXPECT_EQ(
+      1, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange.BOOKMARK",
+                                         /*LOCAL_DELETION=*/0));
+  EXPECT_EQ(
+      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange.BOOKMARK",
+                                         /*LOCAL_CREATION=*/1));
+  EXPECT_EQ(3, histogram_tester.GetBucketCount(
+                   "Sync.ModelTypeEntityChange.BOOKMARK", /*LOCAL_UPDATE=*/2));
+}
+
+TEST(DataTypeDebugInfoEmitterTest, ShouldEmitUpdatesToUMAIfChanged) {
+  base::ObserverList<TypeDebugInfoObserver> observers;
+  DataTypeDebugInfoEmitter emitter(BOOKMARKS, &observers);
+
+  UpdateCounters* counters = emitter.GetMutableUpdateCounters();
+  counters->num_updates_received += 3;
+  counters->num_tombstone_updates_received += 1;
+
+  base::HistogramTester histogram_tester;
+  emitter.EmitUpdateCountersUpdate();
+  EXPECT_EQ(
+      1, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange.BOOKMARK",
+                                         /*REMOTE_DELETION=*/3));
+  EXPECT_EQ(
+      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange.BOOKMARK",
+                                         /*REMOTE_UPDATE=*/4));
+}
+
+TEST(DataTypeDebugInfoEmitterTest, ShouldNotEmitUpdatesToUMAIfNotChanged) {
+  base::ObserverList<TypeDebugInfoObserver> observers;
+  DataTypeDebugInfoEmitter emitter(BOOKMARKS, &observers);
+
+  base::HistogramTester histogram_tester;
+  emitter.EmitUpdateCountersUpdate();
+  histogram_tester.ExpectTotalCount("Sync.ModelTypeEntityChange.BOOKMARK", 0);
+}
+
+// Tests that at each EmitUpdateCountersUpdate() call, only the changes since
+// the last call to EmitUpdateCountersUpdate() are reported to UMA.
+TEST(DataTypeDebugInfoEmitterTest, ShouldEmitUpdatesToUMAIncrementally) {
+  base::ObserverList<TypeDebugInfoObserver> observers;
+  DataTypeDebugInfoEmitter emitter(BOOKMARKS, &observers);
+
+  UpdateCounters* counters = emitter.GetMutableUpdateCounters();
+  counters->num_updates_received += 3;
+  counters->num_tombstone_updates_received += 1;
+
+  // First emission - tested in the test above.
+  emitter.EmitUpdateCountersUpdate();
+
+  counters = emitter.GetMutableUpdateCounters();
+  counters->num_updates_received += 3;
+  counters->num_tombstone_updates_received += 2;
+
+  // Test the second emission that it only reports the increment in counters.
+  base::HistogramTester histogram_tester;
+  emitter.EmitUpdateCountersUpdate();
+  EXPECT_EQ(
+      2, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange.BOOKMARK",
+                                         /*REMOTE_DELETION=*/3));
+  EXPECT_EQ(
+      1, histogram_tester.GetBucketCount("Sync.ModelTypeEntityChange.BOOKMARK",
+                                         /*REMOTE_UPDATE=*/4));
+}
+
+}  // namespace
+}  // namespace syncer
diff --git a/components/sync/syncable/directory_backing_store.cc b/components/sync/syncable/directory_backing_store.cc
index 6b681c4b..8c97f4b 100644
--- a/components/sync/syncable/directory_backing_store.cc
+++ b/components/sync/syncable/directory_backing_store.cc
@@ -280,16 +280,14 @@
                                const int (&entries_counts)[MODEL_TYPE_COUNT]) {
   int total_entry_counts = 0;
   for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
-    std::string model_type;
-    if (RealModelTypeToNotificationType((ModelType)i, &model_type)) {
-      std::string full_histogram_name = "Sync.ModelTypeCount." + model_type;
-      base::HistogramBase* histogram = base::Histogram::FactoryGet(
-          full_histogram_name, 1, 1000000, 50,
-          base::HistogramBase::kUmaTargetedHistogramFlag);
-      if (histogram)
-        histogram->Add(entries_counts[i]);
-      total_entry_counts += entries_counts[i];
-    }
+    std::string model_type = ModelTypeToHistogramSuffix((ModelType)i);
+    std::string full_histogram_name = "Sync.ModelTypeCount." + model_type;
+    base::HistogramBase* histogram = base::Histogram::FactoryGet(
+        full_histogram_name, 1, 1000000, 50,
+        base::HistogramBase::kUmaTargetedHistogramFlag);
+    if (histogram)
+      histogram->Add(entries_counts[i]);
+    total_entry_counts += entries_counts[i];
   }
   UMA_HISTOGRAM_COUNTS("Sync.ModelTypeCount", total_entry_counts);
   UMA_HISTOGRAM_COUNTS("Sync.ExtraSyncDataCount",
diff --git a/components/sync/syncable/model_type.cc b/components/sync/syncable/model_type.cc
index b3b23a6..68ec049 100644
--- a/components/sync/syncable/model_type.cc
+++ b/components/sync/syncable/model_type.cc
@@ -32,7 +32,9 @@
 struct ModelTypeInfo {
   ModelType model_type;
   // Model Type notification string.
-  // This needs to match the corresponding proto message name in sync.proto
+  // This needs to match the corresponding proto message name in sync.proto. It
+  // is also used to identify the model type in the SyncModelType
+  // histogram_suffix in histograms.xml. Must always be kept in sync.
   const char* notification_type;
   // Root tag for Model Type
   // This should be the same as the model type but all lowercase.
@@ -49,8 +51,10 @@
 };
 
 // Below struct entries are in the same order as their definition in the
-// ModelType enum. Don't forget to update the ModelType enum when you make
-// changes to this list.
+// ModelType enum. When making changes to this list, don't forget to
+//  - update the ModelType enum,
+//  - update the SyncModelTypes enum in enums.xml, and
+//  - update the SyncModelType histogram suffix in histograms.xml.
 // Struct field values should be unique across the entire map.
 const ModelTypeInfo kModelTypeInfoMap[] = {
     {UNSPECIFIED, "", "", "Unspecified", -1, 0},
@@ -493,6 +497,17 @@
   return "Invalid";
 }
 
+const char* ModelTypeToHistogramSuffix(ModelType model_type) {
+  if (model_type >= UNSPECIFIED && model_type < MODEL_TYPE_COUNT) {
+    // We use the same string that is used for notification types because they
+    // satisfy all we need (being stable and explanatory).
+    return kModelTypeInfoMap[model_type].notification_type;
+  }
+  NOTREACHED() << "No known suffix for model type "
+               << static_cast<int>(model_type) << ".";
+  return "Invalid";
+}
+
 // The normal rules about histograms apply here.  Always append to the bottom of
 // the list, and be careful to not reuse integer values that have already been
 // assigned.
diff --git a/components/sync/user_events/user_event_sync_bridge.cc b/components/sync/user_events/user_event_sync_bridge.cc
index 6b6041d..846356c 100644
--- a/components/sync/user_events/user_event_sync_bridge.cc
+++ b/components/sync/user_events/user_event_sync_bridge.cc
@@ -59,15 +59,6 @@
   return entity_data;
 }
 
-std::unique_ptr<EntityData> CopyToEntityData(
-    const UserEventSpecifics specifics) {
-  auto entity_data = std::make_unique<EntityData>();
-  entity_data->non_unique_name =
-      base::Int64ToString(specifics.event_time_usec());
-  *entity_data->specifics.mutable_user_event() = specifics;
-  return entity_data;
-}
-
 }  // namespace
 
 UserEventSyncBridge::UserEventSyncBridge(
@@ -358,11 +349,12 @@
   }
 
   auto batch = std::make_unique<MutableDataBatch>();
-  UserEventSpecifics specifics;
   for (const Record& r : *data_records) {
-    if (specifics.ParseFromString(r.value)) {
-      DCHECK_EQ(r.id, GetStorageKeyFromSpecifics(specifics));
-      batch->Put(r.id, CopyToEntityData(specifics));
+    auto specifics = std::make_unique<UserEventSpecifics>();
+
+    if (specifics->ParseFromString(r.value)) {
+      DCHECK_EQ(r.id, GetStorageKeyFromSpecifics(*specifics));
+      batch->Put(r.id, MoveToEntityData(std::move(specifics)));
     } else {
       change_processor()->ReportError(
           {FROM_HERE, "Failed deserializing user events."});
diff --git a/components/test/data/ntp/render/1200x800_DefaultMV.png b/components/test/data/ntp/render/1200x800_DefaultMV.png
index 958b314..f453798 100644
--- a/components/test/data/ntp/render/1200x800_DefaultMV.png
+++ b/components/test/data/ntp/render/1200x800_DefaultMV.png
Binary files differ
diff --git a/components/ukm/debug/BUILD.gn b/components/ukm/debug/BUILD.gn
index f40504a..e4f6781 100644
--- a/components/ukm/debug/BUILD.gn
+++ b/components/ukm/debug/BUILD.gn
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//third_party/closure_compiler/compile_js.gni")
+
 source_set("util") {
   sources = [
     "ukm_debug_data_extractor.cc",
@@ -13,3 +15,16 @@
     "//services/metrics/public/cpp:ukm_builders",
   ]
 }
+
+js_type_check("closure_compile") {
+  deps = [
+    ":ukm_internals",
+  ]
+}
+
+js_library("ukm_internals") {
+  deps = [
+    "//ui/webui/resources/js:cr",
+    "//ui/webui/resources/js:util",
+  ]
+}
diff --git a/components/ukm/debug/ukm_debug_data_extractor.cc b/components/ukm/debug/ukm_debug_data_extractor.cc
index fc768528..89fd400e 100644
--- a/components/ukm/debug/ukm_debug_data_extractor.cc
+++ b/components/ukm/debug/ukm_debug_data_extractor.cc
@@ -114,74 +114,5 @@
   return std::move(ukm_data);
 }
 
-// static
-std::string UkmDebugDataExtractor::GetHTMLData(const UkmService* ukm_service) {
-  std::string output;
-  output.append(R"""(<!DOCTYPE html>
-  <html>
-    <head>
-      <meta http-equiv="Content-Security-Policy"
-            content="object-src 'none'; script-src 'none'">
-      <title>UKM Debug</title>
-    </head>
-    <body>
-      <h1>UKM Debug page</h1>
-  )""");
-
-  if (ukm_service) {
-    output.append(
-        // 'id' attribute set so tests can extract this element.
-        base::StringPrintf("<p>IsEnabled:<span id='state'>%s</span></p>",
-                           ukm_service->recording_enabled_ ? "True" : "False"));
-    output.append(base::StringPrintf("<p>ClientId:<span id='clientid'>%" PRIu64
-                                     "</span></p>",
-                                     ukm_service->client_id_));
-    output.append(
-        base::StringPrintf("<p>SessionId:%d</p>", ukm_service->session_id_));
-
-    const auto& decode_map = ukm_service->decode_map_;
-    std::map<SourceId, SourceData> source_data;
-    for (const auto& kv : ukm_service->recordings_.sources) {
-      source_data[kv.first].source = kv.second.get();
-    }
-
-    for (const auto& v : ukm_service->recordings_.entries) {
-      source_data[v->source_id].entries.push_back(v.get());
-    }
-
-    output.append("<h2>Sources</h2>");
-    for (const auto& kv : source_data) {
-      const auto* src = kv.second.source;
-      if (src) {
-        output.append(base::StringPrintf("<h3>Id:%" PRId64 " Url:%s</h3>",
-                                         src->id(), src->url().spec().c_str()));
-      } else {
-        output.append(base::StringPrintf("<h3>Id:%" PRId64 "</h3>", kv.first));
-      }
-      for (auto* entry : kv.second.entries) {
-        const auto it = decode_map.find(entry->event_hash);
-        if (it == decode_map.end()) {
-          output.append(base::StringPrintf(
-              "<h4>Entry: Unknown %" PRIu64 "</h4>", entry->event_hash));
-          continue;
-        }
-        output.append(base::StringPrintf("<h4>Entry:%s</h4>", it->second.name));
-        for (const auto& metric : entry->metrics) {
-          output.append(base::StringPrintf(
-              "<h5>Metric:%s Value:%" PRId64 "</h5>",
-              GetName(it->second, metric.first).c_str(), metric.second));
-        }
-      }
-    }
-  }
-
-  output.append(R"""(
-    </body>
-  </html>
-  )""");
-
-  return output;
-}
-
 }  // namespace debug
 }  // namespace ukm
diff --git a/components/ukm/debug/ukm_debug_data_extractor.h b/components/ukm/debug/ukm_debug_data_extractor.h
index 0a55cdf..dc2810d 100644
--- a/components/ukm/debug/ukm_debug_data_extractor.h
+++ b/components/ukm/debug/ukm_debug_data_extractor.h
@@ -26,10 +26,6 @@
   // Returns UKM data structured in a DictionaryValue.
   static base::Value GetStructuredData(const UkmService* ukm_service);
 
-  // Returns UKM data as an HTML page.
-  // TODO(etiennep): Use GetStructuredData() instead.
-  static std::string GetHTMLData(const UkmService* ukm_service);
-
  private:
   DISALLOW_COPY_AND_ASSIGN(UkmDebugDataExtractor);
 };
diff --git a/chrome/browser/resources/ukm/ukm_internals.html b/components/ukm/debug/ukm_internals.html
similarity index 100%
rename from chrome/browser/resources/ukm/ukm_internals.html
rename to components/ukm/debug/ukm_internals.html
diff --git a/components/ukm/debug/ukm_internals.js b/components/ukm/debug/ukm_internals.js
new file mode 100644
index 0000000..85c1c7a
--- /dev/null
+++ b/components/ukm/debug/ukm_internals.js
@@ -0,0 +1,78 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @typedef {{
+ *   name: string,
+ *   value: string
+ * }}
+ */
+var Metric;
+
+/**
+ * @typedef {{
+ *   name: string,
+ *   metrics: !Array<!Metric>
+ * }}
+ */
+var UkmEntry;
+
+/**
+ * @typedef {{
+ *   url: string,
+ *   id: string,
+ *   entries: !Array<UkmEntry>,
+ * }}
+ */
+var UkmDataSource;
+
+/**
+ * The Ukm data sent from the browser.
+ * @typedef {{
+ *   state: boolean,
+ *   client_id: string,
+ *   session_id: string,
+ *   sources: !Array<!UkmDataSource>,
+ * }}
+ */
+var UkmData;
+
+/**
+ * Fetches data from the Ukm service and updates the DOM to display it as a
+ * list.
+ */
+function updateUkmData() {
+  cr.sendWithPromise('requestUkmData').then((/** @type {UkmData} */ data) => {
+    $('state').innerText = data.state ? 'True' : 'False';
+    $('clientid').innerText = data.client_id;
+    $('sessionid').innerText = data.session_id;
+
+    let sourceDiv = $('sources');
+    for (const source of data.sources) {
+      const sourceElement = document.createElement('h3');
+      if (source.url !== undefined)
+        sourceElement.innerText = `Id: ${source.id} Url: ${source.url}`;
+      else
+        sourceElement.innerText = `Id: ${source.id}`;
+      sourceDiv.appendChild(sourceElement);
+
+      for (const entry of source.entries) {
+        const entryElement = document.createElement('h4');
+        entryElement.innerText = `Entry: ${entry.name}`;
+        sourceDiv.appendChild(entryElement);
+
+        if (entry.metrics === undefined)
+          continue;
+        for (const metric of entry.metrics) {
+          const metricElement = document.createElement('h5');
+          metricElement.innerText =
+              `Metric: ${metric.name} Value: ${metric.value}`;
+          sourceDiv.appendChild(metricElement);
+        }
+      }
+    }
+  });
+}
+
+updateUkmData();
diff --git a/components/unified_consent/unified_consent_service.cc b/components/unified_consent/unified_consent_service.cc
index 4747e0d..34795671 100644
--- a/components/unified_consent/unified_consent_service.cc
+++ b/components/unified_consent/unified_consent_service.cc
@@ -135,7 +135,10 @@
     return;
   }
 
-  DCHECK(sync_service_->IsSyncAllowed());
+  DCHECK(!sync_service_->HasDisableReason(
+      syncer::SyncService::DISABLE_REASON_PLATFORM_OVERRIDE));
+  DCHECK(!sync_service_->HasDisableReason(
+      syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY));
   DCHECK(identity_manager_->HasPrimaryAccount());
   DCHECK_LT(MigrationState::NOT_INITIALIZED, GetMigrationState());
 
diff --git a/components/unified_consent/url_keyed_data_collection_consent_helper.cc b/components/unified_consent/url_keyed_data_collection_consent_helper.cc
index a504fdb..6ad5213 100644
--- a/components/unified_consent/url_keyed_data_collection_consent_helper.cc
+++ b/components/unified_consent/url_keyed_data_collection_consent_helper.cc
@@ -87,8 +87,10 @@
       sync_data_type_(sync_data_type),
       sync_data_type_upload_state_(
           syncer::GetUploadToGoogleState(sync_service_, sync_data_type_)) {
-  DCHECK(sync_service_);
-  sync_service_->AddObserver(this);
+  if (sync_service_)
+    sync_service_->AddObserver(this);
+  else
+    DCHECK_EQ(syncer::UploadState::NOT_ACTIVE, sync_data_type_upload_state_);
 }
 
 SyncBasedUrlKeyedDataCollectionConsentHelper::
diff --git a/components/unified_consent/url_keyed_data_collection_consent_helper_unittest.cc b/components/unified_consent/url_keyed_data_collection_consent_helper_unittest.cc
index a83653c..d677ccb 100644
--- a/components/unified_consent/url_keyed_data_collection_consent_helper_unittest.cc
+++ b/components/unified_consent/url_keyed_data_collection_consent_helper_unittest.cc
@@ -137,6 +137,16 @@
 }
 
 TEST_F(UrlKeyedDataCollectionConsentHelperTest,
+       AnonymizedDataCollection_UnifiedConsentDisabled_NullSyncService) {
+  std::unique_ptr<UrlKeyedDataCollectionConsentHelper> helper =
+      UrlKeyedDataCollectionConsentHelper::
+          NewAnonymizedDataCollectionConsentHelper(
+              false /* is_unified_consent_enabled */, &pref_service_,
+              nullptr /* sync_service */);
+  EXPECT_FALSE(helper->IsEnabled());
+}
+
+TEST_F(UrlKeyedDataCollectionConsentHelperTest,
        PersonalizeddDataCollection_UnifiedConsentEnabled) {
   std::unique_ptr<UrlKeyedDataCollectionConsentHelper> helper =
       UrlKeyedDataCollectionConsentHelper::
@@ -171,5 +181,25 @@
   helper->RemoveObserver(this);
 }
 
+TEST_F(UrlKeyedDataCollectionConsentHelperTest,
+       PersonalizedDataCollection_NullSyncService) {
+  {
+    std::unique_ptr<UrlKeyedDataCollectionConsentHelper> helper =
+        UrlKeyedDataCollectionConsentHelper::
+            NewPersonalizedDataCollectionConsentHelper(
+                false /* is_unified_consent_enabled */,
+                nullptr /* sync_service */);
+    EXPECT_FALSE(helper->IsEnabled());
+  }
+  {
+    std::unique_ptr<UrlKeyedDataCollectionConsentHelper> helper =
+        UrlKeyedDataCollectionConsentHelper::
+            NewPersonalizedDataCollectionConsentHelper(
+                true /* is_unified_consent_enabled */,
+                nullptr /* sync_service */);
+    EXPECT_FALSE(helper->IsEnabled());
+  }
+}
+
 }  // namespace
 }  // namespace unified_consent
diff --git a/components/viz/service/surfaces/surface_dependency_tracker.cc b/components/viz/service/surfaces/surface_dependency_tracker.cc
index a8773e6b..08a14bc 100644
--- a/components/viz/service/surfaces/surface_dependency_tracker.cc
+++ b/components/viz/service/surfaces/surface_dependency_tracker.cc
@@ -19,8 +19,6 @@
 void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) {
   DCHECK(surface->HasPendingFrame());
 
-  const CompositorFrame& pending_frame = surface->GetPendingFrame();
-
   if (IsSurfaceLate(surface)) {
     ActivateLateSurfaceSubtree(surface);
     return;
@@ -28,8 +26,7 @@
 
   // Activation dependencies that aren't currently known to the surface manager
   // or do not have an active CompositorFrame block this frame.
-  for (const SurfaceId& surface_id :
-       pending_frame.metadata.activation_dependencies) {
+  for (const SurfaceId& surface_id : surface->activation_dependencies()) {
     Surface* dependency = surface_manager_->GetSurfaceForId(surface_id);
     if (!dependency || !dependency->HasActiveFrame()) {
       blocked_surfaces_from_dependency_[surface_id.frame_sink_id()].insert(
@@ -75,12 +72,7 @@
   if (!surface->HasPendingFrame())
     return;
 
-  const CompositorFrame& pending_frame = surface->GetPendingFrame();
-
-  DCHECK(!pending_frame.metadata.activation_dependencies.empty());
-
-  for (const SurfaceId& surface_id :
-       pending_frame.metadata.activation_dependencies) {
+  for (const SurfaceId& surface_id : surface->activation_dependencies()) {
     auto it =
         blocked_surfaces_from_dependency_.find(surface_id.frame_sink_id());
     if (it == blocked_surfaces_from_dependency_.end())
@@ -110,10 +102,7 @@
 void SurfaceDependencyTracker::ActivateLateSurfaceSubtree(Surface* surface) {
   DCHECK(surface->HasPendingFrame());
 
-  const CompositorFrame& pending_frame = surface->GetPendingFrame();
-
-  for (const SurfaceId& surface_id :
-       pending_frame.metadata.activation_dependencies) {
+  for (const SurfaceId& surface_id : surface->activation_dependencies()) {
     Surface* dependency = surface_manager_->GetSurfaceForId(surface_id);
     if (dependency && dependency->HasPendingFrame())
       ActivateLateSurfaceSubtree(dependency);
@@ -125,8 +114,6 @@
 void SurfaceDependencyTracker::UpdateSurfaceDeadline(Surface* surface) {
   DCHECK(surface->HasPendingFrame());
 
-  const CompositorFrame& pending_frame = surface->GetPendingFrame();
-
   // Inherit the deadline from the first parent blocked on this surface.
   auto it = blocked_surfaces_from_dependency_.find(
       surface->surface_id().frame_sink_id());
@@ -146,8 +133,7 @@
          surface->has_deadline());
 
   // Recursively propagate the newly set deadline to children.
-  for (const SurfaceId& surface_id :
-       pending_frame.metadata.activation_dependencies) {
+  for (const SurfaceId& surface_id : surface->activation_dependencies()) {
     Surface* dependency = surface_manager_->GetSurfaceForId(surface_id);
     if (dependency && dependency->HasPendingFrame())
       UpdateSurfaceDeadline(dependency);
diff --git a/components/webdata_services/web_data_service_wrapper.cc b/components/webdata_services/web_data_service_wrapper.cc
index 8bcd4d3..0287a89 100644
--- a/components/webdata_services/web_data_service_wrapper.cc
+++ b/components/webdata_services/web_data_service_wrapper.cc
@@ -18,6 +18,7 @@
 #include "components/autofill/core/browser/webdata/autofill_profile_syncable_service.h"
 #include "components/autofill/core/browser/webdata/autofill_table.h"
 #include "components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h"
+#include "components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h"
 #include "components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/common/autofill_features.h"
@@ -71,6 +72,9 @@
   }
 }
 
+// TODO(jkrcal): Rename this function when the last webdata sync type get
+// converted to USS, e.g. to InitSyncBridgesOnDBSequence(). Check also other
+// related functions.
 void InitSyncableAccountServicesOnDBSequence(
     scoped_refptr<base::SingleThreadTaskRunner> db_task_runner,
     const syncer::SyncableService::StartSyncFlare& sync_flare,
@@ -79,15 +83,21 @@
     const std::string& app_locale,
     autofill::AutofillWebDataBackend* autofill_backend) {
   DCHECK(db_task_runner->RunsTasksInCurrentSequence());
-  autofill::AutofillWalletSyncableService::CreateForWebDataServiceAndBackend(
-      autofill_web_data.get(), autofill_backend, app_locale);
+
+  if (base::FeatureList::IsEnabled(switches::kSyncUSSAutofillWalletData)) {
+    autofill::AutofillWalletSyncBridge::CreateForWebDataServiceAndBackend(
+        app_locale, autofill_backend, autofill_web_data.get());
+  } else {
+    autofill::AutofillWalletSyncableService::CreateForWebDataServiceAndBackend(
+        autofill_web_data.get(), autofill_backend, app_locale);
+    autofill::AutofillWalletSyncableService::FromWebDataService(
+        autofill_web_data.get())
+        ->InjectStartSyncFlare(sync_flare);
+  }
+
   autofill::AutofillWalletMetadataSyncableService::
       CreateForWebDataServiceAndBackend(autofill_web_data.get(),
                                         autofill_backend, app_locale);
-
-  autofill::AutofillWalletSyncableService::FromWebDataService(
-      autofill_web_data.get())
-      ->InjectStartSyncFlare(sync_flare);
 }
 
 }  // namespace
diff --git a/components/zucchini/BUILD.gn b/components/zucchini/BUILD.gn
index 77dc810..c871d9d1 100644
--- a/components/zucchini/BUILD.gn
+++ b/components/zucchini/BUILD.gn
@@ -78,8 +78,8 @@
     "rel32_finder.h",
     "rel32_utils.cc",
     "rel32_utils.h",
-    "reloc_utils.cc",
-    "reloc_utils.h",
+    "reloc_win32.cc",
+    "reloc_win32.h",
     "suffix_array.h",
     "target_pool.cc",
     "target_pool.h",
@@ -169,7 +169,7 @@
     "reference_set_unittest.cc",
     "rel32_finder_unittest.cc",
     "rel32_utils_unittest.cc",
-    "reloc_utils_unittest.cc",
+    "reloc_win32_unittest.cc",
     "suffix_array_unittest.cc",
     "target_pool_unittest.cc",
     "targets_affinity_unittest.cc",
diff --git a/components/zucchini/disassembler_win32.cc b/components/zucchini/disassembler_win32.cc
index a932bea2..7eba0f4 100644
--- a/components/zucchini/disassembler_win32.cc
+++ b/components/zucchini/disassembler_win32.cc
@@ -15,7 +15,7 @@
 #include "components/zucchini/buffer_source.h"
 #include "components/zucchini/rel32_finder.h"
 #include "components/zucchini/rel32_utils.h"
-#include "components/zucchini/reloc_utils.h"
+#include "components/zucchini/reloc_win32.h"
 
 namespace zucchini {
 
diff --git a/components/zucchini/reloc_utils.cc b/components/zucchini/reloc_win32.cc
similarity index 98%
rename from components/zucchini/reloc_utils.cc
rename to components/zucchini/reloc_win32.cc
index d6f69b9..2f993ad1 100644
--- a/components/zucchini/reloc_utils.cc
+++ b/components/zucchini/reloc_win32.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/zucchini/reloc_utils.h"
+#include "components/zucchini/reloc_win32.h"
 
 #include <algorithm>
 #include <tuple>
diff --git a/components/zucchini/reloc_utils.h b/components/zucchini/reloc_win32.h
similarity index 97%
rename from components/zucchini/reloc_utils.h
rename to components/zucchini/reloc_win32.h
index aac1efb..207c6e7 100644
--- a/components/zucchini/reloc_utils.h
+++ b/components/zucchini/reloc_win32.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_ZUCCHINI_RELOC_UTILS_H_
-#define COMPONENTS_ZUCCHINI_RELOC_UTILS_H_
+#ifndef COMPONENTS_ZUCCHINI_RELOC_WIN32_H_
+#define COMPONENTS_ZUCCHINI_RELOC_WIN32_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -137,4 +137,4 @@
 
 }  // namespace zucchini
 
-#endif  // COMPONENTS_ZUCCHINI_RELOC_UTILS_H_
+#endif  // COMPONENTS_ZUCCHINI_RELOC_WIN32_H_
diff --git a/components/zucchini/reloc_utils_unittest.cc b/components/zucchini/reloc_win32_unittest.cc
similarity index 99%
rename from components/zucchini/reloc_utils_unittest.cc
rename to components/zucchini/reloc_win32_unittest.cc
index 65acf5b..ca9bbe6 100644
--- a/components/zucchini/reloc_utils_unittest.cc
+++ b/components/zucchini/reloc_win32_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/zucchini/reloc_utils.h"
+#include "components/zucchini/reloc_win32.h"
 
 #include <stdint.h>
 
diff --git a/content/browser/background_fetch/background_fetch_service_impl.cc b/content/browser/background_fetch/background_fetch_service_impl.cc
index 596cfaa..864a1704c 100644
--- a/content/browser/background_fetch/background_fetch_service_impl.cc
+++ b/content/browser/background_fetch/background_fetch_service_impl.cc
@@ -106,10 +106,14 @@
     int64_t service_worker_registration_id,
     const std::string& developer_id,
     const std::string& unique_id,
-    const std::string& title,
+    const base::Optional<std::string>& title,
+    const SkBitmap& icon,
     UpdateUICallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!ValidateUniqueId(unique_id) || !ValidateTitle(title)) {
+
+  // TODO(crbug.com/865063): Remove the check for |title| when updating both the
+  // title and icons is supported.
+  if (!ValidateUniqueId(unique_id) || !title || !ValidateTitle(*title)) {
     std::move(callback).Run(
         blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
     return;
@@ -117,7 +121,7 @@
 
   BackgroundFetchRegistrationId registration_id(
       service_worker_registration_id, origin_, developer_id, unique_id);
-  background_fetch_context_->UpdateUI(registration_id, title,
+  background_fetch_context_->UpdateUI(registration_id, *title,
                                       std::move(callback));
 }
 
diff --git a/content/browser/background_fetch/background_fetch_service_impl.h b/content/browser/background_fetch/background_fetch_service_impl.h
index c61095e1..d59fbe16 100644
--- a/content/browser/background_fetch/background_fetch_service_impl.h
+++ b/content/browser/background_fetch/background_fetch_service_impl.h
@@ -47,7 +47,8 @@
   void UpdateUI(int64_t service_worker_registration_id,
                 const std::string& developer_id,
                 const std::string& unique_id,
-                const std::string& title,
+                const base::Optional<std::string>& title,
+                const SkBitmap& icon,
                 UpdateUICallback callback) override;
   void Abort(int64_t service_worker_registration_id,
              const std::string& developer_id,
diff --git a/content/browser/background_fetch/background_fetch_service_unittest.cc b/content/browser/background_fetch/background_fetch_service_unittest.cc
index 6e2a9c6..36f5702 100644
--- a/content/browser/background_fetch/background_fetch_service_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -183,7 +183,7 @@
 
     base::RunLoop run_loop;
     service_->UpdateUI(service_worker_registration_id, unique_id, developer_id,
-                       title,
+                       title, SkBitmap(),
                        base::BindOnce(&BackgroundFetchServiceTest::DidGetError,
                                       base::Unretained(this),
                                       run_loop.QuitClosure(), out_error));
diff --git a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
index eb9c846..bb71805 100644
--- a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
+++ b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
@@ -58,8 +58,7 @@
 
   media_web_contents_observer_ = initiator_->media_web_contents_observer();
 
-  window_ =
-      GetContentClient()->browser()->CreateWindowForPictureInPicture(this);
+  EnsureWindow();
   DCHECK(window_) << "Picture in Picture requires a valid window.";
 }
 
@@ -84,23 +83,25 @@
 }
 
 void PictureInPictureWindowControllerImpl::Close(bool should_pause_video) {
-  DCHECK(window_);
-
-  if (!window_->IsVisible())
+  if (!window_ || !window_->IsVisible())
     return;
 
   window_->Hide();
-  initiator_->SetHasPictureInPictureVideo(false);
+  CloseInternal(should_pause_video);
+}
 
-  surface_id_ = viz::SurfaceId();
-
-  OnLeavingPictureInPicture(should_pause_video);
+void PictureInPictureWindowControllerImpl::OnWindowDestroyed() {
+  window_ = nullptr;
+  embedder_ = nullptr;
+  CloseInternal(true /* should_pause_video */);
 }
 
 void PictureInPictureWindowControllerImpl::EmbedSurface(
     const viz::SurfaceId& surface_id,
     const gfx::Size& natural_size) {
+  EnsureWindow();
   DCHECK(window_);
+
   DCHECK(surface_id.is_valid());
   surface_id_ = surface_id;
 
@@ -195,4 +196,21 @@
   }
 }
 
+void PictureInPictureWindowControllerImpl::CloseInternal(
+    bool should_pause_video) {
+  initiator_->SetHasPictureInPictureVideo(false);
+
+  surface_id_ = viz::SurfaceId();
+
+  OnLeavingPictureInPicture(should_pause_video);
+}
+
+void PictureInPictureWindowControllerImpl::EnsureWindow() {
+  if (window_)
+    return;
+
+  window_ =
+      GetContentClient()->browser()->CreateWindowForPictureInPicture(this);
+}
+
 }  // namespace content
diff --git a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
index 8cd191f..7ce6d85 100644
--- a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
+++ b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
@@ -36,6 +36,7 @@
   // PictureInPictureWindowController:
   CONTENT_EXPORT gfx::Size Show() override;
   CONTENT_EXPORT void Close(bool should_pause_video) override;
+  CONTENT_EXPORT void OnWindowDestroyed() override;
   CONTENT_EXPORT void ClickCustomControl(
       const std::string& control_id) override;
   CONTENT_EXPORT void EmbedSurface(const viz::SurfaceId& surface_id,
@@ -59,6 +60,14 @@
   // Signal to the media player that |this| is leaving Picture-in-Picture mode.
   void OnLeavingPictureInPicture(bool should_pause_video);
 
+  // Internal method to set the states after the window was closed, whether via
+  // the system or Chromium.
+  void CloseInternal(bool should_pause_video);
+
+  // Creates a new window if the previous one was destroyed. It can happen
+  // because of the system control of the window.
+  void EnsureWindow();
+
   std::unique_ptr<OverlayWindow> window_;
   std::unique_ptr<OverlaySurfaceEmbedder> embedder_;
   WebContentsImpl* const initiator_;
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc
index faa3314..a4d9ed9 100644
--- a/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -767,7 +767,13 @@
   EXPECT_FALSE(HasPendingEvents());
 }
 
-TEST_F(InputRouterImplTest, GestureTypesIgnoringAck) {
+// TODO(https://crbug.com/866946): Test is flaky on Fuchsia.
+#if defined(OS_FUCHSIA)
+#define MAYBE_GestureTypesIgnoringAck DISABLED_GestureTypesIgnoringAck
+#else
+#define MAYBE_GestureTypesIgnoringAck GestureTypesIgnoringAck
+#endif
+TEST_F(InputRouterImplTest, MAYBE_GestureTypesIgnoringAck) {
   // We test every gesture type, ensuring that the stream of gestures is valid.
   const WebInputEvent::Type eventTypes[] = {
       WebInputEvent::kGestureTapDown,     WebInputEvent::kGestureShowPress,
diff --git a/content/browser/speech/speech_recognition_dispatcher_host.cc b/content/browser/speech/speech_recognition_dispatcher_host.cc
index 4e8664e..87617e6 100644
--- a/content/browser/speech/speech_recognition_dispatcher_host.cc
+++ b/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -201,7 +201,11 @@
     : session_id_(SpeechRecognitionManager::kSessionIDInvalid),
       client_(std::move(client_ptr_info)),
       stopped_(false),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  client_.set_connection_error_handler(
+      base::BindOnce(&SpeechRecognitionSession::ConnectionErrorHandler,
+                     base::Unretained(this)));
+}
 
 SpeechRecognitionSession::~SpeechRecognitionSession() {
   // If a connection error happens and the session hasn't been stopped yet,
@@ -273,4 +277,9 @@
 void SpeechRecognitionSession::OnEnvironmentEstimationComplete(int session_id) {
 }
 
+void SpeechRecognitionSession::ConnectionErrorHandler() {
+  if (!stopped_)
+    Abort();
+}
+
 }  // namespace content
diff --git a/content/browser/speech/speech_recognition_dispatcher_host.h b/content/browser/speech/speech_recognition_dispatcher_host.h
index ffa9bd51..9eeeb44 100644
--- a/content/browser/speech/speech_recognition_dispatcher_host.h
+++ b/content/browser/speech/speech_recognition_dispatcher_host.h
@@ -109,6 +109,8 @@
                            float noise_volume) override;
 
  private:
+  void ConnectionErrorHandler();
+
   int session_id_;
   blink::mojom::SpeechRecognitionSessionClientPtr client_;
   bool stopped_;
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 717e332..279b13f 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -406,6 +406,9 @@
   WebRuntimeFeatures::EnableWorkStealingInScriptRunner(
       base::FeatureList::IsEnabled(features::kWorkStealingInScriptRunner));
 
+  WebRuntimeFeatures::EnableScheduledScriptStreaming(
+      base::FeatureList::IsEnabled(features::kScheduledScriptStreaming));
+
   WebRuntimeFeatures::EnableFeatureFromString(
       "FeaturePolicyForPermissions",
       base::FeatureList::IsEnabled(features::kUseFeaturePolicyForPermissions));
diff --git a/content/public/browser/picture_in_picture_window_controller.h b/content/public/browser/picture_in_picture_window_controller.h
index 64f01043..6df6f22 100644
--- a/content/public/browser/picture_in_picture_window_controller.h
+++ b/content/public/browser/picture_in_picture_window_controller.h
@@ -38,7 +38,14 @@
   // Returns the size of the window in pixels.
   virtual gfx::Size Show() = 0;
 
+  // Called to notify the controller that the window was requested to be closed
+  // by the user or the content.
   virtual void Close(bool should_pause_video) = 0;
+
+  // Called by the window implementation to notify the controller that the
+  // window was requested to be closed and destroyed by the system.
+  virtual void OnWindowDestroyed() = 0;
+
   virtual void ClickCustomControl(const std::string& control_id) = 0;
   virtual void EmbedSurface(const viz::SurfaceId& surface_id,
                             const gfx::Size& natural_size) = 0;
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 12feb84..04d6bae 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -590,6 +590,10 @@
 const base::Feature kWorkStealingInScriptRunner{
     "WorkStealingInScriptRunner", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enabled scheduler use for script streaming.
+const base::Feature kScheduledScriptStreaming{
+    "ScheduledScriptStreaming", base::FEATURE_DISABLED_BY_DEFAULT};
+
 #if defined(OS_ANDROID)
 // Autofill Accessibility in Android.
 // crbug.com/627860
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 8f0e58ea..d6249a7 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -135,6 +135,7 @@
 CONTENT_EXPORT extern const base::Feature kWebXrOrientationSensorDevice;
 CONTENT_EXPORT extern const base::Feature kWipeCorruptV2IDBDatabases;
 CONTENT_EXPORT extern const base::Feature kWorkStealingInScriptRunner;
+CONTENT_EXPORT extern const base::Feature kScheduledScriptStreaming;
 
 #if defined(OS_ANDROID)
 CONTENT_EXPORT extern const base::Feature kAndroidAutofillAccessibility;
diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc
index 5326845..80559a1 100644
--- a/content/renderer/render_process_impl.cc
+++ b/content/renderer/render_process_impl.cc
@@ -144,8 +144,10 @@
   SetV8FlagIfFeature(features::kV8VmFuture, "--future");
   SetV8FlagIfNotFeature(features::kV8VmFuture, "--no-future");
 
-  SetV8FlagIfFeature(features::kWebAssemblyBaseline, "--wasm-tier-up");
-  SetV8FlagIfNotFeature(features::kWebAssemblyBaseline, "--no-wasm-tier-up");
+  SetV8FlagIfFeature(features::kWebAssemblyBaseline,
+                     "--liftoff --wasm-tier-up");
+  SetV8FlagIfNotFeature(features::kWebAssemblyBaseline,
+                        "--no-liftoff --no-wasm-tier-up");
 
   if (base::FeatureList::IsEnabled(features::kWebAssemblyThreads)) {
     constexpr char kFlags[] =
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc
index d573edc2..0ec1525 100644
--- a/content/shell/app/shell_main_delegate.cc
+++ b/content/shell/app/shell_main_delegate.cc
@@ -248,6 +248,7 @@
     command_line.AppendSwitch(switches::kEnablePreciseMemoryInfo);
 
     command_line.AppendSwitchASCII(network::switches::kHostResolverRules,
+                                   "MAP nonexistent.*.test ~NOTFOUND,"
                                    "MAP *.test 127.0.0.1");
 
     command_line.AppendSwitch(switches::kEnablePartialRaster);
diff --git a/device/usb/BUILD.gn b/device/usb/BUILD.gn
index 3248fe6b4..5b183fcc 100644
--- a/device/usb/BUILD.gn
+++ b/device/usb/BUILD.gn
@@ -81,9 +81,6 @@
 
   if (is_win || is_mac) {
     sources += [
-      "scoped_libusb_device_handle.cc",
-      "scoped_libusb_device_handle.h",
-      "scoped_libusb_device_ref.cc",
       "scoped_libusb_device_ref.h",
       "usb_context.cc",
       "usb_context.h",
diff --git a/device/usb/scoped_libusb_device_handle.cc b/device/usb/scoped_libusb_device_handle.cc
deleted file mode 100644
index 4223a81..0000000
--- a/device/usb/scoped_libusb_device_handle.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/usb/scoped_libusb_device_handle.h"
-
-#include "device/usb/usb_context.h"
-#include "third_party/libusb/src/libusb/libusb.h"
-
-namespace device {
-
-ScopedLibusbDeviceHandle::ScopedLibusbDeviceHandle(
-    libusb_device_handle* handle,
-    scoped_refptr<UsbContext> context)
-    : handle_(handle), context_(std::move(context)) {}
-
-ScopedLibusbDeviceHandle::ScopedLibusbDeviceHandle(
-    ScopedLibusbDeviceHandle&& other)
-    : handle_(other.handle_), context_(std::move(other.context_)) {
-  other.handle_ = nullptr;
-}
-
-ScopedLibusbDeviceHandle::~ScopedLibusbDeviceHandle() {
-  Reset();
-}
-
-void ScopedLibusbDeviceHandle::Reset() {
-  libusb_close(handle_);
-  handle_ = nullptr;
-  context_.reset();
-}
-
-bool ScopedLibusbDeviceHandle::IsValid() const {
-  return handle_ != nullptr;
-}
-
-}  // namespace device
diff --git a/device/usb/scoped_libusb_device_handle.h b/device/usb/scoped_libusb_device_handle.h
deleted file mode 100644
index a4eb378..0000000
--- a/device/usb/scoped_libusb_device_handle.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef DEVICE_USB_SCOPED_LIBUSB_DEVICE_HANDLE_H_
-#define DEVICE_USB_SCOPED_LIBUSB_DEVICE_HANDLE_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-
-struct libusb_device_handle;
-
-namespace device {
-
-class UsbContext;
-
-// This class owns a reference to a libusb_device_handle as well as a reference
-// to the libusb_context. The libusb_context must outlive any
-// libusb_device_handle instances created from it.
-class ScopedLibusbDeviceHandle {
- public:
-  ScopedLibusbDeviceHandle(libusb_device_handle* handle,
-                           scoped_refptr<UsbContext> context);
-  ScopedLibusbDeviceHandle(ScopedLibusbDeviceHandle&& other);
-  ~ScopedLibusbDeviceHandle();
-
-  libusb_device_handle* get() const { return handle_; }
-
-  void Reset();
-  bool IsValid() const;
-
- private:
-  libusb_device_handle* handle_;
-  scoped_refptr<UsbContext> context_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedLibusbDeviceHandle);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_USB_SCOPED_LIBUSB_DEVICE_HANDLE_H_
diff --git a/device/usb/scoped_libusb_device_ref.cc b/device/usb/scoped_libusb_device_ref.cc
deleted file mode 100644
index b3ac5e8..0000000
--- a/device/usb/scoped_libusb_device_ref.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/usb/scoped_libusb_device_ref.h"
-
-#include "device/usb/usb_context.h"
-#include "third_party/libusb/src/libusb/libusb.h"
-
-namespace device {
-
-ScopedLibusbDeviceRef::ScopedLibusbDeviceRef(libusb_device* device,
-                                             scoped_refptr<UsbContext> context)
-    : device_(device), context_(std::move(context)) {}
-
-ScopedLibusbDeviceRef::ScopedLibusbDeviceRef(ScopedLibusbDeviceRef&& other)
-    : device_(other.device_), context_(std::move(other.context_)) {
-  other.device_ = nullptr;
-}
-
-ScopedLibusbDeviceRef::~ScopedLibusbDeviceRef() {
-  Reset();
-}
-
-void ScopedLibusbDeviceRef::Reset() {
-  libusb_unref_device(device_);
-  device_ = nullptr;
-  context_.reset();
-}
-
-bool ScopedLibusbDeviceRef::IsValid() const {
-  return device_ != nullptr;
-}
-
-bool operator==(const ScopedLibusbDeviceRef& ref, libusb_device* device) {
-  return ref.get() == device;
-}
-
-}  // namespace device
diff --git a/device/usb/scoped_libusb_device_ref.h b/device/usb/scoped_libusb_device_ref.h
index 73a3731..05a21b2 100644
--- a/device/usb/scoped_libusb_device_ref.h
+++ b/device/usb/scoped_libusb_device_ref.h
@@ -5,40 +5,19 @@
 #ifndef DEVICE_USB_SCOPED_LIBUSB_DEVICE_REF_H_
 #define DEVICE_USB_SCOPED_LIBUSB_DEVICE_REF_H_
 
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-
-struct libusb_device;
+#include "base/scoped_generic.h"
+#include "third_party/libusb/src/libusb/libusb.h"
 
 namespace device {
 
-class UsbContext;
+struct LibusbDeviceRefTraits {
+  static libusb_device* InvalidValue() { return nullptr; }
 
-// This class owns a reference to a libusb_device as well as a reference to
-// the libusb_context. The libusb_context must outlive any libusb_device
-// instances created from it.
-class ScopedLibusbDeviceRef {
- public:
-  ScopedLibusbDeviceRef(libusb_device* device,
-                        scoped_refptr<UsbContext> context);
-  ScopedLibusbDeviceRef(ScopedLibusbDeviceRef&& other);
-  ~ScopedLibusbDeviceRef();
-
-  libusb_device* get() const { return device_; }
-
-  scoped_refptr<UsbContext> GetContext() const { return context_; }
-
-  void Reset();
-  bool IsValid() const;
-
- private:
-  libusb_device* device_;
-  scoped_refptr<UsbContext> context_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedLibusbDeviceRef);
+  static void Free(libusb_device* device) { libusb_unref_device(device); }
 };
 
-bool operator==(const ScopedLibusbDeviceRef& ref, libusb_device* device);
+using ScopedLibusbDeviceRef =
+    base::ScopedGeneric<libusb_device*, LibusbDeviceRefTraits>;
 
 }  // namespace device
 
diff --git a/device/usb/usb_device_handle_impl.cc b/device/usb/usb_device_handle_impl.cc
index b8c2307a..cce0691 100644
--- a/device/usb/usb_device_handle_impl.cc
+++ b/device/usb/usb_device_handle_impl.cc
@@ -311,7 +311,7 @@
   libusb_fill_control_setup(buffer->front(), type, request, value, index,
                             length);
   libusb_fill_control_transfer(transfer->platform_transfer_,
-                               device_handle->handle(), buffer->front(),
+                               device_handle->handle_, buffer->front(),
                                &UsbDeviceHandleImpl::Transfer::PlatformCallback,
                                transfer.get(), timeout);
 
@@ -341,7 +341,7 @@
   }
 
   libusb_fill_bulk_transfer(
-      transfer->platform_transfer_, device_handle->handle(), endpoint,
+      transfer->platform_transfer_, device_handle->handle_, endpoint,
       buffer->front(), length, &UsbDeviceHandleImpl::Transfer::PlatformCallback,
       transfer.get(), timeout);
 
@@ -371,7 +371,7 @@
   }
 
   libusb_fill_interrupt_transfer(
-      transfer->platform_transfer_, device_handle->handle(), endpoint,
+      transfer->platform_transfer_, device_handle->handle_, endpoint,
       buffer->front(), length, &UsbDeviceHandleImpl::Transfer::PlatformCallback,
       transfer.get(), timeout);
 
@@ -401,10 +401,10 @@
     return nullptr;
   }
 
-  libusb_fill_iso_transfer(
-      transfer->platform_transfer_, device_handle->handle(), endpoint,
-      buffer->front(), static_cast<int>(length), num_packets,
-      &Transfer::PlatformCallback, transfer.get(), timeout);
+  libusb_fill_iso_transfer(transfer->platform_transfer_, device_handle->handle_,
+                           endpoint, buffer->front(), static_cast<int>(length),
+                           num_packets, &Transfer::PlatformCallback,
+                           transfer.get(), timeout);
 
   for (size_t i = 0; i < packet_lengths.size(); ++i)
     transfer->platform_transfer_->iso_packet_desc[i].length = packet_lengths[i];
@@ -798,14 +798,16 @@
 }
 
 UsbDeviceHandleImpl::UsbDeviceHandleImpl(
+    scoped_refptr<UsbContext> context,
     scoped_refptr<UsbDeviceImpl> device,
-    ScopedLibusbDeviceHandle handle,
+    PlatformUsbDeviceHandle handle,
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
-    : device_(std::move(device)),
-      handle_(std::move(handle)),
+    : device_(device),
+      handle_(handle),
+      context_(context),
       task_runner_(base::ThreadTaskRunnerHandle::Get()),
       blocking_task_runner_(blocking_task_runner) {
-  DCHECK(handle_.IsValid()) << "Cannot create device with an invalid handle.";
+  DCHECK(handle) << "Cannot create device with NULL handle.";
 }
 
 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
@@ -815,19 +817,17 @@
   // any thread. libusb is not safe to reentrancy so be sure not to try to close
   // the device from inside a transfer completion callback.
   if (blocking_task_runner_->RunsTasksInCurrentSequence()) {
-    handle_.Reset();
+    libusb_close(handle_);
   } else {
-    blocking_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(base::DoNothing::Once<ScopedLibusbDeviceHandle>(),
-                       std::move(handle_)));
+    blocking_task_runner_->PostTask(FROM_HERE,
+                                    base::BindOnce(&libusb_close, handle_));
   }
 }
 
 void UsbDeviceHandleImpl::SetConfigurationOnBlockingThread(
     int configuration_value,
     ResultCallback callback) {
-  int rv = libusb_set_configuration(handle(), configuration_value);
+  int rv = libusb_set_configuration(handle_, configuration_value);
   if (rv != LIBUSB_SUCCESS) {
     USB_LOG(EVENT) << "Failed to set configuration " << configuration_value
                    << ": " << ConvertPlatformUsbErrorToString(rv);
@@ -855,7 +855,7 @@
 void UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread(
     int interface_number,
     ResultCallback callback) {
-  int rv = libusb_claim_interface(handle(), interface_number);
+  int rv = libusb_claim_interface(handle_, interface_number);
   scoped_refptr<InterfaceClaimer> interface_claimer;
   if (rv == LIBUSB_SUCCESS) {
     interface_claimer =
@@ -897,7 +897,7 @@
     int interface_number,
     int alternate_setting,
     ResultCallback callback) {
-  int rv = libusb_set_interface_alt_setting(handle(), interface_number,
+  int rv = libusb_set_interface_alt_setting(handle_, interface_number,
                                             alternate_setting);
   if (rv != LIBUSB_SUCCESS) {
     USB_LOG(EVENT) << "Failed to set interface " << interface_number
@@ -930,7 +930,7 @@
 }
 
 void UsbDeviceHandleImpl::ResetDeviceOnBlockingThread(ResultCallback callback) {
-  int rv = libusb_reset_device(handle());
+  int rv = libusb_reset_device(handle_);
   if (rv != LIBUSB_SUCCESS) {
     USB_LOG(EVENT) << "Failed to reset device: "
                    << ConvertPlatformUsbErrorToString(rv);
@@ -941,7 +941,7 @@
 
 void UsbDeviceHandleImpl::ClearHaltOnBlockingThread(uint8_t endpoint,
                                                     ResultCallback callback) {
-  int rv = libusb_clear_halt(handle(), endpoint);
+  int rv = libusb_clear_halt(handle_, endpoint);
   if (rv != LIBUSB_SUCCESS) {
     USB_LOG(EVENT) << "Failed to clear halt: "
                    << ConvertPlatformUsbErrorToString(rv);
diff --git a/device/usb/usb_device_handle_impl.h b/device/usb/usb_device_handle_impl.h
index 32dbe04..acf0332d 100644
--- a/device/usb/usb_device_handle_impl.h
+++ b/device/usb/usb_device_handle_impl.h
@@ -17,7 +17,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/threading/thread_checker.h"
-#include "device/usb/scoped_libusb_device_handle.h"
 #include "device/usb/usb_device_handle.h"
 #include "third_party/libusb/src/libusb/libusb.h"
 
@@ -35,8 +34,10 @@
   const UsbEndpointDescriptor* endpoint;
 };
 
+class UsbContext;
 class UsbDeviceImpl;
 
+typedef libusb_device_handle* PlatformUsbDeviceHandle;
 typedef libusb_iso_packet_descriptor* PlatformUsbIsoPacketDescriptor;
 typedef libusb_transfer* PlatformUsbTransferHandle;
 
@@ -89,13 +90,14 @@
 
   // This constructor is called by UsbDeviceImpl.
   UsbDeviceHandleImpl(
+      scoped_refptr<UsbContext> context,
       scoped_refptr<UsbDeviceImpl> device,
-      ScopedLibusbDeviceHandle handle,
+      PlatformUsbDeviceHandle handle,
       scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
 
   ~UsbDeviceHandleImpl() override;
 
-  libusb_device_handle* handle() const { return handle_.get(); }
+  PlatformUsbDeviceHandle handle() const { return handle_; }
 
  private:
   class InterfaceClaimer;
@@ -172,7 +174,7 @@
 
   scoped_refptr<UsbDeviceImpl> device_;
 
-  ScopedLibusbDeviceHandle handle_;
+  PlatformUsbDeviceHandle handle_;
 
   typedef std::map<int, scoped_refptr<InterfaceClaimer>> ClaimedInterfaceMap;
   ClaimedInterfaceMap claimed_interfaces_;
@@ -184,6 +186,10 @@
   typedef std::map<int, EndpointMapValue> EndpointMap;
   EndpointMap endpoint_map_;
 
+  // Retain the UsbContext so that the platform context will not be destroyed
+  // before this handle.
+  scoped_refptr<UsbContext> context_;
+
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
 
diff --git a/device/usb/usb_device_impl.cc b/device/usb/usb_device_impl.cc
index d6eb68d..056c6c3 100644
--- a/device/usb/usb_device_impl.cc
+++ b/device/usb/usb_device_impl.cc
@@ -28,7 +28,8 @@
 
 namespace device {
 
-UsbDeviceImpl::UsbDeviceImpl(ScopedLibusbDeviceRef platform_device,
+UsbDeviceImpl::UsbDeviceImpl(scoped_refptr<UsbContext> context,
+                             ScopedLibusbDeviceRef platform_device,
                              const libusb_device_descriptor& descriptor)
     : UsbDevice(descriptor.bcdUSB,
                 descriptor.bDeviceClass,
@@ -40,8 +41,9 @@
                 base::string16(),
                 base::string16(),
                 base::string16()),
+      context_(std::move(context)),
       platform_device_(std::move(platform_device)) {
-  CHECK(platform_device_.IsValid()) << "platform_device must be valid";
+  CHECK(platform_device_.is_valid()) << "platform_device must be valid";
   ReadAllConfigurations();
   RefreshActiveConfiguration();
 }
@@ -102,14 +104,12 @@
     scoped_refptr<base::TaskRunner> task_runner,
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
   base::AssertBlockingAllowed();
-  libusb_device_handle* handle;
+  PlatformUsbDeviceHandle handle;
   const int rv = libusb_open(platform_device(), &handle);
-  ScopedLibusbDeviceHandle scoped_handle(handle, platform_device_.GetContext());
   if (LIBUSB_SUCCESS == rv) {
     task_runner->PostTask(
-        FROM_HERE,
-        base::BindOnce(&UsbDeviceImpl::Opened, this, std::move(scoped_handle),
-                       std::move(callback), blocking_task_runner));
+        FROM_HERE, base::BindOnce(&UsbDeviceImpl::Opened, this, handle,
+                                  std::move(callback), blocking_task_runner));
   } else {
     USB_LOG(EVENT) << "Failed to open device: "
                    << ConvertPlatformUsbErrorToString(rv);
@@ -119,12 +119,12 @@
 }
 
 void UsbDeviceImpl::Opened(
-    ScopedLibusbDeviceHandle platform_handle,
+    PlatformUsbDeviceHandle platform_handle,
     OpenCallback callback,
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
   DCHECK(thread_checker_.CalledOnValidThread());
   scoped_refptr<UsbDeviceHandle> device_handle = new UsbDeviceHandleImpl(
-      this, std::move(platform_handle), blocking_task_runner);
+      context_, this, platform_handle, blocking_task_runner);
   handles().push_back(device_handle.get());
   std::move(callback).Run(device_handle);
 }
diff --git a/device/usb/usb_device_impl.h b/device/usb/usb_device_impl.h
index 9e3d2c7..16ab891 100644
--- a/device/usb/usb_device_impl.h
+++ b/device/usb/usb_device_impl.h
@@ -21,7 +21,9 @@
 #include "device/usb/usb_descriptors.h"
 #include "device/usb/usb_device.h"
 
+struct libusb_device;
 struct libusb_device_descriptor;
+struct libusb_device_handle;
 
 namespace base {
 class SequencedTaskRunner;
@@ -29,12 +31,15 @@
 
 namespace device {
 
-class ScopedLibusbDeviceHandle;
 class UsbDeviceHandleImpl;
+class UsbContext;
+
+typedef struct libusb_device_handle* PlatformUsbDeviceHandle;
 
 class UsbDeviceImpl : public UsbDevice {
  public:
-  UsbDeviceImpl(ScopedLibusbDeviceRef platform_device,
+  UsbDeviceImpl(scoped_refptr<UsbContext> context,
+                ScopedLibusbDeviceRef platform_device,
                 const libusb_device_descriptor& descriptor);
 
   // UsbDevice implementation:
@@ -74,13 +79,15 @@
       OpenCallback callback,
       scoped_refptr<base::TaskRunner> task_runner,
       scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
-  void Opened(ScopedLibusbDeviceHandle platform_handle,
+  void Opened(PlatformUsbDeviceHandle platform_handle,
               OpenCallback callback,
               scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
 
   base::ThreadChecker thread_checker_;
   bool visited_ = false;
 
+  // The libusb_context must not be released before the libusb_device.
+  const scoped_refptr<UsbContext> context_;
   const ScopedLibusbDeviceRef platform_device_;
 
   DISALLOW_COPY_AND_ASSIGN(UsbDeviceImpl);
diff --git a/device/usb/usb_service_impl.cc b/device/usb/usb_service_impl.cc
index 626ece05..83e14c6f0 100644
--- a/device/usb/usb_service_impl.cc
+++ b/device/usb/usb_service_impl.cc
@@ -131,7 +131,7 @@
   std::vector<ScopedLibusbDeviceRef> scoped_devices;
   scoped_devices.reserve(device_count);
   for (ssize_t i = 0; i < device_count; ++i)
-    scoped_devices.emplace_back(platform_devices[i], usb_context);
+    scoped_devices.emplace_back(platform_devices[i]);
 
   // Free the list but don't unref the devices because ownership has been
   // been transfered to the elements of |scoped_devices|.
@@ -231,7 +231,6 @@
       device_observer_(this),
 #endif
       weak_factory_(this) {
-  weak_self_ = weak_factory_.GetWeakPtr();
   base::PostTaskWithTraits(
       FROM_HERE, kBlockingTaskTraits,
       base::Bind(&InitializeUsbContextOnBlockingThread, task_runner(),
@@ -362,7 +361,7 @@
       // Mark the existing device object visited and remove it from the list so
       // it will not be ignored.
       it->second->set_visited(true);
-      device.Reset();
+      device.reset();
     }
   }
 
@@ -383,7 +382,7 @@
   // that have been removed don't remain in |ignored_devices_| indefinitely.
   ignored_devices_.clear();
   for (auto& device : *devices) {
-    if (device.IsValid())
+    if (device.is_valid())
       ignored_devices_.push_back(std::move(device));
   }
 
@@ -442,8 +441,8 @@
 
   devices_being_enumerated_.insert(platform_device.get());
 
-  auto device = base::MakeRefCounted<UsbDeviceImpl>(std::move(platform_device),
-                                                    descriptor);
+  auto device = base::MakeRefCounted<UsbDeviceImpl>(
+      context_, std::move(platform_device), descriptor);
   base::OnceClosure add_device =
       base::BindOnce(&UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(),
                      refresh_complete, device);
@@ -459,8 +458,7 @@
     libusb_ref_device(device->platform_device());
     base::OnceClosure enumeration_failed = base::BindOnce(
         &UsbServiceImpl::EnumerationFailed, weak_factory_.GetWeakPtr(),
-        ScopedLibusbDeviceRef(device->platform_device(), context_),
-        refresh_complete);
+        ScopedLibusbDeviceRef(device->platform_device()), refresh_complete);
 
     device->Open(base::BindOnce(
         &OnDeviceOpenedReadDescriptors, descriptor.iManufacturer,
@@ -520,18 +518,18 @@
   // libusb does not transfer ownership of |device_raw| to this function so a
   // reference must be taken here.
   libusb_ref_device(device_raw);
-  ScopedLibusbDeviceRef device(device_raw, self->context_);
+  ScopedLibusbDeviceRef device(device_raw);
 
   switch (event) {
     case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
       self->task_runner()->PostTask(
           FROM_HERE, base::BindOnce(&UsbServiceImpl::OnPlatformDeviceAdded,
-                                    self->weak_self_, std::move(device)));
+                                    base::Unretained(self), std::move(device)));
       break;
     case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
       self->task_runner()->PostTask(
           FROM_HERE, base::BindOnce(&UsbServiceImpl::OnPlatformDeviceRemoved,
-                                    self->weak_self_, std::move(device)));
+                                    base::Unretained(self), std::move(device)));
       break;
     default:
       NOTREACHED();
diff --git a/device/usb/usb_service_impl.h b/device/usb/usb_service_impl.h
index 36f7115..e7e89d0 100644
--- a/device/usb/usb_service_impl.h
+++ b/device/usb/usb_service_impl.h
@@ -122,10 +122,6 @@
   ScopedObserver<DeviceMonitorWin, DeviceMonitorWin::Observer> device_observer_;
 #endif  // OS_WIN
 
-  // This WeakPtr is used to safely post hotplug events back to the thread this
-  // object lives on.
-  base::WeakPtr<UsbServiceImpl> weak_self_;
-
   base::WeakPtrFactory<UsbServiceImpl> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(UsbServiceImpl);
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index f0a7cb1..9a11ad0d 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -160,8 +160,6 @@
       "test/fake_vr_display_impl_client.h",
       "test/fake_vr_service_client.cc",
       "test/fake_vr_service_client.h",
-      "test/mock_vr_display_impl.cc",
-      "test/mock_vr_display_impl.h",
       "vr_export.h",
     ]
 
diff --git a/device/vr/android/gvr/gvr_device.cc b/device/vr/android/gvr/gvr_device.cc
index 20166c65..9d4c9b17 100644
--- a/device/vr/android/gvr/gvr_device.cc
+++ b/device/vr/android/gvr/gvr_device.cc
@@ -179,32 +179,31 @@
 void GvrDevice::RequestSession(
     mojom::XRDeviceRuntimeSessionOptionsPtr options,
     mojom::XRRuntime::RequestSessionCallback callback) {
+  if (!options->immersive) {
+    // TODO(https://crbug.com/695937): This should be NOTREACHED() once we no
+    // longer need the hacked GRV non-immersive mode.
+    ReturnNonImmersiveSession(std::move(callback));
+    return;
+  }
+
   GvrDelegateProvider* delegate_provider = GetGvrDelegateProvider();
   if (!delegate_provider) {
     std::move(callback).Run(nullptr, nullptr);
     return;
   }
 
-  if (options->immersive) {
-    // StartWebXRPresentation is async as we may trigger a DON (Device ON) flow
-    // that pauses Chrome.
-    delegate_provider->StartWebXRPresentation(
-        GetVRDisplayInfo(), std::move(options),
-        base::BindOnce(&GvrDevice::OnStartPresentResult,
-                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
-  } else {
-    // TODO(https://crbug.com/695937): This should be NOTREACHED() once
-    // orientation device handles non-immersive VR sessions.
-    // TODO(https://crbug.com/842025): Handle this when RequestSession is called
-    // for non-immersive sessions.
-    NOTREACHED();
-  }
+  // StartWebXRPresentation is async as we may trigger a DON (Device ON) flow
+  // that pauses Chrome.
+  delegate_provider->StartWebXRPresentation(
+      GetVRDisplayInfo(), std::move(options),
+      base::BindOnce(&GvrDevice::OnStartPresentResult,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void GvrDevice::OnStartPresentResult(
     mojom::XRRuntime::RequestSessionCallback callback,
     mojom::XRSessionPtr session) {
-  if (!session || !session->connection) {
+  if (!session) {
     std::move(callback).Run(nullptr, nullptr);
     return;
   }
@@ -223,8 +222,7 @@
       base::BindOnce(&GvrDevice::OnPresentingControllerMojoConnectionError,
                      base::Unretained(this)));
 
-  std::move(callback).Run(std::move(session->connection),
-                          std::move(session_controller));
+  std::move(callback).Run(std::move(session), std::move(session_controller));
 }
 
 // XRSessionController
@@ -246,7 +244,7 @@
 }
 
 void GvrDevice::OnMagicWindowFrameDataRequest(
-    mojom::VRMagicWindowProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   mojom::XRFrameDataPtr frame_data = mojom::XRFrameData::New();
   frame_data->pose =
       GvrDelegate::GetVRPosePtrWithNeckModel(gvr_api_.get(), nullptr);
diff --git a/device/vr/android/gvr/gvr_device.h b/device/vr/android/gvr/gvr_device.h
index 6061fcbe..e401efc0 100644
--- a/device/vr/android/gvr/gvr_device.h
+++ b/device/vr/android/gvr/gvr_device.h
@@ -42,7 +42,7 @@
   // VRDeviceBase
   void OnListeningForActivate(bool listening) override;
   void OnMagicWindowFrameDataRequest(
-      mojom::VRMagicWindowProvider::GetFrameDataCallback callback) override;
+      mojom::XRFrameDataProvider::GetFrameDataCallback callback) override;
 
   void OnStartPresentResult(mojom::XRRuntime::RequestSessionCallback callback,
                             mojom::XRSessionPtr session);
diff --git a/device/vr/oculus/oculus_device.cc b/device/vr/oculus/oculus_device.cc
index 51b2627..eeb68ee 100644
--- a/device/vr/oculus/oculus_device.cc
+++ b/device/vr/oculus/oculus_device.cc
@@ -113,6 +113,11 @@
 void OculusDevice::RequestSession(
     mojom::XRDeviceRuntimeSessionOptionsPtr options,
     mojom::XRRuntime::RequestSessionCallback callback) {
+  if (!options->immersive) {
+    ReturnNonImmersiveSession(std::move(callback));
+    return;
+  }
+
   StopOvrSession();
 
   if (!render_loop_->IsRunning())
@@ -137,9 +142,7 @@
 void OculusDevice::OnRequestSessionResult(
     mojom::XRRuntime::RequestSessionCallback callback,
     bool result,
-    mojom::VRSubmitFrameClientRequest request,
-    mojom::VRPresentationProviderPtrInfo provider_info,
-    mojom::VRDisplayFrameTransportOptionsPtr transport_options) {
+    mojom::XRSessionPtr session) {
   if (!result) {
     std::move(callback).Run(nullptr, nullptr);
 
@@ -150,11 +153,6 @@
 
   OnStartPresenting();
 
-  auto connection = mojom::XRPresentationConnection::New();
-  connection->client_request = std::move(request);
-  connection->provider = std::move(provider_info);
-  connection->transport_options = std::move(transport_options);
-
   mojom::XRSessionControllerPtr session_controller;
   exclusive_controller_binding_.Bind(mojo::MakeRequest(&session_controller));
 
@@ -164,7 +162,7 @@
       base::BindOnce(&OculusDevice::OnPresentingControllerMojoConnectionError,
                      base::Unretained(this)));
 
-  std::move(callback).Run(std::move(connection), std::move(session_controller));
+  std::move(callback).Run(std::move(session), std::move(session_controller));
 
   if (!oculus_gamepad_factory_) {
     oculus_gamepad_factory_ =
@@ -227,7 +225,7 @@
 }
 
 void OculusDevice::OnMagicWindowFrameDataRequest(
-    mojom::VRMagicWindowProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   if (!session_) {
     std::move(callback).Run(nullptr);
     return;
diff --git a/device/vr/oculus/oculus_device.h b/device/vr/oculus/oculus_device.h
index cff84ccd..9002ac33 100644
--- a/device/vr/oculus/oculus_device.h
+++ b/device/vr/oculus/oculus_device.h
@@ -31,13 +31,10 @@
       mojom::XRDeviceRuntimeSessionOptionsPtr options,
       mojom::XRRuntime::RequestSessionCallback callback) override;
   void OnMagicWindowFrameDataRequest(
-      mojom::VRMagicWindowProvider::GetFrameDataCallback callback) override;
-  void OnRequestSessionResult(
-      mojom::XRRuntime::RequestSessionCallback callback,
-      bool result,
-      mojom::VRSubmitFrameClientRequest request,
-      mojom::VRPresentationProviderPtrInfo provider_info,
-      mojom::VRDisplayFrameTransportOptionsPtr transport_options);
+      mojom::XRFrameDataProvider::GetFrameDataCallback callback) override;
+  void OnRequestSessionResult(mojom::XRRuntime::RequestSessionCallback callback,
+                              bool result,
+                              mojom::XRSessionPtr session);
 
   bool IsInitialized() { return !!session_; }
 
diff --git a/device/vr/oculus/oculus_render_loop.cc b/device/vr/oculus/oculus_render_loop.cc
index 80a37b6e..f914b14 100644
--- a/device/vr/oculus/oculus_render_loop.cc
+++ b/device/vr/oculus/oculus_render_loop.cc
@@ -48,7 +48,8 @@
         on_controller_updated)
     : base::Thread("OculusRenderLoop"),
       main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      binding_(this),
+      presentation_binding_(this),
+      frame_data_binding_(this),
       on_presentation_ended_(on_presentation_ended),
       on_controller_updated_(on_controller_updated),
       weak_ptr_factory_(this) {
@@ -69,7 +70,8 @@
 void OculusRenderLoop::CleanUp() {
   submit_client_ = nullptr;
   StopOvrSession();
-  binding_.Close();
+  presentation_binding_.Close();
+  frame_data_binding_.Close();
 }
 
 void OculusRenderLoop::SubmitFrameMissing(int16_t frame_index,
@@ -241,28 +243,36 @@
 #endif
           ) {
     main_thread_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(std::move(callback), false, nullptr, nullptr, nullptr));
+        FROM_HERE, base::BindOnce(std::move(callback), false, nullptr));
     return;
   }
 
-  binding_.Close();
-  device::mojom::VRPresentationProviderPtr provider;
-  binding_.Bind(mojo::MakeRequest(&provider));
+  presentation_binding_.Close();
+  frame_data_binding_.Close();
+  device::mojom::XRPresentationProviderPtr presentation_provider;
+  device::mojom::XRFrameDataProviderPtr frame_data_provider;
+  presentation_binding_.Bind(mojo::MakeRequest(&presentation_provider));
+  frame_data_binding_.Bind(mojo::MakeRequest(&frame_data_provider));
 
-  device::mojom::VRDisplayFrameTransportOptionsPtr transport_options =
-      device::mojom::VRDisplayFrameTransportOptions::New();
+  device::mojom::XRPresentationTransportOptionsPtr transport_options =
+      device::mojom::XRPresentationTransportOptions::New();
   transport_options->transport_method =
-      device::mojom::VRDisplayFrameTransportMethod::SUBMIT_AS_TEXTURE_HANDLE;
+      device::mojom::XRPresentationTransportMethod::SUBMIT_AS_TEXTURE_HANDLE;
   // Only set boolean options that we need. Default is false, and we should be
   // able to safely ignore ones that our implementation doesn't care about.
   transport_options->wait_for_transfer_notification = true;
 
+  auto submit_frame_sink = device::mojom::XRPresentationConnection::New();
+  submit_frame_sink->provider = presentation_provider.PassInterface();
+  submit_frame_sink->client_request = mojo::MakeRequest(&submit_client_);
+  submit_frame_sink->transport_options = std::move(transport_options);
+
+  auto session = device::mojom::XRSession::New();
+  session->data_provider = frame_data_provider.PassInterface();
+  session->submit_frame_sink = std::move(submit_frame_sink);
+
   main_thread_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(std::move(callback), true,
-                     mojo::MakeRequest(&submit_client_),
-                     provider.PassInterface(), std::move(transport_options)));
+      FROM_HERE, base::BindOnce(std::move(callback), true, std::move(session)));
   is_presenting_ = true;
 }
 
@@ -296,7 +306,8 @@
 
 void OculusRenderLoop::ExitPresent() {
   is_presenting_ = false;
-  binding_.Close();
+  presentation_binding_.Close();
+  frame_data_binding_.Close();
   submit_client_ = nullptr;
   ClearPendingFrame();
 
@@ -312,7 +323,7 @@
 }
 
 void OculusRenderLoop::GetFrameData(
-    mojom::VRPresentationProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   DCHECK(is_presenting_);
 
   if (has_outstanding_frame_) {
diff --git a/device/vr/oculus/oculus_render_loop.h b/device/vr/oculus/oculus_render_loop.h
index c8186b7..26cfdd5 100644
--- a/device/vr/oculus/oculus_render_loop.h
+++ b/device/vr/oculus/oculus_render_loop.h
@@ -23,13 +23,12 @@
 
 const int kMaxOculusRenderLoopInputId = (ovrControllerType_Remote + 1);
 
-class OculusRenderLoop : public base::Thread, mojom::VRPresentationProvider {
+class OculusRenderLoop : public base::Thread,
+                         mojom::XRPresentationProvider,
+                         mojom::XRFrameDataProvider {
  public:
   using RequestSessionCallback =
-      base::OnceCallback<void(bool result,
-                              mojom::VRSubmitFrameClientRequest,
-                              mojom::VRPresentationProviderPtrInfo,
-                              mojom::VRDisplayFrameTransportOptionsPtr)>;
+      base::OnceCallback<void(bool result, mojom::XRSessionPtr)>;
 
   OculusRenderLoop(
       base::RepeatingCallback<void()> on_presentation_ended,
@@ -43,7 +42,7 @@
   void ExitPresent();
   base::WeakPtr<OculusRenderLoop> GetWeakPtr();
 
-  // VRPresentationProvider overrides:
+  // XRPresentationProvider overrides:
   void SubmitFrameMissing(int16_t frame_index, const gpu::SyncToken&) override;
   void SubmitFrame(int16_t frame_index,
                    const gpu::MailboxHolder& mailbox,
@@ -58,7 +57,7 @@
                          const gfx::RectF& right_bounds,
                          const gfx::Size& source_size) override;
   void GetFrameData(
-      mojom::VRPresentationProvider::GetFrameDataCallback callback) override;
+      mojom::XRFrameDataProvider::GetFrameDataCallback callback) override;
 
  private:
   // base::Thread overrides:
@@ -98,13 +97,14 @@
   gfx::RectF right_bounds_;
   gfx::Size source_size_;
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-  mojom::VRSubmitFrameClientPtr submit_client_;
+  mojom::XRPresentationClientPtr submit_client_;
   ovrSession session_ = nullptr;
   ovrGraphicsLuid luid_ = {};
   ovrPosef last_render_pose_;
   ovrTextureSwapChain texture_swap_chain_ = 0;
   double sensor_time_;
-  mojo::Binding<mojom::VRPresentationProvider> binding_;
+  mojo::Binding<mojom::XRPresentationProvider> presentation_binding_;
+  mojo::Binding<mojom::XRFrameDataProvider> frame_data_binding_;
   bool primary_input_pressed[kMaxOculusRenderLoopInputId];
   base::RepeatingCallback<void()> on_presentation_ended_;
   base::RepeatingCallback<
diff --git a/device/vr/openvr/openvr_device.cc b/device/vr/openvr/openvr_device.cc
index 09ab3ef..e3d4aa2 100644
--- a/device/vr/openvr/openvr_device.cc
+++ b/device/vr/openvr/openvr_device.cc
@@ -173,6 +173,11 @@
 void OpenVRDevice::RequestSession(
     mojom::XRDeviceRuntimeSessionOptionsPtr options,
     mojom::XRRuntime::RequestSessionCallback callback) {
+  if (!options->immersive) {
+    ReturnNonImmersiveSession(std::move(callback));
+    return;
+  }
+
   if (!render_loop_->IsRunning())
     render_loop_->Start();
 
@@ -211,9 +216,7 @@
 void OpenVRDevice::OnRequestSessionResult(
     mojom::XRRuntime::RequestSessionCallback callback,
     bool result,
-    mojom::VRSubmitFrameClientRequest request,
-    mojom::VRPresentationProviderPtrInfo provider_info,
-    mojom::VRDisplayFrameTransportOptionsPtr transport_options) {
+    mojom::XRSessionPtr session) {
   if (!result) {
     OnPresentationEnded();
     std::move(callback).Run(nullptr, nullptr);
@@ -222,11 +225,6 @@
 
   OnStartPresenting();
 
-  auto connection = mojom::XRPresentationConnection::New();
-  connection->client_request = std::move(request);
-  connection->provider = std::move(provider_info);
-  connection->transport_options = std::move(transport_options);
-
   mojom::XRSessionControllerPtr session_controller;
   exclusive_controller_binding_.Bind(mojo::MakeRequest(&session_controller));
 
@@ -236,7 +234,7 @@
       base::BindOnce(&OpenVRDevice::OnPresentingControllerMojoConnectionError,
                      base::Unretained(this)));
 
-  std::move(callback).Run(std::move(connection), std::move(session_controller));
+  std::move(callback).Run(std::move(session), std::move(session_controller));
 }
 
 // XRSessionController
@@ -255,7 +253,7 @@
 }
 
 void OpenVRDevice::OnMagicWindowFrameDataRequest(
-    mojom::VRPresentationProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   if (!openvr_) {
     std::move(callback).Run(nullptr);
     return;
diff --git a/device/vr/openvr/openvr_device.h b/device/vr/openvr/openvr_device.h
index c5af92f..95f4794 100644
--- a/device/vr/openvr/openvr_device.h
+++ b/device/vr/openvr/openvr_device.h
@@ -36,19 +36,16 @@
 
   void OnPollingEvents();
 
-  void OnRequestSessionResult(
-      mojom::XRRuntime::RequestSessionCallback callback,
-      bool result,
-      mojom::VRSubmitFrameClientRequest request,
-      mojom::VRPresentationProviderPtrInfo provider_info,
-      mojom::VRDisplayFrameTransportOptionsPtr transport_options);
+  void OnRequestSessionResult(mojom::XRRuntime::RequestSessionCallback callback,
+                              bool result,
+                              mojom::XRSessionPtr session);
 
   bool IsInitialized() { return !!openvr_; }
 
  private:
   // VRDeviceBase
   void OnMagicWindowFrameDataRequest(
-      mojom::VRMagicWindowProvider::GetFrameDataCallback callback) override;
+      mojom::XRFrameDataProvider::GetFrameDataCallback callback) override;
 
   // XRSessionController
   void SetFrameDataRestricted(bool restricted) override;
diff --git a/device/vr/openvr/openvr_render_loop.cc b/device/vr/openvr/openvr_render_loop.cc
index fa37e4d..ce598d1 100644
--- a/device/vr/openvr/openvr_render_loop.cc
+++ b/device/vr/openvr/openvr_render_loop.cc
@@ -50,7 +50,8 @@
     : base::Thread("OpenVRRenderLoop"),
       main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       update_gamepad_(std::move(update_gamepad)),
-      binding_(this),
+      presentation_binding_(this),
+      frame_data_binding_(this),
       weak_ptr_factory_(this) {
   DCHECK(main_thread_task_runner_);
 }
@@ -148,7 +149,8 @@
 
 void OpenVRRenderLoop::CleanUp() {
   submit_client_ = nullptr;
-  binding_.Close();
+  presentation_binding_.Close();
+  frame_data_binding_.Close();
 }
 
 void OpenVRRenderLoop::UpdateLayerBounds(int16_t frame_id,
@@ -169,15 +171,15 @@
     mojom::XRDeviceRuntimeSessionOptionsPtr options,
     RequestSessionCallback callback) {
   DCHECK(options->immersive);
-  binding_.Close();
+  presentation_binding_.Close();
+  frame_data_binding_.Close();
 
   if (!openvr_) {
     openvr_ = std::make_unique<OpenVRWrapper>(true);
     if (!openvr_->IsInitialized()) {
       openvr_ = nullptr;
       main_thread_task_runner_->PostTask(
-          FROM_HERE, base::BindOnce(std::move(callback), false, nullptr,
-                                    nullptr, nullptr));
+          FROM_HERE, base::BindOnce(std::move(callback), false, nullptr));
       return;
     }
 
@@ -193,20 +195,22 @@
       !texture_helper_.EnsureInitialized()) {
     openvr_ = nullptr;
     main_thread_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(std::move(callback), false, nullptr, nullptr, nullptr));
+        FROM_HERE, base::BindOnce(std::move(callback), false, nullptr));
     return;
   }
 #endif
   DCHECK(!on_presentation_ended_);
   on_presentation_ended_ = std::move(on_presentation_ended);
-  device::mojom::VRPresentationProviderPtr provider;
-  binding_.Bind(mojo::MakeRequest(&provider));
 
-  device::mojom::VRDisplayFrameTransportOptionsPtr transport_options =
-      device::mojom::VRDisplayFrameTransportOptions::New();
+  device::mojom::XRPresentationProviderPtr presentation_provider;
+  device::mojom::XRFrameDataProviderPtr frame_data_provider;
+  presentation_binding_.Bind(mojo::MakeRequest(&presentation_provider));
+  frame_data_binding_.Bind(mojo::MakeRequest(&frame_data_provider));
+
+  device::mojom::XRPresentationTransportOptionsPtr transport_options =
+      device::mojom::XRPresentationTransportOptions::New();
   transport_options->transport_method =
-      device::mojom::VRDisplayFrameTransportMethod::SUBMIT_AS_TEXTURE_HANDLE;
+      device::mojom::XRPresentationTransportMethod::SUBMIT_AS_TEXTURE_HANDLE;
   // Only set boolean options that we need. Default is false, and we should be
   // able to safely ignore ones that our implementation doesn't care about.
   transport_options->wait_for_transfer_notification = true;
@@ -220,11 +224,17 @@
     input_active_state.controller_role = vr::TrackedControllerRole_Invalid;
   }
 
+  auto submit_frame_sink = device::mojom::XRPresentationConnection::New();
+  submit_frame_sink->provider = presentation_provider.PassInterface();
+  submit_frame_sink->client_request = mojo::MakeRequest(&submit_client_);
+  submit_frame_sink->transport_options = std::move(transport_options);
+
+  auto session = device::mojom::XRSession::New();
+  session->data_provider = frame_data_provider.PassInterface();
+  session->submit_frame_sink = std::move(submit_frame_sink);
+
   main_thread_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(std::move(callback), true,
-                     mojo::MakeRequest(&submit_client_),
-                     provider.PassInterface(), std::move(transport_options)));
+      FROM_HERE, base::BindOnce(std::move(callback), true, std::move(session)));
   is_presenting_ = true;
   openvr_->GetCompositor()->SuspendRendering(false);
 
@@ -247,7 +257,8 @@
 
 void OpenVRRenderLoop::ExitPresent() {
   is_presenting_ = false;
-  binding_.Close();
+  presentation_binding_.Close();
+  frame_data_binding_.Close();
   submit_client_ = nullptr;
   if (openvr_)
     openvr_->GetCompositor()->SuspendRendering(true);
@@ -325,7 +336,7 @@
 }
 
 void OpenVRRenderLoop::GetFrameData(
-    mojom::VRPresentationProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   DCHECK(is_presenting_);
 
   if (has_outstanding_frame_) {
diff --git a/device/vr/openvr/openvr_render_loop.h b/device/vr/openvr/openvr_render_loop.h
index df7fdc3..a27f7f4 100644
--- a/device/vr/openvr/openvr_render_loop.h
+++ b/device/vr/openvr/openvr_render_loop.h
@@ -25,13 +25,12 @@
 class OpenVRWrapper;
 struct OpenVRGamepadState;
 
-class OpenVRRenderLoop : public base::Thread, mojom::VRPresentationProvider {
+class OpenVRRenderLoop : public base::Thread,
+                         mojom::XRPresentationProvider,
+                         mojom::XRFrameDataProvider {
  public:
   using RequestSessionCallback =
-      base::OnceCallback<void(bool result,
-                              mojom::VRSubmitFrameClientRequest,
-                              mojom::VRPresentationProviderPtrInfo,
-                              mojom::VRDisplayFrameTransportOptionsPtr)>;
+      base::OnceCallback<void(bool result, mojom::XRSessionPtr)>;
 
   OpenVRRenderLoop(
       base::RepeatingCallback<void(OpenVRGamepadState)> update_gamepad);
@@ -43,7 +42,7 @@
   void ExitPresent();
   base::WeakPtr<OpenVRRenderLoop> GetWeakPtr();
 
-  // VRPresentationProvider overrides:
+  // XRPresentationProvider overrides:
   void SubmitFrameMissing(int16_t frame_index, const gpu::SyncToken&) override;
   void SubmitFrame(int16_t frame_index,
                    const gpu::MailboxHolder& mailbox,
@@ -58,7 +57,7 @@
                          const gfx::RectF& right_bounds,
                          const gfx::Size& source_size) override;
   void GetFrameData(
-      VRPresentationProvider::GetFrameDataCallback callback) override;
+      XRFrameDataProvider::GetFrameDataCallback callback) override;
 
  private:
   // base::Thread overrides:
@@ -94,11 +93,12 @@
   gfx::RectF right_bounds_;
   gfx::Size source_size_;
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-  mojom::VRSubmitFrameClientPtr submit_client_;
+  mojom::XRPresentationClientPtr submit_client_;
   base::RepeatingCallback<void(OpenVRGamepadState)> update_gamepad_;
   base::OnceCallback<void()> on_presentation_ended_;
   std::unique_ptr<OpenVRWrapper> openvr_;
-  mojo::Binding<mojom::VRPresentationProvider> binding_;
+  mojo::Binding<mojom::XRPresentationProvider> presentation_binding_;
+  mojo::Binding<mojom::XRFrameDataProvider> frame_data_binding_;
   base::WeakPtrFactory<OpenVRRenderLoop> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(OpenVRRenderLoop);
diff --git a/device/vr/orientation/orientation_device.cc b/device/vr/orientation/orientation_device.cc
index ee322dd..2de5b21 100644
--- a/device/vr/orientation/orientation_device.cc
+++ b/device/vr/orientation/orientation_device.cc
@@ -144,11 +144,11 @@
   DCHECK(!options->immersive);
   // TODO(offenwanger): Perform a check to see if sensors are available when
   // RequestSession is called for non-immersive sessions.
-  std::move(callback).Run(nullptr, nullptr);
+  ReturnNonImmersiveSession(std::move(callback));
 }
 
 void VROrientationDevice::OnMagicWindowFrameDataRequest(
-    mojom::VRMagicWindowProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   mojom::VRPosePtr pose = mojom::VRPose::New();
   pose->orientation.emplace(4);
 
diff --git a/device/vr/orientation/orientation_device.h b/device/vr/orientation/orientation_device.h
index f9f3b19..0ac5337 100644
--- a/device/vr/orientation/orientation_device.h
+++ b/device/vr/orientation/orientation_device.h
@@ -49,7 +49,7 @@
 
   // VRDeviceBase
   void OnMagicWindowFrameDataRequest(
-      mojom::VRMagicWindowProvider::GetFrameDataCallback callback) override;
+      mojom::XRFrameDataProvider::GetFrameDataCallback callback) override;
 
   // Indicates whether the device was able to connect to orientation events.
   bool IsAvailable() const { return available_; }
diff --git a/device/vr/public/mojom/README.md b/device/vr/public/mojom/README.md
index 273b0d5e..dab1c92 100644
--- a/device/vr/public/mojom/README.md
+++ b/device/vr/public/mojom/README.md
@@ -6,6 +6,24 @@
 the browser process.  The ones that cannot live in the browser, are hosted in a
 service.
 
+# Supported Session types
+
+## Magic-window:
+Magic window sessions are requested by sites that request poses, but render
+through the normal Chrome compositor pipeline.
+It serves as a basic mode that requires only some way to get orientation poses.
+
+## Immersive:
+Immersive sessions are where the site wishes to request poses, then render
+content back to a display other than chrome. The common case for this is Head
+Mounted Displays (HMD), like Vive, Oculus, or Daydream.
+
+## Enviroment Integration
+This type of session allows for enviroment integration by providing functions
+that allow the site to query the enviroment, such as HitTest. A Enviroment
+Integration session may also supply data in addition to the pose, such as a
+camera frame.
+
 # Renderer <-> Browser interfaces (defined in vr_service.mojom)
 VRService - lives in the browser process, corresponds to a single frame.  Root
 object to obtain other XR objects.
@@ -24,23 +42,23 @@
 process.  They may live in the browser process or may live in the isolated
 service.
 
-## Presentation-related:
-Presentation is exclusive access to a headset where a site may display
-a stereo view to the user.
 
-VRPresentationProvider - lives in the XRDevice process.  Implements the details
+## Data related:
+All sessions need to be able to get data from a XR device.
+
+XRFrameDataProvider - lives in the XRDevice process.  Provides a way to obtain
+poses and other forms of data needed to render frames.
+
+## Presentation related:
+Presentation is exclusive access to a device, where the experience takes over
+the device's display, such as presenting a stereo view in an HMD.
+
+XRPresentationProvider - lives in the XRDevice process.  Implements the details
 for a presentation session, such as submitting frames to the underlying VR API.
 
-VRSubmitFrameClient - lives in the renderer process.  Is notified when various
+XRPresentationClient - lives in the renderer process.  Is notified when various
 rendering events occur, so it can reclaim/reuse textures.
 
-## Magic-window related:
-Magic window is a mode where a site may request poses, but renders through the
-normal Chrome compositor pipeline.
-
-VRMagicWindowProvider - lives in the XRDevice process.  Provides a way to obtain
-poses.
-
 # Browser <-> Device interfaces (defined in isolated_xr_service.mojom)
 The XRDevice process may be the browser process or an isolated service for
 different devices implementations.  A device provider in the browser will choose
diff --git a/device/vr/public/mojom/isolated_xr_service.mojom b/device/vr/public/mojom/isolated_xr_service.mojom
index a1bcacda..83320de 100644
--- a/device/vr/public/mojom/isolated_xr_service.mojom
+++ b/device/vr/public/mojom/isolated_xr_service.mojom
@@ -6,10 +6,10 @@
 
 import "device/vr/public/mojom/vr_service.mojom";
 
-// The XRSessionController lives in the vr device service, and corresponds to a
-// VRPresentationProvider or a VRMagicWindowProvider.  The client is the browser
-// process, which will pause or stop sessions depending events/state such as
-// focus or other tabs requesting presentation.
+// The XRSessionController lives in the vr device service, and corresponds to
+// a set of the XRSession bindings.  The client is the browser process, which
+// will pause or stop sessions depending events/state such as focus or other
+// tabs requesting immersive sessions.
 // Sessions are stopped by closing the mojo connection.
 interface XRSessionController {
   // A session may be paused temporarily for example when a non-presenting
@@ -58,22 +58,14 @@
 // browser process is the client, and may in turn expose device information to
 // render processes using vr_service interfaces, such as VRDisplayHost.
 interface XRRuntime {
-  // Attempt to start a presentation session.  Clients may submit graphics to be
-  // displayed in the headset.  Called by the browser process, but the
-  // VRPresentationProvider may be passed to the renderer process to allow
-  // submitting graphics without going through an extra IPC hop through the
-  // browser process.
+  // Attempt to start a session. Called by the browser process, but the result
+  // will probably be passed to the renderer process to allow getting data and
+  // possibly submitting graphics without going through an extra IPC hop through
+  // the browser process.
   RequestSession(XRDeviceRuntimeSessionOptions options) => (
-                     device.mojom.XRPresentationConnection? connection,
+                     XRSession? session,
                      XRSessionController? controller);
 
-  // Attempt to start a "magic window" session.  Magic window sessions allow
-  // Clients to obtain poses (device position and orientation), but rendering
-  // goes through the standard Chrome compositor.
-  RequestMagicWindowSession() =>
-      (device.mojom.VRMagicWindowProvider? session,
-       device.mojom.XRSessionController? controller);
-
   // The browser may register for changes to a device. Initial VRDisplayInfo
   // will immediately be returned to the listener to prevent races.
   ListenToDeviceChanges(XRRuntimeEventListener listener) =>
diff --git a/device/vr/public/mojom/vr_service.mojom b/device/vr/public/mojom/vr_service.mojom
index 108c4291..a00fd3c 100644
--- a/device/vr/public/mojom/vr_service.mojom
+++ b/device/vr/public/mojom/vr_service.mojom
@@ -41,17 +41,25 @@
   bool use_legacy_webvr_render_path;
 };
 
-// TODO(offenwanger) Rearrange these two interfaces to merge duplicate
-// functionality.
+// This structure contains all the mojo interfaces for different kinds of
+// XRSession. The only interface required by all sessions is the
+// XRFrameDataProvider. It must always be present. Other interfaces are set as
+// apropriate based on the session creation options. (for example, an immersive
+// session ought to have a XRPresentationConnection to submit the frames to the
+// immersive enviroment).
 struct XRSession {
-  VRMagicWindowProvider? magic_window_provider;
-  XRPresentationConnection? connection;
+  XRFrameDataProvider data_provider;
+  XRPresentationConnection? submit_frame_sink;
+  XREnviromentIntegrationProvider? enviroment_provider;
 };
 
+// This structure contains the infomation and interfaces needed to create a two
+// way connection between the renderer and a device to synchronize and submit
+// frames to a sink outside of Chrome.
 struct XRPresentationConnection {
-  VRSubmitFrameClient& client_request;
-  VRPresentationProvider provider;
-  VRDisplayFrameTransportOptions transport_options;
+  XRPresentationProvider provider;
+  XRPresentationClient& client_request;
+  XRPresentationTransportOptions transport_options;
 };
 
 struct XRInputSourceDescription {
@@ -171,7 +179,7 @@
 };
 
 // Frame transport method from the Renderer's point of view.
-enum VRDisplayFrameTransportMethod {
+enum XRPresentationTransportMethod {
   NONE = 0,
 
   // Renderer should create a new texture handle (Windows) or
@@ -185,10 +193,10 @@
   DRAW_INTO_TEXTURE_MAILBOX = 3,
 };
 
-struct VRDisplayFrameTransportOptions {
-  VRDisplayFrameTransportMethod transport_method;
+struct XRPresentationTransportOptions {
+  XRPresentationTransportMethod transport_method;
 
-  // Booleans indicating which of the VRSubmitFrameClient callbacks
+  // Booleans indicating which of the XRPresentationClient callbacks
   // are in use. Default is false, the device implementation should set
   // the ones to true that it needs and can ignore the rest.
   bool wait_for_transfer_notification;
@@ -249,40 +257,6 @@
                      VRDisplayInfo display_info);
 };
 
-// After submitting a frame, the VRPresentationProvider will notify the client
-// about several stages of the render pipeline.  This allows pipelining
-// efficiency.  Following VRPresentationProvider::Submit*, the submitted frame
-// will be transferred (read from, perhaps copied to another texture), and then
-// rendered (submitted to the underlying VR API).
-// The client lives in the render process, implemented by VRDisplay.
-//
-// See VRDisplayFrameTransportConfiguration which configures which of these
-// callbacks are in use.
-interface VRSubmitFrameClient {
-  // The VRPresentationProvider calls this to indicate that the submitted frame
-  // has been transferred, so the backing data (mailbox or GpuMemoryBuffer) can
-  // be reused or discarded.  Note that this is a convenience/optimization
-  // feature, not a security feature - if a site discards the data early we may
-  // drop a frame, but nothing will otherwise misbehave.
-  // When the frame wasn't successfully transferred, the client should create a
-  // new mailbox/GpuMemoryBuffer rather than reusing an existing one to recover
-  // for subsequent frames.
-  OnSubmitFrameTransferred(bool success);
-
-  // The VRPresentationProvider calls this after the frame was handed off to the
-  // underlying VR API. This allows some pipelining of CPU/GPU work, while
-  // delaying expensive tasks for a subsequent frame until the current frame has
-  // completed.
-  OnSubmitFrameRendered();
-
-  // This callback provides a GpuFence corresponding to the previous frame's
-  // rendering completion, intended for use with a server wait issued before
-  // the following wait to prevent its rendering work from competing with
-  // the previous frame.
-  OnSubmitFrameGpuFence(gfx.mojom.GpuFenceHandle gpu_fence_handle);
-};
-
-
 // Provides a communication channel from the renderer to the browser-side host
 // of a (device/) VrDisplayImpl.
 interface VRDisplayHost {
@@ -298,47 +272,44 @@
   ExitPresent();
 };
 
-// Provides the necessary functionality for a non-presenting WebXR session to
-// draw magic window content.
+// Provides the necessary functionality for a WebXR session to get data for
+// drawing frames. The kind of data it gets depends on what kind of session was
+// requested.
 // This interface is hosted in the Browser process, but will move to a sandboxed
 // utility process on Windows.  The render process communicates with it.
-// For AR displays (VRDisplayCapabilities.can_provide_pass_through_images
-// is true), clients can use GetFrameData to get images.
-// TODO(836478): rename VRMagicWindowProvider to NonImmersiveWindowProvider or
-// similar.
-interface VRMagicWindowProvider {
+interface XRFrameDataProvider {
   // frame_data is optional and will not be set if and only if the call fails
   // for some reason, such as device disconnection.
   GetFrameData() => (XRFrameData? frame_data);
+};
 
-  // Different devices can have different native orientations - 0
-  // is the native orientation, and then increments of 90 degrees
-  // from there.
+// Provides functionality for integrating enviroment information into an
+// XRSession. For example, some AR sessions would implement hit test to allow
+// developers to get the information about the world that its sensors supply.
+interface XREnviromentIntegrationProvider {
+  // Different devices can have different native orientations - 0 is the native
+  // orientation, and then increments of 90 degrees from there. Session geometry
+  // is needed by the device when integrating enviroment image data, i.e. camera
+  // feeds, into a session.
   UpdateSessionGeometry(
       gfx.mojom.Size frame_size,
       display.mojom.Rotation display_rotation);
 
-  // Performs a raycast into the magic window scene and returns a list of
-  // XRHitResults sorted from closest to furthest hit from the ray. Each
-  // hit result contains a hit_matrix containing the transform of the hit
-  // where the rotation represents the normal of the surface hit.
+  // Performs a raycast into the scene and returns a list of XRHitResults sorted
+  // from closest to furthest hit from the ray. Each hit result contains a
+  // hit_matrix containing the transform of the hit where the rotation
+  // represents the normal of the surface hit.
   // An empty result list means there were no hits. If a nullopt is returned,
   // there was an error.
-  // TODO(https://crbug.com/842025): have one "session" type, merging
-  // VRMagicWindowProvider and VRPresentationProvider because RequestHitTest
-  // makes sense for both types of sessions.
   RequestHitTest(XRRay ray) => (array<XRHitResult>? results);
 };
 
-// Provides the necessary functionality for a presenting WebVR page to draw
-// frames for a VrDisplay.
+// Provides the necessary functionality for sending frames to a headset.
 // This interface is hosted in the Browser process, but will move to a sandboxed
 // utility process on Windows.  The render process communicates with it.
-interface VRPresentationProvider {
-  // frame_data is optional and will not be set if and only if the call fails
-  // for some reason, such as device disconnection.
-  GetFrameData() => (XRFrameData? frame_data);
-
+interface XRPresentationProvider {
+  // This function tells the device which parts of the canvas should be rendered
+  // to which view.
   UpdateLayerBounds(int16 frame_id, gfx.mojom.RectF left_bounds,
                     gfx.mojom.RectF right_bounds, gfx.mojom.Size source_size);
 
@@ -346,26 +317,59 @@
   // ensure that every GetFrameData has a matching Submit call. This happens for
   // WebXR if there were no drawing operations to the opaque framebuffer, and
   // for WebVR 1.1 if the application didn't call SubmitFrame. Usable with any
-  // VRDisplayFrameTransportMethod. This path does *not* call the
+  // XRPresentationTransportMethod. This path does *not* call the
   // SubmitFrameClient methods such as OnSubmitFrameTransferred. This is
   // intended to help separate frames while presenting, it may or may not
   // be called for the last animating frame when presentation ends.
   SubmitFrameMissing(int16 frame_id, gpu.mojom.SyncToken sync_token);
 
-  // VRDisplayFrameTransportMethod SUBMIT_AS_MAILBOX_HOLDER
+  // XRPresentationTransportMethod SUBMIT_AS_MAILBOX_HOLDER
   SubmitFrame(int16 frame_id, gpu.mojom.MailboxHolder mailbox_holder,
               mojo_base.mojom.TimeDelta time_waited);
 
-  // VRDisplayFrameTransportMethod SUBMIT_AS_TEXTURE_HANDLE
+  // XRPresentationTransportMethod SUBMIT_AS_TEXTURE_HANDLE
   // TODO(https://crbug.com/676224): Support preprocessing of mojom files, since
   // this is Windows only.
   SubmitFrameWithTextureHandle(int16 frameId, handle texture);
 
-  // VRDisplayFrameTransportMethod DRAW_INTO_TEXTURE_MAILBOX
+  // XRPresentationTransportMethod DRAW_INTO_TEXTURE_MAILBOX
   SubmitFrameDrawnIntoTexture(int16 frameId, gpu.mojom.SyncToken sync_token,
                               mojo_base.mojom.TimeDelta time_waited);
 };
 
+// After submitting a frame, the XRPresentationProvider will notify the client
+// about several stages of the render pipeline.  This allows pipelining
+// efficiency.  Following XRPresentationProvider::Submit*, the submitted frame
+// will be transferred (read from, perhaps copied to another texture), and then
+// rendered (submitted to the underlying VR API).
+// The client lives in the render process.
+//
+// See XRPresentationTransportOptions which configures which of these
+// callbacks are in use.
+interface XRPresentationClient {
+  // The XRPresentationProvider calls this to indicate that the submitted frame
+  // has been transferred, so the backing data (mailbox or GpuMemoryBuffer) can
+  // be reused or discarded.  Note that this is a convenience/optimization
+  // feature, not a security feature - if a site discards the data early we may
+  // drop a frame, but nothing will otherwise misbehave.
+  // When the frame wasn't successfully transferred, the client should create a
+  // new mailbox/GpuMemoryBuffer rather than reusing an existing one to recover
+  // for subsequent frames.
+  OnSubmitFrameTransferred(bool success);
+
+  // The XRPresentationProvider calls this after the frame was handed off to the
+  // underlying VR API. This allows some pipelining of CPU/GPU work, while
+  // delaying expensive tasks for a subsequent frame until the current frame has
+  // completed.
+  OnSubmitFrameRendered();
+
+  // This callback provides a GpuFence corresponding to the previous frame's
+  // rendering completion, intended for use with a server wait issued before
+  // the following wait to prevent its rendering work from competing with
+  // the previous frame.
+  OnSubmitFrameGpuFence(gfx.mojom.GpuFenceHandle gpu_fence_handle);
+};
+
 interface VRDisplayClient {
   OnChanged(VRDisplayInfo display);
   OnExitPresent();
diff --git a/device/vr/test/fake_vr_device.cc b/device/vr/test/fake_vr_device.cc
index 4a5740d..626a2953 100644
--- a/device/vr/test/fake_vr_device.cc
+++ b/device/vr/test/fake_vr_device.cc
@@ -54,18 +54,9 @@
     mojom::XRDeviceRuntimeSessionOptionsPtr options,
     mojom::XRRuntime::RequestSessionCallback callback) {
   OnStartPresenting();
-
-  mojom::XRSessionControllerPtr exclusive_session_controller;
-  controller_binding_.Bind(mojo::MakeRequest(&exclusive_session_controller));
-
-  // Unretained is safe because the error handler won't be called after
-  // controller_binding_ is destroyed.
-  controller_binding_.set_connection_error_handler(
-      base::BindOnce(&FakeVRDevice::OnPresentingControllerMojoConnectionError,
-                     base::Unretained(this)));
-
-  std::move(callback).Run(mojom::XRPresentationConnection::New(),
-                          std::move(exclusive_session_controller));
+  // The current tests never use the return values, so it's fine to return
+  // invalid data here.
+  std::move(callback).Run(nullptr, nullptr);
 }
 
 void FakeVRDevice::OnPresentingControllerMojoConnectionError() {
@@ -74,7 +65,7 @@
 }
 
 void FakeVRDevice::OnMagicWindowFrameDataRequest(
-    mojom::VRMagicWindowProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   mojom::XRFrameDataPtr frame_data = mojom::XRFrameData::New();
   frame_data->pose = pose_.Clone();
   std::move(callback).Run(std::move(frame_data));
diff --git a/device/vr/test/fake_vr_device.h b/device/vr/test/fake_vr_device.h
index cfe8601..4e7c70a 100644
--- a/device/vr/test/fake_vr_device.h
+++ b/device/vr/test/fake_vr_device.h
@@ -35,7 +35,7 @@
   void OnPresentingControllerMojoConnectionError();
 
   void OnMagicWindowFrameDataRequest(
-      mojom::VRMagicWindowProvider::GetFrameDataCallback callback) override;
+      mojom::XRFrameDataProvider::GetFrameDataCallback callback) override;
 
   mojom::VRDisplayInfoPtr InitBasicDevice();
   mojom::VREyeParametersPtr InitEye(float fov, float offset, uint32_t size);
diff --git a/device/vr/test/mock_vr_display_impl.cc b/device/vr/test/mock_vr_display_impl.cc
deleted file mode 100644
index 4c63aeb..0000000
--- a/device/vr/test/mock_vr_display_impl.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/vr/test/mock_vr_display_impl.h"
-
-namespace device {
-
-MockVRDisplayImpl::MockVRDisplayImpl(
-    device::VRDeviceBase* device,
-    mojom::VRMagicWindowProviderRequest session,
-    mojom::XRSessionControllerRequest controller,
-    bool is_frame_focused)
-    : VRDisplayImpl(device, std::move(session), std::move(controller)) {
-  SetFrameDataRestricted(!is_frame_focused);
-}
-
-MockVRDisplayImpl::~MockVRDisplayImpl() = default;
-
-}  // namespace device
diff --git a/device/vr/test/mock_vr_display_impl.h b/device/vr/test/mock_vr_display_impl.h
deleted file mode 100644
index 32d0e1b8..0000000
--- a/device/vr/test/mock_vr_display_impl.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef DEVICE_VR_TEST_MOCK_VR_DISPLAY_IMPL_H
-#define DEVICE_VR_TEST_MOCK_VR_DISPLAY_IMPL_H
-
-#include "base/macros.h"
-#include "device/vr/vr_display_impl.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace device {
-
-class MockVRDisplayImpl : public VRDisplayImpl {
- public:
-  MockVRDisplayImpl(device::VRDeviceBase* device,
-                    mojom::VRMagicWindowProviderRequest session,
-                    mojom::XRSessionControllerRequest controller,
-                    bool in_frame_focused);
-  ~MockVRDisplayImpl() override;
-
-  MOCK_METHOD1(DoOnChanged, void(mojom::VRDisplayInfo* vr_device_info));
-  void OnChanged(mojom::VRDisplayInfoPtr vr_device_info) {
-    DoOnChanged(vr_device_info.get());
-  }
-
-  MOCK_METHOD2(OnActivate,
-               void(mojom::VRDisplayEventReason, base::Callback<void(bool)>));
-
-  MOCK_METHOD0(ListeningForActivate, bool());
-  MOCK_METHOD0(InFocusedFrame, bool());
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockVRDisplayImpl);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_VR_TEST_MOCK_VR_DISPLAY_IMPL_H
diff --git a/device/vr/vr_device_base.cc b/device/vr/vr_device_base.cc
index 1c7703a..d5f3e5f 100644
--- a/device/vr/vr_device_base.cc
+++ b/device/vr/vr_device_base.cc
@@ -53,7 +53,7 @@
 }
 
 void VRDeviceBase::GetFrameData(
-    mojom::VRMagicWindowProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   if (!magic_window_enabled_) {
     std::move(callback).Run(nullptr);
     return;
@@ -95,7 +95,7 @@
 void VRDeviceBase::OnListeningForActivate(bool listening) {}
 
 void VRDeviceBase::OnMagicWindowFrameDataRequest(
-    mojom::VRMagicWindowProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   std::move(callback).Run(nullptr);
 }
 
@@ -105,18 +105,27 @@
 
 void VRDeviceBase::RequestHitTest(
     mojom::XRRayPtr ray,
-    mojom::VRMagicWindowProvider::RequestHitTestCallback callback) {
+    mojom::XREnviromentIntegrationProvider::RequestHitTestCallback callback) {
   NOTREACHED() << "Unexpected call to a device without hit-test support";
   std::move(callback).Run(base::nullopt);
 }
 
-void VRDeviceBase::RequestMagicWindowSession(
-    mojom::XRRuntime::RequestMagicWindowSessionCallback callback) {
-  mojom::VRMagicWindowProviderPtr provider;
+void VRDeviceBase::ReturnNonImmersiveSession(
+    mojom::XRRuntime::RequestSessionCallback callback) {
+  mojom::XRFrameDataProviderPtr data_provider;
+  mojom::XREnviromentIntegrationProviderPtr enviroment_provider;
   mojom::XRSessionControllerPtr controller;
   magic_window_sessions_.push_back(std::make_unique<VRDisplayImpl>(
-      this, mojo::MakeRequest(&provider), mojo::MakeRequest(&controller)));
-  std::move(callback).Run(std::move(provider), std::move(controller));
+      this, mojo::MakeRequest(&data_provider),
+      mojo::MakeRequest(&enviroment_provider), mojo::MakeRequest(&controller)));
+
+  auto session = mojom::XRSession::New();
+  session->data_provider = data_provider.PassInterface();
+  // TODO(offenwanger) Not all session will want the enviroment provider. This
+  // should be refactored so it's only passed when it's requested.
+  session->enviroment_provider = enviroment_provider.PassInterface();
+
+  std::move(callback).Run(std::move(session), std::move(controller));
 }
 
 void VRDeviceBase::EndMagicWindowSession(VRDisplayImpl* session) {
diff --git a/device/vr/vr_device_base.h b/device/vr/vr_device_base.h
index 04f6c506..230a0acf 100644
--- a/device/vr/vr_device_base.h
+++ b/device/vr/vr_device_base.h
@@ -31,12 +31,11 @@
       mojom::XRRuntime::ListenToDeviceChangesCallback callback) final;
   void SetListeningForActivate(bool is_listening) override;
 
-  void GetFrameData(
-      mojom::VRMagicWindowProvider::GetFrameDataCallback callback);
+  void GetFrameData(mojom::XRFrameDataProvider::GetFrameDataCallback callback);
 
   virtual void RequestHitTest(
       mojom::XRRayPtr ray,
-      mojom::VRMagicWindowProvider::RequestHitTestCallback callback);
+      mojom::XREnviromentIntegrationProvider::RequestHitTestCallback callback);
   unsigned int GetId() const;
 
   bool HasExclusiveSession();
@@ -75,17 +74,16 @@
   void OnActivate(mojom::VRDisplayEventReason reason,
                   base::Callback<void(bool)> on_handled);
 
+  void ReturnNonImmersiveSession(
+      mojom::XRRuntime::RequestSessionCallback callback);
+
   std::vector<std::unique_ptr<VRDisplayImpl>> magic_window_sessions_;
 
  private:
   // TODO(https://crbug.com/842227): Rename methods to HandleOnXXX
   virtual void OnListeningForActivate(bool listening);
   virtual void OnMagicWindowFrameDataRequest(
-      mojom::VRMagicWindowProvider::GetFrameDataCallback callback);
-
-  // XRRuntime
-  void RequestMagicWindowSession(
-      mojom::XRRuntime::RequestMagicWindowSessionCallback callback) override;
+      mojom::XRFrameDataProvider::GetFrameDataCallback callback);
 
   mojom::XRRuntimeEventListenerPtr listener_;
 
diff --git a/device/vr/vr_device_base_unittest.cc b/device/vr/vr_device_base_unittest.cc
index 5025d3ed..10cdc517 100644
--- a/device/vr/vr_device_base_unittest.cc
+++ b/device/vr/vr_device_base_unittest.cc
@@ -11,8 +11,8 @@
 #include "device/vr/public/mojom/vr_service.mojom.h"
 #include "device/vr/test/fake_vr_device.h"
 #include "device/vr/test/fake_vr_service_client.h"
-#include "device/vr/test/mock_vr_display_impl.h"
 #include "device/vr/vr_device_base.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace device {
@@ -95,14 +95,6 @@
     client_ = std::make_unique<FakeVRServiceClient>(mojo::MakeRequest(&proxy));
   }
 
-  std::unique_ptr<MockVRDisplayImpl> MakeMockDisplay(VRDeviceBase* device) {
-    mojom::VRMagicWindowProviderPtr session;
-    mojom::XRSessionControllerPtr controller;
-    return std::make_unique<testing::NiceMock<MockVRDisplayImpl>>(
-        device, mojo::MakeRequest(&session), mojo::MakeRequest(&controller),
-        false);
-  }
-
   std::unique_ptr<VRDeviceBaseForTesting> MakeVRDevice() {
     std::unique_ptr<VRDeviceBaseForTesting> device =
         std::make_unique<VRDeviceBaseForTesting>();
diff --git a/device/vr/vr_display_impl.cc b/device/vr/vr_display_impl.cc
index b4e482b..d6b0ce5 100644
--- a/device/vr/vr_display_impl.cc
+++ b/device/vr/vr_display_impl.cc
@@ -17,14 +17,13 @@
 
 VRDisplayImpl::VRDisplayImpl(
     VRDeviceBase* device,
-    mojom::VRMagicWindowProviderRequest magic_window_request,
+    mojom::XRFrameDataProviderRequest magic_window_request,
+    mojom::XREnviromentIntegrationProviderRequest enviroment_request,
     mojom::XRSessionControllerRequest session_request)
-    : magic_window_binding_(this),
-      session_controller_binding_(this),
+    : magic_window_binding_(this, std::move(magic_window_request)),
+      enviroment_binding_(this, std::move(enviroment_request)),
+      session_controller_binding_(this, std::move(session_request)),
       device_(device) {
-  magic_window_binding_.Bind(std::move(magic_window_request));
-  session_controller_binding_.Bind(std::move(session_request));
-
   // Unretained is safe because the binding will close when we are destroyed,
   // so we won't receive any more callbacks after that.
   session_controller_binding_.set_connection_error_handler(base::BindOnce(
@@ -35,7 +34,7 @@
 
 // Gets frame data for sessions.
 void VRDisplayImpl::GetFrameData(
-    mojom::VRMagicWindowProvider::GetFrameDataCallback callback) {
+    mojom::XRFrameDataProvider::GetFrameDataCallback callback) {
   if (device_->HasExclusiveSession() || restrict_frame_data_) {
     std::move(callback).Run(nullptr);
     return;
@@ -63,7 +62,7 @@
 
 void VRDisplayImpl::RequestHitTest(
     mojom::XRRayPtr ray,
-    mojom::VRMagicWindowProvider::RequestHitTestCallback callback) {
+    mojom::XREnviromentIntegrationProvider::RequestHitTestCallback callback) {
   if (restrict_frame_data_) {
     std::move(callback).Run(base::nullopt);
     return;
diff --git a/device/vr/vr_display_impl.h b/device/vr/vr_display_impl.h
index 0d0bd8f..980798e 100644
--- a/device/vr/vr_display_impl.h
+++ b/device/vr/vr_display_impl.h
@@ -20,15 +20,18 @@
 
 class VRDeviceBase;
 
-// VR device process implementation of a VRMagicWindowProvider within a WebVR
+// VR device process implementation of a XRFrameDataProvider within a WebVR
 // or WebXR site session.
 // VRDisplayImpl objects are owned by their respective XRRuntime instances.
 // TODO(offenwanger): Rename this.
-class DEVICE_VR_EXPORT VRDisplayImpl : public mojom::VRMagicWindowProvider,
-                                       public mojom::XRSessionController {
+class DEVICE_VR_EXPORT VRDisplayImpl
+    : public mojom::XRFrameDataProvider,
+      public mojom::XREnviromentIntegrationProvider,
+      public mojom::XRSessionController {
  public:
   VRDisplayImpl(VRDeviceBase* device,
-                mojom::VRMagicWindowProviderRequest,
+                mojom::XRFrameDataProviderRequest,
+                mojom::XREnviromentIntegrationProviderRequest,
                 mojom::XRSessionControllerRequest);
   ~VRDisplayImpl() override;
 
@@ -39,7 +42,7 @@
 
   // Accessible to tests.
  protected:
-  // mojom::VRMagicWindowProvider
+  // mojom::XRFrameDataProvider
   void GetFrameData(GetFrameDataCallback callback) override;
   void UpdateSessionGeometry(const gfx::Size& frame_size,
                              display::Display::Rotation rotation) override;
@@ -51,7 +54,8 @@
 
   void OnMojoConnectionError();
 
-  mojo::Binding<mojom::VRMagicWindowProvider> magic_window_binding_;
+  mojo::Binding<mojom::XRFrameDataProvider> magic_window_binding_;
+  mojo::Binding<mojom::XREnviromentIntegrationProvider> enviroment_binding_;
   mojo::Binding<mojom::XRSessionController> session_controller_binding_;
   device::VRDeviceBase* device_;
   bool restrict_frame_data_ = true;
diff --git a/device/vr/vr_display_impl_unittest.cc b/device/vr/vr_display_impl_unittest.cc
index 6735be75..d4de7de 100644
--- a/device/vr/vr_display_impl_unittest.cc
+++ b/device/vr/vr_display_impl_unittest.cc
@@ -21,13 +21,6 @@
   VRDisplayImplTest() {}
   ~VRDisplayImplTest() override {}
   void onDisplaySynced() {}
-  void onPresentComplete(
-      device::mojom::XRPresentationConnectionPtr connection,
-      mojom::XRSessionControllerPtr immersive_session_controller) {
-    is_request_presenting_success_ = connection ? true : false;
-
-    immersive_session_controller_ = std::move(immersive_session_controller);
-  }
 
  protected:
   void SetUp() override {
@@ -39,9 +32,11 @@
 
   std::unique_ptr<VRDisplayImpl> MakeDisplay(
       mojom::XRSessionControllerPtr* controller) {
-    mojom::VRMagicWindowProviderPtr session;
+    mojom::XRFrameDataProviderPtr data_provider;
+    mojom::XREnviromentIntegrationProviderPtr enviroment_provider;
     auto display = std::make_unique<VRDisplayImpl>(
-        device(), mojo::MakeRequest(&session), mojo::MakeRequest(controller));
+        device(), mojo::MakeRequest(&data_provider),
+        mojo::MakeRequest(&enviroment_provider), mojo::MakeRequest(controller));
     static_cast<mojom::XRSessionController*>(display.get())
         ->SetFrameDataRestricted(true);
     return display;
@@ -50,13 +45,13 @@
   void RequestSession(VRDisplayImpl* display_impl) {
     device_->RequestSession(
         mojom::XRDeviceRuntimeSessionOptionsPtr(),
-        base::BindOnce(&VRDisplayImplTest::onPresentComplete,
-                       base::Unretained(this)));
+        base::BindOnce(
+            [](device::mojom::XRSessionPtr session,
+               mojom::XRSessionControllerPtr immersive_session_controller) {}));
   }
 
   void ExitPresent() {
     device_->StopSession();
-    immersive_session_controller_ = nullptr;
   }
 
   bool presenting() { return device_->IsPresenting(); }
@@ -64,10 +59,8 @@
   FakeVRServiceClient* client() { return client_.get(); }
 
   base::MessageLoop message_loop_;
-  bool is_request_presenting_success_ = false;
   std::unique_ptr<FakeVRDevice> device_;
   std::unique_ptr<FakeVRServiceClient> client_;
-  mojom::XRSessionControllerPtr immersive_session_controller_;
 
   DISALLOW_COPY_AND_ASSIGN(VRDisplayImplTest);
 };
@@ -77,6 +70,7 @@
   std::unique_ptr<VRDisplayImpl> display_1 = MakeDisplay(&controller1);
   static_cast<mojom::XRSessionController*>(display_1.get())
       ->SetFrameDataRestricted(false);
+
   mojom::XRSessionControllerPtr controller2;
   std::unique_ptr<VRDisplayImpl> display_2 = MakeDisplay(&controller2);
   static_cast<mojom::XRSessionController*>(display_2.get())
@@ -92,31 +86,36 @@
     EXPECT_EQ(expect_null, !data);
   };
 
-  static_cast<mojom::VRMagicWindowProvider*>(display_1.get())
+  static_cast<mojom::XRFrameDataProvider*>(display_1.get())
       ->GetFrameData(base::BindOnce(callback, false, &was_called));
+
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(was_called);
   was_called = false;
-  static_cast<mojom::VRMagicWindowProvider*>(display_2.get())
+
+  static_cast<mojom::XRFrameDataProvider*>(display_2.get())
       ->GetFrameData(base::BindOnce(callback, false, &was_called));
+
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(was_called);
   was_called = false;
 
   // Attempt to present.
   RequestSession(display_1.get());
-  EXPECT_TRUE(is_request_presenting_success_);
   EXPECT_TRUE(presenting());
   EXPECT_TRUE(device()->HasExclusiveSession());
 
-  // While a device is presenting, noone should have access to magic window.
-  static_cast<mojom::VRMagicWindowProvider*>(display_1.get())
+  // While a device is presenting, no one should have access to magic window.
+  static_cast<mojom::XRFrameDataProvider*>(display_1.get())
       ->GetFrameData(base::BindOnce(callback, true, &was_called));
+
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(was_called);
   was_called = false;
-  static_cast<mojom::VRMagicWindowProvider*>(display_2.get())
+
+  static_cast<mojom::XRFrameDataProvider*>(display_2.get())
       ->GetFrameData(base::BindOnce(callback, true, &was_called));
+
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(was_called);
   was_called = false;
@@ -128,13 +127,16 @@
 
   // Once presentation had ended both services should be able to access the
   // device.
-  static_cast<mojom::VRMagicWindowProvider*>(display_1.get())
+  static_cast<mojom::XRFrameDataProvider*>(display_1.get())
       ->GetFrameData(base::BindOnce(callback, false, &was_called));
+
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(was_called);
   was_called = false;
-  static_cast<mojom::VRMagicWindowProvider*>(display_2.get())
+
+  static_cast<mojom::XRFrameDataProvider*>(display_2.get())
       ->GetFrameData(base::BindOnce(callback, false, &was_called));
+
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(was_called);
   was_called = false;
diff --git a/extensions/browser/api/socket/BUILD.gn b/extensions/browser/api/socket/BUILD.gn
index a707906e..e20046a05 100644
--- a/extensions/browser/api/socket/BUILD.gn
+++ b/extensions/browser/api/socket/BUILD.gn
@@ -9,6 +9,8 @@
 
 source_set("socket") {
   sources = [
+    "mojo_data_pump.cc",
+    "mojo_data_pump.h",
     "socket.cc",
     "socket.h",
     "socket_api.cc",
diff --git a/extensions/browser/api/socket/mojo_data_pump.cc b/extensions/browser/api/socket/mojo_data_pump.cc
new file mode 100644
index 0000000..fdc22f73
--- /dev/null
+++ b/extensions/browser/api/socket/mojo_data_pump.cc
@@ -0,0 +1,117 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/api/socket/mojo_data_pump.h"
+
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+
+namespace extensions {
+
+MojoDataPump::MojoDataPump(mojo::ScopedDataPipeConsumerHandle receive_stream,
+                           mojo::ScopedDataPipeProducerHandle send_stream)
+    : receive_stream_(std::move(receive_stream)),
+      receive_stream_watcher_(FROM_HERE,
+                              mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+      send_stream_(std::move(send_stream)),
+      send_stream_watcher_(FROM_HERE,
+                           mojo::SimpleWatcher::ArmingPolicy::MANUAL) {
+  DCHECK(receive_stream_.is_valid());
+  DCHECK(send_stream_.is_valid());
+  receive_stream_watcher_.Watch(
+      receive_stream_.get(),
+      MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+      MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+      base::BindRepeating(&MojoDataPump::ReceiveMore, base::Unretained(this)));
+  send_stream_watcher_.Watch(
+      send_stream_.get(),
+      MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+      MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+      base::BindRepeating(&MojoDataPump::SendMore, base::Unretained(this)));
+}
+
+MojoDataPump::~MojoDataPump() {}
+
+void MojoDataPump::Read(int count, ReadCallback callback) {
+  DCHECK(callback);
+  DCHECK(!read_callback_);
+
+  if (count <= 0) {
+    std::move(callback).Run(net::ERR_INVALID_ARGUMENT, nullptr);
+    return;
+  }
+
+  read_size_ = count;
+  read_callback_ = std::move(callback);
+  receive_stream_watcher_.ArmOrNotify();
+}
+
+void MojoDataPump::Write(net::IOBuffer* io_buffer,
+                         int io_buffer_size,
+                         net::CompletionOnceCallback callback) {
+  DCHECK(callback);
+  DCHECK(!write_callback_);
+
+  write_callback_ = std::move(callback);
+  pending_write_buffer_ = io_buffer;
+  pending_write_buffer_size_ = io_buffer_size;
+
+  send_stream_watcher_.ArmOrNotify();
+}
+
+void MojoDataPump::ReceiveMore(MojoResult result,
+                               const mojo::HandleSignalsState& /* ignored */) {
+  DCHECK(read_callback_);
+  DCHECK_NE(0u, read_size_);
+
+  if (result != MOJO_RESULT_OK) {
+    read_size_ = 0;
+    std::move(read_callback_).Run(net::ERR_FAILED, nullptr);
+    return;
+  }
+
+  uint32_t num_bytes = read_size_;
+  auto io_buffer =
+      base::MakeRefCounted<net::IOBuffer>(static_cast<size_t>(num_bytes));
+  result = receive_stream_->ReadData(io_buffer->data(), &num_bytes,
+                                     MOJO_READ_DATA_FLAG_NONE);
+  if (result != MOJO_RESULT_OK) {
+    read_size_ = 0;
+    std::move(read_callback_).Run(net::ERR_FAILED, nullptr);
+    return;
+  }
+
+  if (result == MOJO_RESULT_SHOULD_WAIT) {
+    receive_stream_watcher_.ArmOrNotify();
+    return;
+  }
+  read_size_ = 0;
+  std::move(read_callback_).Run(num_bytes, io_buffer);
+}
+
+void MojoDataPump::SendMore(MojoResult result,
+                            const mojo::HandleSignalsState& state) {
+  DCHECK(write_callback_);
+
+  uint32_t num_bytes = pending_write_buffer_size_;
+  result = send_stream_->WriteData(pending_write_buffer_->data(), &num_bytes,
+                                   MOJO_WRITE_DATA_FLAG_NONE);
+  if (result == MOJO_RESULT_SHOULD_WAIT) {
+    send_stream_watcher_.ArmOrNotify();
+    return;
+  }
+  pending_write_buffer_ = nullptr;
+  pending_write_buffer_size_ = 0;
+  if (result != MOJO_RESULT_OK) {
+    std::move(write_callback_).Run(net::ERR_FAILED);
+    return;
+  }
+  std::move(write_callback_).Run(num_bytes);
+}
+
+}  // namespace extensions
diff --git a/extensions/browser/api/socket/mojo_data_pump.h b/extensions/browser/api/socket/mojo_data_pump.h
new file mode 100644
index 0000000..f4f6876
--- /dev/null
+++ b/extensions/browser/api/socket/mojo_data_pump.h
@@ -0,0 +1,71 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_BROWSER_API_SOCKET_MOJO_DATA_PUMP_H_
+#define EXTENSIONS_BROWSER_API_SOCKET_MOJO_DATA_PUMP_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "extensions/browser/api/socket/socket.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "net/base/completion_once_callback.h"
+
+namespace net {
+class IOBuffer;
+};
+
+namespace extensions {
+
+// Helper class to read from a mojo consumer handle and write to mojo producer
+// handle.
+class MojoDataPump {
+ public:
+  using ReadCallback =
+      base::OnceCallback<void(int, scoped_refptr<net::IOBuffer> io_buffer)>;
+
+  MojoDataPump(mojo::ScopedDataPipeConsumerHandle receive_stream,
+               mojo::ScopedDataPipeProducerHandle send_stream);
+
+  ~MojoDataPump();
+
+  // Reads from |receive_stream|. It's illegal to call Read() when a previous
+  // one hasn't completed yet.
+  void Read(int count, ReadCallback callback);
+
+  // Writes to |send_stream|. It's illegal to call Write() when a previous one
+  // hasn't completed yet.
+  void Write(net::IOBuffer* io_buffer,
+             int io_buffer_size,
+             net::CompletionOnceCallback callback);
+
+  // Returns whether a read is pending.
+  bool HasPendingRead() const { return !read_callback_.is_null(); }
+
+  // Returns whether a write is pending.
+  bool HasPendingWrite() const { return !write_callback_.is_null(); }
+
+ private:
+  void OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, int result);
+  void StartWatching();
+  void ReceiveMore(MojoResult result, const mojo::HandleSignalsState& state);
+  void SendMore(MojoResult result, const mojo::HandleSignalsState& state);
+
+  mojo::ScopedDataPipeConsumerHandle receive_stream_;
+  mojo::SimpleWatcher receive_stream_watcher_;
+  mojo::ScopedDataPipeProducerHandle send_stream_;
+  mojo::SimpleWatcher send_stream_watcher_;
+
+  ReadCallback read_callback_;
+  net::CompletionOnceCallback write_callback_;
+  scoped_refptr<net::IOBuffer> pending_write_buffer_;
+  int pending_write_buffer_size_ = 0;
+  uint32_t read_size_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(MojoDataPump);
+};
+
+}  //  namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_API_SOCKET_MOJO_DATA_PUMP_H_
diff --git a/extensions/browser/api/socket/socket.cc b/extensions/browser/api/socket/socket.cc
index 74f1132d..23dac927 100644
--- a/extensions/browser/api/socket/socket.cc
+++ b/extensions/browser/api/socket/socket.cc
@@ -85,20 +85,27 @@
     WriteData();
 }
 
-bool Socket::SetKeepAlive(bool enable, int delay) { return false; }
-
-bool Socket::SetNoDelay(bool no_delay) { return false; }
-
-int Socket::Listen(const std::string& address,
-                   uint16_t port,
-                   int backlog,
-                   std::string* error_msg) {
-  *error_msg = kSocketTypeNotSupported;
-  return net::ERR_FAILED;
+void Socket::SetKeepAlive(bool enable,
+                          int delay,
+                          SetKeepAliveCallback callback) {
+  std::move(callback).Run(false);
 }
 
-void Socket::Accept(const AcceptCompletionCallback& callback) {
-  callback.Run(net::ERR_FAILED, NULL);
+void Socket::SetNoDelay(bool no_delay, SetNoDelayCallback callback) {
+  std::move(callback).Run(false);
+}
+
+void Socket::Listen(const std::string& address,
+                    uint16_t port,
+                    int backlog,
+                    ListenCallback callback) {
+  std::move(callback).Run(net::ERR_FAILED, kSocketTypeNotSupported);
+}
+
+void Socket::Accept(AcceptCompletionCallback callback) {
+  std::move(callback).Run(net::ERR_FAILED, nullptr /* socket */, base::nullopt,
+                          mojo::ScopedDataPipeConsumerHandle(),
+                          mojo::ScopedDataPipeProducerHandle());
 }
 
 // static
diff --git a/extensions/browser/api/socket/socket.h b/extensions/browser/api/socket/socket.h
index d83b94c..a55eede 100644
--- a/extensions/browser/api/socket/socket.h
+++ b/extensions/browser/api/socket/socket.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <string>
 #include <utility>
 
@@ -17,11 +18,13 @@
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/api/api_resource.h"
 #include "extensions/browser/api/api_resource_manager.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/ip_endpoint.h"
 #include "net/socket/tcp_client_socket.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/mojom/tcp_socket.mojom.h"
+#include "services/network/public/mojom/tls_socket.mojom.h"
 
 #if defined(OS_CHROMEOS)
 #include "extensions/browser/api/socket/app_firewall_hole_manager.h"
@@ -36,7 +39,9 @@
 namespace extensions {
 
 using CompletionCallback = base::Callback<void(int)>;
-using ReadCompletionCallback = base::Callback<
+using SetNoDelayCallback = base::OnceCallback<void(bool)>;
+using SetKeepAliveCallback = base::OnceCallback<void(bool)>;
+using ReadCompletionCallback = base::OnceCallback<
     void(int, scoped_refptr<net::IOBuffer> io_buffer, bool socket_destroying)>;
 using RecvFromCompletionCallback =
     base::Callback<void(int,
@@ -44,8 +49,15 @@
                         bool socket_destroying,
                         const std::string&,
                         uint16_t)>;
+using ListenCallback =
+    base::OnceCallback<void(int, const std::string& error_msg)>;
+
 using AcceptCompletionCallback =
-    base::Callback<void(int, std::unique_ptr<net::TCPClientSocket>)>;
+    base::OnceCallback<void(int,
+                            network::mojom::TCPConnectedSocketPtr,
+                            const base::Optional<net::IPEndPoint>&,
+                            mojo::ScopedDataPipeConsumerHandle,
+                            mojo::ScopedDataPipeProducerHandle)>;
 
 // A Socket wraps a low-level socket and includes housekeeping information that
 // we need to manage it in the context of an extension.
@@ -78,7 +90,7 @@
   // the remote endpoint. In order to upgrade this socket to TLS, callers
   // must also supply the hostname of the endpoint via set_hostname().
   virtual void Connect(const net::AddressList& address,
-                       const CompletionCallback& callback) = 0;
+                       net::CompletionOnceCallback callback) = 0;
   // |socket_destroying| is true if disconnect is due to destruction of the
   // socket.
   virtual void Disconnect(bool socket_destroying) = 0;
@@ -88,7 +100,7 @@
 
   // The |callback| will be called with the number of bytes read into the
   // buffer, or a negative number if an error occurred.
-  virtual void Read(int count, const ReadCompletionCallback& callback) = 0;
+  virtual void Read(int count, ReadCompletionCallback callback) = 0;
 
   // The |callback| will be called with |byte_count| or a negative number if an
   // error occurred.
@@ -103,13 +115,15 @@
                       const net::IPEndPoint& address,
                       const CompletionCallback& callback) = 0;
 
-  virtual bool SetKeepAlive(bool enable, int delay);
-  virtual bool SetNoDelay(bool no_delay);
-  virtual int Listen(const std::string& address,
-                     uint16_t port,
-                     int backlog,
-                     std::string* error_msg);
-  virtual void Accept(const AcceptCompletionCallback& callback);
+  virtual void SetKeepAlive(bool enable,
+                            int delay,
+                            SetKeepAliveCallback callback);
+  virtual void SetNoDelay(bool no_delay, SetNoDelayCallback callback);
+  virtual void Listen(const std::string& address,
+                      uint16_t port,
+                      int backlog,
+                      ListenCallback callback);
+  virtual void Accept(AcceptCompletionCallback callback);
 
   virtual bool IsConnected() = 0;
 
diff --git a/extensions/browser/api/socket/socket_api.cc b/extensions/browser/api/socket/socket_api.cc
index 8f7c8cf..3d33656 100644
--- a/extensions/browser/api/socket/socket_api.cc
+++ b/extensions/browser/api/socket/socket_api.cc
@@ -4,7 +4,6 @@
 
 #include "extensions/browser/api/socket/socket_api.h"
 
-#include <memory>
 #include <utility>
 #include <vector>
 
@@ -254,7 +253,7 @@
 void SocketCreateFunction::Work() {
   Socket* socket = NULL;
   if (socket_type_ == kSocketTypeTCP) {
-    socket = new TCPSocket(extension_->id());
+    socket = new TCPSocket(browser_context(), extension_->id());
   } else if (socket_type_ == kSocketTypeUDP) {
     socket =
         new UDPSocket(std::move(socket_), std::move(socket_receiver_request_),
@@ -463,15 +462,27 @@
     return;
   }
 
-  int result =
-      socket->Listen(params_->address, params_->port,
-                     params_->backlog.get() ? *params_->backlog : 5, &error_);
-  SetResult(std::make_unique<base::Value>(result));
-  if (result != net::OK) {
+  socket->Listen(params_->address, params_->port,
+                 params_->backlog.get() ? *params_->backlog : 5,
+                 base::BindOnce(&SocketListenFunction::OnCompleted, this));
+}
+
+void SocketListenFunction::OnCompleted(int result,
+                                       const std::string& error_msg) {
+  DCHECK_NE(net::ERR_IO_PENDING, result);
+  Socket* socket = GetSocket(params_->socket_id);
+  if (!socket) {
+    error_ = kSocketNotFoundError;
+    SetResult(std::make_unique<base::Value>(-1));
     AsyncWorkCompleted();
     return;
   }
-
+  SetResult(std::make_unique<base::Value>(result));
+  if (result != net::OK) {
+    error_ = error_msg;
+    AsyncWorkCompleted();
+    return;
+  }
   OpenFirewallHole(params_->address, params_->socket_id, socket);
 }
 
@@ -488,21 +499,27 @@
 void SocketAcceptFunction::AsyncWorkStart() {
   Socket* socket = GetSocket(params_->socket_id);
   if (socket) {
-    socket->Accept(base::Bind(&SocketAcceptFunction::OnAccept, this));
+    socket->Accept(base::BindOnce(&SocketAcceptFunction::OnAccept, this));
   } else {
     error_ = kSocketNotFoundError;
-    OnAccept(-1, NULL);
+    OnAccept(net::ERR_FAILED, nullptr, base::nullopt,
+             mojo::ScopedDataPipeConsumerHandle(),
+             mojo::ScopedDataPipeProducerHandle());
   }
 }
 
 void SocketAcceptFunction::OnAccept(
     int result_code,
-    std::unique_ptr<net::TCPClientSocket> socket) {
+    network::mojom::TCPConnectedSocketPtr socket,
+    const base::Optional<net::IPEndPoint>& remote_addr,
+    mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
+    mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
   std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
   result->SetInteger(kResultCodeKey, result_code);
-  if (socket) {
+  if (result_code == net::OK) {
     Socket* client_socket =
-        new TCPSocket(std::move(socket), extension_id(), true);
+        new TCPSocket(std::move(socket), std::move(receive_pipe_handle),
+                      std::move(send_pipe_handle), remote_addr, extension_id());
     result->SetInteger(kSocketIdKey, AddSocket(client_socket));
   }
   SetResult(std::move(result));
@@ -529,7 +546,7 @@
   }
 
   socket->Read(params_->buffer_size.get() ? *params_->buffer_size : 4096,
-               base::BindRepeating(&SocketReadFunction::OnCompleted, this));
+               base::BindOnce(&SocketReadFunction::OnCompleted, this));
 }
 
 void SocketReadFunction::OnCompleted(int bytes_read,
@@ -731,18 +748,25 @@
   return true;
 }
 
-void SocketSetKeepAliveFunction::Work() {
-  bool result = false;
+void SocketSetKeepAliveFunction::AsyncWorkStart() {
   Socket* socket = GetSocket(params_->socket_id);
-  if (socket) {
-    int delay = 0;
-    if (params_->delay.get())
-      delay = *params_->delay;
-    result = socket->SetKeepAlive(params_->enable, delay);
-  } else {
+  if (!socket) {
+    SetResult(std::make_unique<base::Value>(false));
     error_ = kSocketNotFoundError;
+    AsyncWorkCompleted();
+    return;
   }
-  SetResult(std::make_unique<base::Value>(result));
+  int delay = 0;
+  if (params_->delay.get())
+    delay = *params_->delay;
+  socket->SetKeepAlive(
+      params_->enable, delay,
+      base::BindOnce(&SocketSetKeepAliveFunction::OnCompleted, this));
+}
+
+void SocketSetKeepAliveFunction::OnCompleted(bool success) {
+  SetResult(std::make_unique<base::Value>(success));
+  AsyncWorkCompleted();
 }
 
 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {}
@@ -755,14 +779,22 @@
   return true;
 }
 
-void SocketSetNoDelayFunction::Work() {
-  bool result = false;
+void SocketSetNoDelayFunction::AsyncWorkStart() {
   Socket* socket = GetSocket(params_->socket_id);
-  if (socket)
-    result = socket->SetNoDelay(params_->no_delay);
-  else
+  if (!socket) {
     error_ = kSocketNotFoundError;
-  SetResult(std::make_unique<base::Value>(result));
+    SetResult(std::make_unique<base::Value>(false));
+    AsyncWorkCompleted();
+    return;
+  }
+  socket->SetNoDelay(
+      params_->no_delay,
+      base::BindOnce(&SocketSetNoDelayFunction::OnCompleted, this));
+}
+
+void SocketSetNoDelayFunction::OnCompleted(bool success) {
+  SetResult(std::make_unique<base::Value>(success));
+  AsyncWorkCompleted();
 }
 
 SocketGetInfoFunction::SocketGetInfoFunction() {}
@@ -1084,8 +1116,6 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   params_ = api::socket::Secure::Params::Create(*args_);
   EXTENSION_FUNCTION_VALIDATE(params_.get());
-  url_request_getter_ = content::BrowserContext::GetDefaultStoragePartition(
-      browser_context())->GetURLRequestContext();
   return true;
 }
 
@@ -1103,8 +1133,7 @@
   }
 
   // Make sure that the socket is a TCP client socket.
-  if (socket->GetSocketType() != Socket::TYPE_TCP ||
-      static_cast<TCPSocket*>(socket)->ClientStream() == NULL) {
+  if (socket->GetSocketType() != Socket::TYPE_TCP) {
     SetResult(std::make_unique<base::Value>(net::ERR_INVALID_ARGUMENT));
     error_ = kSecureSocketTypeError;
     AsyncWorkCompleted();
@@ -1118,31 +1147,32 @@
     return;
   }
 
-  net::URLRequestContext* url_request_context =
-      url_request_getter_->GetURLRequestContext();
-
-  TLSSocket::UpgradeSocketToTLS(
-      socket, url_request_context->ssl_config_service(),
-      url_request_context->cert_verifier(),
-      url_request_context->transport_security_state(),
-      url_request_context->cert_transparency_verifier(),
-      url_request_context->ct_policy_enforcer(), extension_id(),
+  TCPSocket* tcp_socket = static_cast<TCPSocket*>(socket);
+  tcp_socket->UpgradeToTLS(
       params_->options.get(),
-      base::Bind(&SocketSecureFunction::TlsConnectDone, this));
+      base::BindOnce(&SocketSecureFunction::TlsConnectDone, this));
 }
 
-void SocketSecureFunction::TlsConnectDone(std::unique_ptr<TLSSocket> socket,
-                                          int result) {
-  // if an error occurred, socket MUST be NULL.
-  DCHECK(result == net::OK || socket == NULL);
-
-  if (socket && result == net::OK) {
-    ReplaceSocket(params_->socket_id, socket.release());
-  } else {
+void SocketSecureFunction::TlsConnectDone(
+    int result,
+    network::mojom::TLSClientSocketPtr tls_socket,
+    const net::IPEndPoint& local_addr,
+    const net::IPEndPoint& peer_addr,
+    mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
+    mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
+  if (result != net::OK) {
     RemoveSocket(params_->socket_id);
     error_ = net::ErrorToString(result);
+    results_ = api::socket::Secure::Results::Create(result);
+    AsyncWorkCompleted();
+    return;
   }
 
+  auto socket =
+      std::make_unique<TLSSocket>(std::move(tls_socket), local_addr, peer_addr,
+                                  std::move(receive_pipe_handle),
+                                  std::move(send_pipe_handle), extension_id());
+  ReplaceSocket(params_->socket_id, socket.release());
   results_ = api::socket::Secure::Results::Create(result);
   AsyncWorkCompleted();
 }
diff --git a/extensions/browser/api/socket/socket_api.h b/extensions/browser/api/socket/socket_api.h
index cf52938..eae243f 100644
--- a/extensions/browser/api/socket/socket_api.h
+++ b/extensions/browser/api/socket/socket_api.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <memory>
 #include <string>
 
 #include "base/gtest_prod_util.h"
@@ -41,7 +42,6 @@
 
 namespace extensions {
 class Socket;
-class TLSSocket;
 
 // A simple interface to ApiResourceManager<Socket> or derived class. The goal
 // of this interface is to allow Socket API functions to use distinct instances
@@ -184,8 +184,10 @@
   FRIEND_TEST_ALL_PREFIXES(SocketUnitTest, Create);
   enum SocketType { kSocketTypeInvalid = -1, kSocketTypeTCP, kSocketTypeUDP };
 
+  // These two fields are only applicable if |socket_type_| is UDP.
   network::mojom::UDPSocketPtrInfo socket_;
   network::mojom::UDPSocketReceiverRequest socket_receiver_request_;
+
   std::unique_ptr<api::socket::Create::Params> params_;
   SocketType socket_type_;
 };
@@ -278,6 +280,7 @@
   void AsyncWorkStart() override;
 
  private:
+  void OnCompleted(int result, const std::string& error_msg);
   std::unique_ptr<api::socket::Listen::Params> params_;
 };
 
@@ -295,7 +298,11 @@
   void AsyncWorkStart() override;
 
  private:
-  void OnAccept(int result_code, std::unique_ptr<net::TCPClientSocket> socket);
+  void OnAccept(int result_code,
+                network::mojom::TCPConnectedSocketPtr socket,
+                const base::Optional<net::IPEndPoint>& remote_addr,
+                mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
+                mojo::ScopedDataPipeProducerHandle send_pipe_handle);
 
   std::unique_ptr<api::socket::Accept::Params> params_;
 };
@@ -400,9 +407,11 @@
 
   // AsyncApiFunction:
   bool Prepare() override;
-  void Work() override;
+  void AsyncWorkStart() override;
 
  private:
+  void OnCompleted(bool success);
+
   std::unique_ptr<api::socket::SetKeepAlive::Params> params_;
 };
 
@@ -417,9 +426,11 @@
 
   // AsyncApiFunction:
   bool Prepare() override;
-  void Work() override;
+  void AsyncWorkStart() override;
 
  private:
+  void OnCompleted(bool success);
+
   std::unique_ptr<api::socket::SetNoDelay::Params> params_;
 };
 
@@ -561,11 +572,14 @@
   void AsyncWorkStart() override;
 
  private:
-  // Callback from TLSSocket::UpgradeSocketToTLS().
-  void TlsConnectDone(std::unique_ptr<TLSSocket> socket, int result);
+  void TlsConnectDone(int result,
+                      network::mojom::TLSClientSocketPtr tls_socket,
+                      const net::IPEndPoint& local_addr,
+                      const net::IPEndPoint& peer_addr,
+                      mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
+                      mojo::ScopedDataPipeProducerHandle send_pipe_handle);
 
   std::unique_ptr<api::socket::Secure::Params> params_;
-  scoped_refptr<net::URLRequestContextGetter> url_request_getter_;
 
   DISALLOW_COPY_AND_ASSIGN(SocketSecureFunction);
 };
diff --git a/extensions/browser/api/socket/tcp_socket.cc b/extensions/browser/api/socket/tcp_socket.cc
index a1ee755..e80bd771 100644
--- a/extensions/browser/api/socket/tcp_socket.cc
+++ b/extensions/browser/api/socket/tcp_socket.cc
@@ -4,21 +4,49 @@
 
 #include "extensions/browser/api/socket/tcp_socket.h"
 
+#include <utility>
+
 #include "base/callback_helpers.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
 #include "extensions/browser/api/api_resource.h"
+#include "extensions/browser/api/socket/mojo_data_pump.h"
 #include "net/base/address_list.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
-#include "net/log/net_log_source.h"
-#include "net/socket/tcp_client_socket.h"
+#include "net/base/url_util.h"
+#include "services/network/public/mojom/ssl_config.mojom.h"
 
 namespace extensions {
 
+namespace {
+
+// Returns true if successfully parsed the SSL protocol version that is
+// represented by a string. Returns false if |version_str| is invalid.
+bool SSLProtocolVersionFromString(const std::string& version_str,
+                                  network::mojom::SSLVersion* version_out) {
+  if (version_str == "tls1") {
+    *version_out = network::mojom::SSLVersion::kTLS1;
+    return true;
+  }
+  if (version_str == "tls1.1") {
+    *version_out = network::mojom::SSLVersion::kTLS11;
+    return true;
+  }
+  if (version_str == "tls1.2") {
+    *version_out = network::mojom::SSLVersion::kTLS12;
+    return true;
+  }
+  return false;
+}
+
+}  // namespace
+
 const char kTCPSocketTypeInvalidError[] =
     "Cannot call both connect and listen on the same socket.";
 const char kSocketListenError[] = "Could not listen on the specified port.";
@@ -45,38 +73,31 @@
   return g_server_factory.Pointer();
 }
 
-TCPSocket::TCPSocket(const std::string& owner_extension_id)
-    : Socket(owner_extension_id), socket_mode_(UNKNOWN) {}
-
-TCPSocket::TCPSocket(std::unique_ptr<net::TCPClientSocket> tcp_client_socket,
-                     const std::string& owner_extension_id,
-                     bool is_connected)
-    : Socket(owner_extension_id),
-      socket_(std::move(tcp_client_socket)),
-      socket_mode_(CLIENT) {
-  this->is_connected_ = is_connected;
-}
-
-TCPSocket::TCPSocket(std::unique_ptr<net::TCPServerSocket> tcp_server_socket,
+TCPSocket::TCPSocket(content::BrowserContext* browser_context,
                      const std::string& owner_extension_id)
     : Socket(owner_extension_id),
-      server_socket_(std::move(tcp_server_socket)),
-      socket_mode_(SERVER) {}
+      browser_context_(browser_context),
+      socket_mode_(UNKNOWN),
+      mojo_data_pump_(nullptr),
+      task_runner_(base::SequencedTaskRunnerHandle::Get()),
+      weak_factory_(this) {}
 
-// static
-TCPSocket* TCPSocket::CreateSocketForTesting(
-    std::unique_ptr<net::TCPClientSocket> tcp_client_socket,
-    const std::string& owner_extension_id,
-    bool is_connected) {
-  return new TCPSocket(std::move(tcp_client_socket), owner_extension_id,
-                       is_connected);
-}
+TCPSocket::TCPSocket(network::mojom::TCPConnectedSocketPtr socket,
+                     mojo::ScopedDataPipeConsumerHandle receive_stream,
+                     mojo::ScopedDataPipeProducerHandle send_stream,
+                     const base::Optional<net::IPEndPoint>& remote_addr,
+                     const std::string& owner_extension_id)
+    : Socket(owner_extension_id),
+      browser_context_(nullptr),
+      socket_mode_(CLIENT),
+      client_socket_(std::move(socket)),
+      mojo_data_pump_(std::make_unique<MojoDataPump>(std::move(receive_stream),
+                                                     std::move(send_stream))),
+      task_runner_(base::SequencedTaskRunnerHandle::Get()),
+      peer_addr_(remote_addr),
 
-// static
-TCPSocket* TCPSocket::CreateServerSocketForTesting(
-    std::unique_ptr<net::TCPServerSocket> tcp_server_socket,
-    const std::string& owner_extension_id) {
-  return new TCPSocket(std::move(tcp_server_socket), owner_extension_id);
+      weak_factory_(this) {
+  is_connected_ = true;
 }
 
 TCPSocket::~TCPSocket() {
@@ -84,48 +105,57 @@
 }
 
 void TCPSocket::Connect(const net::AddressList& address,
-                        const CompletionCallback& callback) {
-  DCHECK(!callback.is_null());
+                        net::CompletionOnceCallback callback) {
+  DCHECK(callback);
 
-  if (socket_mode_ == SERVER || !connect_callback_.is_null()) {
-    callback.Run(net::ERR_CONNECTION_FAILED);
+  if (socket_mode_ == SERVER || connect_callback_) {
+    std::move(callback).Run(net::ERR_CONNECTION_FAILED);
     return;
   }
 
   if (is_connected_) {
-    callback.Run(net::ERR_SOCKET_IS_CONNECTED);
+    std::move(callback).Run(net::ERR_SOCKET_IS_CONNECTED);
     return;
   }
 
-  DCHECK(!server_socket_.get());
+  DCHECK(!server_socket_);
   socket_mode_ = CLIENT;
-  connect_callback_ = callback;
+  connect_callback_ = std::move(callback);
 
-  int result = net::ERR_CONNECTION_FAILED;
-  if (!is_connected_) {
-    socket_.reset(
-        new net::TCPClientSocket(address, NULL, NULL, net::NetLogSource()));
-    result = socket_->Connect(
-        base::Bind(&TCPSocket::OnConnectComplete, base::Unretained(this)));
-  }
+  // |completion_callback| is called on current thread.
+  network::mojom::NetworkContext::CreateTCPConnectedSocketCallback
+      completion_callback = base::BindOnce(&TCPSocket::OnConnectComplete,
+                                           weak_factory_.GetWeakPtr());
 
-  if (result != net::ERR_IO_PENDING)
-    OnConnectComplete(result);
+  // |completion_callback_ui| is called on the UI thread.
+  network::mojom::NetworkContext::CreateTCPConnectedSocketCallback
+      completion_callback_ui =
+          base::BindOnce(&TCPSocket::OnConnectCompleteOnUIThread, task_runner_,
+                         std::move(completion_callback));
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&TCPSocket::ConnectOnUIThread, storage_partition_,
+                     browser_context_, address,
+                     mojo::MakeRequest(&client_socket_),
+                     std::move(completion_callback_ui)));
 }
 
 void TCPSocket::Disconnect(bool socket_destroying) {
   is_connected_ = false;
-  if (socket_.get())
-    socket_->Disconnect();
-  server_socket_.reset(NULL);
+  local_addr_ = base::nullopt;
+  peer_addr_ = base::nullopt;
+  mojo_data_pump_ = nullptr;
+  client_socket_.reset();
+  server_socket_.reset();
+  listen_callback_.Reset();
   connect_callback_.Reset();
+  accept_callback_.Reset();
   // TODO(devlin): Should we do this for all callbacks?
-  if (!read_callback_.is_null()) {
-    base::ResetAndReturn(&read_callback_)
+  if (read_callback_) {
+    std::move(read_callback_)
         .Run(net::ERR_CONNECTION_CLOSED, nullptr, socket_destroying);
   }
-  accept_callback_.Reset();
-  accept_socket_.reset(NULL);
 }
 
 void TCPSocket::Bind(const std::string& address,
@@ -134,42 +164,30 @@
   callback.Run(net::ERR_FAILED);
 }
 
-void TCPSocket::Read(int count, const ReadCompletionCallback& callback) {
-  DCHECK(!callback.is_null());
+void TCPSocket::Read(int count, ReadCompletionCallback callback) {
+  DCHECK(callback);
 
   const bool socket_destroying = false;
   if (socket_mode_ != CLIENT) {
-    callback.Run(net::ERR_FAILED, nullptr, socket_destroying);
+    std::move(callback).Run(net::ERR_FAILED, nullptr, socket_destroying);
     return;
   }
 
-  if (!read_callback_.is_null() || !connect_callback_.is_null()) {
+  if (!mojo_data_pump_) {
+    std::move(callback).Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr,
+                            socket_destroying);
+    return;
+  }
+  if (mojo_data_pump_->HasPendingRead() || connect_callback_) {
     // It's illegal to read a net::TCPSocket while a pending Connect or Read is
     // already in progress.
-    callback.Run(net::ERR_IO_PENDING, nullptr, socket_destroying);
+    std::move(callback).Run(net::ERR_IO_PENDING, nullptr, socket_destroying);
     return;
   }
 
-  if (count < 0) {
-    callback.Run(net::ERR_INVALID_ARGUMENT, nullptr, socket_destroying);
-    return;
-  }
-
-  if (!socket_.get() || !is_connected_) {
-    callback.Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr, socket_destroying);
-    return;
-  }
-
-  read_callback_ = callback;
-  scoped_refptr<net::IOBuffer> io_buffer = new net::IOBuffer(count);
-  int result = socket_->Read(
-      io_buffer.get(),
-      count,
-      base::Bind(
-          &TCPSocket::OnReadComplete, base::Unretained(this), io_buffer));
-
-  if (result != net::ERR_IO_PENDING)
-    OnReadComplete(io_buffer, result);
+  read_callback_ = std::move(callback);
+  mojo_data_pump_->Read(count, base::BindOnce(&TCPSocket::OnReadComplete,
+                                              base::Unretained(this)));
 }
 
 void TCPSocket::RecvFrom(int count,
@@ -185,85 +203,105 @@
   callback.Run(net::ERR_FAILED);
 }
 
-bool TCPSocket::SetKeepAlive(bool enable, int delay) {
-  if (!socket_.get())
-    return false;
-  return socket_->SetKeepAlive(enable, delay);
-}
-
-bool TCPSocket::SetNoDelay(bool no_delay) {
-  if (!socket_.get())
-    return false;
-  return socket_->SetNoDelay(no_delay);
-}
-
-int TCPSocket::Listen(const std::string& address,
-                      uint16_t port,
-                      int backlog,
-                      std::string* error_msg) {
-  if (socket_mode_ == CLIENT) {
-    *error_msg = kTCPSocketTypeInvalidError;
-    return net::ERR_NOT_IMPLEMENTED;
+void TCPSocket::SetKeepAlive(bool enable,
+                             int delay,
+                             SetKeepAliveCallback callback) {
+  if (!client_socket_) {
+    std::move(callback).Run(net::ERR_FAILED);
+    return;
   }
-  DCHECK(!socket_.get());
+  client_socket_->SetKeepAlive(enable, delay, std::move(callback));
+}
+
+void TCPSocket::SetNoDelay(bool no_delay, SetNoDelayCallback callback) {
+  if (!client_socket_) {
+    std::move(callback).Run(net::ERR_FAILED);
+    return;
+  }
+  client_socket_->SetNoDelay(no_delay, std::move(callback));
+}
+
+void TCPSocket::Listen(const std::string& address,
+                       uint16_t port,
+                       int backlog,
+                       ListenCallback callback) {
+  DCHECK(!server_socket_);
+  DCHECK(!client_socket_);
+  DCHECK(!listen_callback_);
+
+  if (socket_mode_ == CLIENT) {
+    std::move(callback).Run(net::ERR_NOT_IMPLEMENTED,
+                            kTCPSocketTypeInvalidError);
+    return;
+  }
+
+  net::IPEndPoint ip_end_point;
+  if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) {
+    std::move(callback).Run(net::ERR_INVALID_ARGUMENT, "");
+    return;
+  }
+
   socket_mode_ = SERVER;
 
-  if (!server_socket_.get()) {
-    server_socket_.reset(new net::TCPServerSocket(NULL, net::NetLogSource()));
-  }
+  listen_callback_ = std::move(callback);
 
-  int result = server_socket_->ListenWithAddressAndPort(address, port, backlog);
-  if (result) {
-    server_socket_.reset();
-    *error_msg = kSocketListenError;
-  }
-  return result;
+  // |completion_callback| is called on current thread.
+  network::mojom::NetworkContext::CreateTCPServerSocketCallback
+      completion_callback = base::BindOnce(&TCPSocket::OnListenComplete,
+                                           weak_factory_.GetWeakPtr());
+
+  // |completion_callback_ui| is called on the UI thread.
+  network::mojom::NetworkContext::CreateTCPServerSocketCallback
+      completion_callback_ui =
+          base::BindOnce(&TCPSocket::OnListenCompleteOnUIThread, task_runner_,
+                         std::move(completion_callback));
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&TCPSocket::ListenOnUIThread, storage_partition_,
+                     browser_context_, ip_end_point, backlog,
+                     mojo::MakeRequest(&server_socket_),
+                     std::move(completion_callback_ui)));
 }
 
-void TCPSocket::Accept(const AcceptCompletionCallback& callback) {
+void TCPSocket::Accept(AcceptCompletionCallback callback) {
   if (socket_mode_ != SERVER || !server_socket_.get()) {
-    callback.Run(net::ERR_FAILED, NULL);
+    std::move(callback).Run(net::ERR_FAILED, nullptr, base::nullopt,
+                            mojo::ScopedDataPipeConsumerHandle(),
+                            mojo::ScopedDataPipeProducerHandle());
     return;
   }
 
   // Limits to only 1 blocked accept call.
-  if (!accept_callback_.is_null()) {
-    callback.Run(net::ERR_FAILED, NULL);
+  if (accept_callback_) {
+    std::move(callback).Run(net::ERR_FAILED, nullptr, base::nullopt,
+                            mojo::ScopedDataPipeConsumerHandle(),
+                            mojo::ScopedDataPipeProducerHandle());
     return;
   }
 
-  int result = server_socket_->Accept(
-      &accept_socket_,
-      base::Bind(&TCPSocket::OnAccept, base::Unretained(this)));
-  if (result == net::ERR_IO_PENDING) {
-    accept_callback_ = callback;
-  } else if (result == net::OK) {
-    accept_callback_ = callback;
-    this->OnAccept(result);
-  } else {
-    callback.Run(result, NULL);
-  }
+  accept_callback_ = std::move(callback);
+  server_socket_->Accept(
+      nullptr /* observer */,
+      base::BindOnce(&TCPSocket::OnAccept, base::Unretained(this)));
 }
 
 bool TCPSocket::IsConnected() {
-  RefreshConnectionStatus();
   return is_connected_;
 }
 
 bool TCPSocket::GetPeerAddress(net::IPEndPoint* address) {
-  if (!socket_.get())
+  if (!peer_addr_)
     return false;
-  return !socket_->GetPeerAddress(address);
+  *address = peer_addr_.value();
+  return true;
 }
 
 bool TCPSocket::GetLocalAddress(net::IPEndPoint* address) {
-  if (socket_.get()) {
-    return !socket_->GetLocalAddress(address);
-  } else if (server_socket_.get()) {
-    return !server_socket_->GetLocalAddress(address);
-  } else {
+  if (!local_addr_)
     return false;
-  }
+  *address = local_addr_.value();
+  return true;
 }
 
 Socket::SocketType TCPSocket::GetSocketType() const { return Socket::TYPE_TCP; }
@@ -271,97 +309,265 @@
 int TCPSocket::WriteImpl(net::IOBuffer* io_buffer,
                          int io_buffer_size,
                          const net::CompletionCallback& callback) {
-  if (socket_mode_ != CLIENT)
-    return net::ERR_FAILED;
-  else if (!socket_.get() || !IsConnected())
+  if (!mojo_data_pump_)
     return net::ERR_SOCKET_NOT_CONNECTED;
-  else
-    return socket_->Write(io_buffer, io_buffer_size, callback,
-                          Socket::GetNetworkTrafficAnnotationTag());
+
+  mojo_data_pump_->Write(io_buffer, io_buffer_size,
+                         base::BindOnce(&TCPSocket::OnWriteComplete,
+                                        base::Unretained(this), callback));
+  return net::ERR_IO_PENDING;
 }
 
-void TCPSocket::RefreshConnectionStatus() {
-  if (!is_connected_)
+// static
+void TCPSocket::ConnectOnUIThread(
+    content::StoragePartition* storage_partition,
+    content::BrowserContext* browser_context,
+    const net::AddressList& remote_addr_list,
+    network::mojom::TCPConnectedSocketRequest request,
+    network::mojom::NetworkContext::CreateTCPConnectedSocketCallback
+        completion_callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  if (!storage_partition) {
+    storage_partition =
+        content::BrowserContext::GetDefaultStoragePartition(browser_context);
+  }
+  storage_partition->GetNetworkContext()->CreateTCPConnectedSocket(
+      base::nullopt, remote_addr_list,
+      net::MutableNetworkTrafficAnnotationTag(
+          Socket::GetNetworkTrafficAnnotationTag()),
+      std::move(request), nullptr /* observer */,
+      std::move(completion_callback));
+}
+
+// static
+void TCPSocket::OnConnectCompleteOnUIThread(
+    scoped_refptr<base::SequencedTaskRunner> original_task_runner,
+    network::mojom::NetworkContext::CreateTCPConnectedSocketCallback callback,
+    int result,
+    const base::Optional<net::IPEndPoint>& local_addr,
+    const base::Optional<net::IPEndPoint>& peer_addr,
+    mojo::ScopedDataPipeConsumerHandle receive_stream,
+    mojo::ScopedDataPipeProducerHandle send_stream) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  original_task_runner->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(callback), result, local_addr, peer_addr,
+                     std::move(receive_stream), std::move(send_stream)));
+}
+
+void TCPSocket::OnConnectComplete(
+    int result,
+    const base::Optional<net::IPEndPoint>& local_addr,
+    const base::Optional<net::IPEndPoint>& peer_addr,
+    mojo::ScopedDataPipeConsumerHandle receive_stream,
+    mojo::ScopedDataPipeProducerHandle send_stream) {
+  DCHECK(!is_connected_);
+  DCHECK(connect_callback_);
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+  if (result == net::OK) {
+    is_connected_ = true;
+    local_addr_ = local_addr;
+    peer_addr_ = peer_addr;
+    mojo_data_pump_ = std::make_unique<MojoDataPump>(std::move(receive_stream),
+                                                     std::move(send_stream));
+  }
+  std::move(connect_callback_).Run(result);
+}
+
+// static
+void TCPSocket::ListenOnUIThread(
+    content::StoragePartition* storage_partition,
+    content::BrowserContext* browser_context,
+    const net::IPEndPoint& local_addr,
+    int backlog,
+    network::mojom::TCPServerSocketRequest request,
+    network::mojom::NetworkContext::CreateTCPServerSocketCallback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  if (!storage_partition) {
+    storage_partition =
+        content::BrowserContext::GetDefaultStoragePartition(browser_context);
+  }
+  storage_partition->GetNetworkContext()->CreateTCPServerSocket(
+      local_addr, backlog,
+      net::MutableNetworkTrafficAnnotationTag(
+          Socket::GetNetworkTrafficAnnotationTag()),
+      std::move(request), std::move(callback));
+}
+
+// static
+void TCPSocket::OnListenCompleteOnUIThread(
+    const scoped_refptr<base::SequencedTaskRunner>& original_task_runner,
+    network::mojom::NetworkContext::CreateTCPServerSocketCallback callback,
+    int result,
+    const base::Optional<net::IPEndPoint>& local_addr) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  original_task_runner->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), result, local_addr));
+}
+
+void TCPSocket::OnListenComplete(
+    int result,
+    const base::Optional<net::IPEndPoint>& local_addr) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+  DCHECK(listen_callback_);
+
+  if (result != net::OK) {
+    server_socket_.reset();
+    std::move(listen_callback_).Run(result, kSocketListenError);
     return;
-  if (server_socket_)
-    return;
-  if (!socket_->IsConnected()) {
+  }
+  local_addr_ = local_addr;
+  std::move(listen_callback_).Run(result, "");
+}
+
+content::StoragePartition* TCPSocket::GetStoragePartitionHelper() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  return storage_partition_
+             ? storage_partition_
+             : content::BrowserContext::GetDefaultStoragePartition(
+                   browser_context_);
+}
+
+void TCPSocket::OnAccept(int result,
+                         const base::Optional<net::IPEndPoint>& remote_addr,
+                         network::mojom::TCPConnectedSocketPtr connected_socket,
+                         mojo::ScopedDataPipeConsumerHandle receive_stream,
+                         mojo::ScopedDataPipeProducerHandle send_stream) {
+  DCHECK(accept_callback_);
+  std::move(accept_callback_)
+      .Run(result, std::move(connected_socket), remote_addr,
+           std::move(receive_stream), std::move(send_stream));
+}
+
+void TCPSocket::OnWriteComplete(const net::CompletionCallback& callback,
+                                int result) {
+  if (result < 0) {
+    // Write side has terminated. This can be an error or a graceful close.
+    // TCPSocketEventDispatcher doesn't distinguish between the two.
     Disconnect(false /* socket_destroying */);
   }
+  callback.Run(result);
 }
 
-void TCPSocket::OnConnectComplete(int result) {
-  DCHECK(!connect_callback_.is_null());
-  DCHECK(!is_connected_);
-  is_connected_ = result == net::OK;
+void TCPSocket::OnReadComplete(int result,
+                               scoped_refptr<net::IOBuffer> io_buffer) {
+  DCHECK(read_callback_);
 
-  // The completion callback may re-enter TCPSocket, e.g. to Read(); therefore
-  // we reset |connect_callback_| before calling it.
-  CompletionCallback connect_callback = connect_callback_;
-  connect_callback_.Reset();
-  connect_callback.Run(result);
-}
-
-void TCPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer,
-                               int result) {
-  DCHECK(!read_callback_.is_null());
-  read_callback_.Run(result, io_buffer, false /* socket_destroying */);
-  read_callback_.Reset();
-}
-
-void TCPSocket::OnAccept(int result) {
-  DCHECK(!accept_callback_.is_null());
-  if (result == net::OK && accept_socket_.get()) {
-    accept_callback_.Run(result,
-                         base::WrapUnique(static_cast<net::TCPClientSocket*>(
-                             accept_socket_.release())));
-  } else {
-    accept_callback_.Run(result, NULL);
+  // Use a local variable for |read_callback_|, because otherwise Disconnect()
+  // will try to invoke |read_callback_| with a hardcoded result code.
+  ReadCompletionCallback callback = std::move(read_callback_);
+  if (result < 0) {
+    // Read side has terminated. This can be an error or a graceful close.
+    // TCPSocketEventDispatcher doesn't distinguish between the two.
+    Disconnect(false /* socket_destroying */);
   }
-  accept_callback_.Reset();
+  std::move(callback).Run(result, io_buffer, false /* socket_destroying */);
 }
 
-void TCPSocket::Release() {
-  // Release() is only invoked when the underlying sockets are taken (via
-  // ClientStream()) by TLSSocket. TLSSocket only supports CLIENT-mode
-  // sockets.
-  DCHECK(!server_socket_.release() && !accept_socket_.release() &&
-         socket_mode_ == CLIENT)
-      << "Called in server mode.";
-
-  // Release() doesn't disconnect the underlying sockets, but it does
-  // disconnect them from this TCPSocket.
-  is_connected_ = false;
-
-  connect_callback_.Reset();
-  read_callback_.Reset();
-  accept_callback_.Reset();
-
-  DCHECK(socket_.get()) << "Called on null client socket.";
-  ignore_result(socket_.release());
+void TCPSocket::OnUpgradeToTLSComplete(
+    UpgradeToTLSCallback callback,
+    network::mojom::TLSClientSocketPtr tls_socket,
+    const net::IPEndPoint& local_addr,
+    const net::IPEndPoint& peer_addr,
+    int result,
+    mojo::ScopedDataPipeConsumerHandle receive_stream,
+    mojo::ScopedDataPipeProducerHandle send_stream) {
+  std::move(callback).Run(result, std::move(tls_socket), local_addr, peer_addr,
+                          std::move(receive_stream), std::move(send_stream));
 }
 
-net::TCPClientSocket* TCPSocket::ClientStream() {
-  if (socket_mode_ != CLIENT || GetSocketType() != TYPE_TCP)
-    return NULL;
-  return socket_.get();
+void TCPSocket::UpgradeToTLS(api::socket::SecureOptions* options,
+                             UpgradeToTLSCallback callback) {
+  if (!client_socket_ || !mojo_data_pump_ ||
+      mojo_data_pump_->HasPendingRead() || mojo_data_pump_->HasPendingWrite()) {
+    std::move(callback).Run(net::ERR_FAILED, nullptr, net::IPEndPoint(),
+                            net::IPEndPoint(),
+                            mojo::ScopedDataPipeConsumerHandle(),
+                            mojo::ScopedDataPipeProducerHandle());
+    return;
+  }
+  if (!local_addr_ || !peer_addr_) {
+    DVLOG(1) << "Could not get local address or peer address.";
+    std::move(callback).Run(net::ERR_FAILED, nullptr, net::IPEndPoint(),
+                            net::IPEndPoint(),
+                            mojo::ScopedDataPipeConsumerHandle(),
+                            mojo::ScopedDataPipeProducerHandle());
+    return;
+  }
+
+  // Convert any U-LABELs to A-LABELs.
+  url::CanonHostInfo host_info;
+  std::string canon_host = net::CanonicalizeHost(hostname(), &host_info);
+
+  // Canonicalization shouldn't fail: the socket is already connected with a
+  // host, using this hostname.
+  if (host_info.family == url::CanonHostInfo::BROKEN) {
+    DVLOG(1) << "Could not canonicalize hostname";
+    std::move(callback).Run(net::ERR_FAILED, nullptr, net::IPEndPoint(),
+                            net::IPEndPoint(),
+                            mojo::ScopedDataPipeConsumerHandle(),
+                            mojo::ScopedDataPipeProducerHandle());
+    return;
+  }
+
+  mojo_data_pump_ = nullptr;
+  network::mojom::TLSClientSocketOptionsPtr mojo_socket_options =
+      network::mojom::TLSClientSocketOptions::New();
+  if (options && options->tls_version.get()) {
+    network::mojom::SSLVersion version_min, version_max;
+    bool has_version_min = false;
+    bool has_version_max = false;
+    api::socket::TLSVersionConstraints* versions = options->tls_version.get();
+    if (versions->min.get()) {
+      has_version_min =
+          SSLProtocolVersionFromString(*versions->min, &version_min);
+    }
+    if (versions->max.get()) {
+      has_version_max =
+          SSLProtocolVersionFromString(*versions->max, &version_max);
+    }
+    if (has_version_min)
+      mojo_socket_options->version_min = version_min;
+    if (has_version_max)
+      mojo_socket_options->version_max = version_max;
+  }
+  network::mojom::TLSClientSocketPtr tls_socket;
+  network::mojom::TLSClientSocketRequest tls_socket_request =
+      mojo::MakeRequest(&tls_socket);
+  net::HostPortPair host_port_pair(canon_host, peer_addr_.value().port());
+  client_socket_->UpgradeToTLS(
+      host_port_pair, std::move(mojo_socket_options),
+      net::MutableNetworkTrafficAnnotationTag(
+          Socket::GetNetworkTrafficAnnotationTag()),
+      std::move(tls_socket_request), nullptr /* observer */,
+      base::BindOnce(&TCPSocket::OnUpgradeToTLSComplete, base::Unretained(this),
+                     std::move(callback), std::move(tls_socket),
+                     local_addr_.value(), peer_addr_.value()));
 }
 
-bool TCPSocket::HasPendingRead() const {
-  return !read_callback_.is_null();
-}
-
-ResumableTCPSocket::ResumableTCPSocket(const std::string& owner_extension_id)
-    : TCPSocket(owner_extension_id),
+ResumableTCPSocket::ResumableTCPSocket(content::BrowserContext* browser_context,
+                                       const std::string& owner_extension_id)
+    : TCPSocket(browser_context, owner_extension_id),
       persistent_(false),
       buffer_size_(0),
       paused_(false) {}
 
 ResumableTCPSocket::ResumableTCPSocket(
-    std::unique_ptr<net::TCPClientSocket> tcp_client_socket,
-    const std::string& owner_extension_id,
-    bool is_connected)
-    : TCPSocket(std::move(tcp_client_socket), owner_extension_id, is_connected),
+    network::mojom::TCPConnectedSocketPtr socket,
+    mojo::ScopedDataPipeConsumerHandle receive_stream,
+    mojo::ScopedDataPipeProducerHandle send_stream,
+    const base::Optional<net::IPEndPoint>& remote_addr,
+    const std::string& owner_extension_id)
+    : TCPSocket(std::move(socket),
+                std::move(receive_stream),
+                std::move(send_stream),
+                remote_addr,
+                owner_extension_id),
       persistent_(false),
       buffer_size_(0),
       paused_(false) {}
@@ -377,8 +583,11 @@
 bool ResumableTCPSocket::IsPersistent() const { return persistent(); }
 
 ResumableTCPServerSocket::ResumableTCPServerSocket(
+    content::BrowserContext* browser_context,
     const std::string& owner_extension_id)
-    : TCPSocket(owner_extension_id), persistent_(false), paused_(false) {}
+    : TCPSocket(browser_context, owner_extension_id),
+      persistent_(false),
+      paused_(false) {}
 
 bool ResumableTCPServerSocket::IsPersistent() const { return persistent(); }
 
diff --git a/extensions/browser/api/socket/tcp_socket.h b/extensions/browser/api/socket/tcp_socket.h
index bdff76ed..f834301 100644
--- a/extensions/browser/api/socket/tcp_socket.h
+++ b/extensions/browser/api/socket/tcp_socket.h
@@ -7,76 +7,88 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <string>
 
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
 #include "extensions/browser/api/socket/socket.h"
+#include "extensions/browser/api/socket/tcp_socket.h"
+#include "extensions/common/api/socket.h"
+#include "net/base/completion_once_callback.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+#include "services/network/public/mojom/tcp_socket.mojom.h"
+#include "services/network/public/mojom/tls_socket.mojom.h"
 
-// This looks like it should be forward-declarable, but it does some tricky
-// moves that make it easier to just include it.
-#include "net/socket/tcp_client_socket.h"
-#include "net/socket/tcp_server_socket.h"
-
-namespace net {
-class Socket;
+namespace content {
+class BrowserContext;
+class StoragePartition;
 }
 
 namespace extensions {
 
+class MojoDataPump;
+
 class TCPSocket : public Socket {
  public:
-  explicit TCPSocket(const std::string& owner_extension_id);
-  TCPSocket(std::unique_ptr<net::TCPClientSocket> tcp_client_socket,
-            const std::string& owner_extension_id,
-            bool is_connected = false);
+  using UpgradeToTLSCallback =
+      base::OnceCallback<void(int,
+                              network::mojom::TLSClientSocketPtr,
+                              const net::IPEndPoint&,
+                              const net::IPEndPoint&,
+                              mojo::ScopedDataPipeConsumerHandle,
+                              mojo::ScopedDataPipeProducerHandle)>;
+
+  // Constuctor for when |socket_mode_| is unknown. The |socket_mode_| will be
+  // filled in when the consumer calls Listen/Connect.
+  TCPSocket(content::BrowserContext* browser_context,
+            const std::string& owner_extension_id);
+
+  // Created using TCPServerSocket::Accept().
+  TCPSocket(network::mojom::TCPConnectedSocketPtr socket,
+            mojo::ScopedDataPipeConsumerHandle receive_stream,
+            mojo::ScopedDataPipeProducerHandle send_stream,
+            const base::Optional<net::IPEndPoint>& remote_addr,
+            const std::string& owner_extension_id);
 
   ~TCPSocket() override;
 
   void Connect(const net::AddressList& address,
-               const CompletionCallback& callback) override;
+               net::CompletionOnceCallback callback) override;
   void Disconnect(bool socket_destroying) override;
   void Bind(const std::string& address,
             uint16_t port,
             const CompletionCallback& callback) override;
-  void Read(int count, const ReadCompletionCallback& callback) override;
+  void Read(int count, ReadCompletionCallback callback) override;
   void RecvFrom(int count, const RecvFromCompletionCallback& callback) override;
   void SendTo(scoped_refptr<net::IOBuffer> io_buffer,
               int byte_count,
               const net::IPEndPoint& address,
               const CompletionCallback& callback) override;
-  bool SetKeepAlive(bool enable, int delay) override;
-  bool SetNoDelay(bool no_delay) override;
-  int Listen(const std::string& address,
-             uint16_t port,
-             int backlog,
-             std::string* error_msg) override;
-  void Accept(const AcceptCompletionCallback& callback) override;
+  void SetKeepAlive(bool enable,
+                    int delay,
+                    SetKeepAliveCallback callback) override;
+  void SetNoDelay(bool no_delay, SetNoDelayCallback callback) override;
+  void Listen(const std::string& address,
+              uint16_t port,
+              int backlog,
+              ListenCallback callback) override;
+  void Accept(AcceptCompletionCallback callback) override;
 
   bool IsConnected() override;
 
   bool GetPeerAddress(net::IPEndPoint* address) override;
   bool GetLocalAddress(net::IPEndPoint* address) override;
 
-  // Like Disconnect(), only Release() doesn't delete the underlying stream
-  // or attempt to close it. Useful when giving away ownership with
-  // ClientStream().
-  virtual void Release();
-
   Socket::SocketType GetSocketType() const override;
 
-  static TCPSocket* CreateSocketForTesting(
-      std::unique_ptr<net::TCPClientSocket> tcp_client_socket,
-      const std::string& owner_extension_id,
-      bool is_connected = false);
-  static TCPSocket* CreateServerSocketForTesting(
-      std::unique_ptr<net::TCPServerSocket> tcp_server_socket,
-      const std::string& owner_extension_id);
+  void UpgradeToTLS(api::socket::SecureOptions* options,
+                    UpgradeToTLSCallback callback);
 
-  // Returns NULL if GetSocketType() isn't TYPE_TCP or if the connection
-  // wasn't set up via Connect() (vs Listen()/Accept()).
-  net::TCPClientSocket* ClientStream();
-
-  // Whether a Read() has been issued, that hasn't come back yet.
-  bool HasPendingRead() const;
+  void SetStoragePartitionForTest(
+      content::StoragePartition* storage_partition) {
+    storage_partition_ = storage_partition;
+  }
 
  protected:
   int WriteImpl(net::IOBuffer* io_buffer,
@@ -84,26 +96,101 @@
                 const net::CompletionCallback& callback) override;
 
  private:
-  void RefreshConnectionStatus();
-  void OnConnectComplete(int result);
-  void OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, int result);
-  void OnAccept(int result);
+  // Connects a client TCP socket. This is done on the UI thread because
+  // StoragePartition::GetNetworkContext() needs to happen on the UI thread.
+  // The completion callback is posted back to the thread on which |this| lives.
+  static void ConnectOnUIThread(
+      content::StoragePartition* storage_partition,
+      content::BrowserContext* browser_context,
+      const net::AddressList& remote_address_list,
+      network::mojom::TCPConnectedSocketRequest request,
+      network::mojom::NetworkContext::CreateTCPConnectedSocketCallback
+          callback);
+  static void OnConnectCompleteOnUIThread(
+      scoped_refptr<base::SequencedTaskRunner> original_task_runner,
+      network::mojom::NetworkContext::CreateTCPConnectedSocketCallback callback,
+      int result,
+      const base::Optional<net::IPEndPoint>& local_addr,
+      const base::Optional<net::IPEndPoint>& peer_addr,
+      mojo::ScopedDataPipeConsumerHandle receive_stream,
+      mojo::ScopedDataPipeProducerHandle send_stream);
+  void OnConnectComplete(int result,
+                         const base::Optional<net::IPEndPoint>& local_addr,
+                         const base::Optional<net::IPEndPoint>& peer_addr,
+                         mojo::ScopedDataPipeConsumerHandle receive_stream,
+                         mojo::ScopedDataPipeProducerHandle send_stream);
 
-  TCPSocket(std::unique_ptr<net::TCPServerSocket> tcp_server_socket,
-            const std::string& owner_extension_id);
+  // Connects a server TCP socket. This is done on the UI thread because
+  // StoragePartition::GetNetworkContext() needs to happen on the UI thread.
+  // The completion callback is posted back to the thread on which |this| lives.
+  static void ListenOnUIThread(
+      content::StoragePartition* storage_partition,
+      content::BrowserContext* browser_context,
+      const net::IPEndPoint& local_addr,
+      int backlog,
+      network::mojom::TCPServerSocketRequest request,
+      network::mojom::NetworkContext::CreateTCPServerSocketCallback callback);
+  static void OnListenCompleteOnUIThread(
+      const scoped_refptr<base::SequencedTaskRunner>& original_task_runner,
+      network::mojom::NetworkContext::CreateTCPServerSocketCallback callback,
+      int result,
+      const base::Optional<net::IPEndPoint>& local_addr);
+  void OnListenComplete(int result,
+                        const base::Optional<net::IPEndPoint>& local_addr);
+  void OnAccept(int result,
+                const base::Optional<net::IPEndPoint>& remote_addr,
+                network::mojom::TCPConnectedSocketPtr connected_socket,
+                mojo::ScopedDataPipeConsumerHandle receive_stream,
+                mojo::ScopedDataPipeProducerHandle send_stream);
+  void OnWriteComplete(const net::CompletionCallback& callback, int result);
+  void OnReadComplete(int result, scoped_refptr<net::IOBuffer> io_buffer);
+  void OnUpgradeToTLSComplete(UpgradeToTLSCallback callback,
+                              network::mojom::TLSClientSocketPtr tls_socket,
+                              const net::IPEndPoint& local_addr,
+                              const net::IPEndPoint& peer_addr,
+                              int result,
+                              mojo::ScopedDataPipeConsumerHandle receive_stream,
+                              mojo::ScopedDataPipeProducerHandle send_stream);
 
-  std::unique_ptr<net::TCPClientSocket> socket_;
-  std::unique_ptr<net::TCPServerSocket> server_socket_;
+  content::StoragePartition* GetStoragePartitionHelper();
 
-  enum SocketMode { UNKNOWN = 0, CLIENT, SERVER, };
+  enum SocketMode {
+    UNKNOWN = 0,
+    CLIENT,
+    SERVER,
+  };
+
+  // |this| doesn't outlive |browser_context_| because |this| is owned by
+  // ApiResourceManager which is a BrowserContextKeyedAPI.
+  content::BrowserContext* browser_context_;
+
   SocketMode socket_mode_;
 
-  CompletionCallback connect_callback_;
+  // CLIENT mode.
+  network::mojom::TCPConnectedSocketPtr client_socket_;
+  // SERVER mode.
+  network::mojom::TCPServerSocketPtr server_socket_;
 
+  net::CompletionOnceCallback connect_callback_;
+  ListenCallback listen_callback_;
+  AcceptCompletionCallback accept_callback_;
   ReadCompletionCallback read_callback_;
 
-  std::unique_ptr<net::StreamSocket> accept_socket_;
-  AcceptCompletionCallback accept_callback_;
+  std::unique_ptr<MojoDataPump> mojo_data_pump_;
+
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+  base::Optional<net::IPEndPoint> local_addr_;
+  base::Optional<net::IPEndPoint> peer_addr_;
+
+  // Only used in tests.
+  content::StoragePartition* storage_partition_ = nullptr;
+
+  // WeakPtr is used when posting tasks to |task_runner_| which might outlive
+  // |this|.
+  base::WeakPtrFactory<TCPSocket> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(TCPSocket);
 };
 
 // TCP Socket instances from the "sockets.tcp" namespace. These are regular
@@ -111,11 +198,14 @@
 // the "sockets.tcp" namespace.
 class ResumableTCPSocket : public TCPSocket {
  public:
-  explicit ResumableTCPSocket(const std::string& owner_extension_id);
-  explicit ResumableTCPSocket(
-      std::unique_ptr<net::TCPClientSocket> tcp_client_socket,
-      const std::string& owner_extension_id,
-      bool is_connected);
+  ResumableTCPSocket(content::BrowserContext* browser_context,
+                     const std::string& owner_extension_id);
+  // Created using TCPServerSocket::Accept().
+  ResumableTCPSocket(network::mojom::TCPConnectedSocketPtr socket,
+                     mojo::ScopedDataPipeConsumerHandle receive_stream,
+                     mojo::ScopedDataPipeProducerHandle send_stream,
+                     const base::Optional<net::IPEndPoint>& remote_addr,
+                     const std::string& owner_extension_id);
 
   ~ResumableTCPSocket() override;
 
@@ -155,7 +245,8 @@
 // defined in the "sockets.tcpServer" namespace.
 class ResumableTCPServerSocket : public TCPSocket {
  public:
-  explicit ResumableTCPServerSocket(const std::string& owner_extension_id);
+  ResumableTCPServerSocket(content::BrowserContext* browser_context,
+                           const std::string& owner_extension_id);
 
   // Overriden from ApiResource
   bool IsPersistent() const override;
diff --git a/extensions/browser/api/socket/tls_socket.cc b/extensions/browser/api/socket/tls_socket.cc
index aa2a4a0..0c39bf0c 100644
--- a/extensions/browser/api/socket/tls_socket.cc
+++ b/extensions/browser/api/socket/tls_socket.cc
@@ -10,307 +10,142 @@
 #include "base/logging.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/api/api_resource.h"
+#include "extensions/browser/api/socket/mojo_data_pump.h"
 #include "net/base/address_list.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
 #include "net/base/url_util.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/socket/client_socket_handle.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/socket/tcp_client_socket.h"
 #include "url/url_canon.h"
 
-namespace {
-
-// Returns the SSL protocol version (as a uint16_t) represented by a string.
-// Returns 0 if the string is invalid.
-uint16_t SSLProtocolVersionFromString(const std::string& version_str) {
-  uint16_t version = 0;  // Invalid.
-  if (version_str == "tls1") {
-    version = net::SSL_PROTOCOL_VERSION_TLS1;
-  } else if (version_str == "tls1.1") {
-    version = net::SSL_PROTOCOL_VERSION_TLS1_1;
-  } else if (version_str == "tls1.2") {
-    version = net::SSL_PROTOCOL_VERSION_TLS1_2;
-  }
-  return version;
-}
-
-void TlsConnectDone(std::unique_ptr<net::SSLClientSocket> ssl_socket,
-                    const std::string& extension_id,
-                    const extensions::TLSSocket::SecureCallback& callback,
-                    int result) {
-  DVLOG(1) << "Got back result " << result << " " << net::ErrorToString(result);
-
-  // No matter how the TLS connection attempt went, the underlying socket's
-  // no longer bound to the original TCPSocket. It belongs to |ssl_socket|,
-  // which is promoted here to a new API-accessible socket (via a TLSSocket
-  // wrapper), or deleted.
-  if (result != net::OK) {
-    callback.Run(nullptr, result);
-    return;
-  };
-
-  // Wrap the StreamSocket in a TLSSocket, which matches the extension socket
-  // API. Set the handle of the socket to the new value, so that it can be
-  // used for read/write/close/etc.
-  std::unique_ptr<extensions::TLSSocket> wrapper(
-      new extensions::TLSSocket(std::move(ssl_socket), extension_id));
-
-  // Caller will end up deleting the prior TCPSocket, once it calls
-  // SetSocket(..,wrapper).
-  callback.Run(std::move(wrapper), result);
-}
-
-}  // namespace
-
 namespace extensions {
 
 const char kTLSSocketTypeInvalidError[] =
     "Cannot listen on a socket that is already connected.";
 
-TLSSocket::TLSSocket(std::unique_ptr<net::StreamSocket> tls_socket,
+TLSSocket::TLSSocket(network::mojom::TLSClientSocketPtr tls_socket,
+                     const net::IPEndPoint& local_addr,
+                     const net::IPEndPoint& peer_addr,
+                     mojo::ScopedDataPipeConsumerHandle receive_stream,
+                     mojo::ScopedDataPipeProducerHandle send_stream,
                      const std::string& owner_extension_id)
-    : ResumableTCPSocket(owner_extension_id),
-      tls_socket_(std::move(tls_socket)) {}
+    : ResumableTCPSocket(nullptr, owner_extension_id),
+      tls_socket_(std::move(tls_socket)),
+      local_addr_(local_addr),
+      peer_addr_(peer_addr),
+      mojo_data_pump_(std::make_unique<MojoDataPump>(std::move(receive_stream),
+                                                     std::move(send_stream))) {
+  DCHECK(tls_socket_);
+  is_connected_ = true;
+}
 
 TLSSocket::~TLSSocket() {
   Disconnect(true /* socket_destroying */);
 }
 
 void TLSSocket::Connect(const net::AddressList& address,
-                        const CompletionCallback& callback) {
-  callback.Run(net::ERR_CONNECTION_FAILED);
+                        net::CompletionOnceCallback callback) {
+  std::move(callback).Run(net::ERR_CONNECTION_FAILED);
 }
 
 void TLSSocket::Disconnect(bool socket_destroying) {
-  if (tls_socket_) {
-    tls_socket_->Disconnect();
-    tls_socket_.reset();
+  is_connected_ = false;
+  tls_socket_.reset();
+  local_addr_ = base::nullopt;
+  peer_addr_ = base::nullopt;
+  mojo_data_pump_ = nullptr;
+  // TODO(devlin): Should we do this for all callbacks?
+  if (read_callback_) {
+    std::move(read_callback_)
+        .Run(net::ERR_CONNECTION_CLOSED, nullptr, socket_destroying);
   }
 }
 
-void TLSSocket::Read(int count, const ReadCompletionCallback& callback) {
-  DCHECK(!callback.is_null());
+void TLSSocket::Read(int count, ReadCompletionCallback callback) {
+  DCHECK(callback);
+  DCHECK(!read_callback_);
 
   const bool socket_destroying = false;
-  if (!read_callback_.is_null()) {
-    callback.Run(net::ERR_IO_PENDING, nullptr, socket_destroying);
+  if (!mojo_data_pump_) {
+    std::move(callback).Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr,
+                            socket_destroying);
     return;
   }
-
-  if (count <= 0) {
-    callback.Run(net::ERR_INVALID_ARGUMENT, nullptr, socket_destroying);
+  if (mojo_data_pump_->HasPendingRead()) {
+    std::move(callback).Run(net::ERR_IO_PENDING, nullptr, socket_destroying);
     return;
   }
-
-  if (!tls_socket_.get()) {
-    callback.Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr, socket_destroying);
-    return;
-  }
-
-  read_callback_ = callback;
-  scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(count));
-  // |tls_socket_| is owned by this class and the callback won't be run once
-  // |tls_socket_| is gone (as in an a call to Disconnect()). Therefore, it is
-  // safe to use base::Unretained() here.
-  int result = tls_socket_->Read(
-      io_buffer.get(),
-      count,
-      base::Bind(
-          &TLSSocket::OnReadComplete, base::Unretained(this), io_buffer));
-
-  if (result != net::ERR_IO_PENDING) {
-    OnReadComplete(io_buffer, result);
-  }
+  read_callback_ = std::move(callback);
+  mojo_data_pump_->Read(count, base::BindOnce(&TLSSocket::OnReadComplete,
+                                              base::Unretained(this)));
 }
 
-void TLSSocket::OnReadComplete(const scoped_refptr<net::IOBuffer>& io_buffer,
-                               int result) {
-  DCHECK(!read_callback_.is_null());
-  base::ResetAndReturn(&read_callback_)
-      .Run(result, io_buffer, false /* socket_destroying */);
-}
-
-int TLSSocket::WriteImpl(net::IOBuffer* io_buffer,
-                         int io_buffer_size,
-                         const net::CompletionCallback& callback) {
-  if (!IsConnected()) {
-    return net::ERR_SOCKET_NOT_CONNECTED;
-  }
-  return tls_socket_->Write(io_buffer, io_buffer_size, callback,
-                            Socket::GetNetworkTrafficAnnotationTag());
-}
-
-bool TLSSocket::SetKeepAlive(bool enable, int delay) {
-  return false;
-}
-
-bool TLSSocket::SetNoDelay(bool no_delay) {
-  return false;
-}
-
-int TLSSocket::Listen(const std::string& address,
-                      uint16_t port,
-                      int backlog,
-                      std::string* error_msg) {
-  *error_msg = kTLSSocketTypeInvalidError;
-  return net::ERR_NOT_IMPLEMENTED;
-}
-
-void TLSSocket::Accept(const AcceptCompletionCallback& callback) {
-  callback.Run(net::ERR_FAILED, NULL);
+void TLSSocket::Listen(const std::string& address,
+                       uint16_t port,
+                       int backlog,
+                       ListenCallback callback) {
+  std::move(callback).Run(net::ERR_NOT_IMPLEMENTED, kTLSSocketTypeInvalidError);
 }
 
 bool TLSSocket::IsConnected() {
-  return tls_socket_.get() && tls_socket_->IsConnected();
+  return is_connected_;
 }
 
 bool TLSSocket::GetPeerAddress(net::IPEndPoint* address) {
-  return IsConnected() && tls_socket_->GetPeerAddress(address);
+  if (!IsConnected())
+    return false;
+  if (!peer_addr_)
+    return false;
+  *address = peer_addr_.value();
+  return true;
 }
 
 bool TLSSocket::GetLocalAddress(net::IPEndPoint* address) {
-  return IsConnected() && tls_socket_->GetLocalAddress(address);
+  if (!IsConnected())
+    return false;
+  if (!local_addr_)
+    return false;
+  *address = local_addr_.value();
+  return true;
 }
 
 Socket::SocketType TLSSocket::GetSocketType() const {
   return Socket::TYPE_TLS;
 }
 
-// static
-void TLSSocket::UpgradeSocketToTLS(
-    Socket* socket,
-    net::SSLConfigService* ssl_config_service,
-    net::CertVerifier* cert_verifier,
-    net::TransportSecurityState* transport_security_state,
-    net::CTVerifier* ct_verifier,
-    net::CTPolicyEnforcer* ct_policy_enforcer,
-    const std::string& extension_id,
-    api::socket::SecureOptions* options,
-    const TLSSocket::SecureCallback& callback) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  TCPSocket* tcp_socket = static_cast<TCPSocket*>(socket);
-  std::unique_ptr<net::SSLClientSocket> null_sock;
+int TLSSocket::WriteImpl(net::IOBuffer* io_buffer,
+                         int io_buffer_size,
+                         const net::CompletionCallback& callback) {
+  if (!mojo_data_pump_)
+    return net::ERR_SOCKET_NOT_CONNECTED;
+  mojo_data_pump_->Write(io_buffer, io_buffer_size,
+                         base::BindOnce(&TLSSocket::OnWriteComplete,
+                                        base::Unretained(this), callback));
+  return net::ERR_IO_PENDING;
+}
 
-  if (!tcp_socket || tcp_socket->GetSocketType() != Socket::TYPE_TCP ||
-      !tcp_socket->ClientStream() || !tcp_socket->IsConnected() ||
-      tcp_socket->HasPendingRead()) {
-    DVLOG(1) << "Failing before trying. socket is " << tcp_socket;
-    if (tcp_socket) {
-      DVLOG(1) << "type: " << tcp_socket->GetSocketType()
-               << ", ClientStream is " << tcp_socket->ClientStream()
-               << ", IsConnected: " << tcp_socket->IsConnected()
-               << ", HasPendingRead: " << tcp_socket->HasPendingRead();
-    }
-    TlsConnectDone(std::move(null_sock), extension_id, callback,
-                   net::ERR_INVALID_ARGUMENT);
-    return;
+void TLSSocket::OnWriteComplete(const net::CompletionCallback& callback,
+                                int result) {
+  if (result < 0) {
+    // Write side has terminated. This can be an error or a graceful close.
+    // TCPSocketEventDispatcher doesn't distinguish between the two.
+    Disconnect(false /* socket_destroying */);
   }
+  callback.Run(result);
+}
 
-  net::IPEndPoint dest_host_port_pair;
-  if (!tcp_socket->GetPeerAddress(&dest_host_port_pair)) {
-    DVLOG(1) << "Could not get peer address.";
-    TlsConnectDone(std::move(null_sock), extension_id, callback,
-                   net::ERR_INVALID_ARGUMENT);
-    return;
+void TLSSocket::OnReadComplete(int result,
+                               scoped_refptr<net::IOBuffer> io_buffer) {
+  DCHECK(read_callback_);
+
+  // Use a local variable for |read_callback_|, because otherwise Disconnect()
+  // will try to invoke |read_callback_| with a hardcoded result code.
+  ReadCompletionCallback callback = std::move(read_callback_);
+  if (result < 0) {
+    // Read side has terminated. This can be an error or a graceful close.
+    // TCPSocketEventDispatcher doesn't distinguish between the two.
+    Disconnect(false /* socket_destroying */);
   }
-
-  // Convert any U-LABELs to A-LABELs.
-  url::CanonHostInfo host_info;
-  std::string canon_host =
-      net::CanonicalizeHost(tcp_socket->hostname(), &host_info);
-
-  // Canonicalization shouldn't fail: the socket is already connected with a
-  // host, using this hostname.
-  if (host_info.family == url::CanonHostInfo::BROKEN) {
-    DVLOG(1) << "Could not canonicalize hostname";
-    TlsConnectDone(std::move(null_sock), extension_id, callback,
-                   net::ERR_INVALID_ARGUMENT);
-    return;
-  }
-
-  net::HostPortPair host_and_port(canon_host, dest_host_port_pair.port());
-
-  std::unique_ptr<net::ClientSocketHandle> socket_handle(
-      new net::ClientSocketHandle());
-
-  // Set the socket handle to the socket's client stream (that should be the
-  // only one active here). Then have the old socket release ownership on
-  // that client stream.
-  socket_handle->SetSocket(
-      base::WrapUnique<net::StreamSocket>(tcp_socket->ClientStream()));
-  tcp_socket->Release();
-
-  DCHECK(transport_security_state);
-  net::SSLClientSocketContext context;
-  context.cert_verifier = cert_verifier;
-  context.transport_security_state = transport_security_state;
-  context.cert_transparency_verifier = ct_verifier;
-  context.ct_policy_enforcer = ct_policy_enforcer;
-
-  // Fill in the SSL socket params.
-  net::SSLConfig ssl_config;
-  ssl_config_service->GetSSLConfig(&ssl_config);
-  if (options && options->tls_version.get()) {
-    uint16_t version_min = 0, version_max = 0;
-    api::socket::TLSVersionConstraints* versions = options->tls_version.get();
-    if (versions->min.get()) {
-      version_min = SSLProtocolVersionFromString(*versions->min);
-    }
-    if (versions->max.get()) {
-      version_max = SSLProtocolVersionFromString(*versions->max);
-    }
-    if (version_min) {
-      ssl_config.version_min = version_min;
-    }
-    if (version_max) {
-      ssl_config.version_max = version_max;
-    }
-  }
-
-  net::ClientSocketFactory* socket_factory =
-      net::ClientSocketFactory::GetDefaultFactory();
-
-  // Create the socket.
-  std::unique_ptr<net::SSLClientSocket> ssl_socket(
-      socket_factory->CreateSSLClientSocket(
-          std::move(socket_handle), host_and_port, ssl_config, context));
-
-  DVLOG(1) << "Attempting to secure a connection to " << tcp_socket->hostname()
-           << ":" << dest_host_port_pair.port();
-
-  // We need the contents of |ssl_socket| in order to invoke its Connect()
-  // method. It belongs to |ssl_socket|, and we own that until our internal
-  // callback (|connect_cb|, below) is invoked.
-  net::SSLClientSocket* saved_ssl_socket = ssl_socket.get();
-
-  // Try establish a TLS connection. Pass ownership of |ssl_socket| to
-  // TlsConnectDone, which will pass it on to |callback|. |connect_cb| below
-  // is only for UpgradeSocketToTLS use, and not be confused with the
-  // argument |callback|, which gets invoked by TlsConnectDone() after
-  // Connect() below returns.
-  base::Callback<void(int)> connect_cb(base::Bind(
-      &TlsConnectDone, base::Passed(&ssl_socket), extension_id, callback));
-  int status = saved_ssl_socket->Connect(connect_cb);
-  saved_ssl_socket = NULL;
-
-  // Connect completed synchronously, or failed.
-  if (status != net::ERR_IO_PENDING) {
-    // Note: this can't recurse -- if |socket| is already a connected
-    // TLSSocket, it will return TYPE_TLS instead of TYPE_TCP, causing
-    // UpgradeSocketToTLS() to fail with an error above. If
-    // UpgradeSocketToTLS() is called on |socket| twice, the call to
-    // Release() on |socket| above causes the additional call to
-    // fail with an error above.
-    if (status != net::OK) {
-      DVLOG(1) << "Status is not OK or IO-pending: "
-               << net::ErrorToString(status);
-    }
-    connect_cb.Run(status);
-  }
+  std::move(callback).Run(result, io_buffer, false /* socket_destroying */);
 }
 
 }  // namespace extensions
-
diff --git a/extensions/browser/api/socket/tls_socket.h b/extensions/browser/api/socket/tls_socket.h
index c3208e2..99846ea 100644
--- a/extensions/browser/api/socket/tls_socket.h
+++ b/extensions/browser/api/socket/tls_socket.h
@@ -7,24 +7,19 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <string>
 
+#include "extensions/browser/api/socket/mojo_data_pump.h"
 #include "extensions/browser/api/socket/socket.h"
 #include "extensions/browser/api/socket/socket_api.h"
 #include "extensions/browser/api/socket/tcp_socket.h"
-#include "net/ssl/ssl_config_service.h"
-
-namespace net {
-class Socket;
-class CertVerifier;
-class CTPolicyEnforcer;
-class CTVerifier;
-class TransportSecurityState;
-}
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "services/network/public/mojom/tls_socket.mojom.h"
 
 namespace extensions {
 
-class TLSSocket;
+class MojoDataPump;
 
 // TLS Sockets from the chrome.socket and chrome.sockets.tcp APIs. A regular
 // TCPSocket is converted to a TLSSocket via chrome.socket.secure() or
@@ -38,84 +33,55 @@
 // touch any socket state.
 class TLSSocket : public ResumableTCPSocket {
  public:
-  typedef base::Callback<void(std::unique_ptr<TLSSocket>, int)> SecureCallback;
-
-  TLSSocket(std::unique_ptr<net::StreamSocket> tls_socket,
+  TLSSocket(network::mojom::TLSClientSocketPtr tls_socket,
+            const net::IPEndPoint& local_addr,
+            const net::IPEndPoint& peer_addr,
+            mojo::ScopedDataPipeConsumerHandle receive_stream,
+            mojo::ScopedDataPipeProducerHandle send_stream,
             const std::string& owner_extension_id);
 
   ~TLSSocket() override;
 
-  // Most of these methods either fail or forward the method call on to the
-  // inner net::StreamSocket. The remaining few do actual TLS work.
-
   // Fails.
   void Connect(const net::AddressList& address,
-               const CompletionCallback& callback) override;
+               net::CompletionOnceCallback callback) override;
   // Forwards.
   void Disconnect(bool socket_destroying) override;
 
   // Attempts to read |count| bytes of decrypted data from the TLS socket,
   // invoking |callback| with the actual number of bytes read, or a network
   // error code if an error occurred.
-  void Read(int count, const ReadCompletionCallback& callback) override;
-
-  // Fails. This should have been called on the TCP socket before secure() was
-  // invoked.
-  bool SetKeepAlive(bool enable, int delay) override;
-
-  // Fails. This should have been called on the TCP socket before secure() was
-  // invoked.
-  bool SetNoDelay(bool no_delay) override;
+  void Read(int count, ReadCompletionCallback callback) override;
 
   // Fails. TLSSocket is only a client.
-  int Listen(const std::string& address,
-             uint16_t port,
-             int backlog,
-             std::string* error_msg) override;
-
-  // Fails. TLSSocket is only a client.
-  void Accept(const AcceptCompletionCallback& callback) override;
+  void Listen(const std::string& address,
+              uint16_t port,
+              int backlog,
+              ListenCallback callback) override;
 
   // Forwards.
   bool IsConnected() override;
 
-  // Forwards.
   bool GetPeerAddress(net::IPEndPoint* address) override;
-  // Forwards.
   bool GetLocalAddress(net::IPEndPoint* address) override;
 
   // Returns TYPE_TLS.
   SocketType GetSocketType() const override;
 
-  // Convert |socket| to a TLS socket. |socket| must be an open TCP client
-  // socket. |socket| must not have a pending read. UpgradeSocketToTLS() must
-  // be invoked in the IO thread. |callback| will always be invoked. |options|
-  // may be NULL.
-  // Note: |callback| may be synchronously invoked before
-  // UpgradeSocketToTLS() returns. Currently using the older chrome.socket
-  // version of SecureOptions, to avoid having the older API implementation
-  // depend on the newer one.
-  static void UpgradeSocketToTLS(
-      Socket* socket,
-      net::SSLConfigService* config_service,
-      net::CertVerifier* cert_verifier,
-      net::TransportSecurityState* transport_security_state,
-      net::CTVerifier* ct_verifier,
-      net::CTPolicyEnforcer* ct_policy_enforcer,
-      const std::string& extension_id,
-      api::socket::SecureOptions* options,
-      const SecureCallback& callback);
-
  private:
   int WriteImpl(net::IOBuffer* io_buffer,
                 int io_buffer_size,
                 const net::CompletionCallback& callback) override;
+  void OnWriteComplete(const net::CompletionCallback& callback, int result);
+  void OnReadComplete(int result, scoped_refptr<net::IOBuffer> io_buffer);
 
-  void OnReadComplete(const scoped_refptr<net::IOBuffer>& io_buffer,
-                      int result);
-
-  std::unique_ptr<net::StreamSocket> tls_socket_;
+  network::mojom::TLSClientSocketPtr tls_socket_;
+  base::Optional<net::IPEndPoint> local_addr_;
+  base::Optional<net::IPEndPoint> peer_addr_;
+  std::unique_ptr<MojoDataPump> mojo_data_pump_;
   ReadCompletionCallback read_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(TLSSocket);
 };
 
 }  // namespace extensions
diff --git a/extensions/browser/api/socket/udp_socket.cc b/extensions/browser/api/socket/udp_socket.cc
index 094508e3..f9b8aa9 100644
--- a/extensions/browser/api/socket/udp_socket.cc
+++ b/extensions/browser/api/socket/udp_socket.cc
@@ -5,6 +5,7 @@
 #include "extensions/browser/api/socket/udp_socket.h"
 
 #include <algorithm>
+#include <utility>
 
 #include "base/callback_helpers.h"
 #include "base/lazy_instance.h"
@@ -46,9 +47,9 @@
 }
 
 void UDPSocket::Connect(const net::AddressList& address,
-                        const net::CompletionCallback& callback) {
+                        net::CompletionOnceCallback callback) {
   if (IsConnectedOrBound()) {
-    callback.Run(net::ERR_CONNECTION_FAILED);
+    std::move(callback).Run(net::ERR_CONNECTION_FAILED);
     return;
   }
   // UDP API only connects to the first address received from DNS so
@@ -57,7 +58,7 @@
   socket_->Connect(
       ip_end_point, std::move(socket_options_),
       base::BindOnce(&UDPSocket::OnConnectCompleted, base::Unretained(this),
-                     callback, ip_end_point));
+                     std::move(callback), ip_end_point));
 }
 
 void UDPSocket::Bind(const std::string& address,
@@ -94,27 +95,28 @@
   multicast_groups_.clear();
 }
 
-void UDPSocket::Read(int count, const ReadCompletionCallback& callback) {
+void UDPSocket::Read(int count, ReadCompletionCallback callback) {
   DCHECK(!callback.is_null());
 
   if (!read_callback_.is_null()) {
-    callback.Run(net::ERR_IO_PENDING, nullptr, false /* socket_destroying */);
+    std::move(callback).Run(net::ERR_IO_PENDING, nullptr,
+                            false /* socket_destroying */);
     return;
   }
 
   if (count < 0) {
-    callback.Run(net::ERR_INVALID_ARGUMENT, nullptr,
-                 false /* socket_destroying */);
+    std::move(callback).Run(net::ERR_INVALID_ARGUMENT, nullptr,
+                            false /* socket_destroying */);
     return;
   }
 
   if (!IsConnected()) {
-    callback.Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr,
-                 false /* socket_destroying */);
+    std::move(callback).Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr,
+                            false /* socket_destroying */);
     return;
   }
 
-  read_callback_ = callback;
+  read_callback_ = std::move(callback);
   socket_->ReceiveMoreWithBufferSize(1, count);
   return;
 }
@@ -220,7 +222,7 @@
   uint16_t port = 0;
   if (result != net::OK) {
     if (!read_callback_.is_null()) {
-      base::ResetAndReturn(&read_callback_)
+      std::move(read_callback_)
           .Run(result, nullptr, false /* socket_destroying */);
       return;
     }
@@ -234,7 +236,7 @@
   memcpy(io_buffer->data(), data.value().data(), data.value().size());
 
   if (!read_callback_.is_null()) {
-    base::ResetAndReturn(&read_callback_)
+    std::move(read_callback_)
         .Run(data.value().size(), io_buffer, false /* socket_destroying */);
     return;
   }
@@ -246,18 +248,18 @@
 }
 
 void UDPSocket::OnConnectCompleted(
-    const net::CompletionCallback& callback,
+    net::CompletionOnceCallback callback,
     const net::IPEndPoint& remote_addr,
     int result,
     const base::Optional<net::IPEndPoint>& local_addr) {
   if (result != net::OK) {
-    callback.Run(result);
+    std::move(callback).Run(result);
     return;
   }
   local_addr_ = local_addr;
   peer_addr_ = remote_addr;
   is_connected_ = true;
-  callback.Run(result);
+  std::move(callback).Run(result);
 }
 
 void UDPSocket::OnBindCompleted(
diff --git a/extensions/browser/api/socket/udp_socket.h b/extensions/browser/api/socket/udp_socket.h
index 6f46aaa..9c4fdfc 100644
--- a/extensions/browser/api/socket/udp_socket.h
+++ b/extensions/browser/api/socket/udp_socket.h
@@ -28,12 +28,12 @@
 
   // Socket implementation.
   void Connect(const net::AddressList& address,
-               const CompletionCallback& callback) override;
+               net::CompletionOnceCallback callback) override;
   void Disconnect(bool socket_destroying) override;
   void Bind(const std::string& address,
             uint16_t port,
             const CompletionCallback& callback) override;
-  void Read(int count, const ReadCompletionCallback& callback) override;
+  void Read(int count, ReadCompletionCallback callback) override;
   void RecvFrom(int count, const RecvFromCompletionCallback& callback) override;
   void SendTo(scoped_refptr<net::IOBuffer> io_buffer,
               int byte_count,
@@ -76,7 +76,7 @@
                   const base::Optional<net::IPEndPoint>& src_addr,
                   base::Optional<base::span<const uint8_t>> data) override;
 
-  void OnConnectCompleted(const net::CompletionCallback& user_callback,
+  void OnConnectCompleted(net::CompletionOnceCallback user_callback,
                           const net::IPEndPoint& remote_addr,
                           int result,
                           const base::Optional<net::IPEndPoint>& local_addr);
diff --git a/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc b/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
index dbc43166..c0aeac5 100644
--- a/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
+++ b/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
@@ -4,6 +4,10 @@
 
 #include "extensions/browser/api/sockets_tcp/sockets_tcp_api.h"
 
+#include <string>
+#include <utility>
+#include <vector>
+
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
@@ -124,7 +128,8 @@
 }
 
 void SocketsTcpCreateFunction::Work() {
-  ResumableTCPSocket* socket = new ResumableTCPSocket(extension_->id());
+  ResumableTCPSocket* socket =
+      new ResumableTCPSocket(browser_context(), extension_->id());
 
   sockets_tcp::SocketProperties* properties = params_->properties.get();
   if (properties) {
@@ -203,20 +208,28 @@
   return true;
 }
 
-void SocketsTcpSetKeepAliveFunction::Work() {
+void SocketsTcpSetKeepAliveFunction::AsyncWorkStart() {
   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
   if (!socket) {
     error_ = kSocketNotFoundError;
+    results_ = sockets_tcp::SetKeepAlive::Results::Create(net::ERR_FAILED);
+    AsyncWorkCompleted();
     return;
   }
 
   int delay = params_->delay ? *params_->delay : 0;
 
-  bool success = socket->SetKeepAlive(params_->enable, delay);
+  socket->SetKeepAlive(
+      params_->enable, delay,
+      base::BindOnce(&SocketsTcpSetKeepAliveFunction::OnCompleted, this));
+}
+
+void SocketsTcpSetKeepAliveFunction::OnCompleted(bool success) {
   int net_result = (success ? net::OK : net::ERR_FAILED);
+  results_ = sockets_tcp::SetKeepAlive::Results::Create(net_result);
   if (net_result != net::OK)
     error_ = net::ErrorToString(net_result);
-  results_ = sockets_tcp::SetKeepAlive::Results::Create(net_result);
+  AsyncWorkCompleted();
 }
 
 SocketsTcpSetNoDelayFunction::SocketsTcpSetNoDelayFunction() {}
@@ -229,18 +242,25 @@
   return true;
 }
 
-void SocketsTcpSetNoDelayFunction::Work() {
+void SocketsTcpSetNoDelayFunction::AsyncWorkStart() {
   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
   if (!socket) {
     error_ = kSocketNotFoundError;
+    results_ = sockets_tcp::SetNoDelay::Results::Create(net::ERR_FAILED);
+    AsyncWorkCompleted();
     return;
   }
+  socket->SetNoDelay(
+      params_->no_delay,
+      base::BindOnce(&SocketsTcpSetNoDelayFunction::OnCompleted, this));
+}
 
-  bool success = socket->SetNoDelay(params_->no_delay);
+void SocketsTcpSetNoDelayFunction::OnCompleted(bool success) {
   int net_result = (success ? net::OK : net::ERR_FAILED);
+  results_ = sockets_tcp::SetNoDelay::Results::Create(net_result);
   if (net_result != net::OK)
     error_ = net::ErrorToString(net_result);
-  results_ = sockets_tcp::SetNoDelay::Results::Create(net_result);
+  AsyncWorkCompleted();
 }
 
 SocketsTcpConnectFunction::SocketsTcpConnectFunction()
@@ -458,8 +478,6 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   params_ = api::sockets_tcp::Secure::Params::Create(*args_);
   EXTENSION_FUNCTION_VALIDATE(params_.get());
-  url_request_getter_ = content::BrowserContext::GetDefaultStoragePartition(
-      browser_context())->GetURLRequestContext();
   return true;
 }
 
@@ -481,8 +499,7 @@
 
   // Make sure it's a connected TCP client socket. Error out if it's already
   // secure()'d.
-  if (socket->GetSocketType() != Socket::TYPE_TCP ||
-      socket->ClientStream() == NULL) {
+  if (socket->GetSocketType() != Socket::TYPE_TCP) {
     SetResult(std::make_unique<base::Value>(net::ERR_INVALID_ARGUMENT));
     error_ = kInvalidSocketStateError;
     AsyncWorkCompleted();
@@ -496,9 +513,6 @@
     return;
   }
 
-  net::URLRequestContext* url_request_context =
-      url_request_getter_->GetURLRequestContext();
-
   // UpgradeSocketToTLS() uses the older API's SecureOptions. Copy over the
   // only values inside -- TLSVersionConstraints's |min| and |max|,
   api::socket::SecureOptions legacy_params;
@@ -514,29 +528,33 @@
     }
   }
 
-  TLSSocket::UpgradeSocketToTLS(
-      socket, url_request_context->ssl_config_service(),
-      url_request_context->cert_verifier(),
-      url_request_context->transport_security_state(),
-      url_request_context->cert_transparency_verifier(),
-      url_request_context->ct_policy_enforcer(), extension_id(), &legacy_params,
-      base::Bind(&SocketsTcpSecureFunction::TlsConnectDone, this));
+  network::mojom::TLSClientSocketPtr tls_socket;
+  socket->UpgradeToTLS(
+      &legacy_params,
+      base::BindOnce(&SocketsTcpSecureFunction::TlsConnectDone, this));
 }
 
-void SocketsTcpSecureFunction::TlsConnectDone(std::unique_ptr<TLSSocket> socket,
-                                              int result) {
-  // If an error occurred, socket MUST be NULL
-  DCHECK(result == net::OK || socket == NULL);
-
-  if (socket && result == net::OK) {
-    socket->set_persistent(persistent_);
-    socket->set_paused(paused_);
-    ReplaceSocket(params_->socket_id, socket.release());
-  } else {
+void SocketsTcpSecureFunction::TlsConnectDone(
+    int result,
+    network::mojom::TLSClientSocketPtr tls_socket,
+    const net::IPEndPoint& local_addr,
+    const net::IPEndPoint& peer_addr,
+    mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
+    mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
+  if (result != net::OK) {
     RemoveSocket(params_->socket_id);
     error_ = net::ErrorToString(result);
+    results_ = api::sockets_tcp::Secure::Results::Create(result);
+    AsyncWorkCompleted();
+    return;
   }
-
+  auto socket =
+      std::make_unique<TLSSocket>(std::move(tls_socket), local_addr, peer_addr,
+                                  std::move(receive_pipe_handle),
+                                  std::move(send_pipe_handle), extension_id());
+  socket->set_persistent(persistent_);
+  socket->set_paused(paused_);
+  ReplaceSocket(params_->socket_id, socket.release());
   results_ = api::sockets_tcp::Secure::Results::Create(result);
   AsyncWorkCompleted();
 }
diff --git a/extensions/browser/api/sockets_tcp/sockets_tcp_api.h b/extensions/browser/api/sockets_tcp/sockets_tcp_api.h
index c4b3ee8..fd004e7 100644
--- a/extensions/browser/api/sockets_tcp/sockets_tcp_api.h
+++ b/extensions/browser/api/sockets_tcp/sockets_tcp_api.h
@@ -7,14 +7,16 @@
 
 #include <stddef.h>
 
+#include <memory>
+
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "extensions/browser/api/socket/socket_api.h"
 #include "extensions/common/api/sockets_tcp.h"
+#include "services/network/public/mojom/tcp_socket.mojom.h"
 
 namespace extensions {
 class ResumableTCPSocket;
-class TLSSocket;
 }
 
 namespace extensions {
@@ -108,9 +110,11 @@
 
   // AsyncApiFunction
   bool Prepare() override;
-  void Work() override;
+  void AsyncWorkStart() override;
 
  private:
+  void OnCompleted(bool success);
+
   std::unique_ptr<sockets_tcp::SetKeepAlive::Params> params_;
 };
 
@@ -125,9 +129,11 @@
 
   // AsyncApiFunction
   bool Prepare() override;
-  void Work() override;
+  void AsyncWorkStart() override;
 
  private:
+  void OnCompleted(bool success);
+
   std::unique_ptr<sockets_tcp::SetNoDelay::Params> params_;
 };
 
@@ -255,13 +261,16 @@
   void AsyncWorkStart() override;
 
  private:
-  virtual void TlsConnectDone(std::unique_ptr<extensions::TLSSocket> sock,
-                              int result);
+  void TlsConnectDone(int result,
+                      network::mojom::TLSClientSocketPtr tls_socket,
+                      const net::IPEndPoint& local_addr,
+                      const net::IPEndPoint& peer_addr,
+                      mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
+                      mojo::ScopedDataPipeProducerHandle send_pipe_handle);
 
   bool paused_;
   bool persistent_;
   std::unique_ptr<sockets_tcp::Secure::Params> params_;
-  scoped_refptr<net::URLRequestContextGetter> url_request_getter_;
 
   DISALLOW_COPY_AND_ASSIGN(SocketsTcpSecureFunction);
 };
diff --git a/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc b/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc
index 4d62b093..918b2a0e 100644
--- a/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc
+++ b/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc
@@ -4,8 +4,14 @@
 
 #include <utility>
 
+#include "base/command_line.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/stringprintf.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/service_manager_connection.h"
+#include "content/public/common/service_names.mojom.h"
+#include "content/public/test/network_service_test_helper.h"
 #include "extensions/browser/api/dns/host_resolver_wrapper.h"
 #include "extensions/browser/api/dns/mock_host_resolver_creator.h"
 #include "extensions/browser/api/sockets_tcp/sockets_tcp_api.h"
@@ -16,8 +22,11 @@
 #include "extensions/shell/test/shell_test.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/result_catcher.h"
+#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
+#include "services/network/public/cpp/features.h"
+#include "services/service_manager/public/cpp/connector.h"
 
 namespace extensions {
 
@@ -25,14 +34,18 @@
 
 class SocketsTcpApiTest : public ShellApiTest {
  public:
-  SocketsTcpApiTest()
-      : resolver_event_(base::WaitableEvent::ResetPolicy::MANUAL,
-                        base::WaitableEvent::InitialState::NOT_SIGNALED),
-        resolver_creator_(new MockHostResolverCreator()) {}
+  SocketsTcpApiTest() : resolver_creator_(new MockHostResolverCreator()) {
+    if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+      base::CommandLine::ForCurrentProcess()->AppendSwitch(
+          switches::kUseMockCertVerifierForTesting);
+    }
+  }
 
   void SetUpOnMainThread() override {
     ShellApiTest::SetUpOnMainThread();
 
+    // TODO(xunjieli): Figure out what to do with this in-process host resolver
+    // which doesn't work with the out-of-process network service.
     HostResolverWrapper::GetInstance()->SetHostResolverForTesting(
         resolver_creator_->CreateMockHostResolver());
   }
@@ -45,8 +58,6 @@
   }
 
  private:
-  base::WaitableEvent resolver_event_;
-
   // The MockHostResolver asserts that it's used on the same thread on which
   // it's created, which is actually a stronger rule than its real counterpart.
   // But that's fine; it's good practice.
@@ -101,6 +112,19 @@
 }
 
 IN_PROC_BROWSER_TEST_F(SocketsTcpApiTest, SocketTcpExtensionTLS) {
+  network::mojom::NetworkServiceTestPtr network_service_test;
+  // If network service is running in a utility process, the cert of the
+  // SpawnedTestServer won't be recognized, so inject mock cert verifier through
+  // the test helper interface.
+  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    content::ServiceManagerConnection::GetForProcess()
+        ->GetConnector()
+        ->BindInterface(content::mojom::kNetworkServiceName,
+                        &network_service_test);
+    mojo::ScopedAllowSyncCallForTesting allow_sync_call;
+    network_service_test->MockCertVerifierSetDefaultResult(net::OK);
+  }
+
   std::unique_ptr<net::SpawnedTestServer> test_https_server(
       new net::SpawnedTestServer(
           net::SpawnedTestServer::TYPE_HTTPS, net::BaseTestServer::SSLOptions(),
diff --git a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
index 021ea5f..45b8a780 100644
--- a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
+++ b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
@@ -4,6 +4,8 @@
 
 #include "extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h"
 
+#include <vector>
+
 #include "content/public/common/socket_permission_request.h"
 #include "extensions/browser/api/socket/tcp_socket.h"
 #include "extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h"
@@ -84,8 +86,8 @@
 }
 
 void SocketsTcpServerCreateFunction::Work() {
-  ResumableTCPServerSocket* socket =
-      new ResumableTCPServerSocket(extension_->id());
+  auto* socket =
+      new ResumableTCPServerSocket(browser_context(), extension_->id());
 
   sockets_tcp_server::SocketProperties* properties = params_->properties.get();
   if (properties) {
@@ -190,10 +192,23 @@
     return;
   }
 
-  int net_result = socket->Listen(
+  socket->Listen(
       params_->address, params_->port,
       params_->backlog.get() ? *params_->backlog : kDefaultListenBacklog,
-      &error_);
+      base::BindOnce(&SocketsTcpServerListenFunction::OnCompleted, this));
+}
+
+void SocketsTcpServerListenFunction::OnCompleted(
+    int net_result,
+    const std::string& /* error_msg */) {
+  DCHECK_NE(net::ERR_IO_PENDING, net_result);
+
+  ResumableTCPServerSocket* socket = GetTcpSocket(params_->socket_id);
+  if (!socket) {
+    error_ = kSocketNotFoundError;
+    AsyncWorkCompleted();
+    return;
+  }
   results_ = sockets_tcp_server::Listen::Results::Create(net_result);
   if (net_result == net::OK) {
     socket_event_dispatcher_->OnServerSocketListen(extension_->id(),
diff --git a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h
index b5f93c63..96ed487 100644
--- a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h
+++ b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h
@@ -5,6 +5,9 @@
 #ifndef EXTENSIONS_BROWSER_API_SOCKETS_TCP_SERVER_SOCKETS_TCP_SERVER_API_H_
 #define EXTENSIONS_BROWSER_API_SOCKETS_TCP_SERVER_SOCKETS_TCP_SERVER_API_H_
 
+#include <memory>
+#include <string>
+
 #include "base/gtest_prod_util.h"
 #include "extensions/browser/api/socket/socket_api.h"
 #include "extensions/common/api/sockets_tcp_server.h"
@@ -98,6 +101,8 @@
   void AsyncWorkStart() override;
 
  private:
+  void OnCompleted(int result, const std::string& error_msg);
+
   std::unique_ptr<sockets_tcp_server::Listen::Params> params_;
   TCPServerSocketEventDispatcher* socket_event_dispatcher_;
 };
diff --git a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
index 4854e8b7..565a037 100644
--- a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
+++ b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
@@ -117,19 +117,24 @@
     return;
 
   socket->Accept(
-      base::Bind(&TCPServerSocketEventDispatcher::AcceptCallback, params));
+      base::BindOnce(&TCPServerSocketEventDispatcher::AcceptCallback, params));
 }
 
 // static
 void TCPServerSocketEventDispatcher::AcceptCallback(
     const AcceptParams& params,
     int result_code,
-    std::unique_ptr<net::TCPClientSocket> socket) {
+    network::mojom::TCPConnectedSocketPtr socket,
+    const base::Optional<net::IPEndPoint>& remote_addr,
+    mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
+    mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
   DCHECK_CURRENTLY_ON(params.thread_id);
+  DCHECK_GE(net::OK, result_code);
 
-  if (result_code >= 0) {
-    ResumableTCPSocket* client_socket =
-        new ResumableTCPSocket(std::move(socket), params.extension_id, true);
+  if (result_code == net::OK) {
+    ResumableTCPSocket* client_socket = new ResumableTCPSocket(
+        std::move(socket), std::move(receive_pipe_handle),
+        std::move(send_pipe_handle), remote_addr, params.extension_id);
     client_socket->set_paused(true);
     int client_socket_id = params.client_sockets->Add(client_socket);
 
diff --git a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h
index 98fc928d..3da1e491 100644
--- a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h
+++ b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h
@@ -5,10 +5,14 @@
 #ifndef EXTENSIONS_BROWSER_API_SOCKETS_TCP_SERVER_TCP_SERVER_SOCKET_EVENT_DISPATCHER_H_
 #define EXTENSIONS_BROWSER_API_SOCKETS_TCP_SERVER_TCP_SERVER_SOCKET_EVENT_DISPATCHER_H_
 
+#include <memory>
+#include <string>
+
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/api/api_resource_manager.h"
 #include "extensions/browser/api/sockets_tcp/sockets_tcp_api.h"
 #include "extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h"
+#include "services/network/public/mojom/tcp_socket.mojom.h"
 
 namespace content {
 class BrowserContext;
@@ -77,9 +81,13 @@
   static void StartAccept(const AcceptParams& params);
 
   // Called when socket accepts a new connection.
-  static void AcceptCallback(const AcceptParams& params,
-                             int result_code,
-                             std::unique_ptr<net::TCPClientSocket> socket);
+  static void AcceptCallback(
+      const AcceptParams& params,
+      int result,
+      network::mojom::TCPConnectedSocketPtr socket,
+      const base::Optional<net::IPEndPoint>& remote_addr,
+      mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
+      mojo::ScopedDataPipeProducerHandle send_pipe_handle);
 
   // Post an extension event from |thread_id| to UI thread
   static void PostEvent(const AcceptParams& params,
diff --git a/extensions/browser/api/system_display/system_display_apitest.cc b/extensions/browser/api/system_display/system_display_apitest.cc
index 455341ea..54d9f99 100644
--- a/extensions/browser/api/system_display/system_display_apitest.cc
+++ b/extensions/browser/api/system_display/system_display_apitest.cc
@@ -244,7 +244,13 @@
 
 #if !defined(OS_CHROMEOS)
 
-IN_PROC_BROWSER_TEST_F(SystemDisplayApiTest, SetDisplay) {
+// TODO(crbug.com/866904): Fails sometimes on Win 10 dbg bots.
+#if defined(OS_WIN)
+#define MAYBE_SetDisplay DISABLED_SetDisplay
+#else
+#define MAYBE_SetDisplay SetDisplay
+#endif  // defined(OS_WIN)
+IN_PROC_BROWSER_TEST_F(SystemDisplayApiTest, MAYBE_SetDisplay) {
   scoped_refptr<SystemDisplaySetDisplayPropertiesFunction> set_info_function(
       new SystemDisplaySetDisplayPropertiesFunction());
 
diff --git a/gin/arguments.cc b/gin/arguments.cc
index b492fae6..82d5f43 100644
--- a/gin/arguments.cc
+++ b/gin/arguments.cc
@@ -48,7 +48,7 @@
   return info_->Holder()->CreationContext();
 }
 
-std::string V8TypeAsString(v8::Local<v8::Value> value) {
+std::string V8TypeAsString(v8::Isolate* isolate, v8::Local<v8::Value> value) {
   if (value.IsEmpty())
     return "<empty handle>";
   if (value->IsUndefined())
@@ -56,7 +56,7 @@
   if (value->IsNull())
     return "null";
   std::string result;
-  if (!ConvertFromV8(NULL, value, &result))
+  if (!ConvertFromV8(isolate, value, &result))
     return std::string();
   return result;
 }
@@ -67,7 +67,7 @@
 
   return ThrowTypeError(base::StringPrintf(
       "Error processing argument at index %d, conversion failure from %s",
-      next_ - 1, V8TypeAsString((*info_)[next_ - 1]).c_str()));
+      next_ - 1, V8TypeAsString(isolate_, (*info_)[next_ - 1]).c_str()));
 }
 
 void Arguments::ThrowTypeError(const std::string& message) const {
diff --git a/gin/converter.h b/gin/converter.h
index 72c1d70..a501714 100644
--- a/gin/converter.h
+++ b/gin/converter.h
@@ -255,6 +255,7 @@
 template<typename T>
 bool ConvertFromV8(v8::Isolate* isolate, v8::Local<v8::Value> input,
                    T* result) {
+  DCHECK(isolate);
   return Converter<T>::FromV8(isolate, input, result);
 }
 
diff --git a/google_apis/gcm/base/socket_stream.cc b/google_apis/gcm/base/socket_stream.cc
index 776813b..6674d9c 100644
--- a/google_apis/gcm/base/socket_stream.cc
+++ b/google_apis/gcm/base/socket_stream.cc
@@ -216,9 +216,7 @@
     net::StreamSocket* socket,
     const net::NetworkTrafficAnnotationTag& traffic_annotation)
     : socket_(socket),
-      io_buffer_(new net::IOBuffer(kDefaultBufferSize)),
-      write_buffer_(
-          new net::DrainableIOBuffer(io_buffer_.get(), kDefaultBufferSize)),
+      io_buffer_(new net::IOBufferWithSize(kDefaultBufferSize)),
       next_pos_(0),
       last_error_(net::OK),
       traffic_annotation_(traffic_annotation),
@@ -232,12 +230,12 @@
 bool SocketOutputStream::Next(void** data, int* size) {
   DCHECK_NE(GetState(), CLOSED);
   DCHECK_NE(GetState(), FLUSHING);
-  if (next_pos_ == write_buffer_->size())
+  if (next_pos_ == io_buffer_->size())
     return false;
 
-  *data = write_buffer_->data() + next_pos_;
-  *size = write_buffer_->size() - next_pos_;
-  next_pos_ = write_buffer_->size();
+  *data = io_buffer_->data() + next_pos_;
+  *size = io_buffer_->size() - next_pos_;
+  next_pos_ = io_buffer_->size();
   return true;
 }
 
@@ -259,15 +257,21 @@
 net::Error SocketOutputStream::Flush(const base::Closure& callback) {
   DCHECK_EQ(GetState(), READY);
 
+  if (!write_buffer_) {
+    write_buffer_ = base::MakeRefCounted<net::DrainableIOBuffer>(
+        io_buffer_.get(), next_pos_);
+  }
+
   if (!socket_->IsConnected()) {
     LOG(ERROR) << "Socket was disconnected, closing output stream";
     last_error_ = net::ERR_CONNECTION_CLOSED;
     return net::OK;
   }
 
-  DVLOG(1) << "Flushing " << next_pos_ << " bytes into socket.";
+  DVLOG(1) << "Flushing " << write_buffer_->BytesRemaining()
+           << " bytes into socket.";
   int result =
-      socket_->Write(write_buffer_.get(), next_pos_,
+      socket_->Write(write_buffer_.get(), write_buffer_->BytesRemaining(),
                      base::Bind(&SocketOutputStream::FlushCompletionCallback,
                                 weak_ptr_factory_.GetWeakPtr(), callback),
                      traffic_annotation_);
@@ -322,17 +326,17 @@
 
   DCHECK_GT(result, net::OK);
   last_error_ = net::OK;
+  write_buffer_->DidConsume(result);
 
-  if (write_buffer_->BytesConsumed() + result < next_pos_) {
+  if (write_buffer_->BytesRemaining() > 0) {
     DVLOG(1) << "Partial flush complete. Retrying.";
-     // Only a partial write was completed. Flush again to finish the write.
-    write_buffer_->DidConsume(result);
+    // Only a partial write was completed. Flush again to finish the write.
     Flush(callback);
     return;
   }
 
   DVLOG(1) << "Socket flush complete.";
-  write_buffer_->SetOffset(0);
+  write_buffer_ = nullptr;
   next_pos_ = 0;
   if (!callback.is_null())
     callback.Run();
diff --git a/google_apis/gcm/base/socket_stream.h b/google_apis/gcm/base/socket_stream.h
index 2b85088..c68acd00 100644
--- a/google_apis/gcm/base/socket_stream.h
+++ b/google_apis/gcm/base/socket_stream.h
@@ -23,6 +23,7 @@
 namespace net {
 class DrainableIOBuffer;
 class IOBuffer;
+class IOBufferWithSize;
 class StreamSocket;
 }  // namespace net
 
@@ -186,10 +187,10 @@
 
   // Internal net components.
   net::StreamSocket* const socket_;
-  const scoped_refptr<net::IOBuffer> io_buffer_;
+  const scoped_refptr<net::IOBufferWithSize> io_buffer_;
   // IOBuffer implementation that wraps the data within |io_buffer_| that hasn't
   // been written to the socket yet.
-  const scoped_refptr<net::DrainableIOBuffer> write_buffer_;
+  scoped_refptr<net::DrainableIOBuffer> write_buffer_;
 
   // Starting position of the data within |io_buffer_| to consume on subsequent
   // Next(..) call.  0 <= write_buffer_.BytesConsumed() <= next_pos_
diff --git a/google_apis/gcm/base/socket_stream_unittest.cc b/google_apis/gcm/base/socket_stream_unittest.cc
index 5f263e9f..7da26d1 100644
--- a/google_apis/gcm/base/socket_stream_unittest.cc
+++ b/google_apis/gcm/base/socket_stream_unittest.cc
@@ -7,6 +7,9 @@
 #include <stdint.h>
 
 #include <memory>
+#include <string>
+#include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/macros.h"
@@ -32,6 +35,77 @@
 const char kWriteData[] = "write_data";
 const int kWriteDataSize = arraysize(kWriteData) - 1;
 
+// A net::StreamSocket that returns a partial write only for the first time.
+class FirstWritePartialSocket : public net::StreamSocket {
+ public:
+  FirstWritePartialSocket() {}
+  ~FirstWritePartialSocket() override {}
+
+  // Returns the data that is actually written to the socket.
+  const std::string& actual_data_written() { return actual_data_written_; }
+
+  // net::Socket implementation.
+  int Write(
+      net::IOBuffer* buf,
+      int buf_len,
+      net::CompletionOnceCallback callback,
+      const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
+    // Make the first write as a partial write.
+    if (!write_invoked_) {
+      write_invoked_ = true;
+      actual_data_written_.append(buf->data(), buf_len / 2);
+      return buf_len / 2;
+    }
+    // For subsequent writes, write everything that caller has passed to us.
+    actual_data_written_.append(buf->data(), buf_len);
+    return buf_len;
+  }
+  int Read(net::IOBuffer* buf,
+           int buf_len,
+           net::CompletionOnceCallback callback) override {
+    return net::ERR_IO_PENDING;
+  }
+  int ReadIfReady(net::IOBuffer* buf,
+                  int buf_len,
+                  net::CompletionOnceCallback callback) override {
+    return net::ERR_IO_PENDING;
+  }
+  int CancelReadIfReady() override { return net::OK; }
+  int SetReceiveBufferSize(int32_t size) override { return net::OK; }
+  int SetSendBufferSize(int32_t size) override { return net::OK; }
+
+  // net::StreamSocket implementation.
+  int Connect(net::CompletionOnceCallback callback) override { return net::OK; }
+  void Disconnect() override {}
+  bool IsConnected() const override { return true; }
+  bool IsConnectedAndIdle() const override { return true; };
+  int GetPeerAddress(net::IPEndPoint* address) const override {
+    return net::OK;
+  }
+  int GetLocalAddress(net::IPEndPoint* address) const override {
+    return net::OK;
+  }
+  const net::NetLogWithSource& NetLog() const override { return net_log_; }
+  bool WasEverUsed() const override { return true; }
+  bool WasAlpnNegotiated() const override { return false; }
+  net::NextProto GetNegotiatedProtocol() const override {
+    return net::kProtoUnknown;
+  }
+  bool GetSSLInfo(net::SSLInfo* ssl_info) override { return false; }
+  void GetConnectionAttempts(net::ConnectionAttempts* out) const override {}
+  void ClearConnectionAttempts() override {}
+  void AddConnectionAttempts(const net::ConnectionAttempts& attempts) override {
+  }
+  int64_t GetTotalReceivedBytes() const override { return 0; }
+  void ApplySocketTag(const net::SocketTag& tag) override {}
+
+ private:
+  net::NetLogWithSource net_log_;
+  std::string actual_data_written_;
+  // Whether Write() has been invoked before.
+  bool write_invoked_ = false;
+};
+
 class GCMSocketStreamTest : public testing::Test {
  public:
   GCMSocketStreamTest();
@@ -59,6 +133,10 @@
   SocketOutputStream* output_stream() { return socket_output_stream_.get(); }
   net::StreamSocket* socket() { return socket_.get(); }
 
+  void set_socket_output_stream(std::unique_ptr<SocketOutputStream> stream) {
+    socket_output_stream_ = std::move(stream);
+  }
+
  private:
   void OpenConnection();
   void ResetInputStream();
@@ -329,6 +407,17 @@
                                                   kWriteDataSize)));
 }
 
+// Regression test for crbug.com/866635.
+TEST_F(GCMSocketStreamTest, WritePartialWithLengthChecking) {
+  auto socket = std::make_unique<FirstWritePartialSocket>();
+  auto socket_output_stream = std::make_unique<SocketOutputStream>(
+      socket.get(), TRAFFIC_ANNOTATION_FOR_TESTS);
+  set_socket_output_stream(std::move(socket_output_stream));
+  ASSERT_EQ(kWriteDataSize,
+            DoOutputStreamWrite(base::StringPiece(kWriteData, kWriteDataSize)));
+  EXPECT_EQ(kWriteData, socket->actual_data_written());
+}
+
 // Write a message completely asynchronously (returns IO_PENDING before
 // finishing the write in two go's).
 TEST_F(GCMSocketStreamTest, WriteNone) {
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 33cd9dc..cd23a01 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -41,6 +41,7 @@
 #include "gpu/command_buffer/client/transfer_buffer.h"
 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
 #include "gpu/command_buffer/common/context_creation_attribs.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/common/id_allocator.h"
 #include "gpu/command_buffer/common/swap_buffers_complete_params.h"
 #include "gpu/command_buffer/common/sync_token.h"
@@ -124,11 +125,6 @@
   }
 }
 
-// A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
-GLuint ToGLuint(const void* ptr) {
-  return static_cast<GLuint>(reinterpret_cast<size_t>(ptr));
-}
-
 static base::AtomicSequenceNumber g_flush_id;
 
 uint32_t GenerateNextFlushId() {
diff --git a/gpu/command_buffer/client/vertex_array_object_manager.cc b/gpu/command_buffer/client/vertex_array_object_manager.cc
index 453de8c..0690c5e 100644
--- a/gpu/command_buffer/client/vertex_array_object_manager.cc
+++ b/gpu/command_buffer/client/vertex_array_object_manager.cc
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
 
 namespace gpu {
 namespace gles2 {
@@ -19,11 +20,6 @@
   return (size + 3) & ~3;
 }
 
-// A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
-static GLuint ToGLuint(const void* ptr) {
-  return static_cast<GLuint>(reinterpret_cast<size_t>(ptr));
-}
-
 // This class tracks VertexAttribPointers and helps emulate client side buffers.
 //
 // The way client side buffers work is we shadow all the Vertex Attribs so we
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index e959a0e5..61ffa634 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -53,6 +53,12 @@
   return checked.IsValid();
 }
 
+// A 32-bit and 64-bit compatible way of converting a pointer to a
+// 32-bit usigned integer, suitable to be stored in a GLuint.
+inline uint32_t ToGLuint(const void* ptr) {
+  return static_cast<uint32_t>(reinterpret_cast<size_t>(ptr));
+}
+
 // Returns the address of the first byte after a struct.
 template <typename T>
 const volatile void* AddressAfterStruct(const volatile T& pod) {
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index 4c4b7c60..bf9a384 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -387,11 +387,6 @@
   return feature_info->IsWebGL2OrES3Context();
 }
 
-// A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
-GLuint ToGLuint(const void* ptr) {
-  return static_cast<GLuint>(reinterpret_cast<size_t>(ptr));
-}
-
 base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator =
     LAZY_INSTANCE_INITIALIZER;
 
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index d3b824d7..d9d588a 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -2866,8 +2866,8 @@
       "os": {
         "type": "linux"
       },
-      "vendor_id": "0x15ad",
-      "device_id": ["0x0405"],
+      "gl_vendor": "VMware.*",
+      "gl_renderer": "Gallium.*",
       "features": [
         "disable_timestamp_queries"
       ],
diff --git a/gpu/vulkan/vulkan_command_pool.h b/gpu/vulkan/vulkan_command_pool.h
index b54d5917..bd1b84c 100644
--- a/gpu/vulkan/vulkan_command_pool.h
+++ b/gpu/vulkan/vulkan_command_pool.h
@@ -10,13 +10,14 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "gpu/vulkan/vulkan_export.h"
 
 namespace gpu {
 
 class VulkanCommandBuffer;
 class VulkanDeviceQueue;
 
-class VulkanCommandPool {
+class VULKAN_EXPORT VulkanCommandPool {
  public:
   explicit VulkanCommandPool(VulkanDeviceQueue* device_queue);
   ~VulkanCommandPool();
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 191b4e1..da96b98 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -417,7 +417,7 @@
 // |currentBVC| can be made active.
 - (void)activateBVCAndMakeCurrentBVCPrimary;
 // Sets |currentBVC| as the root view controller for the window.
-- (void)displayCurrentBVC;
+- (void)displayCurrentBVCAndFocusOmnibox:(BOOL)focusOmnibox;
 // Shows the tab switcher UI.
 - (void)showTabSwitcher;
 // Starts a voice search on the current BVC.
@@ -458,8 +458,10 @@
 - (bool)mustShowRestoreInfobar;
 // Begins the process of dismissing the tab switcher with the given current
 // model, switching which BVC is suspended if necessary, but not updating the
-// UI.
-- (void)beginDismissingTabSwitcherWithCurrentModel:(TabModel*)tabModel;
+// UI.  The omnibox will be focused after the tab switcher dismissal is
+// completed if |focusOmnibox| is YES.
+- (void)beginDismissingTabSwitcherWithCurrentModel:(TabModel*)tabModel
+                                      focusOmnibox:(BOOL)focusOmnibox;
 // Completes the process of dismissing the tab switcher, removing it from the
 // screen and showing the appropriate BVC.
 - (void)finishDismissingTabSwitcher;
@@ -1800,7 +1802,7 @@
   [_browserViewWrangler setCurrentBVC:bvc storageSwitcher:self];
 
   if (!_dismissingTabSwitcher)
-    [self displayCurrentBVC];
+    [self displayCurrentBVCAndFocusOmnibox:NO];
 
   // Tell the BVC that was made current that it can use the web.
   [self activateBVCAndMakeCurrentBVCPrimary];
@@ -1894,9 +1896,16 @@
   [self switchGlobalStateToMode:mode];
 }
 
-- (void)displayCurrentBVC {
+- (void)displayCurrentBVCAndFocusOmnibox:(BOOL)focusOmnibox {
+  ProceduralBlock completion = nil;
+  if (focusOmnibox) {
+    __weak BrowserViewController* weakCurrentBVC = self.currentBVC;
+    completion = ^{
+      [weakCurrentBVC.dispatcher focusOmnibox];
+    };
+  }
   [self.viewControllerSwapper showTabViewController:self.currentBVC
-                                         completion:nil];
+                                         completion:completion];
   [self.currentBVC.dispatcher
       setIncognitoContentVisible:(self.currentBVC == self.otrBVC)];
 }
@@ -2016,7 +2025,7 @@
     [self dismissModalDialogsWithCompletion:nil dismissOmnibox:YES];
     [_tabSwitcher tabSwitcherDismissWithModel:tabModel animated:NO];
   } else {
-    [self beginDismissingTabSwitcherWithCurrentModel:tabModel];
+    [self beginDismissingTabSwitcherWithCurrentModel:tabModel focusOmnibox:NO];
     [self finishDismissingTabSwitcher];
   }
 }
@@ -2024,8 +2033,10 @@
 #pragma mark - TabSwitcherDelegate
 
 - (void)tabSwitcher:(id<TabSwitcher>)tabSwitcher
-    shouldFinishWithActiveModel:(TabModel*)tabModel {
-  [self beginDismissingTabSwitcherWithCurrentModel:tabModel];
+    shouldFinishWithActiveModel:(TabModel*)tabModel
+                   focusOmnibox:(BOOL)focusOmnibox {
+  [self beginDismissingTabSwitcherWithCurrentModel:tabModel
+                                      focusOmnibox:focusOmnibox];
 }
 
 - (void)tabSwitcherDismissTransitionDidEnd:(id<TabSwitcher>)tabSwitcher {
@@ -2041,7 +2052,8 @@
 
 #pragma mark - TabSwitcherDelegate helper methods
 
-- (void)beginDismissingTabSwitcherWithCurrentModel:(TabModel*)tabModel {
+- (void)beginDismissingTabSwitcherWithCurrentModel:(TabModel*)tabModel
+                                      focusOmnibox:(BOOL)focusOmnibox {
   DCHECK(tabModel == self.mainTabModel || tabModel == self.otrTabModel);
 
   _dismissingTabSwitcher = YES;
@@ -2059,7 +2071,7 @@
   // _dismissingTabSwitcher is YES.  When the presentation experiment is
   // enabled, force the BVC transition to start.
   if (TabSwitcherPresentsBVCEnabled()) {
-    [self displayCurrentBVC];
+    [self displayCurrentBVCAndFocusOmnibox:focusOmnibox];
   }
 }
 
@@ -2092,7 +2104,7 @@
   _modeToDisplayOnTabSwitcherDismissal = TabSwitcherDismissalMode::NONE;
 
   // Displaying the current BVC dismisses the tab switcher.
-  [self displayCurrentBVC];
+  [self displayCurrentBVCAndFocusOmnibox:NO];
 
   ProceduralBlock action = [self completionBlockForTriggeringAction:
                                      self.NTPActionAfterTabSwitcherDismissal];
diff --git a/ios/chrome/app/resources/ios_resources.grd b/ios/chrome/app/resources/ios_resources.grd
index 9c7dbfa..2cb2ac88 100644
--- a/ios/chrome/app/resources/ios_resources.grd
+++ b/ios/chrome/app/resources/ios_resources.grd
@@ -11,6 +11,8 @@
       <include name="IDR_IOS_OMAHA_HTML" file="omaha/omaha.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
       <include name="IDR_IOS_OMAHA_JS" file="omaha/omaha.js" type="BINDATA" compress="gzip" />
       <include name="IDR_CHROME_BROWSER_MANIFEST_OVERLAY" file="${root_gen_dir}/ios/chrome/app/chrome_browser_manifest_overlay.json" use_base_dir="false" type="BINDATA" />
+      <include name="IDR_IOS_UKM_INTERNALS_HTML" file="../../../../components/ukm/debug/ukm_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+      <include name="IDR_IOS_UKM_INTERNALS_JS" file="../../../../components/ukm/debug/ukm_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
     </includes>
   </release>
 </grit>
diff --git a/ios/chrome/browser/autofill/BUILD.gn b/ios/chrome/browser/autofill/BUILD.gn
index 89f891f9..75658a2 100644
--- a/ios/chrome/browser/autofill/BUILD.gn
+++ b/ios/chrome/browser/autofill/BUILD.gn
@@ -14,7 +14,6 @@
     "form_input_accessory_view_controller.h",
     "form_input_accessory_view_controller.mm",
     "form_input_accessory_view_delegate.h",
-    "form_input_accessory_view_provider.h",
     "form_suggestion_controller.h",
     "form_suggestion_controller.mm",
     "form_suggestion_label.h",
@@ -30,6 +29,7 @@
     "validation_rules_storage_factory.h",
   ]
   deps = [
+    ":autofill_shared",
     "resources:autofill_close",
     "resources:autofill_close_pressed",
     "resources:autofill_keyboard_background",
@@ -72,6 +72,14 @@
   libs = [ "QuartzCore.framework" ]
 }
 
+source_set("autofill_shared") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "form_input_accessory_view_provider.h",
+  ]
+  libs = [ "UIKit.framework" ]
+}
+
 source_set("autofill_internal") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
diff --git a/ios/chrome/browser/metrics/ukm_egtest.mm b/ios/chrome/browser/metrics/ukm_egtest.mm
index 50674449..09cd952 100644
--- a/ios/chrome/browser/metrics/ukm_egtest.mm
+++ b/ios/chrome/browser/metrics/ukm_egtest.mm
@@ -38,6 +38,7 @@
 #endif
 
 using chrome_test_util::AccountsSyncButton;
+using chrome_test_util::ButtonWithAccessibilityLabel;
 using chrome_test_util::ButtonWithAccessibilityLabelId;
 using chrome_test_util::ClearBrowsingDataCollectionView;
 using chrome_test_util::GetIncognitoTabCount;
@@ -194,13 +195,17 @@
 // Signs out of sync.
 void SignOut() {
   [ChromeEarlGreyUI openSettingsMenu];
-  [[EarlGrey selectElementWithMatcher:SettingsAccountButton()]
+  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];
+
+  // Remove |identity| from the device.
+  ChromeIdentity* identity = [SigninEarlGreyUtils fakeIdentity1];
+  [[EarlGrey
+      selectElementWithMatcher:ButtonWithAccessibilityLabel(identity.userEmail)]
       performAction:grey_tap()];
-  [ChromeEarlGreyUI tapAccountsMenuButton:SignOutAccountsButton()];
-  [[EarlGrey selectElementWithMatcher:
-                 ButtonWithAccessibilityLabelId(
-                     IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE)]
+  [[EarlGrey
+      selectElementWithMatcher:ButtonWithAccessibilityLabel(@"Remove account")]
       performAction:grey_tap()];
+
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
 
@@ -216,11 +221,6 @@
 
 @implementation UKMTestCase
 
-// Per crbug.com/853992, Entire test suite is failing regularly.
-+ (NSArray*)testInvocations {
-  return @[];
-}
-
 + (void)setUp {
   [super setUp];
   if (!base::FeatureList::IsEnabled(ukm::kUkmFeature)) {
@@ -466,7 +466,8 @@
 
 // testMetricsReporting not needed, since iOS doesn't use sampling.
 
-- (void)testHistoryDelete {
+// TODO(crbug.com/866598): Re-enable this test.
+- (void)DISABLED_testHistoryDelete {
   uint64_t original_client_id = metrics::UkmEGTestHelper::client_id();
 
   const ukm::SourceId kDummySourceId = 0x54321;
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn
index 451a166..0bb9fa0 100644
--- a/ios/chrome/browser/ui/authentication/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -52,6 +52,7 @@
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/alert_coordinator",
+    "//ios/chrome/browser/ui/authentication/consent_bump",
     "//ios/chrome/browser/ui/collection_view/cells",
     "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
@@ -179,6 +180,7 @@
     "//components/signin/core/browser",
     "//components/signin/core/browser:account_info",
     "//components/unified_consent",
+    "//ios/chrome/app/strings:ios_strings_grit",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/ui/authentication/unified_consent:unified_consent_ui",
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/BUILD.gn b/ios/chrome/browser/ui/authentication/consent_bump/BUILD.gn
new file mode 100644
index 0000000..a0ed320
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/consent_bump/BUILD.gn
@@ -0,0 +1,26 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/chrome_build.gni")
+
+source_set("consent_bump") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "consent_bump_coordinator.h",
+    "consent_bump_coordinator.mm",
+    "consent_bump_personalization_coordinator.h",
+    "consent_bump_personalization_coordinator.mm",
+    "consent_bump_personalization_view_controller.h",
+    "consent_bump_personalization_view_controller.mm",
+    "consent_bump_view_controller.h",
+    "consent_bump_view_controller.mm",
+    "consent_bump_view_controller_delegate.h",
+  ]
+  deps = [
+    "//base",
+    "//ios/chrome/browser/ui/authentication/unified_consent",
+    "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
+    "//ios/chrome/common/ui_util",
+  ]
+}
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h
new file mode 100644
index 0000000..181289c0
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h
@@ -0,0 +1,18 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_COORDINATOR_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_COORDINATOR_H_
+
+#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
+
+// Coordinator handling the consent bump.
+@interface ConsentBumpCoordinator : ChromeCoordinator
+
+// ViewController associated with this coordinator.
+@property(nonatomic, strong, readonly) UIViewController* viewController;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.mm b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.mm
new file mode 100644
index 0000000..d704b09
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.mm
@@ -0,0 +1,115 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_coordinator.h"
+
+#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_coordinator.h"
+#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.h"
+#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller_delegate.h"
+#import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_coordinator.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// Type of child coordinator presented by this coordinator.
+typedef NS_ENUM(NSInteger, PresentedCoordinator) {
+  PresentedCoordinatorUnifiedConsent,
+  PresentedCoordinatorPersonalization,
+};
+}  // namespace
+
+@interface ConsentBumpCoordinator ()<ConsentBumpViewControllerDelegate>
+
+// Which child coordinator is currently presented.
+@property(nonatomic, assign) PresentedCoordinator presentedCoordinator;
+
+// The ViewController of this coordinator, redefined as a
+// ConsentBumpViewController.
+@property(nonatomic, strong)
+    ConsentBumpViewController* consentBumpViewController;
+// The child coordinator presenting the unified consent.
+@property(nonatomic, strong)
+    UnifiedConsentCoordinator* unifiedConsentCoordinator;
+// The child coordinator presenting the presonalization content.
+@property(nonatomic, strong)
+    ConsentBumpPersonalizationCoordinator* personalizationCoordinator;
+
+@end
+
+@implementation ConsentBumpCoordinator
+
+@synthesize presentedCoordinator = _presentedCoordinator;
+@synthesize consentBumpViewController = _consentBumpViewController;
+@synthesize unifiedConsentCoordinator = _unifiedConsentCoordinator;
+@synthesize personalizationCoordinator = _personalizationCoordinator;
+
+#pragma mark - Properties
+
+- (UIViewController*)viewController {
+  return self.consentBumpViewController;
+}
+
+#pragma mark - ChromeCoordinator
+
+- (void)start {
+  self.consentBumpViewController = [[ConsentBumpViewController alloc] init];
+  self.consentBumpViewController.delegate = self;
+
+  self.unifiedConsentCoordinator = [[UnifiedConsentCoordinator alloc] init];
+  [self.unifiedConsentCoordinator start];
+  self.presentedCoordinator = PresentedCoordinatorUnifiedConsent;
+
+  self.consentBumpViewController.contentViewController =
+      self.unifiedConsentCoordinator.viewController;
+}
+
+- (void)stop {
+  self.consentBumpViewController = nil;
+  self.unifiedConsentCoordinator = nil;
+  self.personalizationCoordinator = nil;
+}
+
+#pragma mark - ConsentBumpViewControllerDelegate
+
+- (void)consentBumpViewControllerDidTapPrimaryButton:
+    (ConsentBumpViewController*)consentBumpViewController {
+  switch (self.presentedCoordinator) {
+    case PresentedCoordinatorUnifiedConsent:
+      // TODO(crbug.com/866506): Consent bump accepted.
+      break;
+    case PresentedCoordinatorPersonalization:
+      // TODO(crbug.com/866506): Clarify what should be the behavior at this
+      // point.
+      break;
+  }
+}
+
+- (void)consentBumpViewControllerDidTapSecondaryButton:
+    (ConsentBumpViewController*)consentBumpViewController {
+  switch (self.presentedCoordinator) {
+    case PresentedCoordinatorUnifiedConsent:
+      // Present the personlization.
+      if (!self.personalizationCoordinator) {
+        self.personalizationCoordinator =
+            [[ConsentBumpPersonalizationCoordinator alloc]
+                initWithBaseViewController:nil];
+        [self.personalizationCoordinator start];
+      }
+      self.consentBumpViewController.contentViewController =
+          self.personalizationCoordinator.viewController;
+      self.presentedCoordinator = PresentedCoordinatorPersonalization;
+      break;
+
+    case PresentedCoordinatorPersonalization:
+      // Go back to the unified consent.
+      self.consentBumpViewController.contentViewController =
+          self.unifiedConsentCoordinator.viewController;
+      self.presentedCoordinator = PresentedCoordinatorUnifiedConsent;
+      break;
+  }
+}
+
+@end
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_coordinator.h b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_coordinator.h
new file mode 100644
index 0000000..4611b12d
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_coordinator.h
@@ -0,0 +1,18 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_PERSONALIZATION_COORDINATOR_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_PERSONALIZATION_COORDINATOR_H_
+
+#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
+
+// Coordinator for handling the ConsentBump Personalization screen.
+@interface ConsentBumpPersonalizationCoordinator : ChromeCoordinator
+
+// The view Controller for this coordinator.
+@property(nonatomic, strong, readonly) UIViewController* viewController;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_PERSONALIZATION_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_coordinator.mm b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_coordinator.mm
new file mode 100644
index 0000000..9dff249
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_coordinator.mm
@@ -0,0 +1,42 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_coordinator.h"
+
+#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface ConsentBumpPersonalizationCoordinator ()
+
+// The view controller, redefined as ConsentBumpPersonalizationViewController.
+@property(nonatomic, strong)
+    ConsentBumpPersonalizationViewController* personalizationViewController;
+
+@end
+
+@implementation ConsentBumpPersonalizationCoordinator
+
+@synthesize personalizationViewController = _personalizationViewController;
+
+#pragma mark - Properties
+
+- (UIViewController*)viewController {
+  return self.personalizationViewController;
+}
+
+#pragma mark - ChromeCoordinator
+
+- (void)start {
+  self.personalizationViewController =
+      [[ConsentBumpPersonalizationViewController alloc] init];
+}
+
+- (void)stop {
+  self.personalizationViewController = nil;
+}
+
+@end
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.h b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.h
new file mode 100644
index 0000000..064ba0f
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.h
@@ -0,0 +1,15 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_PERSONALIZATION_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_PERSONALIZATION_VIEW_CONTROLLER_H_
+
+#import <UIKit/UIKit.h>
+
+// View controller displaying the Personalization screen.
+@interface ConsentBumpPersonalizationViewController : UIViewController
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_PERSONALIZATION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm
new file mode 100644
index 0000000..b1d3f554
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm
@@ -0,0 +1,17 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation ConsentBumpPersonalizationViewController
+
+- (void)viewDidLoad {
+  self.view.backgroundColor = [UIColor blueColor];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.h b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.h
new file mode 100644
index 0000000..3640b4a
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.h
@@ -0,0 +1,23 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_VIEW_CONTROLLER_H_
+
+#import <UIKit/UIKit.h>
+
+@protocol ConsentBumpViewControllerDelegate;
+
+// View Controller handling the ConsentBump screen.
+@interface ConsentBumpViewController : UIViewController
+
+// Delegate for the view controller.
+@property(nonatomic, weak) id<ConsentBumpViewControllerDelegate> delegate;
+
+// View controller displayed as child view controller for this ViewController.
+@property(nonatomic, strong) UIViewController* contentViewController;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.mm b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.mm
new file mode 100644
index 0000000..ef7f439
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.mm
@@ -0,0 +1,182 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.h"
+
+#import "ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller_delegate.h"
+#import "ios/chrome/common/ui_util/constraints_ui_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+const CGFloat kMargin = 16;
+const CGFloat kGradientHeight = 40;
+}  // namespace
+
+@interface ConsentBumpViewController ()
+
+@property(nonatomic, strong) UIView* buttonContainer;
+@property(nonatomic, strong) UIButton* primaryButton;
+@property(nonatomic, strong) UIButton* secondaryButton;
+@property(nonatomic, strong) UIView* gradientView;
+@property(nonatomic, strong) CAGradientLayer* gradientLayer;
+
+@end
+
+@implementation ConsentBumpViewController
+
+@synthesize delegate = _delegate;
+@synthesize contentViewController = _contentViewController;
+@synthesize buttonContainer = _buttonContainer;
+@synthesize primaryButton = _primaryButton;
+@synthesize secondaryButton = _secondaryButton;
+@synthesize gradientView = _gradientView;
+@synthesize gradientLayer = _gradientLayer;
+
+#pragma mark - Public
+
+- (void)setContentViewController:(UIViewController*)contentViewController {
+  if (_contentViewController == contentViewController)
+    return;
+
+  // Remove previous VC.
+  [_contentViewController willMoveToParentViewController:nil];
+  [_contentViewController.view removeFromSuperview];
+  [_contentViewController removeFromParentViewController];
+
+  _contentViewController = contentViewController;
+
+  if (!contentViewController)
+    return;
+
+  [self addChildViewController:contentViewController];
+
+  contentViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
+  [self.view insertSubview:contentViewController.view
+              belowSubview:self.gradientView];
+  AddSameConstraintsToSides(
+      self.view, contentViewController.view,
+      LayoutSides::kTop | LayoutSides::kLeading | LayoutSides::kTrailing);
+  [contentViewController.view.bottomAnchor
+      constraintEqualToAnchor:self.buttonContainer.topAnchor]
+      .active = YES;
+
+  [contentViewController didMoveToParentViewController:self];
+}
+
+#pragma mark - Property
+
+- (UIButton*)primaryButton {
+  if (!_primaryButton) {
+    _primaryButton = [UIButton buttonWithType:UIButtonTypeSystem];
+    _primaryButton.translatesAutoresizingMaskIntoConstraints = NO;
+    [_primaryButton setTitle:@"Primary Button" forState:UIControlStateNormal];
+    _primaryButton.backgroundColor = [UIColor blueColor];
+    [_primaryButton setContentHuggingPriority:UILayoutPriorityDefaultHigh
+                                      forAxis:UILayoutConstraintAxisVertical];
+    [_primaryButton addTarget:self
+                       action:@selector(primaryButtonCallback)
+             forControlEvents:UIControlEventTouchUpInside];
+  }
+  return _primaryButton;
+}
+
+- (UIButton*)secondaryButton {
+  if (!_secondaryButton) {
+    _secondaryButton = [UIButton buttonWithType:UIButtonTypeSystem];
+    _secondaryButton.translatesAutoresizingMaskIntoConstraints = NO;
+    [_secondaryButton setTitle:@"Secondary Button"
+                      forState:UIControlStateNormal];
+    [_secondaryButton setContentHuggingPriority:UILayoutPriorityDefaultHigh
+                                        forAxis:UILayoutConstraintAxisVertical];
+    [_secondaryButton addTarget:self
+                         action:@selector(secondaryButtonCallback)
+               forControlEvents:UIControlEventTouchUpInside];
+  }
+  return _secondaryButton;
+}
+
+- (UIView*)buttonContainer {
+  if (!_buttonContainer) {
+    _buttonContainer = [[UIView alloc] init];
+    _buttonContainer.translatesAutoresizingMaskIntoConstraints = NO;
+  }
+  return _buttonContainer;
+}
+
+- (UIView*)gradientView {
+  if (!_gradientView) {
+    _gradientView = [[UIView alloc] initWithFrame:CGRectZero];
+    _gradientView.userInteractionEnabled = NO;
+    _gradientView.translatesAutoresizingMaskIntoConstraints = NO;
+    [_gradientView.layer insertSublayer:self.gradientLayer atIndex:0];
+  }
+  return _gradientView;
+}
+
+- (CAGradientLayer*)gradientLayer {
+  if (!_gradientLayer) {
+    _gradientLayer = [CAGradientLayer layer];
+    _gradientLayer.colors = @[
+      (id)[[UIColor colorWithWhite:1 alpha:0] CGColor],
+      (id)[self.view.backgroundColor CGColor]
+    ];
+  }
+  return _gradientLayer;
+}
+
+#pragma mark - UIViewController
+
+- (void)viewDidLayoutSubviews {
+  [super viewDidLayoutSubviews];
+  self.gradientLayer.frame = self.gradientView.bounds;
+}
+
+- (void)viewDidLoad {
+  self.view.backgroundColor = [UIColor whiteColor];
+
+  // Add subviews.
+  [self.buttonContainer addSubview:self.primaryButton];
+  [self.buttonContainer addSubview:self.secondaryButton];
+  [self.view addSubview:self.buttonContainer];
+  [self.view addSubview:self.gradientView];
+
+  // Constraints.
+  id<LayoutGuideProvider> safeArea = SafeAreaLayoutGuideForView(self.view);
+  AddSameConstraintsToSides(self.view, self.gradientView,
+                            LayoutSides::kLeading | LayoutSides::kTrailing);
+  AddSameConstraintsToSides(
+      safeArea, self.buttonContainer,
+      LayoutSides::kBottom | LayoutSides::kLeading | LayoutSides::kTrailing);
+  AddSameConstraintsToSidesWithInsets(
+      self.secondaryButton, self.buttonContainer,
+      LayoutSides::kLeading | LayoutSides::kTop | LayoutSides::kBottom,
+      ChromeDirectionalEdgeInsetsMake(kMargin, kMargin, kMargin, 0));
+  AddSameConstraintsToSidesWithInsets(
+      self.primaryButton, self.buttonContainer,
+      LayoutSides::kTrailing | LayoutSides::kTop | LayoutSides::kBottom,
+      ChromeDirectionalEdgeInsetsMake(kMargin, 0, kMargin, kMargin));
+  [NSLayoutConstraint activateConstraints:@[
+    [self.gradientView.heightAnchor constraintEqualToConstant:kGradientHeight],
+    [self.gradientView.bottomAnchor
+        constraintEqualToAnchor:self.buttonContainer.topAnchor],
+    [self.primaryButton.leadingAnchor
+        constraintGreaterThanOrEqualToAnchor:self.secondaryButton
+                                                 .trailingAnchor],
+  ]];
+}
+
+#pragma mark - Private
+
+- (void)primaryButtonCallback {
+  [self.delegate consentBumpViewControllerDidTapPrimaryButton:self];
+}
+
+- (void)secondaryButtonCallback {
+  [self.delegate consentBumpViewControllerDidTapSecondaryButton:self];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller_delegate.h b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller_delegate.h
new file mode 100644
index 0000000..8a35f48
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller_delegate.h
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_VIEW_CONTROLLER_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_VIEW_CONTROLLER_DELEGATE_H_
+
+#import <UIKit/UIKit.h>
+
+@class ConsentBumpViewController;
+
+// Protocol for the delegate of the ConsentBumpViewController.
+@protocol ConsentBumpViewControllerDelegate<NSObject>
+
+// Notifies the delegate that the primary button of the view controller has been
+// pressed.
+- (void)consentBumpViewControllerDidTapPrimaryButton:
+    (ConsentBumpViewController*)consentBumpViewController;
+// Notifies the delegate that the secondary button of the view controller has
+// been pressed.
+- (void)consentBumpViewControllerDidTapSecondaryButton:
+    (ConsentBumpViewController*)consentBumpViewController;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CONSENT_BUMP_CONSENT_BUMP_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm
index 85ada002..d1c976fe 100644
--- a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm
+++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm
@@ -6,12 +6,14 @@
 
 #import <EarlGrey/EarlGrey.h>
 
+#include "base/mac/foundation_util.h"
 #include "components/unified_consent/feature.h"
 #include "ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.h"
 #import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h"
 #import "ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_cell.h"
 #import "ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.h"
 #import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.h"
+#include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/public/provider/chrome/browser/signin/chrome_identity.h"
@@ -21,6 +23,27 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+
+// Returns a matcher to test whether the element is a scroll view with a content
+// smaller than the scroll view bounds.
+id<GREYMatcher> ContentViewSmallerThanScrollView() {
+  MatchesBlock matches = ^BOOL(UIView* view) {
+    UIScrollView* scrollView = base::mac::ObjCCast<UIScrollView>(view);
+    return scrollView &&
+           scrollView.contentSize.height < scrollView.bounds.size.height;
+  };
+  DescribeToBlock describe = ^void(id<GREYDescription> description) {
+    [description appendText:
+                     @"Not a scroll view or the scroll view content is bigger "
+                     @"than the scroll view bounds"];
+  };
+  return [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
+                                              descriptionBlock:describe];
+}
+
+}  // namespace
+
 using chrome_test_util::AccountConsistencyConfirmationOkButton;
 using chrome_test_util::AccountConsistencySetupSigninButton;
 using chrome_test_util::ButtonWithAccessibilityLabel;
@@ -66,27 +89,42 @@
 }
 
 + (void)confirmSigninConfirmationDialog {
-  // Confirm sign in. "More" button is shown on short devices (e.g. iPhone 5s,
-  // iPhone SE), so needs to scroll first to dismiss the "More" button before
-  // taping on "OK".
-  // Cannot directly scroll on |kSignInConfirmationCollectionViewId| because it
-  // is a MDC collection view, not a UICollectionView, so itself is not
-  // scrollable.
-  // Wait until the sync confirmation is displayed.
-  id<GREYMatcher> signinUICollectionViewMatcher = nil;
+  // To confirm the dialog, the scroll view content has to be scrolled to the
+  // bottom to transform "MORE" button into the validation button.
+  // EarlGrey fails to scroll to the bottom, using grey_scrollToContentEdge(),
+  // if the scroll view doesn't bounce and by default a scroll view doesn't
+  // bounce when the content fits into the scroll view (the scroll never ends).
+  // To test if the content fits into the scroll view,
+  // ContentViewSmallerThanScrollView() matcher is used on the signin scroll
+  // view.
+  // If the matcher fails, then the scroll view should be scrolled to the
+  // bottom.
+  // Once to the bottom, the consent can be confirmed.
+  id<GREYMatcher> confirmationScrollViewMatcher = nil;
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
   if (base::FeatureList::IsEnabled(unified_consent::kUnifiedConsent)) {
-    signinUICollectionViewMatcher =
+    confirmationScrollViewMatcher =
         grey_accessibilityID(kUnifiedConsentScrollViewIdentifier);
   } else {
-    signinUICollectionViewMatcher = grey_allOf(
+    confirmationScrollViewMatcher = grey_allOf(
         grey_ancestor(
             grey_accessibilityID(kSigninConfirmationCollectionViewId)),
         grey_kindOfClass([UICollectionView class]), nil);
   }
-  [[EarlGrey selectElementWithMatcher:signinUICollectionViewMatcher]
-      performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
-
+  NSError* error = nil;
+  [[EarlGrey selectElementWithMatcher:confirmationScrollViewMatcher]
+      assertWithMatcher:ContentViewSmallerThanScrollView()
+                  error:&error];
+  if (error) {
+    // If the consent is bigger than the scroll view, the primary button should
+    // be "MORE".
+    [[EarlGrey selectElementWithMatcher:
+                   chrome_test_util::ButtonWithAccessibilityLabelId(
+                       IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_SCROLL_BUTTON)]
+        assertWithMatcher:grey_notNil()];
+    [[EarlGrey selectElementWithMatcher:confirmationScrollViewMatcher]
+        performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)];
+  }
   [[EarlGrey selectElementWithMatcher:AccountConsistencyConfirmationOkButton()]
       performAction:grey_tap()];
 }
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm
index f261b31a..cf0c232 100644
--- a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm
@@ -171,7 +171,6 @@
   self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
   self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
   self.scrollView.accessibilityIdentifier = kUnifiedConsentScrollViewIdentifier;
-  self.scrollView.alwaysBounceVertical = YES;
   if (@available(iOS 11, *)) {
     // The observed behavior was buggy. When the view appears on the screen,
     // the scrollvie was not scrolled all the way to the top. Adjusting the
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 5faac3fd..faeb2ae 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -1753,6 +1753,15 @@
     [self.primaryToolbarCoordinator.viewController.view setNeedsLayout];
     [self.primaryToolbarCoordinator.viewController.view layoutIfNeeded];
   }
+
+  // Native content pages depend on |self.view|'s safeArea.  If the BVC is
+  // presented underneath another view (such as the first time welcome view),
+  // the BVC has no safe area set during webController's layout initial, and
+  // won't automatically get another layout without forcing it here.
+  Tab* currentTab = [_model currentTab];
+  if ([self isTabNativePage:currentTab]) {
+    [currentTab.webController.view setNeedsLayout];
+  }
 }
 
 - (void)viewDidLayoutSubviews {
diff --git a/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
index f129259..99c2bb1 100644
--- a/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/autofill_settings_egtest.mm
@@ -127,9 +127,6 @@
 
 // Test that submitting a form ensures saving the data as an autofill profile.
 - (void)testAutofillProfileSaving {
-  // TODO(crbug.com/866730): Re-enable when fixed
-  EARL_GREY_TEST_DISABLED(@"Test broken.");
-
   [self loadAndSubmitTheForm];
   [self openEditAddress:@"George Washington, 1600 Pennsylvania Ave NW"];
 
@@ -150,9 +147,6 @@
 // Test that editing country names is followed by validating the value and
 // replacing it with a canonical one.
 - (void)testAutofillProfileEditing {
-  // TODO(crbug.com/866730): Re-enable when fixed
-  EARL_GREY_TEST_DISABLED(@"Test broken.");
-
   [self loadAndSubmitTheForm];
   [self openEditAddress:@"George Washington, 1600 Pennsylvania Ave NW"];
 
@@ -187,9 +181,6 @@
 
 // Test that the page for viewing autofill profile details is accessible.
 - (void)testAccessibilityOnAutofillProfileViewPage {
-  // TODO(crbug.com/866730): Re-enable when fixed
-  EARL_GREY_TEST_DISABLED(@"Test broken.");
-
   [self loadAndSubmitTheForm];
   [self openEditAddress:@"George Washington, 1600 Pennsylvania Ave NW"];
   chrome_test_util::VerifyAccessibilityForCurrentScreen();
@@ -199,9 +190,6 @@
 
 // Test that the page for editing autofill profile details is accessible.
 - (void)testAccessibilityOnAutofillProfileEditPage {
-  // TODO(crbug.com/866730): Re-enable when fixed
-  EARL_GREY_TEST_DISABLED(@"Test broken.");
-
   [self loadAndSubmitTheForm];
   [self openEditAddress:@"George Washington, 1600 Pennsylvania Ave NW"];
   // Switch on edit mode.
@@ -216,9 +204,6 @@
 // Checks that if the autofill profiles and credit cards list view is in edit
 // mode, the "autofill" and "wallet" switch items are disabled.
 - (void)testListViewEditMode {
-  // TODO(crbug.com/866730): Re-enable when fixed
-  EARL_GREY_TEST_DISABLED(@"Test broken.");
-
   [self loadAndSubmitTheForm];
 
   [ChromeEarlGreyUI openSettingsMenu];
diff --git a/ios/chrome/browser/ui/stack_view/stack_view_controller.mm b/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
index 5e2c131..e8146e4 100644
--- a/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
+++ b/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
@@ -2085,7 +2085,8 @@
   [NSObject cancelPreviousPerformRequestsWithTarget:self];
 
   [_delegate tabSwitcher:self
-      shouldFinishWithActiveModel:_activeCardSet.tabModel];
+      shouldFinishWithActiveModel:_activeCardSet.tabModel
+                     focusOmnibox:NO];
 
   [self animateTransitionWithStyle:STACK_TRANSITION_STYLE_DISMISSING];
 }
@@ -2200,7 +2201,8 @@
   [_activeCardSet.tabModel setCurrentTab:tab];
 
   [_delegate tabSwitcher:self
-      shouldFinishWithActiveModel:_activeCardSet.tabModel];
+      shouldFinishWithActiveModel:_activeCardSet.tabModel
+                     focusOmnibox:NO];
 
   CGFloat statusBarHeight = StatusBarHeight();
   CGRect viewBounds, remainder;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
index 2409a3e..74382d8 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
@@ -85,7 +85,9 @@
 
   // Tell the delegate to display the tab.
   DCHECK(self.delegate);
-  [self.delegate tabSwitcher:self shouldFinishWithActiveModel:targetModel];
+  [self.delegate tabSwitcher:self
+      shouldFinishWithActiveModel:targetModel
+                     focusOmnibox:NO];
 
   return tab;
 }
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
index 224674f..a8cf93c 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -338,7 +338,7 @@
 
 #pragma mark - TabPresentationDelegate
 
-- (void)showActiveTabInPage:(TabGridPage)page {
+- (void)showActiveTabInPage:(TabGridPage)page focusOmnibox:(BOOL)focusOmnibox {
   DCHECK(self.regularTabModel && self.incognitoTabModel);
   TabModel* activeTabModel;
   switch (page) {
@@ -357,7 +357,8 @@
   // Trigger the transition through the TabSwitcher delegate. This will in turn
   // call back into this coordinator via the ViewControllerSwapping protocol.
   [self.tabSwitcher.delegate tabSwitcher:self.tabSwitcher
-             shouldFinishWithActiveModel:activeTabModel];
+             shouldFinishWithActiveModel:activeTabModel
+                            focusOmnibox:focusOmnibox];
 }
 
 #pragma mark - BrowserCommands
@@ -399,19 +400,22 @@
 
 - (void)showActiveRegularTabFromRecentTabs {
   [self.tabSwitcher.delegate tabSwitcher:self.tabSwitcher
-             shouldFinishWithActiveModel:self.regularTabModel];
+             shouldFinishWithActiveModel:self.regularTabModel
+                            focusOmnibox:NO];
 }
 
 #pragma mark - HistoryPresentationDelegate
 
 - (void)showActiveRegularTabFromHistory {
   [self.tabSwitcher.delegate tabSwitcher:self.tabSwitcher
-             shouldFinishWithActiveModel:self.regularTabModel];
+             shouldFinishWithActiveModel:self.regularTabModel
+                            focusOmnibox:NO];
 }
 
 - (void)showActiveIncognitoTabFromHistory {
   [self.tabSwitcher.delegate tabSwitcher:self.tabSwitcher
-             shouldFinishWithActiveModel:self.incognitoTabModel];
+             shouldFinishWithActiveModel:self.incognitoTabModel
+                            focusOmnibox:NO];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm
index ace48fdb..845b86ef 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm
@@ -23,7 +23,8 @@
 @implementation TestTabSwitcherDelegate
 @synthesize didEndCalled = _didEndCalled;
 - (void)tabSwitcher:(id<TabSwitcher>)tabSwitcher
-    shouldFinishWithActiveModel:(TabModel*)tabModel {
+    shouldFinishWithActiveModel:(TabModel*)tabModel
+                   focusOmnibox:(BOOL)focusOmnibox {
   // No-op.
 }
 
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm
index 120b075d..1b2df4c 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm
@@ -20,7 +20,7 @@
 
 // Structure of this control:
 //
-// The page control is similar to a UISegmentedCoffee in appearance, but not in
+// The page control is similar to a UISegmentedControl in appearance, but not in
 // function. This control doesn't have segments that highlight; instead there
 // is a white "slider" that moves across the view onto whichever segment is
 // active. Each segment has an image and (optionally) a label. When the slider
@@ -302,13 +302,11 @@
   CGPoint position = [touch locationInView:self];
   CGFloat deltaX = position.x - self.dragStart.x;
   // Convert to position change.
-  CGFloat postionChange = deltaX / self.sliderRange;
+  CGFloat positionChange = deltaX / self.sliderRange;
 
-  self.sliderPosition = self.dragStartPosition + postionChange;
+  self.sliderPosition = self.dragStartPosition + positionChange;
   [self sendActionsForControlEvents:UIControlEventValueChanged];
-
-  // If the touch is now outside of the control, stop tracking it.
-  return self.touchInside;
+  return YES;
 }
 
 - (void)endTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event {
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
index d051c80..447ffe2 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
@@ -20,8 +20,9 @@
 // Delegate protocol for an object that can handle presenting ("opening") tabs
 // from the tab grid.
 @protocol TabPresentationDelegate<NSObject>
-// Show the active tab in |page|, presented on top of the tab grid.
-- (void)showActiveTabInPage:(TabGridPage)page;
+// Show the active tab in |page|, presented on top of the tab grid.  The
+// omnibox will be focused after the animation if |focusOmnibox| is YES.
+- (void)showActiveTabInPage:(TabGridPage)page focusOmnibox:(BOOL)focusOmnibox;
 @end
 
 // View controller representing a tab switcher. The tab switcher has an
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index f9645b0a..78b612d 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -886,7 +886,7 @@
 
 // Tells the appropriate delegate to create a new item, and then tells the
 // presentation delegate to show the new item.
-- (void)openNewTabInPage:(TabGridPage)page {
+- (void)openNewTabInPage:(TabGridPage)page focusOmnibox:(BOOL)focusOmnibox {
   switch (page) {
     case TabGridPageIncognitoTabs:
       [self.incognitoTabsDelegate addNewItem];
@@ -907,22 +907,23 @@
       break;
   }
   self.activePage = page;
-  [self.tabPresentationDelegate showActiveTabInPage:page];
+  [self.tabPresentationDelegate showActiveTabInPage:page
+                                       focusOmnibox:focusOmnibox];
 }
 
 // Creates and shows a new regular tab.
-- (void)openNewRegularTab {
-  [self openNewTabInPage:TabGridPageRegularTabs];
+- (void)openNewRegularTabForKeyboardCommand {
+  [self openNewTabInPage:TabGridPageRegularTabs focusOmnibox:YES];
 }
 
 // Creates and shows a new incognito tab.
-- (void)openNewIncognitoTab {
-  [self openNewTabInPage:TabGridPageIncognitoTabs];
+- (void)openNewIncognitoTabForKeyboardCommand {
+  [self openNewTabInPage:TabGridPageIncognitoTabs focusOmnibox:YES];
 }
 
 // Creates and shows a new tab in the current page.
-- (void)openNewTabInCurrentPage {
-  [self openNewTabInPage:self.currentPage];
+- (void)openNewTabInCurrentPageForKeyboardCommand {
+  [self openNewTabInPage:self.currentPage focusOmnibox:YES];
 }
 
 // Broadcasts whether incognito tabs are showing.
@@ -957,7 +958,8 @@
         base::UserMetricsAction("MobileTabSwitcherOpenIncognitoTab"));
   }
   self.activePage = self.currentPage;
-  [self.tabPresentationDelegate showActiveTabInPage:self.currentPage];
+  [self.tabPresentationDelegate showActiveTabInPage:self.currentPage
+                                       focusOmnibox:NO];
   gridViewController.showsSelectionUpdates = YES;
 }
 
@@ -1009,7 +1011,8 @@
   // being triggered on release after tabs have been closed and the button
   // disabled. Ensure that action is only taken on a valid state.
   if (![[self gridViewControllerForPage:newActivePage] isGridEmpty]) {
-    [self.tabPresentationDelegate showActiveTabInPage:newActivePage];
+    [self.tabPresentationDelegate showActiveTabInPage:newActivePage
+                                         focusOmnibox:NO];
     // Record when users exit the tab grid to return to the current foreground
     // tab.
     // TODO(crbug.com/856965) : Rename metrics.
@@ -1041,7 +1044,7 @@
 }
 
 - (void)newTabButtonTapped:(id)sender {
-  [self openNewTabInCurrentPage];
+  [self openNewTabInPage:self.currentPage focusOmnibox:NO];
   // Record only when a new tab is created through the + button.
   // TODO(crbug.com/856965) : Rename metrics.
   base::RecordAction(base::UserMetricsAction("MobileToolbarStackViewNewTab"));
@@ -1075,24 +1078,24 @@
 #pragma mark - UIResponder
 
 - (NSArray*)keyCommands {
-  UIKeyCommand* newWindowShortcut =
-      [UIKeyCommand keyCommandWithInput:@"n"
-                          modifierFlags:UIKeyModifierCommand
-                                 action:@selector(openNewRegularTab)
-                   discoverabilityTitle:l10n_util::GetNSStringWithFixup(
-                                            IDS_IOS_TOOLS_MENU_NEW_TAB)];
+  UIKeyCommand* newWindowShortcut = [UIKeyCommand
+       keyCommandWithInput:@"n"
+             modifierFlags:UIKeyModifierCommand
+                    action:@selector(openNewRegularTabForKeyboardCommand)
+      discoverabilityTitle:l10n_util::GetNSStringWithFixup(
+                               IDS_IOS_TOOLS_MENU_NEW_TAB)];
   UIKeyCommand* newIncognitoWindowShortcut = [UIKeyCommand
        keyCommandWithInput:@"n"
              modifierFlags:UIKeyModifierCommand | UIKeyModifierShift
-                    action:@selector(openNewIncognitoTab)
+                    action:@selector(openNewIncognitoTabForKeyboardCommand)
       discoverabilityTitle:l10n_util::GetNSStringWithFixup(
                                IDS_IOS_TOOLS_MENU_NEW_INCOGNITO_TAB)];
-  UIKeyCommand* newTabShortcut =
-      [UIKeyCommand keyCommandWithInput:@"t"
-                          modifierFlags:UIKeyModifierCommand
-                                 action:@selector(openNewTabInCurrentPage)
-                   discoverabilityTitle:l10n_util::GetNSStringWithFixup(
-                                            IDS_IOS_TOOLS_MENU_NEW_TAB)];
+  UIKeyCommand* newTabShortcut = [UIKeyCommand
+       keyCommandWithInput:@"t"
+             modifierFlags:UIKeyModifierCommand
+                    action:@selector(openNewTabInCurrentPageForKeyboardCommand)
+      discoverabilityTitle:l10n_util::GetNSStringWithFixup(
+                               IDS_IOS_TOOLS_MENU_NEW_TAB)];
   return @[ newWindowShortcut, newIncognitoWindowShortcut, newTabShortcut ];
 }
 
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher.h b/ios/chrome/browser/ui/tab_switcher/tab_switcher.h
index 282bab0..8b1da3d 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher.h
@@ -28,7 +28,8 @@
 // Informs the delegate the stack controller should be dismissed with the given
 // active model.
 - (void)tabSwitcher:(id<TabSwitcher>)tabSwitcher
-    shouldFinishWithActiveModel:(TabModel*)tabModel;
+    shouldFinishWithActiveModel:(TabModel*)tabModel
+                   focusOmnibox:(BOOL)focusOmnibox;
 
 // Informs the delegate that the stack controller is done and should be
 // dismissed.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
index 1269ec2..bef8d3c 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_controller.mm
@@ -872,7 +872,9 @@
   DCHECK(model);
   [[self presentedViewController] dismissViewControllerAnimated:NO
                                                      completion:nil];
-  [self.delegate tabSwitcher:self shouldFinishWithActiveModel:model];
+  [self.delegate tabSwitcher:self
+      shouldFinishWithActiveModel:model
+                     focusOmnibox:NO];
   [self performTabSwitcherTransition:TransitionType::TRANSITION_DISMISS
                            withModel:model
                             animated:animated
diff --git a/ios/chrome/browser/ui/webui/BUILD.gn b/ios/chrome/browser/ui/webui/BUILD.gn
index ed080bd5..468737f 100644
--- a/ios/chrome/browser/ui/webui/BUILD.gn
+++ b/ios/chrome/browser/ui/webui/BUILD.gn
@@ -20,8 +20,8 @@
     "suggestions_ui.h",
     "terms_ui.h",
     "terms_ui.mm",
-    "url_keyed_metrics_ui.cc",
-    "url_keyed_metrics_ui.h",
+    "ukm_internals_ui.cc",
+    "ukm_internals_ui.h",
     "version_handler.cc",
     "version_handler.h",
     "version_ui.h",
@@ -46,6 +46,7 @@
     "//components/version_info",
     "//components/version_ui",
     "//google_apis",
+    "//ios/chrome/app/resources:ios_resources",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
diff --git a/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm b/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm
index 2b8b130..77fd1b9 100644
--- a/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm
+++ b/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm
@@ -20,7 +20,7 @@
 #include "ios/chrome/browser/ui/webui/suggestions_ui.h"
 #include "ios/chrome/browser/ui/webui/sync_internals/sync_internals_ui.h"
 #include "ios/chrome/browser/ui/webui/terms_ui.h"
-#include "ios/chrome/browser/ui/webui/url_keyed_metrics_ui.h"
+#include "ios/chrome/browser/ui/webui/ukm_internals_ui.h"
 #include "ios/chrome/browser/ui/webui/version_ui.h"
 #include "url/gurl.h"
 
@@ -91,7 +91,7 @@
   if (url_host == kChromeUIFlagsHost)
     return &NewWebUIIOS<FlagsUI>;
   if (url_host == kChromeUIURLKeyedMetricsHost)
-    return &NewWebUIIOSWithHost<URLKeyedMetricsUI>;
+    return &NewWebUIIOS<UkmInternalsUI>;
 
   return nullptr;
 }
diff --git a/ios/chrome/browser/ui/webui/ukm_internals_ui.cc b/ios/chrome/browser/ui/webui/ukm_internals_ui.cc
new file mode 100644
index 0000000..477780b2
--- /dev/null
+++ b/ios/chrome/browser/ui/webui/ukm_internals_ui.cc
@@ -0,0 +1,88 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ios/chrome/browser/ui/webui/ukm_internals_ui.h"
+
+#include <string>
+
+#include "base/memory/ref_counted_memory.h"
+#include "components/metrics_services_manager/metrics_services_manager.h"
+#include "components/ukm/debug/ukm_debug_data_extractor.h"
+#include "components/ukm/ukm_service.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/chrome_url_constants.h"
+#include "ios/chrome/grit/ios_resources.h"
+#include "ios/web/public/url_data_source_ios.h"
+#include "ios/web/public/web_ui_ios_data_source.h"
+#include "ios/web/public/webui/web_ui_ios.h"
+#include "ios/web/public/webui/web_ui_ios_message_handler.h"
+
+namespace {
+
+web::WebUIIOSDataSource* CreateUkmInternalsUIHTMLSource() {
+  web::WebUIIOSDataSource* source =
+      web::WebUIIOSDataSource::Create(kChromeUIURLKeyedMetricsHost);
+
+  source->AddResourcePath("ukm_internals.js", IDR_IOS_UKM_INTERNALS_JS);
+  source->SetDefaultResource(IDR_IOS_UKM_INTERNALS_HTML);
+  source->UseGzip();
+  return source;
+}
+
+// The handler for Javascript messages for the chrome://ukm/ page.
+class UkmMessageHandler : public web::WebUIIOSMessageHandler {
+ public:
+  explicit UkmMessageHandler(const ukm::UkmService* ukm_service);
+  ~UkmMessageHandler() override;
+
+  // web::WebUIIOSMessageHandler implementation.
+  void RegisterMessages() override;
+
+ private:
+  void HandleRequestUkmData(const base::ListValue* args);
+
+  const ukm::UkmService* ukm_service_;
+
+  DISALLOW_COPY_AND_ASSIGN(UkmMessageHandler);
+};
+
+UkmMessageHandler::UkmMessageHandler(const ukm::UkmService* ukm_service)
+    : ukm_service_(ukm_service) {}
+
+UkmMessageHandler::~UkmMessageHandler() {}
+
+void UkmMessageHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback(
+      "requestUkmData",
+      base::BindRepeating(&UkmMessageHandler::HandleRequestUkmData,
+                          base::Unretained(this)));
+}
+
+void UkmMessageHandler::HandleRequestUkmData(const base::ListValue* args) {
+  base::Value ukm_debug_data =
+      ukm::debug::UkmDebugDataExtractor::GetStructuredData(ukm_service_);
+
+  std::string callback_id;
+  args->GetString(0, &callback_id);
+  web_ui()->ResolveJavascriptCallback(base::Value(callback_id),
+                                      std::move(ukm_debug_data));
+}
+
+}  // namespace
+
+// Changes to this class should be in sync with its non-iOS equivalent
+// chrome/browser/ui/webui/ukm/ukm_internals_ui.cc
+UkmInternalsUI::UkmInternalsUI(web::WebUIIOS* web_ui)
+    : web::WebUIIOSController(web_ui) {
+  ukm::UkmService* ukm_service =
+      GetApplicationContext()->GetMetricsServicesManager()->GetUkmService();
+  web_ui->AddMessageHandler(std::make_unique<UkmMessageHandler>(ukm_service));
+
+  // Set up the chrome://ukm/ source.
+  web::WebUIIOSDataSource::Add(ios::ChromeBrowserState::FromWebUIIOS(web_ui),
+                               CreateUkmInternalsUIHTMLSource());
+}
+
+UkmInternalsUI::~UkmInternalsUI() {}
diff --git a/ios/chrome/browser/ui/webui/ukm_internals_ui.h b/ios/chrome/browser/ui/webui/ukm_internals_ui.h
new file mode 100644
index 0000000..73e583d
--- /dev/null
+++ b/ios/chrome/browser/ui/webui/ukm_internals_ui.h
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_WEBUI_UKM_INTERNALS_UI_H_
+#define IOS_CHROME_BROWSER_UI_WEBUI_UKM_INTERNALS_UI_H_
+
+#include "base/macros.h"
+#include "ios/web/public/webui/web_ui_ios_controller.h"
+
+namespace web {
+class WebUIIOS;
+}
+
+// The WebUI controller for chrome://ukm.
+class UkmInternalsUI : public web::WebUIIOSController {
+ public:
+  explicit UkmInternalsUI(web::WebUIIOS* web_ui);
+  ~UkmInternalsUI() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(UkmInternalsUI);
+};
+
+#endif  // IOS_CHROME_BROWSER_UI_WEBUI_UKM_INTERNALS_UI_H_
diff --git a/ios/chrome/browser/ui/webui/url_keyed_metrics_ui.cc b/ios/chrome/browser/ui/webui/url_keyed_metrics_ui.cc
deleted file mode 100644
index d9851e6..0000000
--- a/ios/chrome/browser/ui/webui/url_keyed_metrics_ui.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ios/chrome/browser/ui/webui/url_keyed_metrics_ui.h"
-
-#include <string>
-
-#include "base/memory/ref_counted_memory.h"
-#include "components/metrics_services_manager/metrics_services_manager.h"
-#include "components/ukm/debug/ukm_debug_data_extractor.h"
-#include "components/ukm/ukm_service.h"
-#include "ios/chrome/browser/application_context.h"
-#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#include "ios/web/public/url_data_source_ios.h"
-
-namespace {
-
-class URLKeyedMetricsUIHTMLSource : public web::URLDataSourceIOS {
- public:
-  // Construct a data source for the specified |source_name|.
-  explicit URLKeyedMetricsUIHTMLSource(const std::string& source_name);
-
-  // web::URLDataSourceIOS implementation.
-  std::string GetSource() const override;
-  void StartDataRequest(
-      const std::string& path,
-      const web::URLDataSourceIOS::GotDataCallback& callback) override;
-  std::string GetMimeType(const std::string& path) const override;
-  bool ShouldDenyXFrameOptions() const override;
-
- private:
-  ~URLKeyedMetricsUIHTMLSource() override;
-
-  ukm::UkmService* GetUkmService();
-  std::string source_name_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(URLKeyedMetricsUIHTMLSource);
-};
-
-}  // namespace
-
-// URLKeyedMetricsUIHTMLSource -------------------------------------------------
-
-URLKeyedMetricsUIHTMLSource::URLKeyedMetricsUIHTMLSource(
-    const std::string& source_name)
-    : source_name_(source_name) {}
-
-URLKeyedMetricsUIHTMLSource::~URLKeyedMetricsUIHTMLSource() {}
-
-std::string URLKeyedMetricsUIHTMLSource::GetSource() const {
-  return source_name_;
-}
-
-void URLKeyedMetricsUIHTMLSource::StartDataRequest(
-    const std::string& path,
-    const web::URLDataSourceIOS::GotDataCallback& callback) {
-  // TODO(crbug.com/843181): Use GetStructuredData() instead.
-  std::string data =
-      ukm::debug::UkmDebugDataExtractor::GetHTMLData(GetUkmService());
-  callback.Run(base::RefCountedString::TakeString(&data));
-}
-
-std::string URLKeyedMetricsUIHTMLSource::GetMimeType(
-    const std::string& path) const {
-  return "text/html";
-}
-
-bool URLKeyedMetricsUIHTMLSource::ShouldDenyXFrameOptions() const {
-  return web::URLDataSourceIOS::ShouldDenyXFrameOptions();
-}
-
-ukm::UkmService* URLKeyedMetricsUIHTMLSource::GetUkmService() {
-  return GetApplicationContext()->GetMetricsServicesManager()->GetUkmService();
-}
-
-// URLKeyedMetricsUI -----------------------------------------------------------
-
-URLKeyedMetricsUI::URLKeyedMetricsUI(web::WebUIIOS* web_ui,
-                                     const std::string& name)
-    : web::WebUIIOSController(web_ui) {
-  web::URLDataSourceIOS::Add(ios::ChromeBrowserState::FromWebUIIOS(web_ui),
-                             new URLKeyedMetricsUIHTMLSource(name));
-}
-
-URLKeyedMetricsUI::~URLKeyedMetricsUI() {}
diff --git a/ios/chrome/browser/ui/webui/url_keyed_metrics_ui.h b/ios/chrome/browser/ui/webui/url_keyed_metrics_ui.h
deleted file mode 100644
index 90a65d9..0000000
--- a/ios/chrome/browser/ui/webui/url_keyed_metrics_ui.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_WEBUI_URL_KEYED_METRICS_UI_H_
-#define IOS_CHROME_BROWSER_UI_WEBUI_URL_KEYED_METRICS_UI_H_
-
-#include "base/macros.h"
-#include "ios/web/public/webui/web_ui_ios_controller.h"
-
-namespace web {
-class WebUIIOS;
-}
-
-// The WebUI controller for chrome://ukm.
-class URLKeyedMetricsUI : public web::WebUIIOSController {
- public:
-  URLKeyedMetricsUI(web::WebUIIOS* web_ui, const std::string& name);
-  ~URLKeyedMetricsUI() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(URLKeyedMetricsUI);
-};
-
-#endif  // IOS_CHROME_BROWSER_UI_WEBUI_URL_KEYED_METRICS_UI_H_
diff --git a/ios/web/public/webui/web_ui_ios.h b/ios/web/public/webui/web_ui_ios.h
index cc97807..feaf67b 100644
--- a/ios/web/public/webui/web_ui_ios.h
+++ b/ios/web/public/webui/web_ui_ios.h
@@ -81,6 +81,18 @@
   virtual void CallJavascriptFunction(
       const std::string& function_name,
       const std::vector<const base::Value*>& args) = 0;
+
+  // Helper method for responding to Javascript requests initiated with
+  // cr.sendWithPromise() (defined in cr.js) for the case where the returned
+  // promise should be resolved (request succeeded).
+  virtual void ResolveJavascriptCallback(const base::Value& callback_id,
+                                         const base::Value& response) = 0;
+
+  // Helper method for responding to Javascript requests initiated with
+  // cr.sendWithPromise() (defined in cr.js), for the case where the returned
+  // promise should be rejected (request failed).
+  virtual void RejectJavascriptCallback(const base::Value& callback_id,
+                                        const base::Value& response) = 0;
 };
 
 }  // namespace web
diff --git a/ios/web/web_state/navigation_context_impl.h b/ios/web/web_state/navigation_context_impl.h
index 0af55de..76e1034 100644
--- a/ios/web/web_state/navigation_context_impl.h
+++ b/ios/web/web_state/navigation_context_impl.h
@@ -73,6 +73,11 @@
   bool IsLoadingErrorPage() const;
   void SetLoadingErrorPage(bool is_loading_error_page);
 
+  // true if this navigation context is a placeholder navigation associated with
+  // a native view URL and the native content is already presented.
+  bool IsNativeContentPresented() const;
+  void SetIsNativeContentPresented(bool is_native_content_presented);
+
  private:
   NavigationContextImpl(WebState* web_state,
                         const GURL& url,
@@ -95,6 +100,7 @@
   int navigation_item_unique_id_ = -1;
   WKNavigationType wk_navigation_type_ = WKNavigationTypeOther;
   bool is_loading_error_page_ = false;
+  bool is_native_content_presented_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(NavigationContextImpl);
 };
diff --git a/ios/web/web_state/navigation_context_impl.mm b/ios/web/web_state/navigation_context_impl.mm
index f7c20a17..322929a 100644
--- a/ios/web/web_state/navigation_context_impl.mm
+++ b/ios/web/web_state/navigation_context_impl.mm
@@ -158,6 +158,15 @@
   is_loading_error_page_ = is_loading_error_page;
 }
 
+bool NavigationContextImpl::IsNativeContentPresented() const {
+  return is_native_content_presented_;
+}
+
+void NavigationContextImpl::SetIsNativeContentPresented(
+    bool is_native_content_presented) {
+  is_native_content_presented_ = is_native_content_presented;
+}
+
 NavigationContextImpl::NavigationContextImpl(WebState* web_state,
                                              const GURL& url,
                                              bool has_user_gesture,
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index a4c59f1..4e48ec8 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -568,14 +568,13 @@
 - (void)updateCurrentBackForwardListItemHolder;
 
 // Presents native content using the native controller for |item| without
-// notifying WebStateObservers. This is used when loading native view for a new
-// navigation to avoid the delay introduced by placeholder navigation.
+// notifying WebStateObservers. This method does not modify the underlying web
+// view. It simply covers the web view with the native content.
+// |-didLoadNativeContentForNavigationItem| must be called some time later
+// to notify WebStateObservers.
 - (void)presentNativeContentForNavigationItem:(web::NavigationItem*)item;
-// Presents native content using the native controller for |item| and notifies
-// WebStateObservers the completion of this navigation. This method does not
-// modify the underlying web view. It simply covers the web view with the native
-// content.
-- (void)loadNativeContentForNavigationItem:(web::NavigationItem*)item;
+// Notifies WebStateObservers the completion of this navigation.
+- (void)didLoadNativeContentForNavigationItem:(web::NavigationItem*)item;
 // Loads a blank page directly into WKWebView as a placeholder for a Native View
 // or WebUI URL. This page has the URL about:blank?for=<encoded original URL>.
 // The completion handler is called in the |webView:didFinishNavigation|
@@ -1799,12 +1798,15 @@
   if (!web::GetWebClient()->IsSlimNavigationManagerEnabled()) {
     // Free the web view.
     [self removeWebView];
-    [self loadNativeContentForNavigationItem:self.currentNavItem];
+    [self presentNativeContentForNavigationItem:self.currentNavItem];
+    [self didLoadNativeContentForNavigationItem:self.currentNavItem];
   } else {
     // Just present the native view now. Leave the rest of native content load
     // until the placeholder navigation finishes.
     [self presentNativeContentForNavigationItem:self.currentNavItem];
-    [self loadPlaceholderInWebViewForURL:self.currentNavItem->GetVirtualURL()];
+    web::NavigationContextImpl* context = [self
+        loadPlaceholderInWebViewForURL:self.currentNavItem->GetVirtualURL()];
+    context->SetIsNativeContentPresented(true);
   }
 }
 
@@ -1826,9 +1828,7 @@
   }
 }
 
-- (void)loadNativeContentForNavigationItem:(web::NavigationItem*)item {
-  [self presentNativeContentForNavigationItem:item];
-
+- (void)didLoadNativeContentForNavigationItem:(web::NavigationItem*)item {
   const GURL targetURL = item ? item->GetURL() : GURL::EmptyGURL();
   const web::Referrer referrer;
   std::unique_ptr<web::NavigationContextImpl> navigationContext =
@@ -1915,8 +1915,9 @@
   if (!_containerView)
     return;
 
-  // WKBasedNavigationManagerImpl requires web usage to be enabled to load any
-  // URL. So bail if web usage is disabled, and let the URL be loaded when web
+  // WKBasedNavigationManagerImpl needs WKWebView to load native views, but
+  // WKWebView cannot be created while web usage is disabled to avoid breaking
+  // clearing browser data. Bail now and let the URL be loaded when web
   // usage is enabled again. This can happen when purging web pages when an
   // interstitial is presented over a native view. See https://crbug.com/865985
   // for details.
@@ -4900,7 +4901,12 @@
       }
 
       if ([self shouldLoadURLInNativeView:item->GetURL()]) {
-        [self loadNativeContentForNavigationItem:item];
+        // Native content may have already been presented if this navigation is
+        // started in |-loadCurrentURLInNativeView|. If not, present it now.
+        if (!context || !context->IsNativeContentPresented()) {
+          [self presentNativeContentForNavigationItem:item];
+        }
+        [self didLoadNativeContentForNavigationItem:item];
       } else if (isWebUIURL) {
         DCHECK(_webUIManager);
         [_webUIManager loadWebUIForURL:item->GetURL()];
diff --git a/ios/web/webui/web_ui_ios_impl.h b/ios/web/webui/web_ui_ios_impl.h
index 5a8e27fc..a431a4f 100644
--- a/ios/web/webui/web_ui_ios_impl.h
+++ b/ios/web/webui/web_ui_ios_impl.h
@@ -56,6 +56,10 @@
   void CallJavascriptFunction(
       const std::string& function_name,
       const std::vector<const base::Value*>& args) override;
+  void ResolveJavascriptCallback(const base::Value& callback_id,
+                                 const base::Value& response) override;
+  void RejectJavascriptCallback(const base::Value& callback_id,
+                                const base::Value& response) override;
 
  private:
   // Executes JavaScript asynchronously on the page.
diff --git a/ios/web/webui/web_ui_ios_impl.mm b/ios/web/webui/web_ui_ios_impl.mm
index 3345d08..3056181 100644
--- a/ios/web/webui/web_ui_ios_impl.mm
+++ b/ios/web/webui/web_ui_ios_impl.mm
@@ -121,6 +121,20 @@
   ExecuteJavascript(GetJavascriptCall(function_name, args));
 }
 
+void WebUIIOSImpl::ResolveJavascriptCallback(const base::Value& callback_id,
+                                             const base::Value& response) {
+  // cr.webUIResponse is a global JS function exposed from cr.js.
+  CallJavascriptFunction("cr.webUIResponse", callback_id, base::Value(true),
+                         response);
+}
+
+void WebUIIOSImpl::RejectJavascriptCallback(const base::Value& callback_id,
+                                            const base::Value& response) {
+  // cr.webUIResponse is a global JS function exposed from cr.js.
+  CallJavascriptFunction("cr.webUIResponse", callback_id, base::Value(false),
+                         response);
+}
+
 void WebUIIOSImpl::RegisterMessageCallback(const std::string& message,
                                            const MessageCallback& callback) {
   message_callbacks_.insert(std::make_pair(message, callback));
diff --git a/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Connector.java b/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Connector.java
index 45f1fc7..54612093 100644
--- a/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Connector.java
+++ b/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Connector.java
@@ -158,7 +158,11 @@
     private void onError(MojoException exception) {
         close();
         if (mErrorHandler != null) {
-            mErrorHandler.onConnectionError(exception);
+            try {
+                mErrorHandler.onConnectionError(exception);
+            } catch (RuntimeException e) {
+                ExceptionHandler.DefaultExceptionHandler.getInstance().handleException(e);
+            }
         }
     }
 
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 380809e6..9c8dee6 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1351,6 +1351,24 @@
       "third_party/quic/core/frames/quic_stream_id_blocked_frame.h",
       "third_party/quic/core/frames/quic_window_update_frame.cc",
       "third_party/quic/core/frames/quic_window_update_frame.h",
+      "third_party/quic/core/http/quic_client_promised_info.cc",
+      "third_party/quic/core/http/quic_client_promised_info.h",
+      "third_party/quic/core/http/quic_client_push_promise_index.cc",
+      "third_party/quic/core/http/quic_client_push_promise_index.h",
+      "third_party/quic/core/http/quic_header_list.cc",
+      "third_party/quic/core/http/quic_header_list.h",
+      "third_party/quic/core/http/quic_headers_stream.cc",
+      "third_party/quic/core/http/quic_headers_stream.h",
+      "third_party/quic/core/http/quic_server_session_base.cc",
+      "third_party/quic/core/http/quic_server_session_base.h",
+      "third_party/quic/core/http/quic_spdy_client_session_base.cc",
+      "third_party/quic/core/http/quic_spdy_client_session_base.h",
+      "third_party/quic/core/http/quic_spdy_session.cc",
+      "third_party/quic/core/http/quic_spdy_session.h",
+      "third_party/quic/core/http/quic_spdy_stream.cc",
+      "third_party/quic/core/http/quic_spdy_stream.h",
+      "third_party/quic/core/http/spdy_utils.cc",
+      "third_party/quic/core/http/spdy_utils.h",
       "third_party/quic/core/packet_number_indexed_queue.h",
       "third_party/quic/core/quic_ack_listener_interface.cc",
       "third_party/quic/core/quic_ack_listener_interface.h",
@@ -1365,10 +1383,6 @@
       "third_party/quic/core/quic_buffer_allocator.h",
       "third_party/quic/core/quic_buffered_packet_store.cc",
       "third_party/quic/core/quic_buffered_packet_store.h",
-      "third_party/quic/core/quic_client_promised_info.cc",
-      "third_party/quic/core/quic_client_promised_info.h",
-      "third_party/quic/core/quic_client_push_promise_index.cc",
-      "third_party/quic/core/quic_client_push_promise_index.h",
       "third_party/quic/core/quic_config.cc",
       "third_party/quic/core/quic_config.h",
       "third_party/quic/core/quic_connection.cc",
@@ -1401,10 +1415,6 @@
       "third_party/quic/core/quic_flow_controller.h",
       "third_party/quic/core/quic_framer.cc",
       "third_party/quic/core/quic_framer.h",
-      "third_party/quic/core/quic_header_list.cc",
-      "third_party/quic/core/quic_header_list.h",
-      "third_party/quic/core/quic_headers_stream.cc",
-      "third_party/quic/core/quic_headers_stream.h",
       "third_party/quic/core/quic_one_block_arena.h",
       "third_party/quic/core/quic_packet_creator.cc",
       "third_party/quic/core/quic_packet_creator.h",
@@ -1420,20 +1430,12 @@
       "third_party/quic/core/quic_sent_packet_manager.h",
       "third_party/quic/core/quic_server_id.cc",
       "third_party/quic/core/quic_server_id.h",
-      "third_party/quic/core/quic_server_session_base.cc",
-      "third_party/quic/core/quic_server_session_base.h",
       "third_party/quic/core/quic_session.cc",
       "third_party/quic/core/quic_session.h",
       "third_party/quic/core/quic_simple_buffer_allocator.cc",
       "third_party/quic/core/quic_simple_buffer_allocator.h",
       "third_party/quic/core/quic_socket_address_coder.cc",
       "third_party/quic/core/quic_socket_address_coder.h",
-      "third_party/quic/core/quic_spdy_client_session_base.cc",
-      "third_party/quic/core/quic_spdy_client_session_base.h",
-      "third_party/quic/core/quic_spdy_session.cc",
-      "third_party/quic/core/quic_spdy_session.h",
-      "third_party/quic/core/quic_spdy_stream.cc",
-      "third_party/quic/core/quic_spdy_stream.h",
       "third_party/quic/core/quic_stream.cc",
       "third_party/quic/core/quic_stream.h",
       "third_party/quic/core/quic_stream_frame_data_producer.h",
@@ -1463,8 +1465,6 @@
       "third_party/quic/core/quic_versions.h",
       "third_party/quic/core/quic_write_blocked_list.cc",
       "third_party/quic/core/quic_write_blocked_list.h",
-      "third_party/quic/core/spdy_utils.cc",
-      "third_party/quic/core/spdy_utils.h",
       "third_party/quic/core/tls_client_handshaker.cc",
       "third_party/quic/core/tls_client_handshaker.h",
       "third_party/quic/core/tls_handshaker.cc",
@@ -3105,8 +3105,6 @@
     "third_party/quic/test_tools/quic_session_peer.h",
     "third_party/quic/test_tools/quic_spdy_session_peer.cc",
     "third_party/quic/test_tools/quic_spdy_session_peer.h",
-    "third_party/quic/test_tools/quic_spdy_stream_peer.cc",
-    "third_party/quic/test_tools/quic_spdy_stream_peer.h",
     "third_party/quic/test_tools/quic_stream_peer.cc",
     "third_party/quic/test_tools/quic_stream_peer.h",
     "third_party/quic/test_tools/quic_stream_send_buffer_peer.cc",
@@ -3197,17 +3195,17 @@
   sources = [
     "third_party/quic/core/chlo_extractor.cc",
     "third_party/quic/core/chlo_extractor.h",
+    "third_party/quic/core/http/quic_spdy_client_session.cc",
+    "third_party/quic/core/http/quic_spdy_client_session.h",
+    "third_party/quic/core/http/quic_spdy_client_stream.cc",
+    "third_party/quic/core/http/quic_spdy_client_stream.h",
+    "third_party/quic/core/http/quic_spdy_server_stream_base.cc",
+    "third_party/quic/core/http/quic_spdy_server_stream_base.h",
     "third_party/quic/core/quic_dispatcher.cc",
     "third_party/quic/core/quic_dispatcher.h",
     "third_party/quic/core/quic_packet_writer_wrapper.cc",
     "third_party/quic/core/quic_packet_writer_wrapper.h",
     "third_party/quic/core/quic_process_packet_interface.h",
-    "third_party/quic/core/quic_spdy_client_session.cc",
-    "third_party/quic/core/quic_spdy_client_session.h",
-    "third_party/quic/core/quic_spdy_client_stream.cc",
-    "third_party/quic/core/quic_spdy_client_stream.h",
-    "third_party/quic/core/quic_spdy_server_stream_base.cc",
-    "third_party/quic/core/quic_spdy_server_stream_base.h",
     "third_party/quic/core/quic_time_wait_list_manager.cc",
     "third_party/quic/core/quic_time_wait_list_manager.h",
     "third_party/quic/core/stateless_rejector.cc",
@@ -4975,13 +4973,15 @@
     "third_party/quic/core/crypto/quic_tls_adapter_test.cc",
     "third_party/quic/core/crypto/transport_parameters_test.cc",
     "third_party/quic/core/frames/quic_frames_test.cc",
+    "third_party/quic/core/http/quic_client_promised_info_test.cc",
+    "third_party/quic/core/http/quic_client_push_promise_index_test.cc",
+    "third_party/quic/core/http/quic_header_list_test.cc",
+    "third_party/quic/core/http/quic_headers_stream_test.cc",
     "third_party/quic/core/packet_number_indexed_queue_test.cc",
     "third_party/quic/core/quic_alarm_test.cc",
     "third_party/quic/core/quic_arena_scoped_ptr_test.cc",
     "third_party/quic/core/quic_bandwidth_test.cc",
     "third_party/quic/core/quic_buffered_packet_store_test.cc",
-    "third_party/quic/core/quic_client_promised_info_test.cc",
-    "third_party/quic/core/quic_client_push_promise_index_test.cc",
     "third_party/quic/core/quic_config_test.cc",
     "third_party/quic/core/quic_connection_test.cc",
     "third_party/quic/core/quic_control_frame_manager_test.cc",
@@ -4992,8 +4992,6 @@
     "third_party/quic/core/quic_error_codes_test.cc",
     "third_party/quic/core/quic_flow_controller_test.cc",
     "third_party/quic/core/quic_framer_test.cc",
-    "third_party/quic/core/quic_header_list_test.cc",
-    "third_party/quic/core/quic_headers_stream_test.cc",
     "third_party/quic/core/quic_ietf_framer_test.cc",
     "third_party/quic/core/tls_handshaker_test.cc",
 
@@ -5065,6 +5063,10 @@
     "test/run_all_unittests.cc",
     "test/tcp_socket_proxy_unittest.cc",
     "third_party/nist-pkits/pkits_testcases-inl.h",
+    "third_party/quic/core/http/quic_server_session_base_test.cc",
+    "third_party/quic/core/http/quic_spdy_session_test.cc",
+    "third_party/quic/core/http/quic_spdy_stream_test.cc",
+    "third_party/quic/core/http/spdy_utils_test.cc",
     "third_party/quic/core/quic_dispatcher_test.cc",
     "third_party/quic/core/quic_one_block_arena_test.cc",
     "third_party/quic/core/quic_packet_creator_test.cc",
@@ -5072,12 +5074,9 @@
     "third_party/quic/core/quic_received_packet_manager_test.cc",
     "third_party/quic/core/quic_sent_packet_manager_test.cc",
     "third_party/quic/core/quic_server_id_test.cc",
-    "third_party/quic/core/quic_server_session_base_test.cc",
     "third_party/quic/core/quic_session_test.cc",
     "third_party/quic/core/quic_simple_buffer_allocator_test.cc",
     "third_party/quic/core/quic_socket_address_coder_test.cc",
-    "third_party/quic/core/quic_spdy_session_test.cc",
-    "third_party/quic/core/quic_spdy_stream_test.cc",
     "third_party/quic/core/quic_stream_send_buffer_test.cc",
     "third_party/quic/core/quic_stream_sequencer_buffer_test.cc",
     "third_party/quic/core/quic_stream_sequencer_test.cc",
@@ -5092,7 +5091,6 @@
     "third_party/quic/core/quic_version_manager_test.cc",
     "third_party/quic/core/quic_versions_test.cc",
     "third_party/quic/core/quic_write_blocked_list_test.cc",
-    "third_party/quic/core/spdy_utils_test.cc",
     "third_party/quic/platform/api/quic_endian_test.cc",
     "third_party/quic/platform/api/quic_hostname_utils_test.cc",
     "third_party/quic/platform/api/quic_lru_cache_test.cc",
@@ -5271,12 +5269,12 @@
   if (is_linux) {
     sources += [
       "third_party/quic/core/chlo_extractor_test.cc",
-      "third_party/quic/core/end_to_end_test.cc",
+      "third_party/quic/core/http/end_to_end_test.cc",
+      "third_party/quic/core/http/quic_spdy_client_session_test.cc",
+      "third_party/quic/core/http/quic_spdy_client_stream_test.cc",
+      "third_party/quic/core/http/quic_spdy_server_stream_base_test.cc",
       "third_party/quic/core/quic_epoll_alarm_factory_test.cc",
       "third_party/quic/core/quic_epoll_connection_helper_test.cc",
-      "third_party/quic/core/quic_spdy_client_session_test.cc",
-      "third_party/quic/core/quic_spdy_client_stream_test.cc",
-      "third_party/quic/core/quic_spdy_server_stream_base_test.cc",
       "third_party/quic/core/stateless_rejector_test.cc",
       "third_party/quic/platform/impl/quic_epoll_clock_test.cc",
       "third_party/quic/platform/impl/quic_socket_utils_test.cc",
diff --git a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
index d943b472..4a3475a 100644
--- a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
@@ -38,8 +38,8 @@
 #include "net/third_party/quic/core/crypto/crypto_protocol.h"
 #include "net/third_party/quic/core/crypto/quic_decrypter.h"
 #include "net/third_party/quic/core/crypto/quic_encrypter.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_connection.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 #include "net/third_party/quic/platform/api/quic_text_utils.h"
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc
index 1cc80d6..7de78f8 100644
--- a/net/quic/chromium/quic_chromium_client_session.cc
+++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -39,8 +39,8 @@
 #include "net/ssl/ssl_connection_status_flags.h"
 #include "net/ssl/ssl_info.h"
 #include "net/ssl/token_binding.h"
-#include "net/third_party/quic/core/quic_client_promised_info.h"
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "third_party/boringssl/src/include/openssl/ssl.h"
diff --git a/net/quic/chromium/quic_chromium_client_session.h b/net/quic/chromium/quic_chromium_client_session.h
index ecae249..43af292 100644
--- a/net/quic/chromium/quic_chromium_client_session.h
+++ b/net/quic/chromium/quic_chromium_client_session.h
@@ -38,11 +38,11 @@
 #include "net/spdy/http2_priority_dependencies.h"
 #include "net/spdy/multiplexed_session.h"
 #include "net/spdy/server_push_delegate.h"
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session_base.h"
 #include "net/third_party/quic/core/quic_crypto_client_stream.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_server_id.h"
-#include "net/third_party/quic/core/quic_spdy_client_session_base.h"
 #include "net/third_party/quic/core/quic_time.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
diff --git a/net/quic/chromium/quic_chromium_client_session_test.cc b/net/quic/chromium/quic_chromium_client_session_test.cc
index f6d2b78..68d0b3c 100644
--- a/net/quic/chromium/quic_chromium_client_session_test.cc
+++ b/net/quic/chromium/quic_chromium_client_session_test.cc
@@ -39,7 +39,7 @@
 #include "net/third_party/quic/core/crypto/crypto_protocol.h"
 #include "net/third_party/quic/core/crypto/quic_decrypter.h"
 #include "net/third_party/quic/core/crypto/quic_encrypter.h"
-#include "net/third_party/quic/core/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
 #include "net/third_party/quic/core/quic_packet_writer.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
diff --git a/net/quic/chromium/quic_chromium_client_stream.cc b/net/quic/chromium/quic_chromium_client_stream.cc
index 8a7e629..fae140f 100644
--- a/net/quic/chromium/quic_chromium_client_stream.cc
+++ b/net/quic/chromium/quic_chromium_client_stream.cc
@@ -16,9 +16,9 @@
 #include "net/quic/chromium/quic_chromium_client_session.h"
 #include "net/quic/chromium/quic_http_utils.h"
 #include "net/spdy/spdy_log_util.h"
-#include "net/third_party/quic/core/quic_spdy_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_session.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_write_blocked_list.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 
 namespace net {
 namespace {
diff --git a/net/quic/chromium/quic_chromium_client_stream.h b/net/quic/chromium/quic_chromium_client_stream.h
index 75ce4f9..dea459f1 100644
--- a/net/quic/chromium/quic_chromium_client_stream.h
+++ b/net/quic/chromium/quic_chromium_client_stream.h
@@ -22,7 +22,7 @@
 #include "net/http/http_response_info.h"
 #include "net/http/http_stream.h"
 #include "net/log/net_log_with_source.h"
-#include "net/third_party/quic/core/quic_spdy_stream.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
diff --git a/net/quic/chromium/quic_chromium_client_stream_test.cc b/net/quic/chromium/quic_chromium_client_stream_test.cc
index 39a97df..39de871 100644
--- a/net/quic/chromium/quic_chromium_client_stream_test.cc
+++ b/net/quic/chromium/quic_chromium_client_stream_test.cc
@@ -15,10 +15,10 @@
 #include "net/quic/chromium/quic_chromium_client_session.h"
 #include "net/test/gtest_util.h"
 #include "net/test/test_with_scoped_task_environment.h"
-#include "net/third_party/quic/core/quic_spdy_client_session_base.h"
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_utils.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quic/test_tools/crypto_test_utils.h"
diff --git a/net/quic/chromium/quic_connection_logger.h b/net/quic/chromium/quic_connection_logger.h
index 9716677..2763935 100644
--- a/net/quic/chromium/quic_connection_logger.h
+++ b/net/quic/chromium/quic_connection_logger.h
@@ -18,9 +18,9 @@
 #include "net/log/net_log_with_source.h"
 #include "net/socket/socket_performance_watcher.h"
 #include "net/third_party/quic/core/crypto/crypto_handshake_message.h"
+#include "net/third_party/quic/core/http/quic_spdy_session.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_packets.h"
-#include "net/third_party/quic/core/quic_spdy_session.h"
 
 namespace base {
 class HistogramBase;
diff --git a/net/quic/chromium/quic_http_stream.cc b/net/quic/chromium/quic_http_stream.cc
index d097326..69aef5b 100644
--- a/net/quic/chromium/quic_http_stream.cc
+++ b/net/quic/chromium/quic_http_stream.cc
@@ -21,10 +21,10 @@
 #include "net/quic/chromium/quic_http_utils.h"
 #include "net/spdy/spdy_http_utils.h"
 #include "net/ssl/ssl_info.h"
-#include "net/third_party/quic/core/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_stream_sequencer.h"
 #include "net/third_party/quic/core/quic_utils.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 #include "net/third_party/spdy/core/spdy_frame_builder.h"
 #include "net/third_party/spdy/core/spdy_framer.h"
diff --git a/net/quic/chromium/quic_http_stream.h b/net/quic/chromium/quic_http_stream.h
index 38c805c6..44be6562 100644
--- a/net/quic/chromium/quic_http_stream.h
+++ b/net/quic/chromium/quic_http_stream.h
@@ -24,7 +24,7 @@
 #include "net/quic/chromium/quic_chromium_client_session.h"
 #include "net/quic/chromium/quic_chromium_client_stream.h"
 #include "net/spdy/multiplexed_http_stream.h"
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
 #include "net/third_party/quic/core/quic_packets.h"
 
 namespace net {
diff --git a/net/quic/chromium/quic_http_stream_test.cc b/net/quic/chromium/quic_http_stream_test.cc
index 2eea213..94686e0 100644
--- a/net/quic/chromium/quic_http_stream_test.cc
+++ b/net/quic/chromium/quic_http_stream_test.cc
@@ -48,9 +48,9 @@
 #include "net/third_party/quic/core/crypto/crypto_protocol.h"
 #include "net/third_party/quic/core/crypto/quic_decrypter.h"
 #include "net/third_party/quic/core/crypto/quic_encrypter.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_write_blocked_list.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 #include "net/third_party/quic/test_tools/crypto_test_utils.h"
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index 74af500..56929b42 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -53,7 +53,7 @@
 #include "net/ssl/token_binding.h"
 #include "net/third_party/quic/core/crypto/proof_verifier.h"
 #include "net/third_party/quic/core/crypto/quic_random.h"
-#include "net/third_party/quic/core/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_clock.h"
diff --git a/net/quic/chromium/quic_stream_factory.h b/net/quic/chromium/quic_stream_factory.h
index 7fe42c6..29db22a 100644
--- a/net/quic/chromium/quic_stream_factory.h
+++ b/net/quic/chromium/quic_stream_factory.h
@@ -35,7 +35,7 @@
 #include "net/quic/chromium/quic_session_key.h"
 #include "net/socket/client_socket_pool.h"
 #include "net/ssl/ssl_config_service.h"
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
 #include "net/third_party/quic/core/quic_config.h"
 #include "net/third_party/quic/core/quic_crypto_stream.h"
 #include "net/third_party/quic/core/quic_packets.h"
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index f550b40b..65eab8e 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -49,7 +49,7 @@
 #include "net/third_party/quic/core/crypto/quic_crypto_client_config.h"
 #include "net/third_party/quic/core/crypto/quic_decrypter.h"
 #include "net/third_party/quic/core/crypto/quic_encrypter.h"
-#include "net/third_party/quic/core/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
 #include "net/third_party/quic/platform/api/quic_test.h"
 #include "net/third_party/quic/test_tools/mock_clock.h"
 #include "net/third_party/quic/test_tools/mock_random.h"
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index c48e02f..2049ec2 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -54,7 +54,7 @@
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/ssl_cipher_suite_names.h"
 #include "net/ssl/ssl_connection_status_flags.h"
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/spdy/core/spdy_frame_builder.h"
 #include "net/third_party/spdy/core/spdy_protocol.h"
 #include "url/url_constants.h"
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender.h b/net/third_party/quic/core/congestion_control/bbr_sender.h
index ba1595aa..6e1f275 100644
--- a/net/third_party/quic/core/congestion_control/bbr_sender.h
+++ b/net/third_party/quic/core/congestion_control/bbr_sender.h
@@ -96,6 +96,8 @@
             QuicPacketCount initial_tcp_congestion_window,
             QuicPacketCount max_tcp_congestion_window,
             QuicRandom* random);
+  BbrSender(const BbrSender&) = delete;
+  BbrSender& operator=(const BbrSender&) = delete;
   ~BbrSender() override;
 
   // Start implementation of SendAlgorithmInterface.
@@ -384,8 +386,6 @@
   bool probe_rtt_disabled_if_app_limited_;
   bool app_limited_since_last_probe_rtt_;
   QuicTime::Delta min_rtt_since_last_probe_rtt_;
-
-  DISALLOW_COPY_AND_ASSIGN(BbrSender);
 };
 
 QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
diff --git a/net/third_party/quic/core/congestion_control/cubic_bytes.h b/net/third_party/quic/core/congestion_control/cubic_bytes.h
index ef1e382..990dae8f 100644
--- a/net/third_party/quic/core/congestion_control/cubic_bytes.h
+++ b/net/third_party/quic/core/congestion_control/cubic_bytes.h
@@ -26,6 +26,8 @@
 class QUIC_EXPORT_PRIVATE CubicBytes {
  public:
   explicit CubicBytes(const QuicClock* clock);
+  CubicBytes(const CubicBytes&) = delete;
+  CubicBytes& operator=(const CubicBytes&) = delete;
 
   void SetNumConnections(int num_connections);
 
@@ -94,8 +96,6 @@
 
   // Last congestion window in packets computed by cubic function.
   QuicByteCount last_target_congestion_window_;
-
-  DISALLOW_COPY_AND_ASSIGN(CubicBytes);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/congestion_control/general_loss_algorithm.h b/net/third_party/quic/core/congestion_control/general_loss_algorithm.h
index 3409279f..e69e0c7 100644
--- a/net/third_party/quic/core/congestion_control/general_loss_algorithm.h
+++ b/net/third_party/quic/core/congestion_control/general_loss_algorithm.h
@@ -27,6 +27,8 @@
 
   GeneralLossAlgorithm();
   explicit GeneralLossAlgorithm(LossDetectionType loss_type);
+  GeneralLossAlgorithm(const GeneralLossAlgorithm&) = delete;
+  GeneralLossAlgorithm& operator=(const GeneralLossAlgorithm&) = delete;
   ~GeneralLossAlgorithm() override {}
 
   LossDetectionType GetLossDetectionType() const override;
@@ -70,8 +72,6 @@
   QuicPacketNumber largest_previously_acked_;
   // The largest lost packet.
   QuicPacketNumber largest_lost_;
-
-  DISALLOW_COPY_AND_ASSIGN(GeneralLossAlgorithm);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/congestion_control/hybrid_slow_start.h b/net/third_party/quic/core/congestion_control/hybrid_slow_start.h
index cbc2b890..a171bcc 100644
--- a/net/third_party/quic/core/congestion_control/hybrid_slow_start.h
+++ b/net/third_party/quic/core/congestion_control/hybrid_slow_start.h
@@ -28,6 +28,8 @@
 class QUIC_EXPORT_PRIVATE HybridSlowStart {
  public:
   HybridSlowStart();
+  HybridSlowStart(const HybridSlowStart&) = delete;
+  HybridSlowStart& operator=(const HybridSlowStart&) = delete;
 
   void OnPacketAcked(QuicPacketNumber acked_packet_number);
 
@@ -75,8 +77,6 @@
   QuicPacketNumber end_packet_number_;  // End of the receive round.
   uint32_t rtt_sample_count_;  // Number of rtt samples in the current round.
   QuicTime::Delta current_min_rtt_;  // The minimum rtt of current round.
-
-  DISALLOW_COPY_AND_ASSIGN(HybridSlowStart);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/congestion_control/pacing_sender.h b/net/third_party/quic/core/congestion_control/pacing_sender.h
index f8eddcd..bb018b5 100644
--- a/net/third_party/quic/core/congestion_control/pacing_sender.h
+++ b/net/third_party/quic/core/congestion_control/pacing_sender.h
@@ -32,6 +32,8 @@
 class QUIC_EXPORT_PRIVATE PacingSender {
  public:
   PacingSender();
+  PacingSender(const PacingSender&) = delete;
+  PacingSender& operator=(const PacingSender&) = delete;
   ~PacingSender();
 
   // Sets the underlying sender. Does not take ownership of |sender|. |sender|
@@ -99,8 +101,6 @@
   // Indicates whether pacing throttles the sending. If true, make up for lost
   // time.
   bool pacing_limited_;
-
-  DISALLOW_COPY_AND_ASSIGN(PacingSender);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/congestion_control/rtt_stats.h b/net/third_party/quic/core/congestion_control/rtt_stats.h
index 168de9d..93d10166 100644
--- a/net/third_party/quic/core/congestion_control/rtt_stats.h
+++ b/net/third_party/quic/core/congestion_control/rtt_stats.h
@@ -25,6 +25,8 @@
 class QUIC_EXPORT_PRIVATE RttStats {
  public:
   RttStats();
+  RttStats(const RttStats&) = delete;
+  RttStats& operator=(const RttStats&) = delete;
 
   // Updates the RTT from an incoming ack which is received |send_delta| after
   // the packet is sent and the peer reports the ack being delayed |ack_delay|.
@@ -101,8 +103,6 @@
   QuicTime::Delta max_ack_delay_;
   // Whether to ignore the peer's max ack delay.
   bool ignore_max_ack_delay_;
-
-  DISALLOW_COPY_AND_ASSIGN(RttStats);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/net/third_party/quic/core/congestion_control/tcp_cubic_sender_bytes.h
index 9651db5..4d550ec 100644
--- a/net/third_party/quic/core/congestion_control/tcp_cubic_sender_bytes.h
+++ b/net/third_party/quic/core/congestion_control/tcp_cubic_sender_bytes.h
@@ -40,6 +40,8 @@
                       QuicPacketCount initial_tcp_congestion_window,
                       QuicPacketCount max_congestion_window,
                       QuicConnectionStats* stats);
+  TcpCubicSenderBytes(const TcpCubicSenderBytes&) = delete;
+  TcpCubicSenderBytes& operator=(const TcpCubicSenderBytes&) = delete;
   ~TcpCubicSenderBytes() override;
 
   // Start implementation of SendAlgorithmInterface.
@@ -164,8 +166,6 @@
 
   // The minimum window when exiting slow start with large reduction.
   QuicByteCount min_slow_start_exit_window_;
-
-  DISALLOW_COPY_AND_ASSIGN(TcpCubicSenderBytes);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/aead_base_decrypter.h b/net/third_party/quic/core/crypto/aead_base_decrypter.h
index e8467e1..5650cf3 100644
--- a/net/third_party/quic/core/crypto/aead_base_decrypter.h
+++ b/net/third_party/quic/core/crypto/aead_base_decrypter.h
@@ -26,6 +26,8 @@
                     size_t auth_tag_size,
                     size_t nonce_size,
                     bool use_ietf_nonce_construction);
+  AeadBaseDecrypter(const AeadBaseDecrypter&) = delete;
+  AeadBaseDecrypter& operator=(const AeadBaseDecrypter&) = delete;
   ~AeadBaseDecrypter() override;
 
   // QuicDecrypter implementation
@@ -67,8 +69,6 @@
   unsigned char iv_[kMaxNonceSize];
 
   ScopedEVPAEADCtx ctx_;
-
-  DISALLOW_COPY_AND_ASSIGN(AeadBaseDecrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/aead_base_encrypter.h b/net/third_party/quic/core/crypto/aead_base_encrypter.h
index 3bf975e..41ea7f4c 100644
--- a/net/third_party/quic/core/crypto/aead_base_encrypter.h
+++ b/net/third_party/quic/core/crypto/aead_base_encrypter.h
@@ -26,6 +26,8 @@
                     size_t auth_tag_size,
                     size_t nonce_size,
                     bool use_ietf_nonce_construction);
+  AeadBaseEncrypter(const AeadBaseEncrypter&) = delete;
+  AeadBaseEncrypter& operator=(const AeadBaseEncrypter&) = delete;
   ~AeadBaseEncrypter() override;
 
   // QuicEncrypter implementation
@@ -74,8 +76,6 @@
   unsigned char iv_[kMaxNonceSize];
 
   ScopedEVPAEADCtx ctx_;
-
-  DISALLOW_COPY_AND_ASSIGN(AeadBaseEncrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/aes_128_gcm_12_decrypter.h b/net/third_party/quic/core/crypto/aes_128_gcm_12_decrypter.h
index 78f3b22..a9027695 100644
--- a/net/third_party/quic/core/crypto/aes_128_gcm_12_decrypter.h
+++ b/net/third_party/quic/core/crypto/aes_128_gcm_12_decrypter.h
@@ -27,12 +27,11 @@
   };
 
   Aes128Gcm12Decrypter();
+  Aes128Gcm12Decrypter(const Aes128Gcm12Decrypter&) = delete;
+  Aes128Gcm12Decrypter& operator=(const Aes128Gcm12Decrypter&) = delete;
   ~Aes128Gcm12Decrypter() override;
 
   uint32_t cipher_id() const override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Aes128Gcm12Decrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/aes_128_gcm_12_encrypter.h b/net/third_party/quic/core/crypto/aes_128_gcm_12_encrypter.h
index d24c21e..06939bb 100644
--- a/net/third_party/quic/core/crypto/aes_128_gcm_12_encrypter.h
+++ b/net/third_party/quic/core/crypto/aes_128_gcm_12_encrypter.h
@@ -25,10 +25,9 @@
   };
 
   Aes128Gcm12Encrypter();
+  Aes128Gcm12Encrypter(const Aes128Gcm12Encrypter&) = delete;
+  Aes128Gcm12Encrypter& operator=(const Aes128Gcm12Encrypter&) = delete;
   ~Aes128Gcm12Encrypter() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Aes128Gcm12Encrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/aes_128_gcm_decrypter.h b/net/third_party/quic/core/crypto/aes_128_gcm_decrypter.h
index bca4fad..347af07 100644
--- a/net/third_party/quic/core/crypto/aes_128_gcm_decrypter.h
+++ b/net/third_party/quic/core/crypto/aes_128_gcm_decrypter.h
@@ -25,12 +25,11 @@
   };
 
   Aes128GcmDecrypter();
+  Aes128GcmDecrypter(const Aes128GcmDecrypter&) = delete;
+  Aes128GcmDecrypter& operator=(const Aes128GcmDecrypter&) = delete;
   ~Aes128GcmDecrypter() override;
 
   uint32_t cipher_id() const override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Aes128GcmDecrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/aes_128_gcm_encrypter.h b/net/third_party/quic/core/crypto/aes_128_gcm_encrypter.h
index e78d6fd..8682db5 100644
--- a/net/third_party/quic/core/crypto/aes_128_gcm_encrypter.h
+++ b/net/third_party/quic/core/crypto/aes_128_gcm_encrypter.h
@@ -23,10 +23,9 @@
   };
 
   Aes128GcmEncrypter();
+  Aes128GcmEncrypter(const Aes128GcmEncrypter&) = delete;
+  Aes128GcmEncrypter& operator=(const Aes128GcmEncrypter&) = delete;
   ~Aes128GcmEncrypter() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Aes128GcmEncrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/aes_256_gcm_decrypter.h b/net/third_party/quic/core/crypto/aes_256_gcm_decrypter.h
index 16618eb..1e5d094 100644
--- a/net/third_party/quic/core/crypto/aes_256_gcm_decrypter.h
+++ b/net/third_party/quic/core/crypto/aes_256_gcm_decrypter.h
@@ -25,12 +25,11 @@
   };
 
   Aes256GcmDecrypter();
+  Aes256GcmDecrypter(const Aes256GcmDecrypter&) = delete;
+  Aes256GcmDecrypter& operator=(const Aes256GcmDecrypter&) = delete;
   ~Aes256GcmDecrypter() override;
 
   uint32_t cipher_id() const override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Aes256GcmDecrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/aes_256_gcm_encrypter.h b/net/third_party/quic/core/crypto/aes_256_gcm_encrypter.h
index 5169b7b..6feb94d7 100644
--- a/net/third_party/quic/core/crypto/aes_256_gcm_encrypter.h
+++ b/net/third_party/quic/core/crypto/aes_256_gcm_encrypter.h
@@ -23,10 +23,9 @@
   };
 
   Aes256GcmEncrypter();
+  Aes256GcmEncrypter(const Aes256GcmEncrypter&) = delete;
+  Aes256GcmEncrypter& operator=(const Aes256GcmEncrypter&) = delete;
   ~Aes256GcmEncrypter() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Aes256GcmEncrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/cert_compressor.h b/net/third_party/quic/core/crypto/cert_compressor.h
index daa6cc9..0669519 100644
--- a/net/third_party/quic/core/crypto/cert_compressor.h
+++ b/net/third_party/quic/core/crypto/cert_compressor.h
@@ -30,6 +30,8 @@
 //      methods and a small chunk of common substrings.
 class QUIC_EXPORT_PRIVATE CertCompressor {
  public:
+  CertCompressor() = delete;
+
   // CompressChain compresses the certificates in |certs| and returns a
   // compressed representation. |common_sets| contains the common certificate
   // sets known locally and |client_common_set_hashes| contains the hashes of
@@ -48,9 +50,6 @@
                               const std::vector<QuicString>& cached_certs,
                               const CommonCertSets* common_sets,
                               std::vector<QuicString>* out_certs);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CertCompressor);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/chacha20_poly1305_decrypter.h b/net/third_party/quic/core/crypto/chacha20_poly1305_decrypter.h
index 9707b3ad..fc9b36a 100644
--- a/net/third_party/quic/core/crypto/chacha20_poly1305_decrypter.h
+++ b/net/third_party/quic/core/crypto/chacha20_poly1305_decrypter.h
@@ -27,12 +27,12 @@
   };
 
   ChaCha20Poly1305Decrypter();
+  ChaCha20Poly1305Decrypter(const ChaCha20Poly1305Decrypter&) = delete;
+  ChaCha20Poly1305Decrypter& operator=(const ChaCha20Poly1305Decrypter&) =
+      delete;
   ~ChaCha20Poly1305Decrypter() override;
 
   uint32_t cipher_id() const override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChaCha20Poly1305Decrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/chacha20_poly1305_encrypter.h b/net/third_party/quic/core/crypto/chacha20_poly1305_encrypter.h
index a995631..d5d762ec 100644
--- a/net/third_party/quic/core/crypto/chacha20_poly1305_encrypter.h
+++ b/net/third_party/quic/core/crypto/chacha20_poly1305_encrypter.h
@@ -25,10 +25,10 @@
   };
 
   ChaCha20Poly1305Encrypter();
+  ChaCha20Poly1305Encrypter(const ChaCha20Poly1305Encrypter&) = delete;
+  ChaCha20Poly1305Encrypter& operator=(const ChaCha20Poly1305Encrypter&) =
+      delete;
   ~ChaCha20Poly1305Encrypter() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChaCha20Poly1305Encrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/chacha20_poly1305_tls_decrypter.h b/net/third_party/quic/core/crypto/chacha20_poly1305_tls_decrypter.h
index b6b477d8..07feb50 100644
--- a/net/third_party/quic/core/crypto/chacha20_poly1305_tls_decrypter.h
+++ b/net/third_party/quic/core/crypto/chacha20_poly1305_tls_decrypter.h
@@ -26,12 +26,12 @@
   };
 
   ChaCha20Poly1305TlsDecrypter();
+  ChaCha20Poly1305TlsDecrypter(const ChaCha20Poly1305TlsDecrypter&) = delete;
+  ChaCha20Poly1305TlsDecrypter& operator=(const ChaCha20Poly1305TlsDecrypter&) =
+      delete;
   ~ChaCha20Poly1305TlsDecrypter() override;
 
   uint32_t cipher_id() const override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChaCha20Poly1305TlsDecrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/chacha20_poly1305_tls_encrypter.h b/net/third_party/quic/core/crypto/chacha20_poly1305_tls_encrypter.h
index 930956c..2db7c9b 100644
--- a/net/third_party/quic/core/crypto/chacha20_poly1305_tls_encrypter.h
+++ b/net/third_party/quic/core/crypto/chacha20_poly1305_tls_encrypter.h
@@ -24,10 +24,10 @@
   };
 
   ChaCha20Poly1305TlsEncrypter();
+  ChaCha20Poly1305TlsEncrypter(const ChaCha20Poly1305TlsEncrypter&) = delete;
+  ChaCha20Poly1305TlsEncrypter& operator=(const ChaCha20Poly1305TlsEncrypter&) =
+      delete;
   ~ChaCha20Poly1305TlsEncrypter() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChaCha20Poly1305TlsEncrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/channel_id.h b/net/third_party/quic/core/crypto/channel_id.h
index 99a5ee3..2a91474 100644
--- a/net/third_party/quic/core/crypto/channel_id.h
+++ b/net/third_party/quic/core/crypto/channel_id.h
@@ -66,6 +66,8 @@
 // ChannelIDVerifier verifies ChannelID signatures.
 class QUIC_EXPORT_PRIVATE ChannelIDVerifier {
  public:
+  ChannelIDVerifier() = delete;
+
   // kContextStr is prepended to the data to be signed in order to ensure that
   // a ChannelID signature cannot be used in a different context. (The
   // terminating NUL byte is inclued.)
@@ -89,9 +91,6 @@
                         QuicStringPiece signed_data,
                         QuicStringPiece signature,
                         bool is_channel_id_signature);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChannelIDVerifier);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/common_cert_set.cc b/net/third_party/quic/core/crypto/common_cert_set.cc
index 4151d39..e81d111b 100644
--- a/net/third_party/quic/core/crypto/common_cert_set.cc
+++ b/net/third_party/quic/core/crypto/common_cert_set.cc
@@ -148,10 +148,11 @@
 
  private:
   CommonCertSetsQUIC() {}
+  CommonCertSetsQUIC(const CommonCertSetsQUIC&) = delete;
+  CommonCertSetsQUIC& operator=(const CommonCertSetsQUIC&) = delete;
   ~CommonCertSetsQUIC() override {}
 
   friend QuicSingletonFriend<CommonCertSetsQUIC>;
-  DISALLOW_COPY_AND_ASSIGN(CommonCertSetsQUIC);
 };
 
 }  // anonymous namespace
diff --git a/net/third_party/quic/core/crypto/crypto_handshake.h b/net/third_party/quic/core/crypto/crypto_handshake.h
index 129b733..77d8599 100644
--- a/net/third_party/quic/core/crypto/crypto_handshake.h
+++ b/net/third_party/quic/core/crypto/crypto_handshake.h
@@ -168,6 +168,8 @@
   static const char kForwardSecureLabel[];
 
   QuicCryptoConfig();
+  QuicCryptoConfig(const QuicCryptoConfig&) = delete;
+  QuicCryptoConfig& operator=(const QuicCryptoConfig&) = delete;
   ~QuicCryptoConfig();
 
   // Key exchange methods. The following two members' values correspond by
@@ -181,9 +183,6 @@
   QuicTagVector tb_key_params;
 
   const CommonCertSets* common_cert_sets;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoConfig);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/crypto_secret_boxer.h b/net/third_party/quic/core/crypto/crypto_secret_boxer.h
index 33beb208c..8723045f 100644
--- a/net/third_party/quic/core/crypto/crypto_secret_boxer.h
+++ b/net/third_party/quic/core/crypto/crypto_secret_boxer.h
@@ -25,6 +25,8 @@
 class QUIC_EXPORT_PRIVATE CryptoSecretBoxer {
  public:
   CryptoSecretBoxer();
+  CryptoSecretBoxer(const CryptoSecretBoxer&) = delete;
+  CryptoSecretBoxer& operator=(const CryptoSecretBoxer&) = delete;
   ~CryptoSecretBoxer();
 
   // GetKeySize returns the number of bytes in a key.
@@ -59,8 +61,6 @@
   // state_ is an opaque pointer to whatever additional state the concrete
   // implementation of CryptoSecretBoxer requires.
   std::unique_ptr<State> state_ GUARDED_BY(lock_);
-
-  DISALLOW_COPY_AND_ASSIGN(CryptoSecretBoxer);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/crypto_utils.h b/net/third_party/quic/core/crypto/crypto_utils.h
index f4930ec7..59294fd 100644
--- a/net/third_party/quic/core/crypto/crypto_utils.h
+++ b/net/third_party/quic/core/crypto/crypto_utils.h
@@ -27,6 +27,8 @@
 
 class QUIC_EXPORT_PRIVATE CryptoUtils {
  public:
+  CryptoUtils() = delete;
+
   // Diversification is a utility class that's used to act like a union type.
   // Values can be created by calling the functions like |NoDiversification|,
   // below.
@@ -218,9 +220,6 @@
   static void HashHandshakeMessage(const CryptoHandshakeMessage& message,
                                    QuicString* output,
                                    Perspective perspective);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CryptoUtils);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/null_decrypter.h b/net/third_party/quic/core/crypto/null_decrypter.h
index 97bc337e..49d22fe 100644
--- a/net/third_party/quic/core/crypto/null_decrypter.h
+++ b/net/third_party/quic/core/crypto/null_decrypter.h
@@ -25,6 +25,8 @@
 class QUIC_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
  public:
   explicit NullDecrypter(Perspective perspective);
+  NullDecrypter(const NullDecrypter&) = delete;
+  NullDecrypter& operator=(const NullDecrypter&) = delete;
   ~NullDecrypter() override {}
 
   // QuicDecrypter implementation
@@ -54,8 +56,6 @@
                           QuicStringPiece data2) const;
 
   Perspective perspective_;
-
-  DISALLOW_COPY_AND_ASSIGN(NullDecrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/null_encrypter.h b/net/third_party/quic/core/crypto/null_encrypter.h
index 1ad9e25..a549d466 100644
--- a/net/third_party/quic/core/crypto/null_encrypter.h
+++ b/net/third_party/quic/core/crypto/null_encrypter.h
@@ -22,6 +22,8 @@
 class QUIC_EXPORT_PRIVATE NullEncrypter : public QuicEncrypter {
  public:
   explicit NullEncrypter(Perspective perspective);
+  NullEncrypter(const NullEncrypter&) = delete;
+  NullEncrypter& operator=(const NullEncrypter&) = delete;
   ~NullEncrypter() override {}
 
   // QuicEncrypter implementation
@@ -47,8 +49,6 @@
   size_t GetHashLength() const;
 
   Perspective perspective_;
-
-  DISALLOW_COPY_AND_ASSIGN(NullEncrypter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/p256_key_exchange.h b/net/third_party/quic/core/crypto/p256_key_exchange.h
index ae01620..c7496829 100644
--- a/net/third_party/quic/core/crypto/p256_key_exchange.h
+++ b/net/third_party/quic/core/crypto/p256_key_exchange.h
@@ -54,12 +54,12 @@
   // |kUncompressedP256PointBytes| bytes.
   P256KeyExchange(bssl::UniquePtr<EC_KEY> private_key,
                   const uint8_t* public_key);
+  P256KeyExchange(const P256KeyExchange&) = delete;
+  P256KeyExchange& operator=(const P256KeyExchange&) = delete;
 
   bssl::UniquePtr<EC_KEY> private_key_;
   // The public key stored as an uncompressed P-256 point.
   uint8_t public_key_[kUncompressedP256PointBytes];
-
-  DISALLOW_COPY_AND_ASSIGN(P256KeyExchange);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/proof_source.h b/net/third_party/quic/core/crypto/proof_source.h
index 3a683dc1..938a4c6 100644
--- a/net/third_party/quic/core/crypto/proof_source.h
+++ b/net/third_party/quic/core/crypto/proof_source.h
@@ -26,14 +26,13 @@
   // certificates.
   struct QUIC_EXPORT_PRIVATE Chain : public QuicReferenceCounted {
     explicit Chain(const std::vector<QuicString>& certs);
+    Chain(const Chain&) = delete;
+    Chain& operator=(const Chain&) = delete;
 
     const std::vector<QuicString> certs;
 
    protected:
     ~Chain() override;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Chain);
   };
 
   // Details is an abstract class which acts as a container for any
diff --git a/net/third_party/quic/core/crypto/quic_crypto_client_config.h b/net/third_party/quic/core/crypto/quic_crypto_client_config.h
index 0f4cb3d..6882d2a 100644
--- a/net/third_party/quic/core/crypto/quic_crypto_client_config.h
+++ b/net/third_party/quic/core/crypto/quic_crypto_client_config.h
@@ -58,6 +58,8 @@
     };
 
     CachedState();
+    CachedState(const CachedState&) = delete;
+    CachedState& operator=(const CachedState&) = delete;
     ~CachedState();
 
     // IsComplete returns true if this object contains enough information to
@@ -192,8 +194,6 @@
     // nonces and connection_ids together in one queue.
     QuicQueue<QuicConnectionId> server_designated_connection_ids_;
     QuicQueue<QuicString> server_nonces_;
-
-    DISALLOW_COPY_AND_ASSIGN(CachedState);
   };
 
   // Used to filter server ids for partial config deletion.
@@ -207,6 +207,8 @@
 
   QuicCryptoClientConfig(std::unique_ptr<ProofVerifier> proof_verifier,
                          bssl::UniquePtr<SSL_CTX> ssl_ctx);
+  QuicCryptoClientConfig(const QuicCryptoClientConfig&) = delete;
+  QuicCryptoClientConfig& operator=(const QuicCryptoClientConfig&) = delete;
   ~QuicCryptoClientConfig();
 
   // LookupOrCreate returns a CachedState for the given |server_id|. If no such
@@ -405,8 +407,6 @@
   // If non-empty, the client will operate in the pre-shared key mode by
   // incorporating |pre_shared_key_| into the key schedule.
   QuicString pre_shared_key_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientConfig);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/crypto/quic_crypto_server_config.cc b/net/third_party/quic/core/crypto/quic_crypto_server_config.cc
index 540dd02..b3a0473 100644
--- a/net/third_party/quic/core/crypto/quic_crypto_server_config.cc
+++ b/net/third_party/quic/core/crypto/quic_crypto_server_config.cc
@@ -77,6 +77,9 @@
           result,
       std::unique_ptr<ValidateClientHelloResultCallback>* done_cb)
       : result_(std::move(result)), done_cb_(done_cb) {}
+  ValidateClientHelloHelper(const ValidateClientHelloHelper&) = delete;
+  ValidateClientHelloHelper& operator=(const ValidateClientHelloHelper&) =
+      delete;
 
   ~ValidateClientHelloHelper() {
     QUIC_BUG_IF(done_cb_ != nullptr)
@@ -102,8 +105,6 @@
   QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
       result_;
   std::unique_ptr<ValidateClientHelloResultCallback>* done_cb_;
-
-  DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper);
 };
 
 // static
diff --git a/net/third_party/quic/core/crypto/quic_crypto_server_config.h b/net/third_party/quic/core/crypto/quic_crypto_server_config.h
index d8f81a63..56bee07 100644
--- a/net/third_party/quic/core/crypto/quic_crypto_server_config.h
+++ b/net/third_party/quic/core/crypto/quic_crypto_server_config.h
@@ -73,11 +73,11 @@
 class PrimaryConfigChangedCallback {
  public:
   PrimaryConfigChangedCallback();
+  PrimaryConfigChangedCallback(const PrimaryConfigChangedCallback&) = delete;
+  PrimaryConfigChangedCallback& operator=(const PrimaryConfigChangedCallback&) =
+      delete;
   virtual ~PrimaryConfigChangedCallback();
   virtual void Run(const QuicString& scid) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PrimaryConfigChangedCallback);
 };
 
 // Callback used to accept the result of the |client_hello| validation step.
@@ -103,27 +103,29 @@
   };
 
   ValidateClientHelloResultCallback();
+  ValidateClientHelloResultCallback(const ValidateClientHelloResultCallback&) =
+      delete;
+  ValidateClientHelloResultCallback& operator=(
+      const ValidateClientHelloResultCallback&) = delete;
   virtual ~ValidateClientHelloResultCallback();
   virtual void Run(QuicReferenceCountedPointer<Result> result,
                    std::unique_ptr<ProofSource::Details> details) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloResultCallback);
 };
 
 // Callback used to accept the result of the ProcessClientHello method.
 class QUIC_EXPORT_PRIVATE ProcessClientHelloResultCallback {
  public:
   ProcessClientHelloResultCallback();
+  ProcessClientHelloResultCallback(const ProcessClientHelloResultCallback&) =
+      delete;
+  ProcessClientHelloResultCallback& operator=(
+      const ProcessClientHelloResultCallback&) = delete;
   virtual ~ProcessClientHelloResultCallback();
   virtual void Run(QuicErrorCode error,
                    const QuicString& error_details,
                    std::unique_ptr<CryptoHandshakeMessage> message,
                    std::unique_ptr<DiversificationNonce> diversification_nonce,
                    std::unique_ptr<ProofSource::Details> details) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ProcessClientHelloResultCallback);
 };
 
 // Callback used to receive the results of a call to
@@ -132,10 +134,11 @@
  public:
   BuildServerConfigUpdateMessageResultCallback() = default;
   virtual ~BuildServerConfigUpdateMessageResultCallback() {}
+  BuildServerConfigUpdateMessageResultCallback(
+      const BuildServerConfigUpdateMessageResultCallback&) = delete;
+  BuildServerConfigUpdateMessageResultCallback& operator=(
+      const BuildServerConfigUpdateMessageResultCallback&) = delete;
   virtual void Run(bool ok, const CryptoHandshakeMessage& message) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(BuildServerConfigUpdateMessageResultCallback);
 };
 
 // Object that is interested in built rejections (which include REJ, SREJ and
@@ -144,12 +147,11 @@
  public:
   RejectionObserver() = default;
   virtual ~RejectionObserver() {}
+  RejectionObserver(const RejectionObserver&) = delete;
+  RejectionObserver& operator=(const RejectionObserver&) = delete;
   // Called after a rejection is built.
   virtual void OnRejectionBuilt(const std::vector<uint32_t>& reasons,
                                 CryptoHandshakeMessage* out) const = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(RejectionObserver);
 };
 
 // QuicCryptoServerConfig contains the crypto configuration of a QUIC server.
@@ -200,6 +202,8 @@
                          QuicRandom* server_nonce_entropy,
                          std::unique_ptr<ProofSource> proof_source,
                          bssl::UniquePtr<SSL_CTX> ssl_ctx);
+  QuicCryptoServerConfig(const QuicCryptoServerConfig&) = delete;
+  QuicCryptoServerConfig& operator=(const QuicCryptoServerConfig&) = delete;
   ~QuicCryptoServerConfig();
 
   // TESTING is a magic parameter for passing to the constructor in tests.
@@ -413,6 +417,8 @@
                                      public QuicReferenceCounted {
    public:
     Config();
+    Config(const Config&) = delete;
+    Config& operator=(const Config&) = delete;
 
     // TODO(rtenneti): since this is a class, we should probably do
     // getters/setters here.
@@ -467,8 +473,6 @@
 
    private:
     ~Config() override;
-
-    DISALLOW_COPY_AND_ASSIGN(Config);
   };
 
   typedef std::map<ServerConfigID, QuicReferenceCountedPointer<Config>>
@@ -773,8 +777,6 @@
   // If non-empty, the server will operate in the pre-shared key mode by
   // incorporating |pre_shared_key_| into the key schedule.
   QuicString pre_shared_key_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerConfig);
 };
 
 struct QUIC_EXPORT_PRIVATE QuicSignedServerConfig
diff --git a/net/third_party/quic/core/crypto/quic_random.cc b/net/third_party/quic/core/crypto/quic_random.cc
index a7a95691..3aa7bc9 100644
--- a/net/third_party/quic/core/crypto/quic_random.cc
+++ b/net/third_party/quic/core/crypto/quic_random.cc
@@ -23,10 +23,11 @@
 
  private:
   DefaultRandom() {}
+  DefaultRandom(const DefaultRandom&) = delete;
+  DefaultRandom& operator=(const DefaultRandom&) = delete;
   ~DefaultRandom() override {}
 
   friend QuicSingletonFriend<DefaultRandom>;
-  DISALLOW_COPY_AND_ASSIGN(DefaultRandom);
 };
 
 DefaultRandom* DefaultRandom::GetInstance() {
diff --git a/net/third_party/quic/core/crypto/scoped_evp_aead_ctx.h b/net/third_party/quic/core/crypto/scoped_evp_aead_ctx.h
index 8de9edd..d0855e8 100644
--- a/net/third_party/quic/core/crypto/scoped_evp_aead_ctx.h
+++ b/net/third_party/quic/core/crypto/scoped_evp_aead_ctx.h
@@ -15,14 +15,14 @@
 class ScopedEVPAEADCtx {
  public:
   ScopedEVPAEADCtx();
+  ScopedEVPAEADCtx(const ScopedEVPAEADCtx&) = delete;
+  ScopedEVPAEADCtx& operator=(const ScopedEVPAEADCtx&) = delete;
   ~ScopedEVPAEADCtx();
 
   EVP_AEAD_CTX* get();
 
  private:
   EVP_AEAD_CTX ctx_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedEVPAEADCtx);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/frames/quic_stream_frame.h b/net/third_party/quic/core/frames/quic_stream_frame.h
index 0e585cd..cf6d981 100644
--- a/net/third_party/quic/core/frames/quic_stream_frame.h
+++ b/net/third_party/quic/core/frames/quic_stream_frame.h
@@ -41,9 +41,8 @@
                   QuicStreamOffset offset,
                   const char* data_buffer,
                   QuicPacketLength data_length);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicStreamFrame);
+  QuicStreamFrame(const QuicStreamFrame&) = delete;
+  QuicStreamFrame& operator=(const QuicStreamFrame&) = delete;
 };
 static_assert(sizeof(QuicStreamFrame) <= 64,
               "Keep the QuicStreamFrame size to a cacheline.");
diff --git a/net/third_party/quic/core/end_to_end_test.cc b/net/third_party/quic/core/http/end_to_end_test.cc
similarity index 99%
rename from net/third_party/quic/core/end_to_end_test.cc
rename to net/third_party/quic/core/http/end_to_end_test.cc
index bb39a7b..d38e060 100644
--- a/net/third_party/quic/core/end_to_end_test.cc
+++ b/net/third_party/quic/core/http/end_to_end_test.cc
@@ -22,6 +22,8 @@
 #include "net/test/test_with_scoped_task_environment.h"
 #include "net/third_party/quic/core/crypto/aes_128_gcm_12_encrypter.h"
 #include "net/third_party/quic/core/crypto/null_encrypter.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
 #include "net/third_party/quic/core/quic_epoll_connection_helper.h"
 #include "net/third_party/quic/core/quic_framer.h"
 #include "net/third_party/quic/core/quic_packet_creator.h"
@@ -29,8 +31,6 @@
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_server_id.h"
 #include "net/third_party/quic/core/quic_session.h"
-#include "net/third_party/quic/core/quic_spdy_client_session_base.h"
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
 #include "net/third_party/quic/core/quic_utils.h"
 #include "net/third_party/quic/platform/api/quic_expect_bug.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
diff --git a/net/third_party/quic/core/quic_client_promised_info.cc b/net/third_party/quic/core/http/quic_client_promised_info.cc
similarity index 97%
rename from net/third_party/quic/core/quic_client_promised_info.cc
rename to net/third_party/quic/core/http/quic_client_promised_info.cc
index ff835e2..b9ecc72 100644
--- a/net/third_party/quic/core/quic_client_promised_info.cc
+++ b/net/third_party/quic/core/http/quic_client_promised_info.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
 
 #include <utility>
 
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
diff --git a/net/third_party/quic/core/quic_client_promised_info.h b/net/third_party/quic/core/http/quic_client_promised_info.h
similarity index 86%
rename from net/third_party/quic/core/quic_client_promised_info.h
rename to net/third_party/quic/core/http/quic_client_promised_info.h
index 41e2259..c56eb6e 100644
--- a/net/third_party/quic/core/quic_client_promised_info.h
+++ b/net/third_party/quic/core/http/quic_client_promised_info.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_CLIENT_PROMISED_INFO_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_CLIENT_PROMISED_INFO_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_CLIENT_PROMISED_INFO_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_CLIENT_PROMISED_INFO_H_
 
 #include <cstddef>
 
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 #include "net/third_party/quic/core/quic_alarm.h"
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
 #include "net/third_party/quic/core/quic_packets.h"
-#include "net/third_party/quic/core/quic_spdy_client_session_base.h"
-#include "net/third_party/quic/core/quic_spdy_stream.h"
 #include "net/third_party/quic/platform/api/quic_export.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 #include "net/third_party/spdy/core/spdy_framer.h"
@@ -33,6 +33,8 @@
   QuicClientPromisedInfo(QuicSpdyClientSessionBase* session,
                          QuicStreamId id,
                          QuicString url);
+  QuicClientPromisedInfo(const QuicClientPromisedInfo&) = delete;
+  QuicClientPromisedInfo& operator=(const QuicClientPromisedInfo&) = delete;
   virtual ~QuicClientPromisedInfo();
 
   void Init();
@@ -105,10 +107,8 @@
   // The promise will commit suicide eventually if it is not claimed by a GET
   // first.
   std::unique_ptr<QuicAlarm> cleanup_alarm_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicClientPromisedInfo);
 };
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_CLIENT_PROMISED_INFO_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_CLIENT_PROMISED_INFO_H_
diff --git a/net/third_party/quic/core/quic_client_promised_info_test.cc b/net/third_party/quic/core/http/quic_client_promised_info_test.cc
similarity index 96%
rename from net/third_party/quic/core/quic_client_promised_info_test.cc
rename to net/third_party/quic/core/http/quic_client_promised_info_test.cc
index 44cd5d6..619b08af 100644
--- a/net/third_party/quic/core/quic_client_promised_info_test.cc
+++ b/net/third_party/quic/core/http/quic_client_promised_info_test.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
 
 #include <memory>
 
 #include "base/macros.h"
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
@@ -41,6 +41,9 @@
         crypto_config_(crypto_test_utils::ProofVerifierForTesting(),
                        TlsClientHandshaker::CreateSslCtx()),
         authorized_(true) {}
+  MockQuicSpdyClientSession(const MockQuicSpdyClientSession&) = delete;
+  MockQuicSpdyClientSession& operator=(const MockQuicSpdyClientSession&) =
+      delete;
   ~MockQuicSpdyClientSession() override {}
 
   bool IsAuthorized(const QuicString& authority) override {
@@ -55,8 +58,6 @@
   QuicCryptoClientConfig crypto_config_;
 
   bool authorized_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockQuicSpdyClientSession);
 };
 
 class QuicClientPromisedInfoTest : public QuicTest {
diff --git a/net/third_party/quic/core/quic_client_push_promise_index.cc b/net/third_party/quic/core/http/quic_client_push_promise_index.cc
similarity index 86%
rename from net/third_party/quic/core/quic_client_push_promise_index.cc
rename to net/third_party/quic/core/http/quic_client_push_promise_index.cc
index 5b29eaa0..4549123 100644
--- a/net/third_party/quic/core/quic_client_push_promise_index.cc
+++ b/net/third_party/quic/core/http/quic_client_push_promise_index.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
 
-#include "net/third_party/quic/core/quic_client_promised_info.h"
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 
 using spdy::SpdyHeaderBlock;
diff --git a/net/third_party/quic/core/quic_client_push_promise_index.h b/net/third_party/quic/core/http/quic_client_push_promise_index.h
similarity index 86%
rename from net/third_party/quic/core/quic_client_push_promise_index.h
rename to net/third_party/quic/core/http/quic_client_push_promise_index.h
index fea5178d..bc62419 100644
--- a/net/third_party/quic/core/quic_client_push_promise_index.h
+++ b/net/third_party/quic/core/http/quic_client_push_promise_index.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
 
-#include "net/third_party/quic/core/quic_spdy_client_session_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session_base.h"
 #include "net/third_party/quic/core/quic_types.h"
 #include "net/third_party/quic/platform/api/quic_export.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
@@ -53,13 +53,15 @@
 
    protected:
     TryHandle() {}
+    TryHandle(const TryHandle&) = delete;
+    TryHandle& operator=(const TryHandle&) = delete;
     ~TryHandle();
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(TryHandle);
   };
 
   QuicClientPushPromiseIndex();
+  QuicClientPushPromiseIndex(const QuicClientPushPromiseIndex&) = delete;
+  QuicClientPushPromiseIndex& operator=(const QuicClientPushPromiseIndex&) =
+      delete;
   virtual ~QuicClientPushPromiseIndex();
 
   // Called by client code, used to enforce affinity between requests
@@ -89,10 +91,8 @@
 
  private:
   QuicPromisedByUrlMap promised_by_url_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicClientPushPromiseIndex);
 };
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_
diff --git a/net/third_party/quic/core/quic_client_push_promise_index_test.cc b/net/third_party/quic/core/http/quic_client_push_promise_index_test.cc
similarity index 91%
rename from net/third_party/quic/core/quic_client_push_promise_index_test.cc
rename to net/third_party/quic/core/http/quic_client_push_promise_index_test.cc
index 9c7c4d9e..27c3e33 100644
--- a/net/third_party/quic/core/quic_client_push_promise_index_test.cc
+++ b/net/third_party/quic/core/http/quic_client_push_promise_index_test.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
 
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 #include "net/third_party/quic/platform/api/quic_test.h"
@@ -34,14 +34,15 @@
                               push_promise_index),
         crypto_config_(crypto_test_utils::ProofVerifierForTesting(),
                        TlsClientHandshaker::CreateSslCtx()) {}
+  MockQuicSpdyClientSession(const MockQuicSpdyClientSession&) = delete;
+  MockQuicSpdyClientSession& operator=(const MockQuicSpdyClientSession&) =
+      delete;
   ~MockQuicSpdyClientSession() override {}
 
   MOCK_METHOD1(CloseStream, void(QuicStreamId stream_id));
 
  private:
   QuicCryptoClientConfig crypto_config_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockQuicSpdyClientSession);
 };
 
 class QuicClientPushPromiseIndexTest : public QuicTest {
diff --git a/net/third_party/quic/core/quic_header_list.cc b/net/third_party/quic/core/http/quic_header_list.cc
similarity index 97%
rename from net/third_party/quic/core/quic_header_list.cc
rename to net/third_party/quic/core/http/quic_header_list.cc
index 87e2a92..e0589680 100644
--- a/net/third_party/quic/core/quic_header_list.cc
+++ b/net/third_party/quic/core/http/quic_header_list.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_header_list.h"
+#include "net/third_party/quic/core/http/quic_header_list.h"
 
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
diff --git a/net/third_party/quic/core/quic_header_list.h b/net/third_party/quic/core/http/quic_header_list.h
similarity index 94%
rename from net/third_party/quic/core/quic_header_list.h
rename to net/third_party/quic/core/http/quic_header_list.h
index 88d5e2a..016b484 100644
--- a/net/third_party/quic/core/quic_header_list.h
+++ b/net/third_party/quic/core/http/quic_header_list.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_HEADER_LIST_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_HEADER_LIST_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_HEADER_LIST_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_HEADER_LIST_H_
 
 #include <algorithm>
 #include <functional>
@@ -85,4 +85,4 @@
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_HEADER_LIST_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_HEADER_LIST_H_
diff --git a/net/third_party/quic/core/quic_header_list_test.cc b/net/third_party/quic/core/http/quic_header_list_test.cc
similarity index 97%
rename from net/third_party/quic/core/quic_header_list_test.cc
rename to net/third_party/quic/core/http/quic_header_list_test.cc
index 9928c7a..af745ac 100644
--- a/net/third_party/quic/core/quic_header_list_test.cc
+++ b/net/third_party/quic/core/http/quic_header_list_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_header_list.h"
+#include "net/third_party/quic/core/http/quic_header_list.h"
 
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
diff --git a/net/third_party/quic/core/quic_headers_stream.cc b/net/third_party/quic/core/http/quic_headers_stream.cc
similarity index 97%
rename from net/third_party/quic/core/quic_headers_stream.cc
rename to net/third_party/quic/core/http/quic_headers_stream.cc
index 115d9a7..b0c914e 100644
--- a/net/third_party/quic/core/quic_headers_stream.cc
+++ b/net/third_party/quic/core/http/quic_headers_stream.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_headers_stream.h"
+#include "net/third_party/quic/core/http/quic_headers_stream.h"
 
-#include "net/third_party/quic/core/quic_spdy_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_session.h"
 #include "net/third_party/quic/platform/api/quic_arraysize.h"
 #include "net/third_party/quic/platform/api/quic_flag_utils.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
diff --git a/net/third_party/quic/core/quic_headers_stream.h b/net/third_party/quic/core/http/quic_headers_stream.h
similarity index 89%
rename from net/third_party/quic/core/quic_headers_stream.h
rename to net/third_party/quic/core/http/quic_headers_stream.h
index 0c0187d1..3221522 100644
--- a/net/third_party/quic/core/quic_headers_stream.h
+++ b/net/third_party/quic/core/http/quic_headers_stream.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_HEADERS_STREAM_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_HEADERS_STREAM_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_HEADERS_STREAM_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_HEADERS_STREAM_H_
 
 #include <cstddef>
 #include <memory>
 
 #include "base/macros.h"
-#include "net/third_party/quic/core/quic_header_list.h"
+#include "net/third_party/quic/core/http/quic_header_list.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_stream.h"
 #include "net/third_party/quic/platform/api/quic_containers.h"
@@ -30,6 +30,8 @@
 class QUIC_EXPORT_PRIVATE QuicHeadersStream : public QuicStream {
  public:
   explicit QuicHeadersStream(QuicSpdySession* session);
+  QuicHeadersStream(const QuicHeadersStream&) = delete;
+  QuicHeadersStream& operator=(const QuicHeadersStream&) = delete;
   ~QuicHeadersStream() override;
 
   // QuicStream implementation
@@ -87,10 +89,8 @@
 
   // Headers that have not been fully acked.
   QuicDeque<CompressedHeaderInfo> unacked_headers_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicHeadersStream);
 };
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_HEADERS_STREAM_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_HEADERS_STREAM_H_
diff --git a/net/third_party/quic/core/quic_headers_stream_test.cc b/net/third_party/quic/core/http/quic_headers_stream_test.cc
similarity index 98%
rename from net/third_party/quic/core/quic_headers_stream_test.cc
rename to net/third_party/quic/core/http/quic_headers_stream_test.cc
index 8016e2a..441403e 100644
--- a/net/third_party/quic/core/quic_headers_stream_test.cc
+++ b/net/third_party/quic/core/http/quic_headers_stream_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_headers_stream.h"
+#include "net/third_party/quic/core/http/quic_headers_stream.h"
 
 #include <cstdint>
 #include <ostream>
@@ -10,9 +10,9 @@
 #include <utility>
 #include <vector>
 
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_data_writer.h"
 #include "net/third_party/quic/core/quic_utils.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_expect_bug.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
@@ -75,11 +75,11 @@
 class MockQuicHpackDebugVisitor : public QuicHpackDebugVisitor {
  public:
   MockQuicHpackDebugVisitor() : QuicHpackDebugVisitor() {}
+  MockQuicHpackDebugVisitor(const MockQuicHpackDebugVisitor&) = delete;
+  MockQuicHpackDebugVisitor& operator=(const MockQuicHpackDebugVisitor&) =
+      delete;
 
   MOCK_METHOD1(OnUseEntry, void(QuicTime::Delta elapsed));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockQuicHpackDebugVisitor);
 };
 
 namespace {
diff --git a/net/third_party/quic/core/quic_server_session_base.cc b/net/third_party/quic/core/http/quic_server_session_base.cc
similarity index 98%
rename from net/third_party/quic/core/quic_server_session_base.cc
rename to net/third_party/quic/core/http/quic_server_session_base.cc
index e9838213..432fafe 100644
--- a/net/third_party/quic/core/quic_server_session_base.cc
+++ b/net/third_party/quic/core/http/quic_server_session_base.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_server_session_base.h"
+#include "net/third_party/quic/core/http/quic_server_session_base.h"
 
 #include "net/third_party/quic/core/proto/cached_network_parameters.pb.h"
 #include "net/third_party/quic/core/quic_connection.h"
diff --git a/net/third_party/quic/core/quic_server_session_base.h b/net/third_party/quic/core/http/quic_server_session_base.h
similarity index 91%
rename from net/third_party/quic/core/quic_server_session_base.h
rename to net/third_party/quic/core/http/quic_server_session_base.h
index dae10a4..1ff4691 100644
--- a/net/third_party/quic/core/quic_server_session_base.h
+++ b/net/third_party/quic/core/http/quic_server_session_base.h
@@ -4,8 +4,8 @@
 //
 // A server specific QuicSession subclass.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_SERVER_SESSION_BASE_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_SERVER_SESSION_BASE_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SERVER_SESSION_BASE_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SERVER_SESSION_BASE_H_
 
 #include <cstdint>
 #include <memory>
@@ -14,9 +14,9 @@
 
 #include "base/macros.h"
 #include "net/third_party/quic/core/crypto/quic_compressed_certs_cache.h"
+#include "net/third_party/quic/core/http/quic_spdy_session.h"
 #include "net/third_party/quic/core/quic_crypto_server_stream.h"
 #include "net/third_party/quic/core/quic_packets.h"
-#include "net/third_party/quic/core/quic_spdy_session.h"
 #include "net/third_party/quic/platform/api/quic_export.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 
@@ -41,6 +41,8 @@
                         QuicCryptoServerStream::Helper* helper,
                         const QuicCryptoServerConfig* crypto_config,
                         QuicCompressedCertsCache* compressed_certs_cache);
+  QuicServerSessionBase(const QuicServerSessionBase&) = delete;
+  QuicServerSessionBase& operator=(const QuicServerSessionBase&) = delete;
 
   // Override the base class to cancel any ongoing asychronous crypto.
   void OnConnectionClosed(QuicErrorCode error,
@@ -129,10 +131,8 @@
   // should go away once we fix http://b//27897982
   int32_t BandwidthToCachedParameterBytesPerSecond(
       const QuicBandwidth& bandwidth);
-
-  DISALLOW_COPY_AND_ASSIGN(QuicServerSessionBase);
 };
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_SERVER_SESSION_BASE_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SERVER_SESSION_BASE_H_
diff --git a/net/third_party/quic/core/quic_server_session_base_test.cc b/net/third_party/quic/core/http/quic_server_session_base_test.cc
similarity index 98%
rename from net/third_party/quic/core/quic_server_session_base_test.cc
rename to net/third_party/quic/core/http/quic_server_session_base_test.cc
index 8ef5d3a..3bbef179 100644
--- a/net/third_party/quic/core/quic_server_session_base_test.cc
+++ b/net/third_party/quic/core/http/quic_server_session_base_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_server_session_base.h"
+#include "net/third_party/quic/core/http/quic_server_session_base.h"
 
 #include <cstdint>
 #include <memory>
@@ -32,7 +32,6 @@
 #include "net/third_party/quic/test_tools/quic_sent_packet_manager_peer.h"
 #include "net/third_party/quic/test_tools/quic_session_peer.h"
 #include "net/third_party/quic/test_tools/quic_spdy_session_peer.h"
-#include "net/third_party/quic/test_tools/quic_spdy_stream_peer.h"
 #include "net/third_party/quic/test_tools/quic_stream_peer.h"
 #include "net/third_party/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h"
 #include "net/third_party/quic/test_tools/quic_test_utils.h"
@@ -383,13 +382,13 @@
             GetQuicReloadableFlag(enable_quic_stateless_reject_support),
             session,
             helper) {}
+  MockQuicCryptoServerStream(const MockQuicCryptoServerStream&) = delete;
+  MockQuicCryptoServerStream& operator=(const MockQuicCryptoServerStream&) =
+      delete;
   ~MockQuicCryptoServerStream() override {}
 
   MOCK_METHOD1(SendServerConfigUpdate,
                void(const CachedNetworkParameters* cached_network_parameters));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream);
 };
 
 TEST_P(QuicServerSessionBaseTest, BandwidthEstimates) {
diff --git a/net/third_party/quic/core/quic_spdy_client_session.cc b/net/third_party/quic/core/http/quic_spdy_client_session.cc
similarity index 95%
rename from net/third_party/quic/core/quic_spdy_client_session.cc
rename to net/third_party/quic/core/http/quic_spdy_client_session.cc
index a6c11a91..d998cf2 100644
--- a/net/third_party/quic/core/quic_spdy_client_session.cc
+++ b/net/third_party/quic/core/http/quic_spdy_client_session.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
 
 #include "net/log/net_log_with_source.h"
 #include "net/quic/chromium/crypto/proof_verifier_chromium.h"
 #include "net/third_party/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_server_id.h"
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
diff --git a/net/third_party/quic/core/quic_spdy_client_session.h b/net/third_party/quic/core/http/quic_spdy_client_session.h
similarity index 87%
rename from net/third_party/quic/core/quic_spdy_client_session.h
rename to net/third_party/quic/core/http/quic_spdy_client_session.h
index 8a3b1ed..06fe99e 100644
--- a/net/third_party/quic/core/quic_spdy_client_session.h
+++ b/net/third_party/quic/core/http/quic_spdy_client_session.h
@@ -4,16 +4,16 @@
 //
 // A client specific QuicSession subclass.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_SESSION_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_SESSION_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_SESSION_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_SESSION_H_
 
 #include <memory>
 
 #include "base/macros.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
 #include "net/third_party/quic/core/quic_crypto_client_stream.h"
 #include "net/third_party/quic/core/quic_packets.h"
-#include "net/third_party/quic/core/quic_spdy_client_session_base.h"
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 
 namespace quic {
@@ -30,6 +30,8 @@
                         const QuicServerId& server_id,
                         QuicCryptoClientConfig* crypto_config,
                         QuicClientPushPromiseIndex* push_promise_index);
+  QuicSpdyClientSession(const QuicSpdyClientSession&) = delete;
+  QuicSpdyClientSession& operator=(const QuicSpdyClientSession&) = delete;
   ~QuicSpdyClientSession() override;
   // Set up the QuicSpdyClientSession. Must be called prior to use.
   void Initialize() override;
@@ -89,10 +91,8 @@
   // If this is set to false, the client will ignore server GOAWAYs and allow
   // the creation of streams regardless of the high chance they will fail.
   bool respect_goaway_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientSession);
 };
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_SESSION_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_SESSION_H_
diff --git a/net/third_party/quic/core/quic_spdy_client_session_base.cc b/net/third_party/quic/core/http/quic_spdy_client_session_base.cc
similarity index 96%
rename from net/third_party/quic/core/quic_spdy_client_session_base.cc
rename to net/third_party/quic/core/http/quic_spdy_client_session_base.cc
index c1d959f..5080011 100644
--- a/net/third_party/quic/core/quic_spdy_client_session_base.cc
+++ b/net/third_party/quic/core/http/quic_spdy_client_session_base.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_client_session_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session_base.h"
 
-#include "net/third_party/quic/core/quic_client_promised_info.h"
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
diff --git a/net/third_party/quic/core/quic_spdy_client_session_base.h b/net/third_party/quic/core/http/quic_spdy_client_session_base.h
similarity index 92%
rename from net/third_party/quic/core/quic_spdy_client_session_base.h
rename to net/third_party/quic/core/http/quic_spdy_client_session_base.h
index a97ff63..b40aab9d 100644
--- a/net/third_party/quic/core/quic_spdy_client_session_base.h
+++ b/net/third_party/quic/core/http/quic_spdy_client_session_base.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_SESSION_BASE_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_SESSION_BASE_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_SESSION_BASE_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_SESSION_BASE_H_
 
 #include "base/macros.h"
+#include "net/third_party/quic/core/http/quic_spdy_session.h"
 #include "net/third_party/quic/core/quic_crypto_client_stream.h"
-#include "net/third_party/quic/core/quic_spdy_session.h"
 #include "net/third_party/quic/platform/api/quic_containers.h"
 #include "net/third_party/quic/platform/api/quic_export.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
@@ -41,6 +41,9 @@
   QuicSpdyClientSessionBase(QuicConnection* connection,
                             QuicClientPushPromiseIndex* push_promise_index,
                             const QuicConfig& config);
+  QuicSpdyClientSessionBase(const QuicSpdyClientSessionBase&) = delete;
+  QuicSpdyClientSessionBase& operator=(const QuicSpdyClientSessionBase&) =
+      delete;
 
   ~QuicSpdyClientSessionBase() override;
 
@@ -129,10 +132,8 @@
   QuicClientPushPromiseIndex* push_promise_index_;
   QuicPromisedByIdMap promised_by_id_;
   QuicStreamId largest_promised_stream_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientSessionBase);
 };
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_SESSION_BASE_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_SESSION_BASE_H_
diff --git a/net/third_party/quic/core/quic_spdy_client_session_test.cc b/net/third_party/quic/core/http/quic_spdy_client_session_test.cc
similarity index 99%
rename from net/third_party/quic/core/quic_spdy_client_session_test.cc
rename to net/third_party/quic/core/http/quic_spdy_client_session_test.cc
index 142fe2af..37ab30a 100644
--- a/net/third_party/quic/core/quic_spdy_client_session_test.cc
+++ b/net/third_party/quic/core/http/quic_spdy_client_session_test.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
 
 #include <memory>
 #include <vector>
 
 #include "net/third_party/quic/core/crypto/aes_128_gcm_12_encrypter.h"
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_arraysize.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
diff --git a/net/third_party/quic/core/quic_spdy_client_stream.cc b/net/third_party/quic/core/http/quic_spdy_client_stream.cc
similarity index 94%
rename from net/third_party/quic/core/quic_spdy_client_stream.cc
rename to net/third_party/quic/core/http/quic_spdy_client_stream.cc
index c03f47d..f6a157b 100644
--- a/net/third_party/quic/core/quic_spdy_client_stream.cc
+++ b/net/third_party/quic/core/http/quic_spdy_client_stream.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
 
 #include <utility>
 
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_alarm.h"
-#include "net/third_party/quic/core/quic_client_promised_info.h"
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/spdy/core/spdy_protocol.h"
 
diff --git a/net/third_party/quic/core/quic_spdy_client_stream.h b/net/third_party/quic/core/http/quic_spdy_client_stream.h
similarity index 88%
rename from net/third_party/quic/core/quic_spdy_client_stream.h
rename to net/third_party/quic/core/http/quic_spdy_client_stream.h
index 5fe0e36..26d7138 100644
--- a/net/third_party/quic/core/quic_spdy_client_stream.h
+++ b/net/third_party/quic/core/http/quic_spdy_client_stream.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_STREAM_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_STREAM_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_STREAM_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_STREAM_H_
 
 #include <cstddef>
 
 #include "base/macros.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 #include "net/third_party/quic/core/quic_packets.h"
-#include "net/third_party/quic/core/quic_spdy_stream.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 #include "net/third_party/spdy/core/spdy_framer.h"
@@ -23,6 +23,8 @@
 class QuicSpdyClientStream : public QuicSpdyStream {
  public:
   QuicSpdyClientStream(QuicStreamId id, QuicSpdyClientSession* session);
+  QuicSpdyClientStream(const QuicSpdyClientStream&) = delete;
+  QuicSpdyClientStream& operator=(const QuicSpdyClientStream&) = delete;
   ~QuicSpdyClientStream() override;
 
   // Override the base class to parse and store headers.
@@ -87,10 +89,8 @@
   // Expect: 100-continue.
   bool has_preliminary_headers_;
   spdy::SpdyHeaderBlock preliminary_headers_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientStream);
 };
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_CLIENT_STREAM_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_STREAM_H_
diff --git a/net/third_party/quic/core/quic_spdy_client_stream_test.cc b/net/third_party/quic/core/http/quic_spdy_client_stream_test.cc
similarity index 95%
rename from net/third_party/quic/core/quic_spdy_client_stream_test.cc
rename to net/third_party/quic/core/http/quic_spdy_client_stream_test.cc
index 33c713b..452c164 100644
--- a/net/third_party/quic/core/quic_spdy_client_stream_test.cc
+++ b/net/third_party/quic/core/http/quic_spdy_client_stream_test.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
 
 #include <memory>
 
 #include "base/macros.h"
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_utils.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
@@ -42,14 +42,15 @@
                               push_promise_index),
         crypto_config_(crypto_test_utils::ProofVerifierForTesting(),
                        TlsClientHandshaker::CreateSslCtx()) {}
+  MockQuicSpdyClientSession(const MockQuicSpdyClientSession&) = delete;
+  MockQuicSpdyClientSession& operator=(const MockQuicSpdyClientSession&) =
+      delete;
   ~MockQuicSpdyClientSession() override = default;
 
   MOCK_METHOD1(CloseStream, void(QuicStreamId stream_id));
 
  private:
   QuicCryptoClientConfig crypto_config_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockQuicSpdyClientSession);
 };
 
 class QuicSpdyClientStreamTest : public QuicTest {
diff --git a/net/third_party/quic/core/quic_spdy_server_stream_base.cc b/net/third_party/quic/core/http/quic_spdy_server_stream_base.cc
similarity index 94%
rename from net/third_party/quic/core/quic_spdy_server_stream_base.cc
rename to net/third_party/quic/core/http/quic_spdy_server_stream_base.cc
index 8ac9c6a..7da7f89 100644
--- a/net/third_party/quic/core/quic_spdy_server_stream_base.cc
+++ b/net/third_party/quic/core/http/quic_spdy_server_stream_base.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_server_stream_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_server_stream_base.h"
 
 #include "net/third_party/quic/core/quic_error_codes.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
diff --git a/net/third_party/quic/core/http/quic_spdy_server_stream_base.h b/net/third_party/quic/core/http/quic_spdy_server_stream_base.h
new file mode 100644
index 0000000..56006b0
--- /dev/null
+++ b/net/third_party/quic/core/http/quic_spdy_server_stream_base.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_SERVER_STREAM_BASE_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_SERVER_STREAM_BASE_H_
+
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
+
+namespace quic {
+
+class QuicSpdyServerStreamBase : public QuicSpdyStream {
+ public:
+  QuicSpdyServerStreamBase(QuicStreamId id, QuicSpdySession* session);
+  QuicSpdyServerStreamBase(const QuicSpdyServerStreamBase&) = delete;
+  QuicSpdyServerStreamBase& operator=(const QuicSpdyServerStreamBase&) = delete;
+
+  // Override the base class to send QUIC_STREAM_NO_ERROR to the peer
+  // when the stream has not received all the data.
+  void CloseWriteSide() override;
+  void StopReading() override;
+};
+
+}  // namespace quic
+
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_SERVER_STREAM_BASE_H_
diff --git a/net/third_party/quic/core/quic_spdy_server_stream_base_test.cc b/net/third_party/quic/core/http/quic_spdy_server_stream_base_test.cc
similarity index 96%
rename from net/third_party/quic/core/quic_spdy_server_stream_base_test.cc
rename to net/third_party/quic/core/http/quic_spdy_server_stream_base_test.cc
index 032914a..44f4039 100644
--- a/net/third_party/quic/core/quic_spdy_server_stream_base_test.cc
+++ b/net/third_party/quic/core/http/quic_spdy_server_stream_base_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_server_stream_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_server_stream_base.h"
 
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quic/platform/api/quic_test.h"
diff --git a/net/third_party/quic/core/quic_spdy_session.cc b/net/third_party/quic/core/http/quic_spdy_session.cc
similarity index 97%
rename from net/third_party/quic/core/quic_spdy_session.cc
rename to net/third_party/quic/core/http/quic_spdy_session.cc
index 9127014..d600c519 100644
--- a/net/third_party/quic/core/quic_spdy_session.cc
+++ b/net/third_party/quic/core/http/quic_spdy_session.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_session.h"
 
 #include <algorithm>
 #include <cstdint>
 #include <utility>
 
-#include "net/third_party/quic/core/quic_headers_stream.h"
+#include "net/third_party/quic/core/http/quic_headers_stream.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_fallthrough.h"
 #include "net/third_party/quic/platform/api/quic_flag_utils.h"
@@ -55,6 +55,8 @@
   HeaderTableDebugVisitor(const QuicClock* clock,
                           std::unique_ptr<QuicHpackDebugVisitor> visitor)
       : clock_(clock), headers_stream_hpack_visitor_(std::move(visitor)) {}
+  HeaderTableDebugVisitor(const HeaderTableDebugVisitor&) = delete;
+  HeaderTableDebugVisitor& operator=(const HeaderTableDebugVisitor&) = delete;
 
   int64_t OnNewEntry(const HpackEntry& entry) override {
     QUIC_DVLOG(1) << entry.GetDebugString();
@@ -74,8 +76,6 @@
  private:
   const QuicClock* clock_;
   std::unique_ptr<QuicHpackDebugVisitor> headers_stream_hpack_visitor_;
-
-  DISALLOW_COPY_AND_ASSIGN(HeaderTableDebugVisitor);
 };
 
 }  // namespace
@@ -87,6 +87,8 @@
       public SpdyFramerDebugVisitorInterface {
  public:
   explicit SpdyFramerVisitor(QuicSpdySession* session) : session_(session) {}
+  SpdyFramerVisitor(const SpdyFramerVisitor&) = delete;
+  SpdyFramerVisitor& operator=(const SpdyFramerVisitor&) = delete;
 
   SpdyHeadersHandlerInterface* OnHeaderFrameStart(
       SpdyStreamId /* stream_id */) override {
@@ -289,8 +291,6 @@
  private:
   QuicSpdySession* session_;
   QuicHeaderList header_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
 };
 
 QuicHpackDebugVisitor::QuicHpackDebugVisitor() {}
diff --git a/net/third_party/quic/core/quic_spdy_session.h b/net/third_party/quic/core/http/quic_spdy_session.h
similarity index 93%
rename from net/third_party/quic/core/quic_spdy_session.h
rename to net/third_party/quic/core/http/quic_spdy_session.h
index 74ed443..9ecf6d0 100644
--- a/net/third_party/quic/core/quic_spdy_session.h
+++ b/net/third_party/quic/core/http/quic_spdy_session.h
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_SESSION_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_SESSION_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
 
 #include <cstddef>
 #include <memory>
 
 #include "base/macros.h"
-#include "net/third_party/quic/core/quic_header_list.h"
-#include "net/third_party/quic/core/quic_headers_stream.h"
+#include "net/third_party/quic/core/http/quic_header_list.h"
+#include "net/third_party/quic/core/http/quic_headers_stream.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 #include "net/third_party/quic/core/quic_session.h"
-#include "net/third_party/quic/core/quic_spdy_stream.h"
 #include "net/third_party/quic/platform/api/quic_export.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
@@ -32,6 +32,8 @@
 class QUIC_EXPORT_PRIVATE QuicHpackDebugVisitor {
  public:
   QuicHpackDebugVisitor();
+  QuicHpackDebugVisitor(const QuicHpackDebugVisitor&) = delete;
+  QuicHpackDebugVisitor& operator=(const QuicHpackDebugVisitor&) = delete;
 
   virtual ~QuicHpackDebugVisitor();
 
@@ -39,9 +41,6 @@
   // the time since the corresponding entry was added to the dynamic
   // table.
   virtual void OnUseEntry(QuicTime::Delta elapsed) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicHpackDebugVisitor);
 };
 
 // A QUIC session with a headers stream.
@@ -51,6 +50,8 @@
   QuicSpdySession(QuicConnection* connection,
                   QuicSession::Visitor* visitor,
                   const QuicConfig& config);
+  QuicSpdySession(const QuicSpdySession&) = delete;
+  QuicSpdySession& operator=(const QuicSpdySession&) = delete;
 
   ~QuicSpdySession() override;
 
@@ -239,10 +240,8 @@
   spdy::SpdyFramer spdy_framer_;
   http2::Http2DecoderAdapter h2_deframer_;
   std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSpdySession);
 };
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_SESSION_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_SESSION_H_
diff --git a/net/third_party/quic/core/quic_spdy_session_test.cc b/net/third_party/quic/core/http/quic_spdy_session_test.cc
similarity index 99%
rename from net/third_party/quic/core/quic_spdy_session_test.cc
rename to net/third_party/quic/core/http/quic_spdy_session_test.cc
index 5edfb7e..fc9c5be 100644
--- a/net/third_party/quic/core/quic_spdy_session_test.cc
+++ b/net/third_party/quic/core/http/quic_spdy_session_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_session.h"
 
 #include <cstdint>
 #include <set>
@@ -28,7 +28,6 @@
 #include "net/third_party/quic/test_tools/quic_flow_controller_peer.h"
 #include "net/third_party/quic/test_tools/quic_session_peer.h"
 #include "net/third_party/quic/test_tools/quic_spdy_session_peer.h"
-#include "net/third_party/quic/test_tools/quic_spdy_stream_peer.h"
 #include "net/third_party/quic/test_tools/quic_stream_peer.h"
 #include "net/third_party/quic/test_tools/quic_stream_send_buffer_peer.h"
 #include "net/third_party/quic/test_tools/quic_test_utils.h"
diff --git a/net/third_party/quic/core/quic_spdy_stream.cc b/net/third_party/quic/core/http/quic_spdy_stream.cc
similarity index 97%
rename from net/third_party/quic/core/quic_spdy_stream.cc
rename to net/third_party/quic/core/http/quic_spdy_stream.cc
index 3a8febc4..fe2c14f 100644
--- a/net/third_party/quic/core/quic_spdy_stream.cc
+++ b/net/third_party/quic/core/http/quic_spdy_stream.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_stream.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 
 #include <utility>
 
-#include "net/third_party/quic/core/quic_spdy_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_session.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_utils.h"
 #include "net/third_party/quic/core/quic_write_blocked_list.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
diff --git a/net/third_party/quic/core/quic_spdy_stream.h b/net/third_party/quic/core/http/quic_spdy_stream.h
similarity index 94%
rename from net/third_party/quic/core/quic_spdy_stream.h
rename to net/third_party/quic/core/http/quic_spdy_stream.h
index 0ebe198..a511cbb 100644
--- a/net/third_party/quic/core/quic_spdy_stream.h
+++ b/net/third_party/quic/core/http/quic_spdy_stream.h
@@ -6,8 +6,8 @@
 // In each direction, the data on such a stream first contains compressed
 // headers then body data.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_STREAM_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_STREAM_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_H_
 
 #include <sys/types.h>
 
@@ -16,7 +16,7 @@
 
 #include "base/macros.h"
 #include "net/base/iovec.h"
-#include "net/third_party/quic/core/quic_header_list.h"
+#include "net/third_party/quic/core/http/quic_header_list.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_stream.h"
 #include "net/third_party/quic/core/quic_stream_sequencer.h"
@@ -29,7 +29,6 @@
 namespace quic {
 
 namespace test {
-class QuicSpdyStreamPeer;
 class QuicStreamPeer;
 }  // namespace test
 
@@ -42,6 +41,8 @@
   class QUIC_EXPORT_PRIVATE Visitor {
    public:
     Visitor() {}
+    Visitor(const Visitor&) = delete;
+    Visitor& operator=(const Visitor&) = delete;
 
     // Called when the stream is closed.
     virtual void OnClose(QuicSpdyStream* stream) = 0;
@@ -52,12 +53,11 @@
 
    protected:
     virtual ~Visitor() {}
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Visitor);
   };
 
   QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session);
+  QuicSpdyStream(const QuicSpdyStream&) = delete;
+  QuicSpdyStream& operator=(const QuicSpdyStream&) = delete;
   ~QuicSpdyStream() override;
 
   // QuicStream implementation
@@ -181,7 +181,6 @@
   void set_headers_decompressed(bool val) { headers_decompressed_ = val; }
 
  private:
-  friend class test::QuicSpdyStreamPeer;
   friend class test::QuicStreamPeer;
   friend class QuicStreamUtils;
 
@@ -200,10 +199,8 @@
   bool trailers_consumed_;
   // The parsed trailers received from the peer.
   spdy::SpdyHeaderBlock received_trailers_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSpdyStream);
 };
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_STREAM_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_H_
diff --git a/net/third_party/quic/core/quic_spdy_stream_test.cc b/net/third_party/quic/core/http/quic_spdy_stream_test.cc
similarity index 99%
rename from net/third_party/quic/core/quic_spdy_stream_test.cc
rename to net/third_party/quic/core/http/quic_spdy_stream_test.cc
index f2a9963..394a180 100644
--- a/net/third_party/quic/core/quic_spdy_stream_test.cc
+++ b/net/third_party/quic/core/http/quic_spdy_stream_test.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/quic_spdy_stream.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 
 #include <memory>
 #include <utility>
 
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_utils.h"
 #include "net/third_party/quic/core/quic_write_blocked_list.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_arraysize.h"
 #include "net/third_party/quic/platform/api/quic_expect_bug.h"
 #include "net/third_party/quic/platform/api/quic_map_util.h"
diff --git a/net/third_party/quic/core/spdy_utils.cc b/net/third_party/quic/core/http/spdy_utils.cc
similarity index 98%
rename from net/third_party/quic/core/spdy_utils.cc
rename to net/third_party/quic/core/http/spdy_utils.cc
index 90ac60c..31e2d09 100644
--- a/net/third_party/quic/core/spdy_utils.cc
+++ b/net/third_party/quic/core/http/spdy_utils.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 
 #include <memory>
 #include <vector>
diff --git a/net/third_party/quic/core/spdy_utils.h b/net/third_party/quic/core/http/spdy_utils.h
similarity index 89%
rename from net/third_party/quic/core/spdy_utils.h
rename to net/third_party/quic/core/http/spdy_utils.h
index b12966d8..ec1bf11 100644
--- a/net/third_party/quic/core/spdy_utils.h
+++ b/net/third_party/quic/core/http/spdy_utils.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_THIRD_PARTY_QUIC_CORE_SPDY_UTILS_H_
-#define NET_THIRD_PARTY_QUIC_CORE_SPDY_UTILS_H_
+#ifndef NET_THIRD_PARTY_QUIC_CORE_HTTP_SPDY_UTILS_H_
+#define NET_THIRD_PARTY_QUIC_CORE_HTTP_SPDY_UTILS_H_
 
 #include <cstddef>
 #include <cstdint>
 
 #include "base/macros.h"
-#include "net/third_party/quic/core/quic_header_list.h"
+#include "net/third_party/quic/core/http/quic_header_list.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/platform/api/quic_export.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
@@ -19,6 +19,8 @@
 
 class QUIC_EXPORT_PRIVATE SpdyUtils {
  public:
+  SpdyUtils() = delete;
+
   // Populate |content length| with the value of the content-length header.
   // Returns true on success, false if parsing fails or content-length header is
   // missing.
@@ -54,11 +56,8 @@
   // which must be fully-qualified.
   static bool PopulateHeaderBlockFromUrl(const QuicString url,
                                          spdy::SpdyHeaderBlock* headers);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SpdyUtils);
 };
 
 }  // namespace quic
 
-#endif  // NET_THIRD_PARTY_QUIC_CORE_SPDY_UTILS_H_
+#endif  // NET_THIRD_PARTY_QUIC_CORE_HTTP_SPDY_UTILS_H_
diff --git a/net/third_party/quic/core/spdy_utils_test.cc b/net/third_party/quic/core/http/spdy_utils_test.cc
similarity index 99%
rename from net/third_party/quic/core/spdy_utils_test.cc
rename to net/third_party/quic/core/http/spdy_utils_test.cc
index 4910e72..3c6b618 100644
--- a/net/third_party/quic/core/spdy_utils_test.cc
+++ b/net/third_party/quic/core/http/spdy_utils_test.cc
@@ -5,7 +5,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 #include "net/third_party/quic/platform/api/quic_test.h"
diff --git a/net/third_party/quic/core/quic_alarm.h b/net/third_party/quic/core/quic_alarm.h
index 966bd7c6..e45464108 100644
--- a/net/third_party/quic/core/quic_alarm.h
+++ b/net/third_party/quic/core/quic_alarm.h
@@ -28,6 +28,8 @@
   };
 
   explicit QuicAlarm(QuicArenaScopedPtr<Delegate> delegate);
+  QuicAlarm(const QuicAlarm&) = delete;
+  QuicAlarm& operator=(const QuicAlarm&) = delete;
   virtual ~QuicAlarm();
 
   // Sets the alarm to fire at |deadline|.  Must not be called while
@@ -78,8 +80,6 @@
  private:
   QuicArenaScopedPtr<Delegate> delegate_;
   QuicTime deadline_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicAlarm);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_arena_scoped_ptr.h b/net/third_party/quic/core/quic_arena_scoped_ptr.h
index 4ff6030c..7a524f85 100644
--- a/net/third_party/quic/core/quic_arena_scoped_ptr.h
+++ b/net/third_party/quic/core/quic_arena_scoped_ptr.h
@@ -73,6 +73,8 @@
 
   // Constructs a QuicArenaScopedPtr with the given representation.
   QuicArenaScopedPtr(void* value, ConstructFrom from);
+  QuicArenaScopedPtr(const QuicArenaScopedPtr&) = delete;
+  QuicArenaScopedPtr& operator=(const QuicArenaScopedPtr&) = delete;
 
   // Low-order bits of value_ that determine if the pointer came from an arena.
   static const uintptr_t kFromArenaMask = 0x1;
@@ -80,8 +82,6 @@
   // Every platform we care about has at least 4B aligned integers, so store the
   // is_from_arena bit in the least significant bit.
   void* value_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicArenaScopedPtr);
 };
 
 template <typename T>
diff --git a/net/third_party/quic/core/quic_connection.cc b/net/third_party/quic/core/quic_connection.cc
index d5460ad..b94f16f 100644
--- a/net/third_party/quic/core/quic_connection.cc
+++ b/net/third_party/quic/core/quic_connection.cc
@@ -85,6 +85,8 @@
  public:
   explicit AckAlarmDelegate(QuicConnection* connection)
       : connection_(connection) {}
+  AckAlarmDelegate(const AckAlarmDelegate&) = delete;
+  AckAlarmDelegate& operator=(const AckAlarmDelegate&) = delete;
 
   void OnAlarm() override {
     DCHECK(connection_->ack_frame_updated());
@@ -94,8 +96,6 @@
 
  private:
   QuicConnection* connection_;
-
-  DISALLOW_COPY_AND_ASSIGN(AckAlarmDelegate);
 };
 
 // This alarm will be scheduled any time a data-bearing packet is sent out.
@@ -105,13 +105,14 @@
  public:
   explicit RetransmissionAlarmDelegate(QuicConnection* connection)
       : connection_(connection) {}
+  RetransmissionAlarmDelegate(const RetransmissionAlarmDelegate&) = delete;
+  RetransmissionAlarmDelegate& operator=(const RetransmissionAlarmDelegate&) =
+      delete;
 
   void OnAlarm() override { connection_->OnRetransmissionTimeout(); }
 
  private:
   QuicConnection* connection_;
-
-  DISALLOW_COPY_AND_ASSIGN(RetransmissionAlarmDelegate);
 };
 
 // An alarm that is scheduled when the SentPacketManager requires a delay
@@ -120,78 +121,82 @@
  public:
   explicit SendAlarmDelegate(QuicConnection* connection)
       : connection_(connection) {}
+  SendAlarmDelegate(const SendAlarmDelegate&) = delete;
+  SendAlarmDelegate& operator=(const SendAlarmDelegate&) = delete;
 
   void OnAlarm() override { connection_->WriteAndBundleAcksIfNotBlocked(); }
 
  private:
   QuicConnection* connection_;
-
-  DISALLOW_COPY_AND_ASSIGN(SendAlarmDelegate);
 };
 
 class PathDegradingAlarmDelegate : public QuicAlarm::Delegate {
  public:
   explicit PathDegradingAlarmDelegate(QuicConnection* connection)
       : connection_(connection) {}
+  PathDegradingAlarmDelegate(const PathDegradingAlarmDelegate&) = delete;
+  PathDegradingAlarmDelegate& operator=(const PathDegradingAlarmDelegate&) =
+      delete;
 
   void OnAlarm() override { connection_->OnPathDegradingTimeout(); }
 
  private:
   QuicConnection* connection_;
-
-  DISALLOW_COPY_AND_ASSIGN(PathDegradingAlarmDelegate);
 };
 
 class TimeoutAlarmDelegate : public QuicAlarm::Delegate {
  public:
   explicit TimeoutAlarmDelegate(QuicConnection* connection)
       : connection_(connection) {}
+  TimeoutAlarmDelegate(const TimeoutAlarmDelegate&) = delete;
+  TimeoutAlarmDelegate& operator=(const TimeoutAlarmDelegate&) = delete;
 
   void OnAlarm() override { connection_->CheckForTimeout(); }
 
  private:
   QuicConnection* connection_;
-
-  DISALLOW_COPY_AND_ASSIGN(TimeoutAlarmDelegate);
 };
 
 class PingAlarmDelegate : public QuicAlarm::Delegate {
  public:
   explicit PingAlarmDelegate(QuicConnection* connection)
       : connection_(connection) {}
+  PingAlarmDelegate(const PingAlarmDelegate&) = delete;
+  PingAlarmDelegate& operator=(const PingAlarmDelegate&) = delete;
 
   void OnAlarm() override { connection_->OnPingTimeout(); }
 
  private:
   QuicConnection* connection_;
-
-  DISALLOW_COPY_AND_ASSIGN(PingAlarmDelegate);
 };
 
 class MtuDiscoveryAlarmDelegate : public QuicAlarm::Delegate {
  public:
   explicit MtuDiscoveryAlarmDelegate(QuicConnection* connection)
       : connection_(connection) {}
+  MtuDiscoveryAlarmDelegate(const MtuDiscoveryAlarmDelegate&) = delete;
+  MtuDiscoveryAlarmDelegate& operator=(const MtuDiscoveryAlarmDelegate&) =
+      delete;
 
   void OnAlarm() override { connection_->DiscoverMtu(); }
 
  private:
   QuicConnection* connection_;
-
-  DISALLOW_COPY_AND_ASSIGN(MtuDiscoveryAlarmDelegate);
 };
 
 class RetransmittableOnWireAlarmDelegate : public QuicAlarm::Delegate {
  public:
   explicit RetransmittableOnWireAlarmDelegate(QuicConnection* connection)
       : connection_(connection) {}
+  RetransmittableOnWireAlarmDelegate(
+      const RetransmittableOnWireAlarmDelegate&) = delete;
+  RetransmittableOnWireAlarmDelegate& operator=(
+      const RetransmittableOnWireAlarmDelegate&) = delete;
 
   void OnAlarm() override { connection_->OnPingTimeout(); }
 
  private:
   QuicConnection* connection_;
-
-  DISALLOW_COPY_AND_ASSIGN(RetransmittableOnWireAlarmDelegate);
 };
 
 }  // namespace
diff --git a/net/third_party/quic/core/quic_connection.h b/net/third_party/quic/core/quic_connection.h
index a3ab651c..a0d370b 100644
--- a/net/third_party/quic/core/quic_connection.h
+++ b/net/third_party/quic/core/quic_connection.h
@@ -337,6 +337,8 @@
                  bool owns_writer,
                  Perspective perspective,
                  const ParsedQuicVersionVector& supported_versions);
+  QuicConnection(const QuicConnection&) = delete;
+  QuicConnection& operator=(const QuicConnection&) = delete;
   ~QuicConnection() override;
 
   // Sets connection parameters from the supplied |config|.
@@ -1295,8 +1297,6 @@
 
   // Latched value of quic_reloadable_flag_quic_retransmissions_app_limited.
   const bool retransmissions_app_limited_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicConnection);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_connection_test.cc b/net/third_party/quic/core/quic_connection_test.cc
index 714f521a..08b3417 100644
--- a/net/third_party/quic/core/quic_connection_test.cc
+++ b/net/third_party/quic/core/quic_connection_test.cc
@@ -91,6 +91,8 @@
 class TaggingEncrypter : public QuicEncrypter {
  public:
   explicit TaggingEncrypter(uint8_t tag) : tag_(tag) {}
+  TaggingEncrypter(const TaggingEncrypter&) = delete;
+  TaggingEncrypter& operator=(const TaggingEncrypter&) = delete;
 
   ~TaggingEncrypter() override {}
 
@@ -142,8 +144,6 @@
   };
 
   const uint8_t tag_;
-
-  DISALLOW_COPY_AND_ASSIGN(TaggingEncrypter);
 };
 
 // TaggingDecrypter ensures that the final kTagSize bytes of the message all
@@ -237,6 +237,8 @@
       : clock_(clock), random_generator_(random_generator) {
     clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
   }
+  TestConnectionHelper(const TestConnectionHelper&) = delete;
+  TestConnectionHelper& operator=(const TestConnectionHelper&) = delete;
 
   // QuicConnectionHelperInterface
   const QuicClock* GetClock() const override { return clock_; }
@@ -251,8 +253,6 @@
   MockClock* clock_;
   MockRandom* random_generator_;
   SimpleBufferAllocator buffer_allocator_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestConnectionHelper);
 };
 
 class TestAlarmFactory : public QuicAlarmFactory {
@@ -268,6 +268,8 @@
   };
 
   TestAlarmFactory() {}
+  TestAlarmFactory(const TestAlarmFactory&) = delete;
+  TestAlarmFactory& operator=(const TestAlarmFactory&) = delete;
 
   QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override {
     return new TestAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate>(delegate));
@@ -278,9 +280,6 @@
       QuicConnectionArena* arena) override {
     return arena->New<TestAlarm>(std::move(delegate));
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestAlarmFactory);
 };
 
 class TestPacketWriter : public QuicPacketWriter {
@@ -302,6 +301,8 @@
         clock_(clock),
         write_pause_time_delta_(QuicTime::Delta::Zero()),
         max_packet_size_(kMaxPacketSize) {}
+  TestPacketWriter(const TestPacketWriter&) = delete;
+  TestPacketWriter& operator=(const TestPacketWriter&) = delete;
 
   // QuicPacketWriter interface
   WriteResult WritePacket(const char* buffer,
@@ -492,8 +493,6 @@
   // time.
   QuicTime::Delta write_pause_time_delta_;
   QuicByteCount max_packet_size_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestPacketWriter);
 };
 
 class TestConnection : public QuicConnection {
@@ -519,6 +518,8 @@
                  QuicMakeUnique<NullEncrypter>(perspective));
     SetDataProducer(&producer_);
   }
+  TestConnection(const TestConnection&) = delete;
+  TestConnection& operator=(const TestConnection&) = delete;
 
   void SendAck() { QuicConnectionPeer::SendAck(this); }
 
@@ -713,8 +714,6 @@
   SimpleSessionNotifier* notifier_;
 
   std::unique_ptr<QuicSocketAddress> next_effective_peer_addr_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestConnection);
 };
 
 enum class AckResponse { kDefer, kImmediate };
@@ -851,6 +850,9 @@
         .Times(AnyNumber());
   }
 
+  QuicConnectionTest(const QuicConnectionTest&) = delete;
+  QuicConnectionTest& operator=(const QuicConnectionTest&) = delete;
+
   ParsedQuicVersion version() { return GetParam().version; }
 
   QuicAckFrame* outgoing_ack() {
@@ -1245,9 +1247,6 @@
   QuicConnectionIdLength connection_id_length_;
 
   SimpleSessionNotifier notifier_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicConnectionTest);
 };
 
 // Run all end to end tests with all supported versions.
diff --git a/net/third_party/quic/core/quic_crypto_client_handshaker.h b/net/third_party/quic/core/quic_crypto_client_handshaker.h
index c2859860c..a7cbb61 100644
--- a/net/third_party/quic/core/quic_crypto_client_handshaker.h
+++ b/net/third_party/quic/core/quic_crypto_client_handshaker.h
@@ -32,6 +32,9 @@
       std::unique_ptr<ProofVerifyContext> verify_context,
       QuicCryptoClientConfig* crypto_config,
       QuicCryptoClientStream::ProofHandler* proof_handler);
+  QuicCryptoClientHandshaker(const QuicCryptoClientHandshaker&) = delete;
+  QuicCryptoClientHandshaker& operator=(const QuicCryptoClientHandshaker&) =
+      delete;
 
   ~QuicCryptoClientHandshaker() override;
 
@@ -233,8 +236,6 @@
   bool handshake_confirmed_;
   QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
       crypto_negotiated_params_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientHandshaker);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_crypto_client_stream.h b/net/third_party/quic/core/quic_crypto_client_stream.h
index 5bb85ce..b04047de8 100644
--- a/net/third_party/quic/core/quic_crypto_client_stream.h
+++ b/net/third_party/quic/core/quic_crypto_client_stream.h
@@ -134,6 +134,8 @@
                          std::unique_ptr<ProofVerifyContext> verify_context,
                          QuicCryptoClientConfig* crypto_config,
                          ProofHandler* proof_handler);
+  QuicCryptoClientStream(const QuicCryptoClientStream&) = delete;
+  QuicCryptoClientStream& operator=(const QuicCryptoClientStream&) = delete;
 
   ~QuicCryptoClientStream() override;
 
@@ -162,8 +164,6 @@
 
  private:
   std::unique_ptr<HandshakerDelegate> handshaker_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientStream);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_crypto_handshaker.h b/net/third_party/quic/core/quic_crypto_handshaker.h
index a88235fc..e5d139c 100644
--- a/net/third_party/quic/core/quic_crypto_handshaker.h
+++ b/net/third_party/quic/core/quic_crypto_handshaker.h
@@ -14,6 +14,8 @@
     : public CryptoFramerVisitorInterface {
  public:
   QuicCryptoHandshaker(QuicCryptoStream* stream, QuicSession* session);
+  QuicCryptoHandshaker(const QuicCryptoHandshaker&) = delete;
+  QuicCryptoHandshaker& operator=(const QuicCryptoHandshaker&) = delete;
 
   ~QuicCryptoHandshaker() override;
 
@@ -41,8 +43,6 @@
 
   // Records last sent crypto handshake message tag.
   QuicTag last_sent_handshake_message_tag_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoHandshaker);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_crypto_server_handshaker.h b/net/third_party/quic/core/quic_crypto_server_handshaker.h
index 3562a92..17a3be6d 100644
--- a/net/third_party/quic/core/quic_crypto_server_handshaker.h
+++ b/net/third_party/quic/core/quic_crypto_server_handshaker.h
@@ -31,6 +31,9 @@
                              QuicCompressedCertsCache* compressed_certs_cache,
                              QuicSession* session,
                              QuicCryptoServerStream::Helper* helper);
+  QuicCryptoServerHandshaker(const QuicCryptoServerHandshaker&) = delete;
+  QuicCryptoServerHandshaker& operator=(const QuicCryptoServerHandshaker&) =
+      delete;
 
   ~QuicCryptoServerHandshaker() override;
 
@@ -79,6 +82,8 @@
   class ValidateCallback : public ValidateClientHelloResultCallback {
    public:
     explicit ValidateCallback(QuicCryptoServerHandshaker* parent);
+    ValidateCallback(const ValidateCallback&) = delete;
+    ValidateCallback& operator=(const ValidateCallback&) = delete;
     // To allow the parent to detach itself from the callback before deletion.
     void Cancel();
 
@@ -88,8 +93,6 @@
 
    private:
     QuicCryptoServerHandshaker* parent_;
-
-    DISALLOW_COPY_AND_ASSIGN(ValidateCallback);
   };
 
   class SendServerConfigUpdateCallback
@@ -221,8 +224,6 @@
   bool handshake_confirmed_;
   QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
       crypto_negotiated_params_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerHandshaker);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_crypto_server_stream.h b/net/third_party/quic/core/quic_crypto_server_stream.h
index 5626f25..1e49e48 100644
--- a/net/third_party/quic/core/quic_crypto_server_stream.h
+++ b/net/third_party/quic/core/quic_crypto_server_stream.h
@@ -161,6 +161,8 @@
                          bool use_stateless_rejects_if_peer_supported,
                          QuicSession* session,
                          Helper* helper);
+  QuicCryptoServerStream(const QuicCryptoServerStream&) = delete;
+  QuicCryptoServerStream& operator=(const QuicCryptoServerStream&) = delete;
 
   ~QuicCryptoServerStream() override;
 
@@ -220,8 +222,6 @@
   const QuicCryptoServerConfig* crypto_config_;
   QuicCompressedCertsCache* compressed_certs_cache_;
   Helper* helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoServerStream);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_crypto_stream.h b/net/third_party/quic/core/quic_crypto_stream.h
index 850502b..1d6a023f 100644
--- a/net/third_party/quic/core/quic_crypto_stream.h
+++ b/net/third_party/quic/core/quic_crypto_stream.h
@@ -34,6 +34,8 @@
 class QUIC_EXPORT_PRIVATE QuicCryptoStream : public QuicStream {
  public:
   explicit QuicCryptoStream(QuicSession* session);
+  QuicCryptoStream(const QuicCryptoStream&) = delete;
+  QuicCryptoStream& operator=(const QuicCryptoStream&) = delete;
 
   ~QuicCryptoStream() override;
 
@@ -108,8 +110,6 @@
   // TODO(fayang): This is not needed once switching from QUIC crypto to
   // TLS 1.3, which never encrypts crypto data.
   QuicIntervalSet<QuicStreamOffset> bytes_consumed_[NUM_ENCRYPTION_LEVELS];
-
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoStream);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_crypto_stream_test.cc b/net/third_party/quic/core/quic_crypto_stream_test.cc
index aa13037..a070950 100644
--- a/net/third_party/quic/core/quic_crypto_stream_test.cc
+++ b/net/third_party/quic/core/quic_crypto_stream_test.cc
@@ -34,6 +34,8 @@
       : QuicCryptoStream(session),
         QuicCryptoHandshaker(this, session),
         params_(new QuicCryptoNegotiatedParameters) {}
+  MockQuicCryptoStream(const MockQuicCryptoStream&) = delete;
+  MockQuicCryptoStream& operator=(const MockQuicCryptoStream&) = delete;
 
   void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
     messages_.push_back(message);
@@ -60,8 +62,6 @@
  private:
   QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
   std::vector<CryptoHandshakeMessage> messages_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoStream);
 };
 
 class QuicCryptoStreamTest : public QuicTest {
@@ -79,6 +79,8 @@
     message_.SetStringPiece(2, "def");
     ConstructHandshakeMessage(Perspective::IS_SERVER);
   }
+  QuicCryptoStreamTest(const QuicCryptoStreamTest&) = delete;
+  QuicCryptoStreamTest& operator=(const QuicCryptoStreamTest&) = delete;
 
   void ConstructHandshakeMessage(Perspective perspective) {
     CryptoFramer framer;
@@ -94,9 +96,6 @@
   MockQuicCryptoStream* stream_;
   CryptoHandshakeMessage message_;
   std::unique_ptr<QuicData> message_data_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicCryptoStreamTest);
 };
 
 TEST_F(QuicCryptoStreamTest, NotInitiallyConected) {
diff --git a/net/third_party/quic/core/quic_data_reader.h b/net/third_party/quic/core/quic_data_reader.h
index 256ed1b..81eaba1 100644
--- a/net/third_party/quic/core/quic_data_reader.h
+++ b/net/third_party/quic/core/quic_data_reader.h
@@ -34,6 +34,8 @@
  public:
   // Caller must provide an underlying buffer to work on.
   QuicDataReader(const char* data, const size_t len, Endianness endianness);
+  QuicDataReader(const QuicDataReader&) = delete;
+  QuicDataReader& operator=(const QuicDataReader&) = delete;
 
   // Empty destructor.
   ~QuicDataReader() {}
@@ -159,8 +161,6 @@
 
   // The endianness to read integers and floating numbers.
   Endianness endianness_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicDataReader);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_data_writer.h b/net/third_party/quic/core/quic_data_writer.h
index 98dbc68..7d7faaa1 100644
--- a/net/third_party/quic/core/quic_data_writer.h
+++ b/net/third_party/quic/core/quic_data_writer.h
@@ -38,6 +38,8 @@
  public:
   // Creates a QuicDataWriter where |buffer| is not owned.
   QuicDataWriter(size_t size, char* buffer, Endianness endianness);
+  QuicDataWriter(const QuicDataWriter&) = delete;
+  QuicDataWriter& operator=(const QuicDataWriter&) = delete;
 
   ~QuicDataWriter();
 
@@ -127,8 +129,6 @@
 
   // The endianness to write integers and floating numbers.
   Endianness endianness_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicDataWriter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_default_packet_writer.h b/net/third_party/quic/core/quic_default_packet_writer.h
index b72daa1..3500f91 100644
--- a/net/third_party/quic/core/quic_default_packet_writer.h
+++ b/net/third_party/quic/core/quic_default_packet_writer.h
@@ -20,6 +20,8 @@
 class QUIC_EXPORT_PRIVATE QuicDefaultPacketWriter : public QuicPacketWriter {
  public:
   explicit QuicDefaultPacketWriter(int fd);
+  QuicDefaultPacketWriter(const QuicDefaultPacketWriter&) = delete;
+  QuicDefaultPacketWriter& operator=(const QuicDefaultPacketWriter&) = delete;
   ~QuicDefaultPacketWriter() override;
 
   // QuicPacketWriter
@@ -47,8 +49,6 @@
  private:
   int fd_;
   bool write_blocked_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicDefaultPacketWriter);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_dispatcher.cc b/net/third_party/quic/core/quic_dispatcher.cc
index b863b78..79430b88 100644
--- a/net/third_party/quic/core/quic_dispatcher.cc
+++ b/net/third_party/quic/core/quic_dispatcher.cc
@@ -35,14 +35,14 @@
  public:
   explicit DeleteSessionsAlarm(QuicDispatcher* dispatcher)
       : dispatcher_(dispatcher) {}
+  DeleteSessionsAlarm(const DeleteSessionsAlarm&) = delete;
+  DeleteSessionsAlarm& operator=(const DeleteSessionsAlarm&) = delete;
 
   void OnAlarm() override { dispatcher_->DeleteSessions(); }
 
  private:
   // Not owned.
   QuicDispatcher* dispatcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(DeleteSessionsAlarm);
 };
 
 // Collects packets serialized by a QuicPacketCreator in order
diff --git a/net/third_party/quic/core/quic_dispatcher.h b/net/third_party/quic/core/quic_dispatcher.h
index 2b5402a..61c6392 100644
--- a/net/third_party/quic/core/quic_dispatcher.h
+++ b/net/third_party/quic/core/quic_dispatcher.h
@@ -50,6 +50,8 @@
                  std::unique_ptr<QuicConnectionHelperInterface> helper,
                  std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
                  std::unique_ptr<QuicAlarmFactory> alarm_factory);
+  QuicDispatcher(const QuicDispatcher&) = delete;
+  QuicDispatcher& operator=(const QuicDispatcher&) = delete;
 
   ~QuicDispatcher() override;
 
@@ -446,8 +448,6 @@
 
   // True if this dispatcher is not draining.
   bool accept_new_connections_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicDispatcher);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_dispatcher_test.cc b/net/third_party/quic/core/quic_dispatcher_test.cc
index 2f9e3d1..2bbdf16 100644
--- a/net/third_party/quic/core/quic_dispatcher_test.cc
+++ b/net/third_party/quic/core/quic_dispatcher_test.cc
@@ -65,6 +65,9 @@
                               crypto_config,
                               compressed_certs_cache),
         crypto_stream_(QuicServerSessionBase::GetMutableCryptoStream()) {}
+  TestQuicSpdyServerSession(const TestQuicSpdyServerSession&) = delete;
+  TestQuicSpdyServerSession& operator=(const TestQuicSpdyServerSession&) =
+      delete;
 
   ~TestQuicSpdyServerSession() override { delete connection(); };
 
@@ -102,8 +105,6 @@
 
  private:
   QuicCryptoServerStreamBase* crypto_stream_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestQuicSpdyServerSession);
 };
 
 class TestDispatcher : public QuicDispatcher {
@@ -805,6 +806,9 @@
             session,
             helper),
         handshake_confirmed_(false) {}
+  MockQuicCryptoServerStream(const MockQuicCryptoServerStream&) = delete;
+  MockQuicCryptoServerStream& operator=(const MockQuicCryptoServerStream&) =
+      delete;
 
   void set_handshake_confirmed_for_testing(bool handshake_confirmed) {
     handshake_confirmed_ = handshake_confirmed;
@@ -814,7 +818,6 @@
 
  private:
   bool handshake_confirmed_;
-  DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream);
 };
 
 struct StatelessRejectTestParams {
diff --git a/net/third_party/quic/core/quic_epoll_alarm_factory.h b/net/third_party/quic/core/quic_epoll_alarm_factory.h
index 87e8ccda..9fe432d 100644
--- a/net/third_party/quic/core/quic_epoll_alarm_factory.h
+++ b/net/third_party/quic/core/quic_epoll_alarm_factory.h
@@ -18,6 +18,8 @@
 class QuicEpollAlarmFactory : public QuicAlarmFactory {
  public:
   explicit QuicEpollAlarmFactory(net::EpollServer* epoll_server);
+  QuicEpollAlarmFactory(const QuicEpollAlarmFactory&) = delete;
+  QuicEpollAlarmFactory& operator=(const QuicEpollAlarmFactory&) = delete;
   ~QuicEpollAlarmFactory() override;
 
   // QuicAlarmFactory interface.
@@ -28,8 +30,6 @@
 
  private:
   net::EpollServer* epoll_server_;  // Not owned.
-
-  DISALLOW_COPY_AND_ASSIGN(QuicEpollAlarmFactory);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_epoll_connection_helper.h b/net/third_party/quic/core/quic_epoll_connection_helper.h
index f55be65..d996e08 100644
--- a/net/third_party/quic/core/quic_epoll_connection_helper.h
+++ b/net/third_party/quic/core/quic_epoll_connection_helper.h
@@ -34,6 +34,9 @@
 class QuicEpollConnectionHelper : public QuicConnectionHelperInterface {
  public:
   QuicEpollConnectionHelper(net::EpollServer* eps, QuicAllocator allocator);
+  QuicEpollConnectionHelper(const QuicEpollConnectionHelper&) = delete;
+  QuicEpollConnectionHelper& operator=(const QuicEpollConnectionHelper&) =
+      delete;
   ~QuicEpollConnectionHelper() override;
 
   // QuicEpollConnectionHelperInterface
@@ -51,8 +54,6 @@
   QuicStreamBufferAllocator stream_buffer_allocator_;
   SimpleBufferAllocator simple_buffer_allocator_;
   QuicAllocator allocator_type_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicEpollConnectionHelper);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_flow_controller.h b/net/third_party/quic/core/quic_flow_controller.h
index 6092f42..fc5deab 100644
--- a/net/third_party/quic/core/quic_flow_controller.h
+++ b/net/third_party/quic/core/quic_flow_controller.h
@@ -48,6 +48,8 @@
                      QuicStreamOffset receive_window_offset,
                      bool should_auto_tune_receive_window,
                      QuicFlowControllerInterface* session_flow_controller);
+  QuicFlowController(const QuicFlowController&) = delete;
+  QuicFlowController& operator=(const QuicFlowController&) = delete;
 
   ~QuicFlowController() override {}
 
@@ -195,8 +197,6 @@
   // Keep time of the last time a window update was sent.  We use this
   // as part of the receive window auto tuning.
   QuicTime prev_window_update_time_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicFlowController);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_flow_controller_test.cc b/net/third_party/quic/core/quic_flow_controller_test.cc
index b4a201b9..b59fac99 100644
--- a/net/third_party/quic/core/quic_flow_controller_test.cc
+++ b/net/third_party/quic/core/quic_flow_controller_test.cc
@@ -26,12 +26,11 @@
 class MockFlowController : public QuicFlowControllerInterface {
  public:
   MockFlowController() {}
+  MockFlowController(const MockFlowController&) = delete;
+  MockFlowController& operator=(const MockFlowController&) = delete;
   ~MockFlowController() override {}
 
   MOCK_METHOD1(EnsureWindowAtLeast, void(QuicByteCount));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockFlowController);
 };
 
 class QuicFlowControllerTest : public QuicTest {
diff --git a/net/third_party/quic/core/quic_framer.h b/net/third_party/quic/core/quic_framer.h
index 95420ef9..74dca318 100644
--- a/net/third_party/quic/core/quic_framer.h
+++ b/net/third_party/quic/core/quic_framer.h
@@ -195,6 +195,8 @@
   QuicFramer(const ParsedQuicVersionVector& supported_versions,
              QuicTime creation_time,
              Perspective perspective);
+  QuicFramer(const QuicFramer&) = delete;
+  QuicFramer& operator=(const QuicFramer&) = delete;
 
   virtual ~QuicFramer();
 
@@ -763,8 +765,6 @@
   // If not null, framer asks data_producer_ to write stream frame data. Not
   // owned. TODO(fayang): Consider add data producer to framer's constructor.
   QuicStreamFrameDataProducer* data_producer_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicFramer);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_one_block_arena.h b/net/third_party/quic/core/quic_one_block_arena.h
index 494331ee..c07c2cc 100644
--- a/net/third_party/quic/core/quic_one_block_arena.h
+++ b/net/third_party/quic/core/quic_one_block_arena.h
@@ -26,6 +26,8 @@
 
  public:
   QuicOneBlockArena();
+  QuicOneBlockArena(const QuicOneBlockArena&) = delete;
+  QuicOneBlockArena& operator=(const QuicOneBlockArena&) = delete;
 
   // Instantiates an object of type |T| with |args|. |args| are perfectly
   // forwarded to |T|'s constructor. The returned pointer's lifetime is
@@ -46,8 +48,6 @@
   QUIC_ALIGNED(8) char storage_[ArenaSize];
   // Current offset into the storage.
   uint32_t offset_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicOneBlockArena);
 };
 
 template <uint32_t ArenaSize>
diff --git a/net/third_party/quic/core/quic_packet_creator.h b/net/third_party/quic/core/quic_packet_creator.h
index 22859e9..2e670a07 100644
--- a/net/third_party/quic/core/quic_packet_creator.h
+++ b/net/third_party/quic/core/quic_packet_creator.h
@@ -55,6 +55,8 @@
   QuicPacketCreator(QuicConnectionId connection_id,
                     QuicFramer* framer,
                     DelegateInterface* delegate);
+  QuicPacketCreator(const QuicPacketCreator&) = delete;
+  QuicPacketCreator& operator=(const QuicPacketCreator&) = delete;
 
   ~QuicPacketCreator();
 
@@ -328,8 +330,6 @@
   // If true, packet_'s transmission type is only set by
   // SetPacketTransmissionType and does not get cleared in ClearPacket.
   bool can_set_transmission_type_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicPacketCreator);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_packet_generator.h b/net/third_party/quic/core/quic_packet_generator.h
index 50a4077..44fb7eba 100644
--- a/net/third_party/quic/core/quic_packet_generator.h
+++ b/net/third_party/quic/core/quic_packet_generator.h
@@ -75,6 +75,8 @@
                       QuicFramer* framer,
                       QuicRandom* random_generator,
                       DelegateInterface* delegate);
+  QuicPacketGenerator(const QuicPacketGenerator&) = delete;
+  QuicPacketGenerator& operator=(const QuicPacketGenerator&) = delete;
 
   ~QuicPacketGenerator();
 
@@ -237,8 +239,6 @@
   QuicStopWaitingFrame pending_stop_waiting_frame_;
 
   QuicRandom* random_generator_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicPacketGenerator);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_packet_generator_test.cc b/net/third_party/quic/core/quic_packet_generator_test.cc
index 4b11b4c..721039d3 100644
--- a/net/third_party/quic/core/quic_packet_generator_test.cc
+++ b/net/third_party/quic/core/quic_packet_generator_test.cc
@@ -40,6 +40,8 @@
 class MockDelegate : public QuicPacketGenerator::DelegateInterface {
  public:
   MockDelegate() {}
+  MockDelegate(const MockDelegate&) = delete;
+  MockDelegate& operator=(const MockDelegate&) = delete;
   ~MockDelegate() override {}
 
   MOCK_METHOD2(ShouldGeneratePacket,
@@ -72,9 +74,6 @@
     EXPECT_CALL(*this, ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA, _))
         .WillRepeatedly(Return(true));
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockDelegate);
 };
 
 // Simple struct for describing the contents of a packet.
diff --git a/net/third_party/quic/core/quic_packet_reader.h b/net/third_party/quic/core/quic_packet_reader.h
index 5fb7abb..f1353379 100644
--- a/net/third_party/quic/core/quic_packet_reader.h
+++ b/net/third_party/quic/core/quic_packet_reader.h
@@ -31,6 +31,8 @@
 class QuicPacketReader {
  public:
   QuicPacketReader();
+  QuicPacketReader(const QuicPacketReader&) = delete;
+  QuicPacketReader& operator=(const QuicPacketReader&) = delete;
 
   virtual ~QuicPacketReader();
 
@@ -84,8 +86,6 @@
   PacketData packets_[kNumPacketsPerReadMmsgCall];
   mmsghdr mmsg_hdr_[kNumPacketsPerReadMmsgCall];
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(QuicPacketReader);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_packet_writer.h b/net/third_party/quic/core/quic_packet_writer.h
index 46e0860..0399a8b9a 100644
--- a/net/third_party/quic/core/quic_packet_writer.h
+++ b/net/third_party/quic/core/quic_packet_writer.h
@@ -28,9 +28,9 @@
 
  private:
   PerPacketOptions(PerPacketOptions&& other) = delete;
+  PerPacketOptions(const PerPacketOptions&) = delete;
+  PerPacketOptions& operator=(const PerPacketOptions&) = delete;
   PerPacketOptions& operator=(PerPacketOptions&& other) = delete;
-
-  DISALLOW_COPY_AND_ASSIGN(PerPacketOptions);
 };
 
 // An interface between writers and the entity managing the
diff --git a/net/third_party/quic/core/quic_packet_writer_wrapper.h b/net/third_party/quic/core/quic_packet_writer_wrapper.h
index 10820f5d..17a5b7b4 100644
--- a/net/third_party/quic/core/quic_packet_writer_wrapper.h
+++ b/net/third_party/quic/core/quic_packet_writer_wrapper.h
@@ -19,6 +19,8 @@
 class QuicPacketWriterWrapper : public QuicPacketWriter {
  public:
   QuicPacketWriterWrapper();
+  QuicPacketWriterWrapper(const QuicPacketWriterWrapper&) = delete;
+  QuicPacketWriterWrapper& operator=(const QuicPacketWriterWrapper&) = delete;
   ~QuicPacketWriterWrapper() override;
 
   // Default implementation of the QuicPacketWriter interface. Passes everything
@@ -53,8 +55,6 @@
 
   QuicPacketWriter* writer_ = nullptr;
   bool owns_writer_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicPacketWriterWrapper);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_packets.h b/net/third_party/quic/core/quic_packets.h
index 7b23cb0..e558340 100644
--- a/net/third_party/quic/core/quic_packets.h
+++ b/net/third_party/quic/core/quic_packets.h
@@ -127,6 +127,8 @@
  public:
   QuicData(const char* buffer, size_t length);
   QuicData(const char* buffer, size_t length, bool owns_buffer);
+  QuicData(const QuicData&) = delete;
+  QuicData& operator=(const QuicData&) = delete;
   virtual ~QuicData();
 
   QuicStringPiece AsStringPiece() const {
@@ -140,8 +142,6 @@
   const char* buffer_;
   size_t length_;
   bool owns_buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicData);
 };
 
 class QUIC_EXPORT_PRIVATE QuicPacket : public QuicData {
@@ -157,6 +157,8 @@
              bool includes_version,
              bool includes_diversification_nonce,
              QuicPacketNumberLength packet_number_length);
+  QuicPacket(const QuicPacket&) = delete;
+  QuicPacket& operator=(const QuicPacket&) = delete;
 
   QuicStringPiece AssociatedData(QuicTransportVersion version) const;
   QuicStringPiece Plaintext(QuicTransportVersion version) const;
@@ -170,14 +172,14 @@
   const bool includes_version_;
   const bool includes_diversification_nonce_;
   const QuicPacketNumberLength packet_number_length_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicPacket);
 };
 
 class QUIC_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData {
  public:
   QuicEncryptedPacket(const char* buffer, size_t length);
   QuicEncryptedPacket(const char* buffer, size_t length, bool owns_buffer);
+  QuicEncryptedPacket(const QuicEncryptedPacket&) = delete;
+  QuicEncryptedPacket& operator=(const QuicEncryptedPacket&) = delete;
 
   // Clones the packet into a new packet which owns the buffer.
   std::unique_ptr<QuicEncryptedPacket> Clone() const;
@@ -189,9 +191,6 @@
   QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
       std::ostream& os,
       const QuicEncryptedPacket& s);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicEncryptedPacket);
 };
 
 // A received encrypted QUIC packet, with a recorded time of receipt.
@@ -208,6 +207,8 @@
                      bool owns_buffer,
                      int ttl,
                      bool ttl_valid);
+  QuicReceivedPacket(const QuicReceivedPacket&) = delete;
+  QuicReceivedPacket& operator=(const QuicReceivedPacket&) = delete;
 
   // Clones the packet into a new packet which owns the buffer.
   std::unique_ptr<QuicReceivedPacket> Clone() const;
@@ -229,8 +230,6 @@
  private:
   const QuicTime receipt_time_;
   int ttl_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicReceivedPacket);
 };
 
 struct QUIC_EXPORT_PRIVATE SerializedPacket {
diff --git a/net/third_party/quic/core/quic_received_packet_manager.h b/net/third_party/quic/core/quic_received_packet_manager.h
index 7c615004..4438194 100644
--- a/net/third_party/quic/core/quic_received_packet_manager.h
+++ b/net/third_party/quic/core/quic_received_packet_manager.h
@@ -23,6 +23,9 @@
 class QUIC_EXPORT_PRIVATE QuicReceivedPacketManager {
  public:
   explicit QuicReceivedPacketManager(QuicConnectionStats* stats);
+  QuicReceivedPacketManager(const QuicReceivedPacketManager&) = delete;
+  QuicReceivedPacketManager& operator=(const QuicReceivedPacketManager&) =
+      delete;
   virtual ~QuicReceivedPacketManager();
 
   // Updates the internal state concerning which packets have been received.
@@ -92,8 +95,6 @@
   QuicTime time_largest_observed_;
 
   QuicConnectionStats* stats_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicReceivedPacketManager);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_sent_packet_manager.h b/net/third_party/quic/core/quic_sent_packet_manager.h
index ef8e796..85e7b48 100644
--- a/net/third_party/quic/core/quic_sent_packet_manager.h
+++ b/net/third_party/quic/core/quic_sent_packet_manager.h
@@ -89,6 +89,8 @@
                         QuicConnectionStats* stats,
                         CongestionControlType congestion_control_type,
                         LossDetectionType loss_type);
+  QuicSentPacketManager(const QuicSentPacketManager&) = delete;
+  QuicSentPacketManager& operator=(const QuicSentPacketManager&) = delete;
   virtual ~QuicSentPacketManager();
 
   virtual void SetFromConfig(const QuicConfig& config);
@@ -551,8 +553,6 @@
   // A reverse iterator of last_ack_frame_.packets. This is reset in
   // OnAckRangeStart, and gradually moves in OnAckRange..
   PacketNumberQueue::const_reverse_iterator acked_packets_iter_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSentPacketManager);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_session.h b/net/third_party/quic/core/quic_session.h
index ce9f92db..b5093e6e 100644
--- a/net/third_party/quic/core/quic_session.h
+++ b/net/third_party/quic/core/quic_session.h
@@ -82,6 +82,8 @@
   QuicSession(QuicConnection* connection,
               Visitor* owner,
               const QuicConfig& config);
+  QuicSession(const QuicSession&) = delete;
+  QuicSession& operator=(const QuicSession&) = delete;
 
   ~QuicSession() override;
 
@@ -551,8 +553,6 @@
   // is not used here.
   // List of streams with pending retransmissions.
   QuicLinkedHashMap<QuicStreamId, bool> streams_with_pending_retransmission_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSession);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_socket_address_coder.h b/net/third_party/quic/core/quic_socket_address_coder.h
index 6894079d..dbb84ad 100644
--- a/net/third_party/quic/core/quic_socket_address_coder.h
+++ b/net/third_party/quic/core/quic_socket_address_coder.h
@@ -21,6 +21,8 @@
  public:
   QuicSocketAddressCoder();
   explicit QuicSocketAddressCoder(const QuicSocketAddress& address);
+  QuicSocketAddressCoder(const QuicSocketAddressCoder&) = delete;
+  QuicSocketAddressCoder& operator=(const QuicSocketAddressCoder&) = delete;
   ~QuicSocketAddressCoder();
 
   QuicString Encode() const;
@@ -33,8 +35,6 @@
 
  private:
   QuicSocketAddress address_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSocketAddressCoder);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_spdy_server_stream_base.h b/net/third_party/quic/core/quic_spdy_server_stream_base.h
deleted file mode 100644
index 74c7fa4..0000000
--- a/net/third_party/quic/core/quic_spdy_server_stream_base.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_SERVER_STREAM_BASE_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_SERVER_STREAM_BASE_H_
-
-#include "net/third_party/quic/core/quic_spdy_stream.h"
-
-namespace quic {
-
-class QuicSpdyServerStreamBase : public QuicSpdyStream {
- public:
-  QuicSpdyServerStreamBase(QuicStreamId id, QuicSpdySession* session);
-
-  // Override the base class to send QUIC_STREAM_NO_ERROR to the peer
-  // when the stream has not received all the data.
-  void CloseWriteSide() override;
-  void StopReading() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicSpdyServerStreamBase);
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_SPDY_SERVER_STREAM_BASE_H_
diff --git a/net/third_party/quic/core/quic_stream.h b/net/third_party/quic/core/quic_stream.h
index 75e0d17..daa5ff49 100644
--- a/net/third_party/quic/core/quic_stream.h
+++ b/net/third_party/quic/core/quic_stream.h
@@ -59,6 +59,8 @@
   // |is_static| is true, then the stream will be given precedence
   // over other streams when determing what streams should write next.
   QuicStream(QuicStreamId id, QuicSession* session, bool is_static);
+  QuicStream(const QuicStream&) = delete;
+  QuicStream& operator=(const QuicStream&) = delete;
 
   virtual ~QuicStream();
 
@@ -433,8 +435,6 @@
   // If true, then this stream has precedence over other streams for write
   // scheduling.
   const bool is_static_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicStream);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_stream_sequencer.h b/net/third_party/quic/core/quic_stream_sequencer.h
index e93d11b..f536f45a 100644
--- a/net/third_party/quic/core/quic_stream_sequencer.h
+++ b/net/third_party/quic/core/quic_stream_sequencer.h
@@ -27,6 +27,8 @@
 class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
  public:
   explicit QuicStreamSequencer(QuicStream* quic_stream);
+  QuicStreamSequencer(const QuicStreamSequencer&) = delete;
+  QuicStreamSequencer& operator=(const QuicStreamSequencer&) = delete;
   virtual ~QuicStreamSequencer();
 
   // If the frame is the next one we need in order to process in-order data,
@@ -152,8 +154,6 @@
   // If false, only call OnDataAvailable() when it becomes newly unblocked.
   // Otherwise, call OnDataAvailable() when number of readable bytes changes.
   bool level_triggered_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicStreamSequencer);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_stream_sequencer_buffer.h b/net/third_party/quic/core/quic_stream_sequencer_buffer.h
index e76be81..45368dd 100644
--- a/net/third_party/quic/core/quic_stream_sequencer_buffer.h
+++ b/net/third_party/quic/core/quic_stream_sequencer_buffer.h
@@ -88,6 +88,9 @@
   };
 
   explicit QuicStreamSequencerBuffer(size_t max_capacity_bytes);
+  QuicStreamSequencerBuffer(const QuicStreamSequencerBuffer&) = delete;
+  QuicStreamSequencerBuffer& operator=(const QuicStreamSequencerBuffer&) =
+      delete;
   ~QuicStreamSequencerBuffer();
 
   // Free the space used to buffer data.
@@ -225,8 +228,6 @@
 
   // Currently received data.
   QuicIntervalSet<QuicStreamOffset> bytes_received_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicStreamSequencerBuffer);
 };
 }  // namespace quic
 
diff --git a/net/third_party/quic/core/quic_sustained_bandwidth_recorder.h b/net/third_party/quic/core/quic_sustained_bandwidth_recorder.h
index 73baa1d0..123d193 100644
--- a/net/third_party/quic/core/quic_sustained_bandwidth_recorder.h
+++ b/net/third_party/quic/core/quic_sustained_bandwidth_recorder.h
@@ -26,6 +26,10 @@
 class QUIC_EXPORT_PRIVATE QuicSustainedBandwidthRecorder {
  public:
   QuicSustainedBandwidthRecorder();
+  QuicSustainedBandwidthRecorder(const QuicSustainedBandwidthRecorder&) =
+      delete;
+  QuicSustainedBandwidthRecorder& operator=(
+      const QuicSustainedBandwidthRecorder&) = delete;
 
   // As long as |in_recovery| is consistently false, multiple calls to this
   // method over a 3 * srtt period results in storage of a valid sustained
@@ -85,8 +89,6 @@
 
   // Timestamp marking the beginning of the latest recording period.
   QuicTime start_time_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSustainedBandwidthRecorder);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_time_wait_list_manager.cc b/net/third_party/quic/core/quic_time_wait_list_manager.cc
index 95bbecf..00aa6d5 100644
--- a/net/third_party/quic/core/quic_time_wait_list_manager.cc
+++ b/net/third_party/quic/core/quic_time_wait_list_manager.cc
@@ -32,6 +32,8 @@
   explicit ConnectionIdCleanUpAlarm(
       QuicTimeWaitListManager* time_wait_list_manager)
       : time_wait_list_manager_(time_wait_list_manager) {}
+  ConnectionIdCleanUpAlarm(const ConnectionIdCleanUpAlarm&) = delete;
+  ConnectionIdCleanUpAlarm& operator=(const ConnectionIdCleanUpAlarm&) = delete;
 
   void OnAlarm() override {
     time_wait_list_manager_->CleanUpOldConnectionIds();
@@ -40,8 +42,6 @@
  private:
   // Not owned.
   QuicTimeWaitListManager* time_wait_list_manager_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConnectionIdCleanUpAlarm);
 };
 
 // This class stores pending public reset packets to be sent to clients.
@@ -59,6 +59,8 @@
       : server_address_(server_address),
         client_address_(client_address),
         packet_(std::move(packet)) {}
+  QueuedPacket(const QueuedPacket&) = delete;
+  QueuedPacket& operator=(const QueuedPacket&) = delete;
 
   const QuicSocketAddress& server_address() const { return server_address_; }
   const QuicSocketAddress& client_address() const { return client_address_; }
@@ -68,8 +70,6 @@
   const QuicSocketAddress server_address_;
   const QuicSocketAddress client_address_;
   std::unique_ptr<QuicEncryptedPacket> packet_;
-
-  DISALLOW_COPY_AND_ASSIGN(QueuedPacket);
 };
 
 QuicTimeWaitListManager::QuicTimeWaitListManager(
diff --git a/net/third_party/quic/core/quic_time_wait_list_manager.h b/net/third_party/quic/core/quic_time_wait_list_manager.h
index bae6a2c..45f559f 100644
--- a/net/third_party/quic/core/quic_time_wait_list_manager.h
+++ b/net/third_party/quic/core/quic_time_wait_list_manager.h
@@ -66,6 +66,8 @@
                           Visitor* visitor,
                           const QuicClock* clock,
                           QuicAlarmFactory* alarm_factory);
+  QuicTimeWaitListManager(const QuicTimeWaitListManager&) = delete;
+  QuicTimeWaitListManager& operator=(const QuicTimeWaitListManager&) = delete;
   ~QuicTimeWaitListManager() override;
 
   // Adds the given connection_id to time wait state for time_wait_period_.
@@ -215,8 +217,6 @@
 
   // Interface that manages blocked writers.
   Visitor* visitor_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicTimeWaitListManager);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_unacked_packet_map.h b/net/third_party/quic/core/quic_unacked_packet_map.h
index ef14e46..656fbca 100644
--- a/net/third_party/quic/core/quic_unacked_packet_map.h
+++ b/net/third_party/quic/core/quic_unacked_packet_map.h
@@ -23,6 +23,8 @@
 class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
  public:
   QuicUnackedPacketMap();
+  QuicUnackedPacketMap(const QuicUnackedPacketMap&) = delete;
+  QuicUnackedPacketMap& operator=(const QuicUnackedPacketMap&) = delete;
   ~QuicUnackedPacketMap();
 
   // Adds |serialized_packet| to the map and marks it as sent at |sent_time|.
@@ -231,8 +233,6 @@
 
   // If true, let session decides what to write.
   bool session_decides_what_to_write_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicUnackedPacketMap);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_utils.h b/net/third_party/quic/core/quic_utils.h
index 5038faf..ba539a8 100644
--- a/net/third_party/quic/core/quic_utils.h
+++ b/net/third_party/quic/core/quic_utils.h
@@ -22,6 +22,8 @@
 
 class QUIC_EXPORT_PRIVATE QuicUtils {
  public:
+  QuicUtils() = delete;
+
   // Returns the 64 bit FNV1a hash of the data.  See
   // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
   static uint64_t FNV1a_64_Hash(QuicStringPiece data);
@@ -87,9 +89,6 @@
   // Returns true if header with |first_byte| is considered as an IETF QUIC
   // packet header.
   static bool IsIetfPacketHeader(uint8_t first_byte);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicUtils);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_write_blocked_list.h b/net/third_party/quic/core/quic_write_blocked_list.h
index 793f8a1..d592123b 100644
--- a/net/third_party/quic/core/quic_write_blocked_list.h
+++ b/net/third_party/quic/core/quic_write_blocked_list.h
@@ -25,6 +25,8 @@
 
  public:
   explicit QuicWriteBlockedList();
+  QuicWriteBlockedList(const QuicWriteBlockedList&) = delete;
+  QuicWriteBlockedList& operator=(const QuicWriteBlockedList&) = delete;
   ~QuicWriteBlockedList();
 
   bool HasWriteBlockedDataStreams() const {
@@ -340,8 +342,6 @@
 
   // Latched value of quic_use_static_stream_collection_in_write_blocked_list.
   const bool use_static_stream_collection_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicWriteBlockedList);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/stateless_rejector.h b/net/third_party/quic/core/stateless_rejector.h
index 925d63f..6904bb8 100644
--- a/net/third_party/quic/core/stateless_rejector.h
+++ b/net/third_party/quic/core/stateless_rejector.h
@@ -33,6 +33,8 @@
                     QuicByteCount chlo_packet_size,
                     const QuicSocketAddress& client_address,
                     const QuicSocketAddress& server_address);
+  StatelessRejector(const StatelessRejector&) = delete;
+  StatelessRejector& operator=(const StatelessRejector&) = delete;
 
   ~StatelessRejector();
 
@@ -110,8 +112,6 @@
   CryptoFramer crypto_framer_;
   QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
   QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
-
-  DISALLOW_COPY_AND_ASSIGN(StatelessRejector);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/tls_client_handshaker.h b/net/third_party/quic/core/tls_client_handshaker.h
index c950b59..9a51d432 100644
--- a/net/third_party/quic/core/tls_client_handshaker.h
+++ b/net/third_party/quic/core/tls_client_handshaker.h
@@ -29,6 +29,8 @@
                       SSL_CTX* ssl_ctx,
                       std::unique_ptr<ProofVerifyContext> verify_context,
                       const QuicString& user_agent_id);
+  TlsClientHandshaker(const TlsClientHandshaker&) = delete;
+  TlsClientHandshaker& operator=(const TlsClientHandshaker&) = delete;
 
   ~TlsClientHandshaker() override;
 
@@ -119,8 +121,6 @@
   bool handshake_confirmed_ = false;
   QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
       crypto_negotiated_params_;
-
-  DISALLOW_COPY_AND_ASSIGN(TlsClientHandshaker);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/tls_handshaker.cc b/net/third_party/quic/core/tls_handshaker.cc
index 08f105e..ad4f1838 100644
--- a/net/third_party/quic/core/tls_handshaker.cc
+++ b/net/third_party/quic/core/tls_handshaker.cc
@@ -38,11 +38,12 @@
     CHECK_LE(0, ssl_ex_data_index_handshaker_);
   }
 
+  SslIndexSingleton(const SslIndexSingleton&) = delete;
+  SslIndexSingleton& operator=(const SslIndexSingleton&) = delete;
+
   friend QuicSingletonFriend<SslIndexSingleton>;
 
   int ssl_ex_data_index_handshaker_;
-
-  DISALLOW_COPY_AND_ASSIGN(SslIndexSingleton);
 };
 
 }  // namespace
diff --git a/net/third_party/quic/core/tls_handshaker.h b/net/third_party/quic/core/tls_handshaker.h
index d6fdea4..4975a11 100644
--- a/net/third_party/quic/core/tls_handshaker.h
+++ b/net/third_party/quic/core/tls_handshaker.h
@@ -28,6 +28,8 @@
   TlsHandshaker(QuicCryptoStream* stream,
                 QuicSession* session,
                 SSL_CTX* ssl_ctx);
+  TlsHandshaker(const TlsHandshaker&) = delete;
+  TlsHandshaker& operator=(const TlsHandshaker&) = delete;
 
   ~TlsHandshaker() override;
 
@@ -81,8 +83,6 @@
   QuicSession* session_;
   QuicTlsAdapter bio_adapter_;
   bssl::UniquePtr<SSL> ssl_;
-
-  DISALLOW_COPY_AND_ASSIGN(TlsHandshaker);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/tls_server_handshaker.h b/net/third_party/quic/core/tls_server_handshaker.h
index 13fbdbb..b0a57a5 100644
--- a/net/third_party/quic/core/tls_server_handshaker.h
+++ b/net/third_party/quic/core/tls_server_handshaker.h
@@ -27,6 +27,8 @@
                       QuicSession* session,
                       SSL_CTX* ssl_ctx,
                       ProofSource* proof_source);
+  TlsServerHandshaker(const TlsServerHandshaker&) = delete;
+  TlsServerHandshaker& operator=(const TlsServerHandshaker&) = delete;
 
   ~TlsServerHandshaker() override;
 
@@ -159,8 +161,6 @@
   bool handshake_confirmed_ = false;
   QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
       crypto_negotiated_params_;
-
-  DISALLOW_COPY_AND_ASSIGN(TlsServerHandshaker);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/platform/api/quic_hostname_utils.h b/net/third_party/quic/platform/api/quic_hostname_utils.h
index 3fa4ffea..5f8d53fa 100644
--- a/net/third_party/quic/platform/api/quic_hostname_utils.h
+++ b/net/third_party/quic/platform/api/quic_hostname_utils.h
@@ -14,6 +14,8 @@
 
 class QUIC_EXPORT_PRIVATE QuicHostnameUtils {
  public:
+  QuicHostnameUtils() = delete;
+
   // Returns true if the sni is valid, false otherwise.
   //  (1) disallow IP addresses;
   //  (2) check that the hostname contains valid characters only; and
@@ -23,9 +25,6 @@
   // Convert hostname to lowercase and remove the trailing '.'.
   // WARNING: mutates |hostname| in place and returns |hostname|.
   static char* NormalizeHostname(char* hostname);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicHostnameUtils);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/platform/api/quic_lru_cache.h b/net/third_party/quic/platform/api/quic_lru_cache.h
index facedb2..771a2cff 100644
--- a/net/third_party/quic/platform/api/quic_lru_cache.h
+++ b/net/third_party/quic/platform/api/quic_lru_cache.h
@@ -19,6 +19,8 @@
 class QuicLRUCache {
  public:
   explicit QuicLRUCache(int64_t total_units) : impl_(total_units) {}
+  QuicLRUCache(const QuicLRUCache&) = delete;
+  QuicLRUCache& operator=(const QuicLRUCache&) = delete;
 
   // Inserts one unit of |key|, |value| pair to the cache. Cache takes ownership
   // of inserted |value|.
@@ -43,8 +45,6 @@
 
  private:
   QuicLRUCacheImpl<K, V> impl_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicLRUCache);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/platform/api/quic_mutex.h b/net/third_party/quic/platform/api/quic_mutex.h
index 280bed2..3637ce59 100644
--- a/net/third_party/quic/platform/api/quic_mutex.h
+++ b/net/third_party/quic/platform/api/quic_mutex.h
@@ -14,6 +14,8 @@
 class QUIC_EXPORT_PRIVATE LOCKABLE QuicMutex {
  public:
   QuicMutex() = default;
+  QuicMutex(const QuicMutex&) = delete;
+  QuicMutex& operator=(const QuicMutex&) = delete;
 
   // Block until this Mutex is free, then acquire it exclusively.
   void WriterLock() EXCLUSIVE_LOCK_FUNCTION();
@@ -34,8 +36,6 @@
 
  private:
   QuicLockImpl impl_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicMutex);
 };
 
 // A helper class that acquires the given QuicMutex shared lock while the
@@ -43,13 +43,13 @@
 class QUIC_EXPORT_PRIVATE SCOPED_LOCKABLE QuicReaderMutexLock {
  public:
   explicit QuicReaderMutexLock(QuicMutex* lock) SHARED_LOCK_FUNCTION(lock);
+  QuicReaderMutexLock(const QuicReaderMutexLock&) = delete;
+  QuicReaderMutexLock& operator=(const QuicReaderMutexLock&) = delete;
 
   ~QuicReaderMutexLock() UNLOCK_FUNCTION();
 
  private:
   QuicMutex* const lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicReaderMutexLock);
 };
 
 // A helper class that acquires the given QuicMutex exclusive lock while the
@@ -57,13 +57,13 @@
 class QUIC_EXPORT_PRIVATE SCOPED_LOCKABLE QuicWriterMutexLock {
  public:
   explicit QuicWriterMutexLock(QuicMutex* lock) EXCLUSIVE_LOCK_FUNCTION(lock);
+  QuicWriterMutexLock(const QuicWriterMutexLock&) = delete;
+  QuicWriterMutexLock& operator=(const QuicWriterMutexLock&) = delete;
 
   ~QuicWriterMutexLock() UNLOCK_FUNCTION();
 
  private:
   QuicMutex* const lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicWriterMutexLock);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/platform/api/quic_url_utils.h b/net/third_party/quic/platform/api/quic_url_utils.h
index 5580c39..65a1467 100644
--- a/net/third_party/quic/platform/api/quic_url_utils.h
+++ b/net/third_party/quic/platform/api/quic_url_utils.h
@@ -15,6 +15,8 @@
 
 class QUIC_EXPORT_PRIVATE QuicUrlUtils {
  public:
+  QuicUrlUtils() = delete;
+
   // Returns hostname, or empty std::string if missing.
   static QuicString HostName(QuicStringPiece url);
 
@@ -29,9 +31,6 @@
   static QuicString GetPushPromiseUrl(QuicStringPiece scheme,
                                       QuicStringPiece authority,
                                       QuicStringPiece path);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicUrlUtils);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/test_tools/limited_mtu_test_writer.h b/net/third_party/quic/test_tools/limited_mtu_test_writer.h
index 105252b..4b9734d 100644
--- a/net/third_party/quic/test_tools/limited_mtu_test_writer.h
+++ b/net/third_party/quic/test_tools/limited_mtu_test_writer.h
@@ -17,6 +17,8 @@
 class LimitedMtuTestWriter : public QuicPacketWriterWrapper {
  public:
   explicit LimitedMtuTestWriter(QuicByteCount mtu);
+  LimitedMtuTestWriter(const LimitedMtuTestWriter&) = delete;
+  LimitedMtuTestWriter& operator=(const LimitedMtuTestWriter&) = delete;
   ~LimitedMtuTestWriter() override;
 
   // Inherited from QuicPacketWriterWrapper.
@@ -28,8 +30,6 @@
 
  private:
   QuicByteCount mtu_;
-
-  DISALLOW_COPY_AND_ASSIGN(LimitedMtuTestWriter);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/mock_clock.h b/net/third_party/quic/test_tools/mock_clock.h
index 3eba3c8..8c94e9a 100644
--- a/net/third_party/quic/test_tools/mock_clock.h
+++ b/net/third_party/quic/test_tools/mock_clock.h
@@ -16,6 +16,8 @@
 class MockClock : public QuicClock {
  public:
   MockClock();
+  MockClock(const MockClock&) = delete;
+  MockClock& operator=(const MockClock&) = delete;
   ~MockClock() override;
 
   // QuicClock implementation:
@@ -31,8 +33,6 @@
 
  private:
   QuicTime now_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockClock);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/test_tools/mock_crypto_client_stream.cc b/net/third_party/quic/test_tools/mock_crypto_client_stream.cc
index 61b0209..ce761ec3 100644
--- a/net/third_party/quic/test_tools/mock_crypto_client_stream.cc
+++ b/net/third_party/quic/test_tools/mock_crypto_client_stream.cc
@@ -8,7 +8,7 @@
 #include "net/third_party/quic/core/crypto/null_encrypter.h"
 #include "net/third_party/quic/core/crypto/quic_decrypter.h"
 #include "net/third_party/quic/core/crypto/quic_encrypter.h"
-#include "net/third_party/quic/core/quic_spdy_client_session_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session_base.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quic/test_tools/mock_decrypter.h"
 #include "net/third_party/quic/test_tools/mock_encrypter.h"
diff --git a/net/third_party/quic/test_tools/mock_crypto_client_stream.h b/net/third_party/quic/test_tools/mock_crypto_client_stream.h
index e258be1..61cbd42 100644
--- a/net/third_party/quic/test_tools/mock_crypto_client_stream.h
+++ b/net/third_party/quic/test_tools/mock_crypto_client_stream.h
@@ -11,10 +11,10 @@
 #include "net/quic/chromium/crypto/proof_verifier_chromium.h"
 #include "net/third_party/quic/core/crypto/crypto_handshake.h"
 #include "net/third_party/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session_base.h"
 #include "net/third_party/quic/core/quic_crypto_client_stream.h"
 #include "net/third_party/quic/core/quic_server_id.h"
 #include "net/third_party/quic/core/quic_session.h"
-#include "net/third_party/quic/core/quic_spdy_client_session_base.h"
 
 namespace quic {
 
diff --git a/net/third_party/quic/test_tools/mock_quic_client_promised_info.h b/net/third_party/quic/test_tools/mock_quic_client_promised_info.h
index e52acd06..20cfbac 100644
--- a/net/third_party/quic/test_tools/mock_quic_client_promised_info.h
+++ b/net/third_party/quic/test_tools/mock_quic_client_promised_info.h
@@ -8,7 +8,7 @@
 #include <string>
 
 #include "base/macros.h"
-#include "net/third_party/quic/core/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
diff --git a/net/third_party/quic/test_tools/mock_quic_dispatcher.h b/net/third_party/quic/test_tools/mock_quic_dispatcher.h
index d6637f9..03096371 100644
--- a/net/third_party/quic/test_tools/mock_quic_dispatcher.h
+++ b/net/third_party/quic/test_tools/mock_quic_dispatcher.h
@@ -26,6 +26,8 @@
       std::unique_ptr<QuicCryptoServerStream::Helper> session_helper,
       std::unique_ptr<QuicAlarmFactory> alarm_factory,
       QuicSimpleServerBackend* quic_simple_server_backend);
+  MockQuicDispatcher(const MockQuicDispatcher&) = delete;
+  MockQuicDispatcher& operator=(const MockQuicDispatcher&) = delete;
 
   ~MockQuicDispatcher() override;
 
@@ -33,9 +35,6 @@
                void(const QuicSocketAddress& server_address,
                     const QuicSocketAddress& client_address,
                     const QuicReceivedPacket& packet));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockQuicDispatcher);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/mock_quic_session_visitor.h b/net/third_party/quic/test_tools/mock_quic_session_visitor.h
index 3ac911b3..b207375c 100644
--- a/net/third_party/quic/test_tools/mock_quic_session_visitor.h
+++ b/net/third_party/quic/test_tools/mock_quic_session_visitor.h
@@ -16,6 +16,8 @@
 class MockQuicSessionVisitor : public QuicTimeWaitListManager::Visitor {
  public:
   MockQuicSessionVisitor();
+  MockQuicSessionVisitor(const MockQuicSessionVisitor&) = delete;
+  MockQuicSessionVisitor& operator=(const MockQuicSessionVisitor&) = delete;
   ~MockQuicSessionVisitor() override;
   MOCK_METHOD3(OnConnectionClosed,
                void(QuicConnectionId connection_id,
@@ -26,14 +28,15 @@
   MOCK_METHOD1(OnRstStreamReceived, void(const QuicRstStreamFrame& frame));
   MOCK_METHOD1(OnConnectionAddedToTimeWaitList,
                void(QuicConnectionId connection_id));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockQuicSessionVisitor);
 };
 
 class MockQuicCryptoServerStreamHelper : public QuicCryptoServerStream::Helper {
  public:
   MockQuicCryptoServerStreamHelper();
+  MockQuicCryptoServerStreamHelper(const MockQuicCryptoServerStreamHelper&) =
+      delete;
+  MockQuicCryptoServerStreamHelper& operator=(
+      const MockQuicCryptoServerStreamHelper&) = delete;
   ~MockQuicCryptoServerStreamHelper() override;
   MOCK_CONST_METHOD1(GenerateConnectionIdForReject,
                      QuicConnectionId(QuicConnectionId connection_id));
@@ -43,9 +46,6 @@
                           const QuicSocketAddress& peer_address,
                           const QuicSocketAddress& self_address,
                           QuicString* error_details));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStreamHelper);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/mock_quic_spdy_client_stream.h b/net/third_party/quic/test_tools/mock_quic_spdy_client_stream.h
index e1c8531..6a0a4d89 100644
--- a/net/third_party/quic/test_tools/mock_quic_spdy_client_stream.h
+++ b/net/third_party/quic/test_tools/mock_quic_spdy_client_stream.h
@@ -6,9 +6,9 @@
 #define NET_THIRD_PARTY_QUIC_TEST_TOOLS_MOCK_QUIC_SPDY_CLIENT_STREAM_H_
 
 #include "base/macros.h"
-#include "net/third_party/quic/core/quic_header_list.h"
+#include "net/third_party/quic/core/http/quic_header_list.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
 #include "net/third_party/quic/core/quic_packets.h"
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace quic {
diff --git a/net/third_party/quic/test_tools/mock_random.h b/net/third_party/quic/test_tools/mock_random.h
index 090bab6a..727c8240 100644
--- a/net/third_party/quic/test_tools/mock_random.h
+++ b/net/third_party/quic/test_tools/mock_random.h
@@ -17,6 +17,8 @@
   // Initializes base_ to 0xDEADBEEF.
   MockRandom();
   explicit MockRandom(uint32_t base);
+  MockRandom(const MockRandom&) = delete;
+  MockRandom& operator=(const MockRandom&) = delete;
 
   // QuicRandom:
   // Fills the |data| buffer with a repeating byte, initially 'r'.
@@ -31,8 +33,6 @@
  private:
   uint32_t base_;
   uint8_t increment_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockRandom);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/packet_dropping_test_writer.h b/net/third_party/quic/test_tools/packet_dropping_test_writer.h
index a9c29c3..e4c47ed 100644
--- a/net/third_party/quic/test_tools/packet_dropping_test_writer.h
+++ b/net/third_party/quic/test_tools/packet_dropping_test_writer.h
@@ -37,6 +37,8 @@
   };
 
   PacketDroppingTestWriter();
+  PacketDroppingTestWriter(const PacketDroppingTestWriter&) = delete;
+  PacketDroppingTestWriter& operator=(const PacketDroppingTestWriter&) = delete;
 
   ~PacketDroppingTestWriter() override;
 
@@ -138,6 +140,8 @@
                  const QuicSocketAddress& peer_address,
                  std::unique_ptr<PerPacketOptions> options,
                  QuicTime send_time);
+    DelayedWrite(const DelayedWrite&) = delete;
+    DelayedWrite& operator=(const DelayedWrite&) = delete;
     // TODO(rtenneti): on windows RValue reference gives errors.
     DelayedWrite(DelayedWrite&& other);
     // TODO(rtenneti): on windows RValue reference gives errors.
@@ -149,9 +153,6 @@
     const QuicSocketAddress peer_address;
     std::unique_ptr<PerPacketOptions> options;
     QuicTime send_time;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(DelayedWrite);
   };
 
   typedef std::list<DelayedWrite> DelayedPacketList;
@@ -175,8 +176,6 @@
   QuicBandwidth fake_bandwidth_ GUARDED_BY(config_mutex_);
   QuicByteCount buffer_size_ GUARDED_BY(config_mutex_);
   int32_t num_consecutive_packet_lost_ GUARDED_BY(config_mutex_);
-
-  DISALLOW_COPY_AND_ASSIGN(PacketDroppingTestWriter);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_buffered_packet_store_peer.h b/net/third_party/quic/test_tools/quic_buffered_packet_store_peer.h
index f2ee116..5450b48 100644
--- a/net/third_party/quic/test_tools/quic_buffered_packet_store_peer.h
+++ b/net/third_party/quic/test_tools/quic_buffered_packet_store_peer.h
@@ -18,12 +18,11 @@
 
 class QuicBufferedPacketStorePeer {
  public:
+  QuicBufferedPacketStorePeer() = delete;
+
   static QuicAlarm* expiration_alarm(QuicBufferedPacketStore* store);
 
   static void set_clock(QuicBufferedPacketStore* store, const QuicClock* clock);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicBufferedPacketStorePeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_client_peer.h b/net/third_party/quic/test_tools/quic_client_peer.h
index c0061062..59d2d6e 100644
--- a/net/third_party/quic/test_tools/quic_client_peer.h
+++ b/net/third_party/quic/test_tools/quic_client_peer.h
@@ -16,13 +16,12 @@
 
 class QuicClientPeer {
  public:
+  QuicClientPeer() = delete;
+
   static bool CreateUDPSocketAndBind(QuicClient* client);
   static void CleanUpUDPSocket(QuicClient* client, int fd);
   static void SetClientPort(QuicClient* client, int port);
   static void SetWriter(QuicClient* client, QuicPacketWriter* writer);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicClientPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_client_promised_info_peer.h b/net/third_party/quic/test_tools/quic_client_promised_info_peer.h
index d169531..693904e 100644
--- a/net/third_party/quic/test_tools/quic_client_promised_info_peer.h
+++ b/net/third_party/quic/test_tools/quic_client_promised_info_peer.h
@@ -6,17 +6,16 @@
 #define NET_THIRD_PARTY_QUIC_TEST_TOOLS_QUIC_CLIENT_PROMISED_INFO_PEER_H_
 
 #include "base/macros.h"
-#include "net/third_party/quic/core/quic_client_promised_info.h"
+#include "net/third_party/quic/core/http/quic_client_promised_info.h"
 
 namespace quic {
 namespace test {
 
 class QuicClientPromisedInfoPeer {
  public:
-  static QuicAlarm* GetAlarm(QuicClientPromisedInfo* promised_stream);
+  QuicClientPromisedInfoPeer() = delete;
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicClientPromisedInfoPeer);
+  static QuicAlarm* GetAlarm(QuicClientPromisedInfo* promised_stream);
 };
 }  // namespace test
 }  // namespace quic
diff --git a/net/third_party/quic/test_tools/quic_config_peer.h b/net/third_party/quic/test_tools/quic_config_peer.h
index 33a802d..2164fd30 100644
--- a/net/third_party/quic/test_tools/quic_config_peer.h
+++ b/net/third_party/quic/test_tools/quic_config_peer.h
@@ -18,6 +18,8 @@
 
 class QuicConfigPeer {
  public:
+  QuicConfigPeer() = delete;
+
   static void SetReceivedInitialStreamFlowControlWindow(QuicConfig* config,
                                                         uint32_t window_bytes);
 
@@ -40,9 +42,6 @@
 
   static void SetReceivedStatelessResetToken(QuicConfig* config,
                                              QuicUint128 token);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicConfigPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_connection_peer.h b/net/third_party/quic/test_tools/quic_connection_peer.h
index fe43104..b5ad7ae 100644
--- a/net/third_party/quic/test_tools/quic_connection_peer.h
+++ b/net/third_party/quic/test_tools/quic_connection_peer.h
@@ -31,6 +31,8 @@
 // Peer to make public a number of otherwise private QuicConnection methods.
 class QuicConnectionPeer {
  public:
+  QuicConnectionPeer() = delete;
+
   static void SendAck(QuicConnection* connection);
 
   static void SetSendAlgorithm(QuicConnection* connection,
@@ -128,9 +130,6 @@
                                    QuicPacketCount max_tracked_packets);
   static void SetSessionDecidesWhatToWrite(QuicConnection* connection);
   static void SetNegotiatedVersion(QuicConnection* connection);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicConnectionPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_dispatcher_peer.h b/net/third_party/quic/test_tools/quic_dispatcher_peer.h
index b97aa8f2..7494d32 100644
--- a/net/third_party/quic/test_tools/quic_dispatcher_peer.h
+++ b/net/third_party/quic/test_tools/quic_dispatcher_peer.h
@@ -16,6 +16,8 @@
 
 class QuicDispatcherPeer {
  public:
+  QuicDispatcherPeer() = delete;
+
   static void SetTimeWaitListManager(
       QuicDispatcher* dispatcher,
       QuicTimeWaitListManager* time_wait_list_manager);
@@ -60,9 +62,6 @@
   static void RestorePerPacketContext(
       QuicDispatcher* dispatcher,
       std::unique_ptr<QuicDispatcher::PerPacketContext>);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicDispatcherPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_flow_controller_peer.h b/net/third_party/quic/test_tools/quic_flow_controller_peer.h
index f423f36..2f99b28 100644
--- a/net/third_party/quic/test_tools/quic_flow_controller_peer.h
+++ b/net/third_party/quic/test_tools/quic_flow_controller_peer.h
@@ -16,6 +16,8 @@
 
 class QuicFlowControllerPeer {
  public:
+  QuicFlowControllerPeer() = delete;
+
   static void SetSendWindowOffset(QuicFlowController* flow_controller,
                                   QuicStreamOffset offset);
 
@@ -36,9 +38,6 @@
 
   static QuicByteCount WindowUpdateThreshold(
       QuicFlowController* flow_controller);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicFlowControllerPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_framer_peer.h b/net/third_party/quic/test_tools/quic_framer_peer.h
index 71255db..d7903bb 100644
--- a/net/third_party/quic/test_tools/quic_framer_peer.h
+++ b/net/third_party/quic/test_tools/quic_framer_peer.h
@@ -16,6 +16,8 @@
 
 class QuicFramerPeer {
  public:
+  QuicFramerPeer() = delete;
+
   static QuicPacketNumber CalculatePacketNumberFromWire(
       QuicFramer* framer,
       QuicPacketNumberLength packet_number_length,
@@ -147,9 +149,6 @@
                                    const QuicFrame& frame,
                                    bool last_frame_in_packet,
                                    QuicPacketNumberLength packet_number_length);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicFramerPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_packet_creator_peer.h b/net/third_party/quic/test_tools/quic_packet_creator_peer.h
index a94cf8d0..35a4f869 100644
--- a/net/third_party/quic/test_tools/quic_packet_creator_peer.h
+++ b/net/third_party/quic/test_tools/quic_packet_creator_peer.h
@@ -16,6 +16,8 @@
 
 class QuicPacketCreatorPeer {
  public:
+  QuicPacketCreatorPeer() = delete;
+
   static bool SendVersionInPacket(QuicPacketCreator* creator);
 
   static void SetSendVersionInPacket(QuicPacketCreator* creator,
@@ -43,9 +45,6 @@
       QuicPacketCreator* creator);
   static EncryptionLevel GetEncryptionLevel(QuicPacketCreator* creator);
   static QuicFramer* framer(QuicPacketCreator* creator);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicPacketCreatorPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_packet_generator_peer.h b/net/third_party/quic/test_tools/quic_packet_generator_peer.h
index fbf853b1..d9f22a5 100644
--- a/net/third_party/quic/test_tools/quic_packet_generator_peer.h
+++ b/net/third_party/quic/test_tools/quic_packet_generator_peer.h
@@ -17,10 +17,9 @@
 
 class QuicPacketGeneratorPeer {
  public:
-  static QuicPacketCreator* GetPacketCreator(QuicPacketGenerator* generator);
+  QuicPacketGeneratorPeer() = delete;
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicPacketGeneratorPeer);
+  static QuicPacketCreator* GetPacketCreator(QuicPacketGenerator* generator);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_sent_packet_manager_peer.h b/net/third_party/quic/test_tools/quic_sent_packet_manager_peer.h
index b75b195a..4aa02b8 100644
--- a/net/third_party/quic/test_tools/quic_sent_packet_manager_peer.h
+++ b/net/third_party/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -17,6 +17,8 @@
 
 class QuicSentPacketManagerPeer {
  public:
+  QuicSentPacketManagerPeer() = delete;
+
   static size_t GetMaxTailLossProbes(
       QuicSentPacketManager* sent_packet_manager);
 
@@ -104,9 +106,6 @@
 
   static void SetNextPacedPacketTime(QuicSentPacketManager* sent_packet_manager,
                                      QuicTime time);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicSentPacketManagerPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_server_peer.h b/net/third_party/quic/test_tools/quic_server_peer.h
index 5759a3b..bf4bff5 100644
--- a/net/third_party/quic/test_tools/quic_server_peer.h
+++ b/net/third_party/quic/test_tools/quic_server_peer.h
@@ -17,12 +17,11 @@
 
 class QuicServerPeer {
  public:
+  QuicServerPeer() = delete;
+
   static bool SetSmallSocket(QuicServer* server);
   static QuicDispatcher* GetDispatcher(QuicServer* server);
   static void SetReader(QuicServer* server, QuicPacketReader* reader);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicServerPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_session_peer.h b/net/third_party/quic/test_tools/quic_session_peer.h
index a3a57310..e0e510c 100644
--- a/net/third_party/quic/test_tools/quic_session_peer.h
+++ b/net/third_party/quic/test_tools/quic_session_peer.h
@@ -25,6 +25,8 @@
 
 class QuicSessionPeer {
  public:
+  QuicSessionPeer() = delete;
+
   static QuicStreamId GetNextOutgoingStreamId(QuicSession* session);
   static void SetNextOutgoingStreamId(QuicSession* session, QuicStreamId id);
   static void SetMaxOpenIncomingStreams(QuicSession* session,
@@ -55,9 +57,6 @@
 
   static QuicStream* GetStream(QuicSession* session, QuicStreamId id);
   static bool IsStreamWriteBlocked(QuicSession* session, QuicStreamId id);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicSessionPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_spdy_session_peer.cc b/net/third_party/quic/test_tools/quic_spdy_session_peer.cc
index ae763a14..60b0359 100644
--- a/net/third_party/quic/test_tools/quic_spdy_session_peer.cc
+++ b/net/third_party/quic/test_tools/quic_spdy_session_peer.cc
@@ -4,7 +4,7 @@
 
 #include "net/third_party/quic/test_tools/quic_spdy_session_peer.h"
 
-#include "net/third_party/quic/core/quic_spdy_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_session.h"
 
 namespace quic {
 namespace test {
diff --git a/net/third_party/quic/test_tools/quic_spdy_session_peer.h b/net/third_party/quic/test_tools/quic_spdy_session_peer.h
index c98986b8..488300d 100644
--- a/net/third_party/quic/test_tools/quic_spdy_session_peer.h
+++ b/net/third_party/quic/test_tools/quic_spdy_session_peer.h
@@ -20,6 +20,8 @@
 
 class QuicSpdySessionPeer {
  public:
+  QuicSpdySessionPeer() = delete;
+
   static QuicHeadersStream* GetHeadersStream(QuicSpdySession* session);
   static void SetHeadersStream(QuicSpdySession* session,
                                QuicHeadersStream* headers_stream);
@@ -54,9 +56,6 @@
   static QuicStreamId GetNthServerInitiatedStreamId(
       const QuicSpdySession& session,
       int n);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicSpdySessionPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_spdy_stream_peer.cc b/net/third_party/quic/test_tools/quic_spdy_stream_peer.cc
deleted file mode 100644
index a491cf5..0000000
--- a/net/third_party/quic/test_tools/quic_spdy_stream_peer.cc
+++ /dev/null
@@ -1,7 +0,0 @@
-// 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 "net/third_party/quic/test_tools/quic_spdy_stream_peer.h"
-
-#include "net/third_party/quic/core/quic_spdy_stream.h"
diff --git a/net/third_party/quic/test_tools/quic_spdy_stream_peer.h b/net/third_party/quic/test_tools/quic_spdy_stream_peer.h
deleted file mode 100644
index 88cb151e..0000000
--- a/net/third_party/quic/test_tools/quic_spdy_stream_peer.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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 NET_THIRD_PARTY_QUIC_TEST_TOOLS_QUIC_SPDY_STREAM_PEER_H_
-#define NET_THIRD_PARTY_QUIC_TEST_TOOLS_QUIC_SPDY_STREAM_PEER_H_
-
-#include "base/macros.h"
-
-namespace quic {
-
-namespace test {
-
-class QuicSpdyStreamPeer {
- public:
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicSpdyStreamPeer);
-};
-
-}  // namespace test
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_TEST_TOOLS_QUIC_SPDY_STREAM_PEER_H_
diff --git a/net/third_party/quic/test_tools/quic_stream_peer.h b/net/third_party/quic/test_tools/quic_stream_peer.h
index fad55440..407aeb7 100644
--- a/net/third_party/quic/test_tools/quic_stream_peer.h
+++ b/net/third_party/quic/test_tools/quic_stream_peer.h
@@ -22,6 +22,8 @@
 
 class QuicStreamPeer {
  public:
+  QuicStreamPeer() = delete;
+
   static void SetWriteSideClosed(bool value, QuicStream* stream);
   static void SetStreamBytesWritten(QuicStreamOffset stream_bytes_written,
                                     QuicStream* stream);
@@ -49,9 +51,6 @@
   static void set_ack_listener(
       QuicStream* stream,
       QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicStreamPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_stream_sequencer_buffer_peer.h b/net/third_party/quic/test_tools/quic_stream_sequencer_buffer_peer.h
index 7937766..7e4def1 100644
--- a/net/third_party/quic/test_tools/quic_stream_sequencer_buffer_peer.h
+++ b/net/third_party/quic/test_tools/quic_stream_sequencer_buffer_peer.h
@@ -14,6 +14,9 @@
 class QuicStreamSequencerBufferPeer {
  public:
   explicit QuicStreamSequencerBufferPeer(QuicStreamSequencerBuffer* buffer);
+  QuicStreamSequencerBufferPeer(const QuicStreamSequencerBufferPeer&) = delete;
+  QuicStreamSequencerBufferPeer& operator=(
+      const QuicStreamSequencerBufferPeer&) = delete;
 
   // Read from this buffer_ into the given destination buffer_ up to the
   // size of the destination. Returns the number of bytes read. Reading from
@@ -52,7 +55,6 @@
 
  private:
   QuicStreamSequencerBuffer* buffer_;
-  DISALLOW_COPY_AND_ASSIGN(QuicStreamSequencerBufferPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_stream_sequencer_peer.h b/net/third_party/quic/test_tools/quic_stream_sequencer_peer.h
index aa97588d..67ef054 100644
--- a/net/third_party/quic/test_tools/quic_stream_sequencer_peer.h
+++ b/net/third_party/quic/test_tools/quic_stream_sequencer_peer.h
@@ -16,6 +16,8 @@
 
 class QuicStreamSequencerPeer {
  public:
+  QuicStreamSequencerPeer() = delete;
+
   static size_t GetNumBufferedBytes(QuicStreamSequencer* sequencer);
 
   static QuicStreamOffset GetCloseOffset(QuicStreamSequencer* sequencer);
@@ -24,9 +26,6 @@
 
   static void SetFrameBufferTotalBytesRead(QuicStreamSequencer* sequencer,
                                            QuicStreamOffset total_bytes_read);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicStreamSequencerPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h b/net/third_party/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
index e398b7d..355237a 100644
--- a/net/third_party/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
+++ b/net/third_party/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h
@@ -18,6 +18,8 @@
 
 class QuicSustainedBandwidthRecorderPeer {
  public:
+  QuicSustainedBandwidthRecorderPeer() = delete;
+
   static void SetBandwidthEstimate(
       QuicSustainedBandwidthRecorder* bandwidth_recorder,
       int32_t bandwidth_estimate_kbytes_per_second);
@@ -26,9 +28,6 @@
       QuicSustainedBandwidthRecorder* bandwidth_recorder,
       int32_t max_bandwidth_estimate_kbytes_per_second,
       int32_t max_bandwidth_timestamp);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(QuicSustainedBandwidthRecorderPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_test_client.cc b/net/third_party/quic/test_tools/quic_test_client.cc
index 38f3f3c..10bb8ea2 100644
--- a/net/third_party/quic/test_tools/quic_test_client.cc
+++ b/net/third_party/quic/test_tools/quic_test_client.cc
@@ -9,12 +9,12 @@
 #include <vector>
 
 #include "net/third_party/quic/core/crypto/proof_verifier.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_epoll_connection_helper.h"
 #include "net/third_party/quic/core/quic_packet_writer_wrapper.h"
 #include "net/third_party/quic/core/quic_server_id.h"
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
 #include "net/third_party/quic/core/quic_utils.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
diff --git a/net/third_party/quic/test_tools/quic_test_client.h b/net/third_party/quic/test_tools/quic_test_client.h
index 4c09e07..903c7e7 100644
--- a/net/third_party/quic/test_tools/quic_test_client.h
+++ b/net/third_party/quic/test_tools/quic_test_client.h
@@ -49,6 +49,8 @@
                      const ParsedQuicVersionVector& supported_versions,
                      net::EpollServer* epoll_server,
                      std::unique_ptr<ProofVerifier> proof_verifier);
+  MockableQuicClient(const MockableQuicClient&) = delete;
+  MockableQuicClient& operator=(const MockableQuicClient&) = delete;
 
   ~MockableQuicClient() override;
 
@@ -69,8 +71,6 @@
  private:
   QuicConnectionId override_connection_id_;  // ConnectionId to use, if nonzero
   CachedNetworkParameters cached_network_paramaters_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockableQuicClient);
 };
 
 // A toy QUIC client used for testing.
@@ -318,6 +318,8 @@
 
  protected:
   QuicTestClient();
+  QuicTestClient(const QuicTestClient&) = delete;
+  QuicTestClient& operator=(const QuicTestClient&) = delete;
 
  private:
   class TestClientDataToResend : public QuicClient::QuicDataToResend {
@@ -395,8 +397,6 @@
   // logic which extracts the SNI from the request URL.
   bool override_sni_set_ = false;
   QuicString override_sni_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicTestClient);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/quic_test_utils.h b/net/third_party/quic/test_tools/quic_test_utils.h
index ef0d0fb..231d60ba 100644
--- a/net/third_party/quic/test_tools/quic_test_utils.h
+++ b/net/third_party/quic/test_tools/quic_test_utils.h
@@ -18,12 +18,12 @@
 #include "net/test/gtest_util.h"
 #include "net/third_party/quic/core/congestion_control/loss_detection_interface.h"
 #include "net/third_party/quic/core/congestion_control/send_algorithm_interface.h"
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_server_session_base.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_connection_close_delegate_interface.h"
 #include "net/third_party/quic/core/quic_framer.h"
 #include "net/third_party/quic/core/quic_sent_packet_manager.h"
-#include "net/third_party/quic/core/quic_server_session_base.h"
 #include "net/third_party/quic/core/quic_simple_buffer_allocator.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
@@ -218,6 +218,8 @@
 class SimpleRandom : public QuicRandom {
  public:
   SimpleRandom() : seed_(0) {}
+  SimpleRandom(const SimpleRandom&) = delete;
+  SimpleRandom& operator=(const SimpleRandom&) = delete;
   ~SimpleRandom() override {}
 
   // Returns a random number in the range [0, kuint64max].
@@ -229,13 +231,13 @@
 
  private:
   uint64_t seed_;
-
-  DISALLOW_COPY_AND_ASSIGN(SimpleRandom);
 };
 
 class MockFramerVisitor : public QuicFramerVisitorInterface {
  public:
   MockFramerVisitor();
+  MockFramerVisitor(const MockFramerVisitor&) = delete;
+  MockFramerVisitor& operator=(const MockFramerVisitor&) = delete;
   ~MockFramerVisitor() override;
 
   MOCK_METHOD1(OnError, void(QuicFramer* framer));
@@ -278,14 +280,13 @@
   MOCK_CONST_METHOD1(IsValidStatelessResetToken, bool(QuicUint128));
   MOCK_METHOD1(OnAuthenticatedIetfStatelessResetPacket,
                void(const QuicIetfStatelessResetPacket&));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockFramerVisitor);
 };
 
 class NoOpFramerVisitor : public QuicFramerVisitorInterface {
  public:
   NoOpFramerVisitor() {}
+  NoOpFramerVisitor(const NoOpFramerVisitor&) = delete;
+  NoOpFramerVisitor& operator=(const NoOpFramerVisitor&) = delete;
 
   void OnError(QuicFramer* framer) override {}
   void OnPacket() override {}
@@ -322,14 +323,14 @@
   bool IsValidStatelessResetToken(QuicUint128 token) const override;
   void OnAuthenticatedIetfStatelessResetPacket(
       const QuicIetfStatelessResetPacket& packet) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NoOpFramerVisitor);
 };
 
 class MockQuicConnectionVisitor : public QuicConnectionVisitorInterface {
  public:
   MockQuicConnectionVisitor();
+  MockQuicConnectionVisitor(const MockQuicConnectionVisitor&) = delete;
+  MockQuicConnectionVisitor& operator=(const MockQuicConnectionVisitor&) =
+      delete;
   ~MockQuicConnectionVisitor() override;
 
   MOCK_METHOD1(OnStreamFrame, void(const QuicStreamFrame& frame));
@@ -360,14 +361,13 @@
   MOCK_METHOD0(SendPing, void());
   MOCK_CONST_METHOD0(AllowSelfAddressChange, bool());
   MOCK_METHOD0(OnForwardProgressConfirmed, void());
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockQuicConnectionVisitor);
 };
 
 class MockQuicConnectionHelper : public QuicConnectionHelperInterface {
  public:
   MockQuicConnectionHelper();
+  MockQuicConnectionHelper(const MockQuicConnectionHelper&) = delete;
+  MockQuicConnectionHelper& operator=(const MockQuicConnectionHelper&) = delete;
   ~MockQuicConnectionHelper() override;
   const QuicClock* GetClock() const override;
   QuicRandom* GetRandomGenerator() override;
@@ -378,8 +378,6 @@
   MockClock clock_;
   MockRandom random_generator_;
   SimpleBufferAllocator buffer_allocator_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockQuicConnectionHelper);
 };
 
 class MockAlarmFactory : public QuicAlarmFactory {
@@ -437,6 +435,8 @@
                      MockAlarmFactory* alarm_factory,
                      Perspective perspective,
                      const ParsedQuicVersionVector& supported_versions);
+  MockQuicConnection(const MockQuicConnection&) = delete;
+  MockQuicConnection& operator=(const MockQuicConnection&) = delete;
 
   ~MockQuicConnection() override;
 
@@ -505,9 +505,6 @@
     return QuicConnection::SendConnectivityProbingPacket(probing_writer,
                                                          peer_address);
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockQuicConnection);
 };
 
 class PacketSavingConnection : public MockQuicConnection {
@@ -520,15 +517,14 @@
                          MockAlarmFactory* alarm_factory,
                          Perspective perspective,
                          const ParsedQuicVersionVector& supported_versions);
+  PacketSavingConnection(const PacketSavingConnection&) = delete;
+  PacketSavingConnection& operator=(const PacketSavingConnection&) = delete;
 
   ~PacketSavingConnection() override;
 
   void SendOrQueuePacket(SerializedPacket* packet) override;
 
   std::vector<std::unique_ptr<QuicEncryptedPacket>> encrypted_packets_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PacketSavingConnection);
 };
 
 class MockQuicSession : public QuicSession {
@@ -538,6 +534,8 @@
 
   // Takes ownership of |connection|.
   explicit MockQuicSession(QuicConnection* connection);
+  MockQuicSession(const MockQuicSession&) = delete;
+  MockQuicSession& operator=(const MockQuicSession&) = delete;
   ~MockQuicSession() override;
 
   QuicCryptoStream* GetMutableCryptoStream() override;
@@ -584,8 +582,6 @@
 
  private:
   std::unique_ptr<QuicCryptoStream> crypto_stream_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockQuicSession);
 };
 
 class MockQuicCryptoStream : public QuicCryptoStream {
@@ -613,6 +609,8 @@
   // Takes ownership of |connection|.
   MockQuicSpdySession(QuicConnection* connection,
                       bool create_mock_crypto_stream);
+  MockQuicSpdySession(const MockQuicSpdySession&) = delete;
+  MockQuicSpdySession& operator=(const MockQuicSpdySession&) = delete;
   ~MockQuicSpdySession() override;
 
   QuicCryptoStream* GetMutableCryptoStream() override;
@@ -693,8 +691,6 @@
  private:
   std::unique_ptr<QuicCryptoStream> crypto_stream_;
   spdy::SpdyHeaderBlock write_headers_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockQuicSpdySession);
 };
 
 class TestQuicSpdyServerSession : public QuicServerSessionBase {
@@ -704,6 +700,9 @@
                             const QuicConfig& config,
                             const QuicCryptoServerConfig* crypto_config,
                             QuicCompressedCertsCache* compressed_certs_cache);
+  TestQuicSpdyServerSession(const TestQuicSpdyServerSession&) = delete;
+  TestQuicSpdyServerSession& operator=(const TestQuicSpdyServerSession&) =
+      delete;
   ~TestQuicSpdyServerSession() override;
 
   MOCK_METHOD1(CreateIncomingDynamicStream, QuicSpdyStream*(QuicStreamId id));
@@ -724,8 +723,6 @@
  private:
   MockQuicSessionVisitor visitor_;
   MockQuicCryptoServerStreamHelper helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestQuicSpdyServerSession);
 };
 
 // A test implementation of QuicClientPushPromiseIndex::Delegate.
@@ -756,6 +753,9 @@
                             const QuicConfig& config,
                             const QuicServerId& server_id,
                             QuicCryptoClientConfig* crypto_config);
+  TestQuicSpdyClientSession(const TestQuicSpdyClientSession&) = delete;
+  TestQuicSpdyClientSession& operator=(const TestQuicSpdyClientSession&) =
+      delete;
   ~TestQuicSpdyClientSession() override;
 
   bool IsAuthorized(const QuicString& authority) override;
@@ -780,13 +780,13 @@
  private:
   std::unique_ptr<QuicCryptoClientStream> crypto_stream_;
   QuicClientPushPromiseIndex push_promise_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestQuicSpdyClientSession);
 };
 
 class MockPacketWriter : public QuicPacketWriter {
  public:
   MockPacketWriter();
+  MockPacketWriter(const MockPacketWriter&) = delete;
+  MockPacketWriter& operator=(const MockPacketWriter&) = delete;
   ~MockPacketWriter() override;
 
   MOCK_METHOD5(WritePacket,
@@ -804,14 +804,13 @@
   MOCK_CONST_METHOD0(IsBatchMode, bool());
   MOCK_CONST_METHOD0(GetNextWriteLocation, char*());
   MOCK_METHOD0(Flush, WriteResult());
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockPacketWriter);
 };
 
 class MockSendAlgorithm : public SendAlgorithmInterface {
  public:
   MockSendAlgorithm();
+  MockSendAlgorithm(const MockSendAlgorithm&) = delete;
+  MockSendAlgorithm& operator=(const MockSendAlgorithm&) = delete;
   ~MockSendAlgorithm() override;
 
   MOCK_METHOD2(SetFromConfig,
@@ -850,14 +849,13 @@
   MOCK_CONST_METHOD0(GetCongestionControlType, CongestionControlType());
   MOCK_METHOD2(AdjustNetworkParameters, void(QuicBandwidth, QuicTime::Delta));
   MOCK_METHOD1(OnApplicationLimited, void(QuicByteCount));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockSendAlgorithm);
 };
 
 class MockLossAlgorithm : public LossDetectionInterface {
  public:
   MockLossAlgorithm();
+  MockLossAlgorithm(const MockLossAlgorithm&) = delete;
+  MockLossAlgorithm& operator=(const MockLossAlgorithm&) = delete;
   ~MockLossAlgorithm() override;
 
   MOCK_CONST_METHOD0(GetLossDetectionType, LossDetectionType());
@@ -873,14 +871,13 @@
                     QuicTime,
                     const RttStats&,
                     QuicPacketNumber));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockLossAlgorithm);
 };
 
 class MockAckListener : public QuicAckListenerInterface {
  public:
   MockAckListener();
+  MockAckListener(const MockAckListener&) = delete;
+  MockAckListener& operator=(const MockAckListener&) = delete;
 
   MOCK_METHOD2(OnPacketAcked,
                void(int acked_bytes, QuicTime::Delta ack_delay_time));
@@ -890,22 +887,18 @@
  protected:
   // Object is ref counted.
   ~MockAckListener() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockAckListener);
 };
 
 class MockNetworkChangeVisitor
     : public QuicSentPacketManager::NetworkChangeVisitor {
  public:
   MockNetworkChangeVisitor();
+  MockNetworkChangeVisitor(const MockNetworkChangeVisitor&) = delete;
+  MockNetworkChangeVisitor& operator=(const MockNetworkChangeVisitor&) = delete;
   ~MockNetworkChangeVisitor() override;
 
   MOCK_METHOD0(OnCongestionChange, void());
   MOCK_METHOD1(OnPathMtuIncreased, void(QuicPacketLength));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockNetworkChangeVisitor);
 };
 
 class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor {
@@ -990,6 +983,9 @@
 class MockPacketCreatorDelegate : public QuicPacketCreator::DelegateInterface {
  public:
   MockPacketCreatorDelegate();
+  MockPacketCreatorDelegate(const MockPacketCreatorDelegate&) = delete;
+  MockPacketCreatorDelegate& operator=(const MockPacketCreatorDelegate&) =
+      delete;
   ~MockPacketCreatorDelegate() override;
 
   MOCK_METHOD0(GetPacketBuffer, char*());
@@ -998,9 +994,6 @@
                void(QuicErrorCode,
                     const QuicString&,
                     ConnectionCloseSource source));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockPacketCreatorDelegate);
 };
 
 class MockSessionNotifier : public SessionNotifierInterface {
diff --git a/net/third_party/quic/test_tools/rtt_stats_peer.h b/net/third_party/quic/test_tools/rtt_stats_peer.h
index b508c84..aba2f23 100644
--- a/net/third_party/quic/test_tools/rtt_stats_peer.h
+++ b/net/third_party/quic/test_tools/rtt_stats_peer.h
@@ -14,12 +14,11 @@
 
 class RttStatsPeer {
  public:
+  RttStatsPeer() = delete;
+
   static void SetSmoothedRtt(RttStats* rtt_stats, QuicTime::Delta rtt_ms);
 
   static void SetMinRtt(RttStats* rtt_stats, QuicTime::Delta rtt_ms);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(RttStatsPeer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/server_thread.h b/net/third_party/quic/test_tools/server_thread.h
index e75e64b..4046e8ac 100644
--- a/net/third_party/quic/test_tools/server_thread.h
+++ b/net/third_party/quic/test_tools/server_thread.h
@@ -23,6 +23,8 @@
 class ServerThread : public base::SimpleThread {
  public:
   ServerThread(QuicServer* server, const QuicSocketAddress& address);
+  ServerThread(const ServerThread&) = delete;
+  ServerThread& operator=(const ServerThread&) = delete;
 
   ~ServerThread() override;
 
@@ -80,8 +82,6 @@
   QuicMutex scheduled_actions_lock_;
   QuicDeque<std::function<void()>> scheduled_actions_
       GUARDED_BY(scheduled_actions_lock_);
-
-  DISALLOW_COPY_AND_ASSIGN(ServerThread);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/simple_quic_framer.cc b/net/third_party/quic/test_tools/simple_quic_framer.cc
index 7d33411..c84585d 100644
--- a/net/third_party/quic/test_tools/simple_quic_framer.cc
+++ b/net/third_party/quic/test_tools/simple_quic_framer.cc
@@ -18,6 +18,8 @@
 class SimpleFramerVisitor : public QuicFramerVisitorInterface {
  public:
   SimpleFramerVisitor() : error_(QUIC_NO_ERROR) {}
+  SimpleFramerVisitor(const SimpleFramerVisitor&) = delete;
+  SimpleFramerVisitor& operator=(const SimpleFramerVisitor&) = delete;
 
   ~SimpleFramerVisitor() override {}
 
@@ -230,8 +232,6 @@
   std::vector<QuicBlockedFrame> blocked_frames_;
   std::vector<QuicNewConnectionIdFrame> new_connection_id_frames_;
   std::vector<std::unique_ptr<QuicString>> stream_data_;
-
-  DISALLOW_COPY_AND_ASSIGN(SimpleFramerVisitor);
 };
 
 SimpleQuicFramer::SimpleQuicFramer()
diff --git a/net/third_party/quic/test_tools/simple_quic_framer.h b/net/third_party/quic/test_tools/simple_quic_framer.h
index 886facd9..37d20f1 100644
--- a/net/third_party/quic/test_tools/simple_quic_framer.h
+++ b/net/third_party/quic/test_tools/simple_quic_framer.h
@@ -27,6 +27,8 @@
   explicit SimpleQuicFramer(const ParsedQuicVersionVector& supported_versions);
   SimpleQuicFramer(const ParsedQuicVersionVector& supported_versions,
                    Perspective perspective);
+  SimpleQuicFramer(const SimpleQuicFramer&) = delete;
+  SimpleQuicFramer& operator=(const SimpleQuicFramer&) = delete;
   ~SimpleQuicFramer();
 
   bool ProcessPacket(const QuicEncryptedPacket& packet);
@@ -54,7 +56,6 @@
  private:
   QuicFramer framer_;
   std::unique_ptr<SimpleFramerVisitor> visitor_;
-  DISALLOW_COPY_AND_ASSIGN(SimpleQuicFramer);
 };
 
 }  // namespace test
diff --git a/net/third_party/quic/test_tools/simulator/actor.h b/net/third_party/quic/test_tools/simulator/actor.h
index d2698f7d..514e8f0 100644
--- a/net/third_party/quic/test_tools/simulator/actor.h
+++ b/net/third_party/quic/test_tools/simulator/actor.h
@@ -55,9 +55,9 @@
   // Since the Actor object registers itself with a simulator using a pointer to
   // itself, do not allow it to be moved.
   Actor(Actor&&) = delete;
+  Actor(const Actor&) = delete;
+  Actor& operator=(const Actor&) = delete;
   Actor& operator=(Actor&&) = delete;
-
-  DISALLOW_COPY_AND_ASSIGN(Actor);
 };
 
 }  // namespace simulator
diff --git a/net/third_party/quic/test_tools/simulator/alarm_factory.h b/net/third_party/quic/test_tools/simulator/alarm_factory.h
index d10cd47..33d7e099 100644
--- a/net/third_party/quic/test_tools/simulator/alarm_factory.h
+++ b/net/third_party/quic/test_tools/simulator/alarm_factory.h
@@ -15,6 +15,8 @@
 class AlarmFactory : public QuicAlarmFactory {
  public:
   AlarmFactory(Simulator* simulator, std::string name);
+  AlarmFactory(const AlarmFactory&) = delete;
+  AlarmFactory& operator=(const AlarmFactory&) = delete;
   ~AlarmFactory() override;
 
   QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
@@ -29,8 +31,6 @@
   Simulator* simulator_;
   std::string name_;
   int counter_;
-
-  DISALLOW_COPY_AND_ASSIGN(AlarmFactory);
 };
 
 }  // namespace simulator
diff --git a/net/third_party/quic/test_tools/simulator/link.h b/net/third_party/quic/test_tools/simulator/link.h
index 8636ee5..64dfabdc 100644
--- a/net/third_party/quic/test_tools/simulator/link.h
+++ b/net/third_party/quic/test_tools/simulator/link.h
@@ -24,6 +24,8 @@
              UnconstrainedPortInterface* sink,
              QuicBandwidth bandwidth,
              QuicTime::Delta propagation_delay);
+  OneWayLink(const OneWayLink&) = delete;
+  OneWayLink& operator=(const OneWayLink&) = delete;
   ~OneWayLink() override;
 
   void AcceptPacket(std::unique_ptr<Packet> packet) override;
@@ -57,8 +59,6 @@
   const QuicTime::Delta propagation_delay_;
 
   QuicTime next_write_at_;
-
-  DISALLOW_COPY_AND_ASSIGN(OneWayLink);
 };
 
 // A full-duplex link between two endpoints, functionally equivalent to two
@@ -75,14 +75,14 @@
                 Endpoint* endpoint_b,
                 QuicBandwidth bandwidth,
                 QuicTime::Delta propagation_delay);
+  SymmetricLink(const SymmetricLink&) = delete;
+  SymmetricLink& operator=(const SymmetricLink&) = delete;
 
   inline QuicBandwidth bandwidth() { return a_to_b_link_.bandwidth(); }
 
  private:
   OneWayLink a_to_b_link_;
   OneWayLink b_to_a_link_;
-
-  DISALLOW_COPY_AND_ASSIGN(SymmetricLink);
 };
 
 }  // namespace simulator
diff --git a/net/third_party/quic/test_tools/simulator/packet_filter.h b/net/third_party/quic/test_tools/simulator/packet_filter.h
index 4c4878e3..e769db1 100644
--- a/net/third_party/quic/test_tools/simulator/packet_filter.h
+++ b/net/third_party/quic/test_tools/simulator/packet_filter.h
@@ -40,6 +40,8 @@
   // Initialize the filter by wrapping around |input|.  Does not take the
   // ownership of |input|.
   PacketFilter(Simulator* simulator, std::string name, Endpoint* input);
+  PacketFilter(const PacketFilter&) = delete;
+  PacketFilter& operator=(const PacketFilter&) = delete;
   ~PacketFilter() override;
 
   // Implementation of ConstrainedPortInterface.
@@ -66,8 +68,6 @@
 
   // The original network endpoint wrapped by the class.
   Endpoint* input_;
-
-  DISALLOW_COPY_AND_ASSIGN(PacketFilter);
 };
 
 }  // namespace simulator
diff --git a/net/third_party/quic/test_tools/simulator/queue.h b/net/third_party/quic/test_tools/simulator/queue.h
index 2d57fee..e9641d30 100644
--- a/net/third_party/quic/test_tools/simulator/queue.h
+++ b/net/third_party/quic/test_tools/simulator/queue.h
@@ -24,6 +24,8 @@
   };
 
   Queue(Simulator* simulator, std::string name, QuicByteCount capacity);
+  Queue(const Queue&) = delete;
+  Queue& operator=(const Queue&) = delete;
   ~Queue() override;
 
   void set_tx_port(ConstrainedPortInterface* port);
@@ -110,8 +112,6 @@
   QuicQueue<EnqueuedPacket> queue_;
 
   ListenerInterface* listener_;
-
-  DISALLOW_COPY_AND_ASSIGN(Queue);
 };
 
 }  // namespace simulator
diff --git a/net/third_party/quic/test_tools/simulator/simulator.h b/net/third_party/quic/test_tools/simulator/simulator.h
index ebb882c..a086eb2 100644
--- a/net/third_party/quic/test_tools/simulator/simulator.h
+++ b/net/third_party/quic/test_tools/simulator/simulator.h
@@ -22,6 +22,8 @@
 class Simulator : public QuicConnectionHelperInterface {
  public:
   Simulator();
+  Simulator(const Simulator&) = delete;
+  Simulator& operator=(const Simulator&) = delete;
   ~Simulator() override;
 
   // Register an actor with the simulator.  Returns a handle which the actor can
@@ -125,8 +127,6 @@
   // unscheduled actors is QuicTime::Infinite().
   QuicUnorderedMap<Actor*, QuicTime> scheduled_times_;
   QuicUnorderedSet<std::string> actor_names_;
-
-  DISALLOW_COPY_AND_ASSIGN(Simulator);
 };
 
 template <class TerminationPredicate>
diff --git a/net/third_party/quic/test_tools/simulator/switch.h b/net/third_party/quic/test_tools/simulator/switch.h
index f344a425..0b272f3 100644
--- a/net/third_party/quic/test_tools/simulator/switch.h
+++ b/net/third_party/quic/test_tools/simulator/switch.h
@@ -23,6 +23,8 @@
          std::string name,
          SwitchPortNumber port_count,
          QuicByteCount queue_capacity);
+  Switch(const Switch&) = delete;
+  Switch& operator=(const Switch&) = delete;
   ~Switch();
 
   // Returns Endpoint associated with the port under number |port_number|.  Just
@@ -45,6 +47,8 @@
          SwitchPortNumber port_number,
          QuicByteCount queue_capacity);
     Port(Port&&) = delete;
+    Port(const Port&) = delete;
+    Port& operator=(const Port&) = delete;
     ~Port() override {}
 
     // Accepts packet to be routed into the switch.
@@ -66,8 +70,6 @@
     bool connected_;
 
     Queue queue_;
-
-    DISALLOW_COPY_AND_ASSIGN(Port);
   };
 
   // Sends the packet to the appropriate port, or to all ports if the
@@ -79,8 +81,6 @@
   // assumed to be stable.
   std::deque<Port> ports_;
   QuicUnorderedMap<std::string, Port*> switching_table_;
-
-  DISALLOW_COPY_AND_ASSIGN(Switch);
 };
 
 }  // namespace simulator
diff --git a/net/third_party/quic/test_tools/simulator/traffic_policer.h b/net/third_party/quic/test_tools/simulator/traffic_policer.h
index 8e389de9..fd38fcf 100644
--- a/net/third_party/quic/test_tools/simulator/traffic_policer.h
+++ b/net/third_party/quic/test_tools/simulator/traffic_policer.h
@@ -25,6 +25,8 @@
                  QuicByteCount max_bucket_size,
                  QuicBandwidth target_bandwidth,
                  Endpoint* input);
+  TrafficPolicer(const TrafficPolicer&) = delete;
+  TrafficPolicer& operator=(const TrafficPolicer&) = delete;
   ~TrafficPolicer() override;
 
  protected:
@@ -44,8 +46,6 @@
 
   // Maps each destination to the number of tokens it has left.
   QuicUnorderedMap<std::string, QuicByteCount> token_buckets_;
-
-  DISALLOW_COPY_AND_ASSIGN(TrafficPolicer);
 };
 
 }  // namespace simulator
diff --git a/net/third_party/quic/tools/quic_backend_response.h b/net/third_party/quic/tools/quic_backend_response.h
index 3d898f8..81698d0 100644
--- a/net/third_party/quic/tools/quic_backend_response.h
+++ b/net/third_party/quic/tools/quic_backend_response.h
@@ -5,7 +5,7 @@
 #ifndef NET_THIRD_PARTY_QUIC_TOOLS_QUIC_BACKEND_RESPONSE_H_
 #define NET_THIRD_PARTY_QUIC_TOOLS_QUIC_BACKEND_RESPONSE_H_
 
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_url.h"
 
 namespace quic {
diff --git a/net/third_party/quic/tools/quic_client.cc b/net/third_party/quic/tools/quic_client.cc
index 97b3feec4..2b00375 100644
--- a/net/third_party/quic/tools/quic_client.cc
+++ b/net/third_party/quic/tools/quic_client.cc
@@ -13,13 +13,13 @@
 
 #include "base/run_loop.h"
 #include "net/third_party/quic/core/crypto/quic_random.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_data_reader.h"
 #include "net/third_party/quic/core/quic_epoll_alarm_factory.h"
 #include "net/third_party/quic/core/quic_epoll_connection_helper.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_server_id.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
diff --git a/net/third_party/quic/tools/quic_client.h b/net/third_party/quic/tools/quic_client.h
index 14747f4..6778176 100644
--- a/net/third_party/quic/tools/quic_client.h
+++ b/net/third_party/quic/tools/quic_client.h
@@ -14,12 +14,12 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 #include "net/third_party/quic/core/quic_config.h"
 #include "net/third_party/quic/core/quic_packet_reader.h"
 #include "net/third_party/quic/core/quic_process_packet_interface.h"
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
-#include "net/third_party/quic/core/quic_spdy_stream.h"
 #include "net/third_party/quic/platform/api/quic_containers.h"
 #include "net/third_party/quic/tools/quic_client_base.h"
 #include "net/third_party/quic/tools/quic_client_epoll_network_helper.h"
@@ -56,6 +56,8 @@
              net::EpollServer* epoll_server,
              std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
              std::unique_ptr<ProofVerifier> proof_verifier);
+  QuicClient(const QuicClient&) = delete;
+  QuicClient& operator=(const QuicClient&) = delete;
 
   ~QuicClient() override;
 
@@ -75,8 +77,6 @@
  private:
   friend class test::QuicClientPeer;
   bool drop_response_body_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicClient);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/tools/quic_client_base.cc b/net/third_party/quic/tools/quic_client_base.cc
index 8166c4e..8b7958d 100644
--- a/net/third_party/quic/tools/quic_client_base.cc
+++ b/net/third_party/quic/tools/quic_client_base.cc
@@ -5,8 +5,8 @@
 #include "net/third_party/quic/tools/quic_client_base.h"
 
 #include "net/third_party/quic/core/crypto/quic_random.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_server_id.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/core/tls_client_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
diff --git a/net/third_party/quic/tools/quic_client_base.h b/net/third_party/quic/tools/quic_client_base.h
index 4503085..e722180 100644
--- a/net/third_party/quic/tools/quic_client_base.h
+++ b/net/third_party/quic/tools/quic_client_base.h
@@ -12,10 +12,10 @@
 
 #include "base/macros.h"
 #include "net/third_party/quic/core/crypto/crypto_handshake.h"
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
 #include "net/third_party/quic/core/quic_config.h"
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
 #include "net/third_party/quic/platform/api/quic_socket_address.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 
@@ -65,6 +65,8 @@
                  QuicAlarmFactory* alarm_factory,
                  std::unique_ptr<NetworkHelper> network_helper,
                  std::unique_ptr<ProofVerifier> proof_verifier);
+  QuicClientBase(const QuicClientBase&) = delete;
+  QuicClientBase& operator=(const QuicClientBase&) = delete;
 
   virtual ~QuicClientBase();
 
@@ -355,8 +357,6 @@
   // The network helper used to create sockets and manage the event loop.
   // Not owned by this class.
   std::unique_ptr<NetworkHelper> network_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicClientBase);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/tools/quic_client_epoll_network_helper.cc b/net/third_party/quic/tools/quic_client_epoll_network_helper.cc
index ae144130..784282f 100644
--- a/net/third_party/quic/tools/quic_client_epoll_network_helper.cc
+++ b/net/third_party/quic/tools/quic_client_epoll_network_helper.cc
@@ -13,13 +13,13 @@
 
 #include "base/run_loop.h"
 #include "net/third_party/quic/core/crypto/quic_random.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_data_reader.h"
 #include "net/third_party/quic/core/quic_epoll_alarm_factory.h"
 #include "net/third_party/quic/core/quic_epoll_connection_helper.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_server_id.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
diff --git a/net/third_party/quic/tools/quic_client_epoll_network_helper.h b/net/third_party/quic/tools/quic_client_epoll_network_helper.h
index 1b20afd..2a6d22e3 100644
--- a/net/third_party/quic/tools/quic_client_epoll_network_helper.h
+++ b/net/third_party/quic/tools/quic_client_epoll_network_helper.h
@@ -14,12 +14,12 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 #include "net/third_party/quic/core/quic_config.h"
 #include "net/third_party/quic/core/quic_packet_reader.h"
 #include "net/third_party/quic/core/quic_process_packet_interface.h"
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
-#include "net/third_party/quic/core/quic_spdy_stream.h"
 #include "net/third_party/quic/platform/api/quic_containers.h"
 #include "net/third_party/quic/tools/quic_client_base.h"
 #include "net/third_party/quic/tools/quic_spdy_client_base.h"
@@ -41,6 +41,9 @@
   // net::EpollServer.
   QuicClientEpollNetworkHelper(net::EpollServer* epoll_server,
                                QuicClientBase* client);
+  QuicClientEpollNetworkHelper(const QuicClientEpollNetworkHelper&) = delete;
+  QuicClientEpollNetworkHelper& operator=(const QuicClientEpollNetworkHelper&) =
+      delete;
 
   ~QuicClientEpollNetworkHelper() override;
 
@@ -130,8 +133,6 @@
   QuicClientBase* client_;
 
   int max_reads_per_epoll_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicClientEpollNetworkHelper);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/tools/quic_memory_cache_backend.cc b/net/third_party/quic/tools/quic_memory_cache_backend.cc
index f6825dd..167fbd93 100644
--- a/net/third_party/quic/tools/quic_memory_cache_backend.cc
+++ b/net/third_party/quic/tools/quic_memory_cache_backend.cc
@@ -6,7 +6,7 @@
 
 #include <utility>
 
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_file_utils.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
diff --git a/net/third_party/quic/tools/quic_memory_cache_backend.h b/net/third_party/quic/tools/quic_memory_cache_backend.h
index 50d03423..ee605a4 100644
--- a/net/third_party/quic/tools/quic_memory_cache_backend.h
+++ b/net/third_party/quic/tools/quic_memory_cache_backend.h
@@ -10,7 +10,7 @@
 #include <memory>
 #include <vector>
 
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_containers.h"
 #include "net/third_party/quic/platform/api/quic_mutex.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
@@ -33,6 +33,8 @@
   class ResourceFile {
    public:
     explicit ResourceFile(const QuicString& file_name);
+    ResourceFile(const ResourceFile&) = delete;
+    ResourceFile& operator=(const ResourceFile&) = delete;
     virtual ~ResourceFile();
 
     void Read();
@@ -68,11 +70,11 @@
     QuicStringPiece host_;
     QuicStringPiece path_;
     QuicMemoryCacheBackend* cache_;
-
-    DISALLOW_COPY_AND_ASSIGN(ResourceFile);
   };
 
   QuicMemoryCacheBackend();
+  QuicMemoryCacheBackend(const QuicMemoryCacheBackend&) = delete;
+  QuicMemoryCacheBackend& operator=(const QuicMemoryCacheBackend&) = delete;
   ~QuicMemoryCacheBackend() override;
 
   // Retrieve a response from this cache for a given host and path..
@@ -184,8 +186,6 @@
   // server threads accessing those responses.
   mutable QuicMutex response_mutex_;
   bool cache_initialized_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicMemoryCacheBackend);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/tools/quic_server.h b/net/third_party/quic/tools/quic_server.h
index 1d5ffa1..322c4ab 100644
--- a/net/third_party/quic/tools/quic_server.h
+++ b/net/third_party/quic/tools/quic_server.h
@@ -42,6 +42,8 @@
              const QuicCryptoServerConfig::ConfigOptions& server_config_options,
              const ParsedQuicVersionVector& supported_versions,
              QuicSimpleServerBackend* quic_simple_server_backend);
+  QuicServer(const QuicServer&) = delete;
+  QuicServer& operator=(const QuicServer&) = delete;
 
   ~QuicServer() override;
 
@@ -148,8 +150,6 @@
   QuicSimpleServerBackend* quic_simple_server_backend_;  // unowned.
 
   base::WeakPtrFactory<QuicServer> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicServer);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/tools/quic_simple_client_session.h b/net/third_party/quic/tools/quic_simple_client_session.h
index 195b40a..05d9121 100644
--- a/net/third_party/quic/tools/quic_simple_client_session.h
+++ b/net/third_party/quic/tools/quic_simple_client_session.h
@@ -5,7 +5,7 @@
 #ifndef NET_THIRD_PARTY_QUIC_TOOLS_QUIC_SIMPLE_CLIENT_SESSION_H_
 #define NET_THIRD_PARTY_QUIC_TOOLS_QUIC_SIMPLE_CLIENT_SESSION_H_
 
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
 #include "net/third_party/quic/tools/quic_simple_client_stream.h"
 
 namespace quic {
diff --git a/net/third_party/quic/tools/quic_simple_client_stream.h b/net/third_party/quic/tools/quic_simple_client_stream.h
index d50c107..dc6abf4c 100644
--- a/net/third_party/quic/tools/quic_simple_client_stream.h
+++ b/net/third_party/quic/tools/quic_simple_client_stream.h
@@ -5,7 +5,7 @@
 #ifndef NET_THIRD_PARTY_QUIC_TOOLS_QUIC_SIMPLE_CLIENT_STREAM_H_
 #define NET_THIRD_PARTY_QUIC_TOOLS_QUIC_SIMPLE_CLIENT_STREAM_H_
 
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
 
 namespace quic {
 
diff --git a/net/third_party/quic/tools/quic_simple_dispatcher.h b/net/third_party/quic/tools/quic_simple_dispatcher.h
index fa460723..25414a1 100644
--- a/net/third_party/quic/tools/quic_simple_dispatcher.h
+++ b/net/third_party/quic/tools/quic_simple_dispatcher.h
@@ -5,8 +5,8 @@
 #ifndef NET_THIRD_PARTY_QUIC_TOOLS_QUIC_SIMPLE_DISPATCHER_H_
 #define NET_THIRD_PARTY_QUIC_TOOLS_QUIC_SIMPLE_DISPATCHER_H_
 
+#include "net/third_party/quic/core/http/quic_server_session_base.h"
 #include "net/third_party/quic/core/quic_dispatcher.h"
-#include "net/third_party/quic/core/quic_server_session_base.h"
 #include "net/third_party/quic/tools/quic_simple_server_backend.h"
 
 namespace quic {
diff --git a/net/third_party/quic/tools/quic_simple_server_session.h b/net/third_party/quic/tools/quic_simple_server_session.h
index 423e433..2551bc43 100644
--- a/net/third_party/quic/tools/quic_simple_server_session.h
+++ b/net/third_party/quic/tools/quic_simple_server_session.h
@@ -17,10 +17,10 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "net/third_party/quic/core/http/quic_server_session_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_session.h"
 #include "net/third_party/quic/core/quic_crypto_server_stream.h"
 #include "net/third_party/quic/core/quic_packets.h"
-#include "net/third_party/quic/core/quic_server_session_base.h"
-#include "net/third_party/quic/core/quic_spdy_session.h"
 #include "net/third_party/quic/platform/api/quic_containers.h"
 #include "net/third_party/quic/tools/quic_backend_response.h"
 #include "net/third_party/quic/tools/quic_simple_server_backend.h"
@@ -60,6 +60,8 @@
                           const QuicCryptoServerConfig* crypto_config,
                           QuicCompressedCertsCache* compressed_certs_cache,
                           QuicSimpleServerBackend* quic_simple_server_backend);
+  QuicSimpleServerSession(const QuicSimpleServerSession&) = delete;
+  QuicSimpleServerSession& operator=(const QuicSimpleServerSession&) = delete;
 
   ~QuicSimpleServerSession() override;
 
@@ -149,8 +151,6 @@
   QuicDeque<PromisedStreamInfo> promised_streams_;
 
   QuicSimpleServerBackend* quic_simple_server_backend_;  // Not owned.
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerSession);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/tools/quic_simple_server_session_test.cc b/net/third_party/quic/tools/quic_simple_server_session_test.cc
index 8352e96a..c9c76aa 100644
--- a/net/third_party/quic/tools/quic_simple_server_session_test.cc
+++ b/net/third_party/quic/tools/quic_simple_server_session_test.cc
@@ -31,7 +31,6 @@
 #include "net/third_party/quic/test_tools/quic_sent_packet_manager_peer.h"
 #include "net/third_party/quic/test_tools/quic_session_peer.h"
 #include "net/third_party/quic/test_tools/quic_spdy_session_peer.h"
-#include "net/third_party/quic/test_tools/quic_spdy_stream_peer.h"
 #include "net/third_party/quic/test_tools/quic_stream_peer.h"
 #include "net/third_party/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h"
 #include "net/third_party/quic/test_tools/quic_test_utils.h"
@@ -88,7 +87,10 @@
                 enable_quic_stateless_reject_support),  // NOLINT
             session,
             helper) {}
-  ~MockQuicCryptoServerStream() override = default;
+  MockQuicCryptoServerStream(const MockQuicCryptoServerStream&) = delete;
+  MockQuicCryptoServerStream& operator=(const MockQuicCryptoServerStream&) =
+      delete;
+  ~MockQuicCryptoServerStream() override {}
 
   MOCK_METHOD1(SendServerConfigUpdate,
                void(const CachedNetworkParameters* cached_network_parameters));
@@ -104,8 +106,6 @@
 
  private:
   bool encryption_established_override_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream);
 };
 
 class MockQuicConnectionWithSendStreamData : public MockQuicConnection {
diff --git a/net/third_party/quic/tools/quic_simple_server_stream.cc b/net/third_party/quic/tools/quic_simple_server_stream.cc
index ee33460..eac3e0c 100644
--- a/net/third_party/quic/tools/quic_simple_server_stream.cc
+++ b/net/third_party/quic/tools/quic_simple_server_stream.cc
@@ -7,8 +7,8 @@
 #include <list>
 #include <utility>
 
-#include "net/third_party/quic/core/quic_spdy_stream.h"
-#include "net/third_party/quic/core/spdy_utils.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
diff --git a/net/third_party/quic/tools/quic_simple_server_stream.h b/net/third_party/quic/tools/quic_simple_server_stream.h
index 8dd096a..226210b 100644
--- a/net/third_party/quic/tools/quic_simple_server_stream.h
+++ b/net/third_party/quic/tools/quic_simple_server_stream.h
@@ -7,9 +7,9 @@
 
 #include "base/macros.h"
 #include "net/http/http_response_headers.h"
+#include "net/third_party/quic/core/http/quic_spdy_server_stream_base.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 #include "net/third_party/quic/core/quic_packets.h"
-#include "net/third_party/quic/core/quic_spdy_server_stream_base.h"
-#include "net/third_party/quic/core/quic_spdy_stream.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 #include "net/third_party/quic/tools/quic_backend_response.h"
 #include "net/third_party/quic/tools/quic_simple_server_backend.h"
@@ -29,6 +29,8 @@
   QuicSimpleServerStream(QuicStreamId id,
                          QuicSpdySession* session,
                          QuicSimpleServerBackend* quic_simple_server_backend);
+  QuicSimpleServerStream(const QuicSimpleServerStream&) = delete;
+  QuicSimpleServerStream& operator=(const QuicSimpleServerStream&) = delete;
   ~QuicSimpleServerStream() override;
 
   // QuicSpdyStream
@@ -97,8 +99,6 @@
   QuicString body_;
 
   QuicSimpleServerBackend* quic_simple_server_backend_;  // Not owned.
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSimpleServerStream);
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/tools/quic_simple_server_stream_test.cc b/net/third_party/quic/tools/quic_simple_server_stream_test.cc
index 771a7c4..8fcd565 100644
--- a/net/third_party/quic/tools/quic_simple_server_stream_test.cc
+++ b/net/third_party/quic/tools/quic_simple_server_stream_test.cc
@@ -9,8 +9,8 @@
 #include <utility>
 
 #include "net/test/gtest_util.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_utils.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/core/tls_server_handshaker.h"
 #include "net/third_party/quic/platform/api/quic_arraysize.h"
 #include "net/third_party/quic/platform/api/quic_expect_bug.h"
@@ -103,6 +103,9 @@
         .WillByDefault(testing::Return(QuicConsumedData(0, false)));
   }
 
+  MockQuicSimpleServerSession(const MockQuicSimpleServerSession&) = delete;
+  MockQuicSimpleServerSession& operator=(const MockQuicSimpleServerSession&) =
+      delete;
   ~MockQuicSimpleServerSession() override = default;
 
   MOCK_METHOD3(OnConnectionClosed,
@@ -165,9 +168,6 @@
   using QuicSession::ActivateStream;
 
   spdy::SpdyHeaderBlock original_request_headers_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockQuicSimpleServerSession);
 };
 
 class QuicSimpleServerStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
diff --git a/net/third_party/quic/tools/quic_spdy_client_base.cc b/net/third_party/quic/tools/quic_spdy_client_base.cc
index 0d34d46..b88fd79 100644
--- a/net/third_party/quic/tools/quic_spdy_client_base.cc
+++ b/net/third_party/quic/tools/quic_spdy_client_base.cc
@@ -5,8 +5,8 @@
 #include "net/third_party/quic/tools/quic_spdy_client_base.h"
 
 #include "net/third_party/quic/core/crypto/quic_random.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_server_id.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
diff --git a/net/third_party/quic/tools/quic_spdy_client_base.h b/net/third_party/quic/tools/quic_spdy_client_base.h
index c896447..edb2003 100644
--- a/net/third_party/quic/tools/quic_spdy_client_base.h
+++ b/net/third_party/quic/tools/quic_spdy_client_base.h
@@ -12,10 +12,10 @@
 
 #include "base/macros.h"
 #include "net/third_party/quic/core/crypto/crypto_handshake.h"
-#include "net/third_party/quic/core/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
+#include "net/third_party/quic/core/http/quic_spdy_client_stream.h"
 #include "net/third_party/quic/core/quic_config.h"
-#include "net/third_party/quic/core/quic_spdy_client_session.h"
-#include "net/third_party/quic/core/quic_spdy_client_stream.h"
 #include "net/third_party/quic/platform/api/quic_socket_address.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 #include "net/third_party/quic/tools/quic_client_base.h"
@@ -53,6 +53,8 @@
     QuicDataToResend(std::unique_ptr<spdy::SpdyHeaderBlock> headers,
                      QuicStringPiece body,
                      bool fin);
+    QuicDataToResend(const QuicDataToResend&) = delete;
+    QuicDataToResend& operator=(const QuicDataToResend&) = delete;
 
     virtual ~QuicDataToResend();
 
@@ -64,9 +66,6 @@
     std::unique_ptr<spdy::SpdyHeaderBlock> headers_;
     QuicStringPiece body_;
     bool fin_;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(QuicDataToResend);
   };
 
   QuicSpdyClientBase(const QuicServerId& server_id,
@@ -76,6 +75,8 @@
                      QuicAlarmFactory* alarm_factory,
                      std::unique_ptr<NetworkHelper> network_helper,
                      std::unique_ptr<ProofVerifier> proof_verifier);
+  QuicSpdyClientBase(const QuicSpdyClientBase&) = delete;
+  QuicSpdyClientBase& operator=(const QuicSpdyClientBase&) = delete;
 
   ~QuicSpdyClientBase() override;
 
@@ -171,14 +172,14 @@
       DCHECK(client);
     }
 
+    ClientQuicDataToResend(const ClientQuicDataToResend&) = delete;
+    ClientQuicDataToResend& operator=(const ClientQuicDataToResend&) = delete;
     ~ClientQuicDataToResend() override {}
 
     void Resend() override;
 
    private:
     QuicSpdyClientBase* client_;
-
-    DISALLOW_COPY_AND_ASSIGN(ClientQuicDataToResend);
   };
 
   // Index of pending promised streams. Must outlive |session_|.
@@ -207,8 +208,6 @@
   std::vector<std::unique_ptr<QuicDataToResend>> data_to_resend_on_connect_;
 
   std::unique_ptr<ClientQuicDataToResend> push_promise_data_to_resend_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicSpdyClientBase);
 };
 
 }  // namespace quic
diff --git a/net/tools/quic/quic_client_message_loop_network_helper.cc b/net/tools/quic/quic_client_message_loop_network_helper.cc
index c6154de..25a00eb 100644
--- a/net/tools/quic/quic_client_message_loop_network_helper.cc
+++ b/net/tools/quic/quic_client_message_loop_network_helper.cc
@@ -21,10 +21,10 @@
 #include "net/socket/udp_client_socket.h"
 #include "net/spdy/spdy_http_utils.h"
 #include "net/third_party/quic/core/crypto/quic_random.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_server_id.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/spdy/core/spdy_header_block.h"
diff --git a/net/tools/quic/quic_client_message_loop_network_helper.h b/net/tools/quic/quic_client_message_loop_network_helper.h
index a41f7fd3..a4e7d42 100644
--- a/net/tools/quic/quic_client_message_loop_network_helper.h
+++ b/net/tools/quic/quic_client_message_loop_network_helper.h
@@ -20,8 +20,8 @@
 #include "net/http/http_response_headers.h"
 #include "net/log/net_log.h"
 #include "net/quic/chromium/quic_chromium_packet_reader.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 #include "net/third_party/quic/core/quic_config.h"
-#include "net/third_party/quic/core/quic_spdy_stream.h"
 #include "net/third_party/quic/platform/impl/quic_chromium_clock.h"
 #include "net/third_party/quic/tools/quic_spdy_client_base.h"
 
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc
index ac17ee6c..d743f723 100644
--- a/net/tools/quic/quic_simple_client.cc
+++ b/net/tools/quic/quic_simple_client.cc
@@ -21,10 +21,10 @@
 #include "net/socket/udp_client_socket.h"
 #include "net/spdy/spdy_http_utils.h"
 #include "net/third_party/quic/core/crypto/quic_random.h"
+#include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_server_id.h"
-#include "net/third_party/quic/core/spdy_utils.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/spdy/core/spdy_header_block.h"
diff --git a/net/tools/quic/quic_simple_client.h b/net/tools/quic/quic_simple_client.h
index d9144b36..4d73cda8 100644
--- a/net/tools/quic/quic_simple_client.h
+++ b/net/tools/quic/quic_simple_client.h
@@ -20,8 +20,8 @@
 #include "net/http/http_response_headers.h"
 #include "net/log/net_log.h"
 #include "net/quic/chromium/quic_chromium_packet_reader.h"
+#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 #include "net/third_party/quic/core/quic_config.h"
-#include "net/third_party/quic/core/quic_spdy_stream.h"
 #include "net/third_party/quic/platform/impl/quic_chromium_clock.h"
 #include "net/third_party/quic/tools/quic_spdy_client_base.h"
 #include "net/tools/quic/quic_client_message_loop_network_helper.h"
diff --git a/net/tools/quic/quic_simple_server_session_helper.h b/net/tools/quic/quic_simple_server_session_helper.h
index b176e26..46f3b65 100644
--- a/net/tools/quic/quic_simple_server_session_helper.h
+++ b/net/tools/quic/quic_simple_server_session_helper.h
@@ -6,7 +6,7 @@
 #define NET_TOOLS_QUIC_QUIC_SIMPLE_SERVER_SESSION_HELPER_H_
 
 #include "net/third_party/quic/core/crypto/quic_random.h"
-#include "net/third_party/quic/core/quic_server_session_base.h"
+#include "net/third_party/quic/core/http/quic_server_session_base.h"
 
 namespace net {
 
diff --git a/ppapi/generators/idl_ast.py b/ppapi/generators/idl_ast.py
index 515dbb0..e95e94e 100644
--- a/ppapi/generators/idl_ast.py
+++ b/ppapi/generators/idl_ast.py
@@ -178,5 +178,3 @@
       errors = filenode.GetProperty('ERRORS')
       if errors:
         self.errors += errors
-
-
diff --git a/ppapi/generators/idl_c_header.py b/ppapi/generators/idl_c_header.py
index b4b98227..9b4513ac 100755
--- a/ppapi/generators/idl_c_header.py
+++ b/ppapi/generators/idl_c_header.py
@@ -371,4 +371,3 @@
 
 if __name__ == '__main__':
   sys.exit(main(sys.argv[1:]))
-
diff --git a/ppapi/generators/idl_namespace.py b/ppapi/generators/idl_namespace.py
index b81411e..21a643c 100755
--- a/ppapi/generators/idl_namespace.py
+++ b/ppapi/generators/idl_namespace.py
@@ -246,4 +246,3 @@
 
 if __name__ == '__main__':
   sys.exit(Main(sys.argv[1:]))
-
diff --git a/ppapi/generators/idl_node.py b/ppapi/generators/idl_node.py
index 55b24d1..feeb430 100755
--- a/ppapi/generators/idl_node.py
+++ b/ppapi/generators/idl_node.py
@@ -444,4 +444,3 @@
 
 if __name__ == '__main__':
   sys.exit(Main())
-
diff --git a/ppapi/generators/idl_parser.py b/ppapi/generators/idl_parser.py
index 823dcf5a..fdd5e88c 100755
--- a/ppapi/generators/idl_parser.py
+++ b/ppapi/generators/idl_parser.py
@@ -1293,4 +1293,3 @@
 
 if __name__ == '__main__':
   sys.exit(Main(sys.argv[1:]))
-
diff --git a/ppapi/generators/idl_propertynode.py b/ppapi/generators/idl_propertynode.py
index e15354a..9152ed7 100755
--- a/ppapi/generators/idl_propertynode.py
+++ b/ppapi/generators/idl_propertynode.py
@@ -111,4 +111,3 @@
 
 if __name__ == '__main__':
   sys.exit(Main())
-
diff --git a/ppapi/generators/idl_release.py b/ppapi/generators/idl_release.py
index ff4aa01d..44068548 100755
--- a/ppapi/generators/idl_release.py
+++ b/ppapi/generators/idl_release.py
@@ -353,4 +353,3 @@
 
 if __name__ == '__main__':
   sys.exit(Main(sys.argv[1:]))
-
diff --git a/ppapi/generators/idl_tests.py b/ppapi/generators/idl_tests.py
index bf6d8a1..b41bb0f66 100755
--- a/ppapi/generators/idl_tests.py
+++ b/ppapi/generators/idl_tests.py
@@ -42,4 +42,3 @@
 
 if __name__ == '__main__':
   sys.exit(main(sys.argv[1:]))
-
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc
index dfc727dd..285f46b 100644
--- a/services/identity/public/cpp/identity_manager.cc
+++ b/services/identity/public/cpp/identity_manager.cc
@@ -260,9 +260,9 @@
   // TODO(843510): Consider setting this info and notifying observers
   // asynchronously in response to GoogleSigninSucceeded() once there are no
   // direct clients of SigninManager.
-  DCHECK(account_info.account_id == primary_account_info_.account_id);
-  DCHECK(account_info.gaia == primary_account_info_.gaia);
-  DCHECK(account_info.email == primary_account_info_.email);
+  DCHECK_EQ(account_info.account_id, primary_account_info_.account_id);
+  DCHECK_EQ(account_info.gaia, primary_account_info_.gaia);
+  DCHECK(gaia::AreEmailsSame(account_info.email, primary_account_info_.email));
   primary_account_info_ = AccountInfo();
 }
 #endif
diff --git a/services/identity/public/cpp/identity_test_utils.cc b/services/identity/public/cpp/identity_test_utils.cc
index 309f856..f1704081 100644
--- a/services/identity/public/cpp/identity_test_utils.cc
+++ b/services/identity/public/cpp/identity_test_utils.cc
@@ -194,7 +194,7 @@
   return account_info;
 }
 
-void ClearPrimaryAccount(SigninManagerForTest* signin_manager,
+void ClearPrimaryAccount(SigninManagerBase* signin_manager,
                          IdentityManager* identity_manager) {
 #if defined(OS_CHROMEOS)
   // TODO(blundell): If we ever need this functionality on ChromeOS (which seems
@@ -209,7 +209,10 @@
       identity_manager, run_loop.QuitClosure(),
       IdentityManagerEvent::PRIMARY_ACCOUNT_CLEARED);
 
-  signin_manager->ForceSignOut();
+  SigninManager* real_signin_manager =
+      SigninManager::FromSigninManagerBase(signin_manager);
+  real_signin_manager->SignOut(signin_metrics::SIGNOUT_TEST,
+                               signin_metrics::SignoutDelete::IGNORE_METRIC);
 
   run_loop.Run();
 #endif
diff --git a/services/identity/public/cpp/identity_test_utils.h b/services/identity/public/cpp/identity_test_utils.h
index ac550f4..e72264fc 100644
--- a/services/identity/public/cpp/identity_test_utils.h
+++ b/services/identity/public/cpp/identity_test_utils.h
@@ -79,11 +79,7 @@
 // Clears the primary account. On non-ChromeOS, results in the firing of the
 // IdentityManager and SigninManager callbacks for signout. Blocks until the
 // primary account is cleared.
-// Note that this function requires FakeSigninManager, as it internally invokes
-// functionality of the fake. If a use case emerges for invoking this
-// functionality with a production SigninManager, contact blundell@chromium.org.
-// NOTE: See disclaimer at top of file re: direct usage.
-void ClearPrimaryAccount(SigninManagerForTest* signin_manager,
+void ClearPrimaryAccount(SigninManagerBase* signin_manager,
                          IdentityManager* identity_manager);
 
 // Makes an account available for the given email address, generating a GAIA ID
diff --git a/storage/OWNERS b/storage/OWNERS
index 4cc173f..ca4682d 100644
--- a/storage/OWNERS
+++ b/storage/OWNERS
@@ -1,5 +1,6 @@
 dmurph@chromium.org
 jsbell@chromium.org
+pwnall@chromium.org
 kinuko@chromium.org
 
 # TEAM: storage-dev@chromium.org
diff --git a/testing/libfuzzer/fuzzers/v8_fuzzer.cc b/testing/libfuzzer/fuzzers/v8_fuzzer.cc
index 3f95f34..ec2c0b6 100644
--- a/testing/libfuzzer/fuzzers/v8_fuzzer.cc
+++ b/testing/libfuzzer/fuzzers/v8_fuzzer.cc
@@ -113,7 +113,11 @@
   bool is_running;
 };
 
-extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
+// Explicitly specify some attributes to avoid issues with the linker dead-
+// stripping the following function on macOS, as it is not called directly
+// by fuzz target. LibFuzzer runtime uses dlsym() to resolve that function.
+extern "C" __attribute__((used)) __attribute__((visibility("default"))) int
+LLVMFuzzerInitialize(int* argc, char*** argv) {
   v8::V8::InitializeICUDefaultLocation((*argv)[0]);
   v8::V8::InitializeExternalStartupData((*argv)[0]);
   v8::V8::SetFlagsFromCommandLine(argc, *argv, true);
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 3fb4f9e..1afbf9fd 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -488,7 +488,6 @@
 crbug.com/591099 fast/block/positioning/positioned-child-inside-relative-positioned-anonymous-block.html [ Failure ]
 crbug.com/591099 fast/borders/bidi-002.html [ Failure ]
 crbug.com/859497 fast/borders/bidi-009a.html [ Failure ]
-crbug.com/591099 fast/borders/border-image-border-radius.html [ Failure ]
 crbug.com/591099 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ]
 crbug.com/591099 fast/box-shadow/box-shadow.html [ Failure ]
 crbug.com/591099 fast/box-sizing/replaced.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 4c29df8..34dea75 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2657,6 +2657,15 @@
 crbug.com/849859 external/wpt/web-animations/timing-model/animations/pausing-an-animation.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/svg/render/reftests/blending-002.svg [ Failure ]
+crbug.com/626703 external/wpt/svg/render/reftests/blending-001.svg [ Failure ]
+crbug.com/626703 [ Win7 ] external/wpt/css/css-lists/content-property/marker-text-matches-armenian.html [ Failure ]
+crbug.com/626703 [ Mac ] external/wpt/css/css-lists/content-property/marker-text-matches-upper-latin.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-lists/content-property/marker-text-matches-disc.html [ Failure ]
+crbug.com/626703 [ Win ] external/wpt/css/css-lists/content-property/marker-text-matches-georgian.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-lists/content-property/marker-text-matches-square.html [ Failure ]
+crbug.com/626703 external/wpt/svg/linking/reftests/use-descendant-combinator-003.html [ Failure ]
+crbug.com/626703 external/wpt/css/css-lists/content-property/marker-text-matches-circle.html [ Failure ]
 crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-safe-overflow-position-001.html [ Failure ]
 crbug.com/626703 external/wpt/content-security-policy/securitypolicyviolation/inside-service-worker.https.html [ Timeout ]
 crbug.com/626703 external/wpt/content-security-policy/securitypolicyviolation/inside-shared-worker.html [ Timeout ]
@@ -3745,7 +3754,8 @@
 
 crbug.com/689781 external/wpt/media-source/mediasource-duration.html [ Failure Pass ]
 
-# When WebAssembly is exposed in V8 (soon), this test has the wrong number of expected Object.getOwnPropertyNames() for global object.
+crbug.com/860637 http/tests/wasm_streaming/regression860637.html [ Skip ]
+crbug.com/860637 virtual/enable_wasm_streaming/http/tests/wasm_streaming/regression860637.html [ Skip ]
 
 crbug.com/681468 fast/forms/suggestion-picker/date-suggestion-picker-appearance-zoom125.html [ Failure Pass ]
 crbug.com/681468 fast/forms/suggestion-picker/date-suggestion-picker-appearance-zoom200.html [ Failure Pass ]
@@ -4612,14 +4622,6 @@
 crbug.com/856601 [ Linux ] external/wpt/touch-events/idlharness.window.html [ Timeout Pass ]
 crbug.com/856601 [ Linux ] http/tests/event-timing/event-timing-retrievability.html [ Timeout Pass ]
 
-### fast/canvas/color-space/ + virtual/gpu/..., color management and transparency.
-crbug.com/859102 fast/canvas/color-space/canvas-drawImage-linear-rgb.html [ Pass Failure ]
-crbug.com/859102 fast/canvas/color-space/canvas-drawImage-p3.html [ Pass Failure ]
-crbug.com/859102 fast/canvas/color-space/canvas-drawImage-rec2020.html [ Pass Failure ]
-crbug.com/859102 virtual/gpu/fast/canvas/color-space/canvas-drawImage-linear-rgb.html [ Pass Failure ]
-crbug.com/859102 virtual/gpu/fast/canvas/color-space/canvas-drawImage-p3.html [ Pass Failure ]
-crbug.com/859102 virtual/gpu/fast/canvas/color-space/canvas-drawImage-rec2020.html [ Pass Failure ]
-
 # Sheriff 2018-07-11
 # Test timeouts following wpt-import@89ccb892...
 crbug.com/862588 [ Linux ] external/wpt/cookie-store/idlharness.tentative.https.html [ Timeout Pass ]
@@ -4627,7 +4629,6 @@
 crbug.com/862588 [ Linux ] external/wpt/push-api/idlharness.https.any.worker.html [ Timeout Pass ]
 crbug.com/862588 [ Linux ] external/wpt/resource-timing/idlharness.any.html [ Timeout Pass ]
 crbug.com/862588 [ Linux ] external/wpt/resource-timing/idlharness.any.worker.html [ Timeout Pass ]
-crbug.com/862588 [ Linux ] external/wpt/selection/interfaces.html [ Timeout Pass ]
 crbug.com/862588 [ Linux ] external/wpt/service-workers/service-worker/interfaces-sw.https.html [ Timeout Pass ]
 crbug.com/862588 [ Linux ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/idlharness.https.window.html [ Timeout Pass ]
 
@@ -4658,3 +4659,21 @@
 crbug.com/866785 [ Mac ] svg/as-border-image/svg-as-border-image-2.html [ Failure Pass ]
 crbug.com/866785 [ Mac ] svg/as-border-image/svg-as-border-image.html [ Failure Pass ]
 crbug.com/866785 [ Mac ] virtual/new-remote-playback-pipeline/media/controls/text-track-menu-pointer-selection.html [ Failure Pass ]
+
+### fast/canvas/color-space/ + virtual/gpu/..., color management and transparency.
+crbug.com/859102 fast/canvas/color-space/canvas-drawImage-linear-rgb.html [ Pass Failure ]
+crbug.com/859102 fast/canvas/color-space/canvas-drawImage-p3.html [ Pass Failure ]
+crbug.com/859102 fast/canvas/color-space/canvas-drawImage-rec2020.html [ Pass Failure ]
+crbug.com/859102 virtual/gpu/fast/canvas/color-space/canvas-drawImage-linear-rgb.html [ Pass Failure ]
+crbug.com/859102 virtual/gpu/fast/canvas/color-space/canvas-drawImage-p3.html [ Pass Failure ]
+crbug.com/859102 virtual/gpu/fast/canvas/color-space/canvas-drawImage-rec2020.html [ Pass Failure ]
+
+### virtual/gpu/fast/canvas/ blending layout tests timeout
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blend-image.html [ Pass Timeout ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-gradient-over-image.html [ Pass Timeout ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-image-over-image.html [ Pass Timeout ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-color.html [ Pass Timeout ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-gradient.html [ Pass Timeout ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-image.html [ Pass Timeout ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-p3.html [ Pass Timeout ]
+crbug.com/866850 [ Linux Mac ] virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/css-parser/unitless-length-quirk.html b/third_party/WebKit/LayoutTests/css-parser/unitless-length-quirk.html
index c0afd56b..1bd667db 100644
--- a/third_party/WebKit/LayoutTests/css-parser/unitless-length-quirk.html
+++ b/third_party/WebKit/LayoutTests/css-parser/unitless-length-quirk.html
@@ -9,6 +9,6 @@
 
 assert_invalid_value("outlineWidth", "50");
 assert_invalid_value("offsetDistance", "60");
-assert_invalid_value("webkitPaddingStart", "12");
-assert_invalid_value("webkitMarginBefore", "24");
+assert_invalid_value("paddingInlineStart", "12");
+assert_invalid_value("marginBlockStart", "24");
 </script>
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-2.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-2.html
index 4117697d..f6a040e 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-2.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-2.html
@@ -66,57 +66,57 @@
 
 <div class="flexbox">
   <div class="first" data-expected-width="75" data-offset-x="0" style="flex: 1 0 0; margin: 0 auto;"></div>
-  <div class="second" data-expected-width="350" data-offset-x="75" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-x="275"></div></div>
-  <div class="third" data-expected-width="75" data-offset-x="425" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div class="second" data-expected-width="350" data-offset-x="75" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-x="275"></div></div>
+  <div class="third" data-expected-width="75" data-offset-x="425" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 
 <div class="flexbox rtl">
   <div class="first" data-expected-width="75" data-offset-x="525" style="flex: 1 0 0; margin: 0 auto;"></div>
-  <div class="second" data-expected-width="350" data-offset-x="175" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-x="175"></div></div>
-  <div class="third" data-expected-width="75" data-offset-x="100" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div class="second" data-expected-width="350" data-offset-x="175" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-x="175"></div></div>
+  <div class="third" data-expected-width="75" data-offset-x="100" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 
 <div class="flexbox row-reverse">
   <div class="first" data-expected-width="75" data-offset-x="525" style="flex: 1 0 0; margin: 0 auto;"></div>
-  <div class="second" data-expected-width="350" data-offset-x="175" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-x="375"></div></div>
-  <div class="third" data-expected-width="75" data-offset-x="0" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div class="second" data-expected-width="350" data-offset-x="175" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-x="375"></div></div>
+  <div class="third" data-expected-width="75" data-offset-x="0" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 
 <div class="flexbox rtl row-reverse">
   <div class="first" data-expected-width="75" data-offset-x="0" style="flex: 1 0 0; margin: 0 auto;"></div>
-  <div class="second" data-expected-width="350" data-offset-x="75" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-x="75"></div></div>
-  <div class="third" data-expected-width="75" data-offset-x="525" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div class="second" data-expected-width="350" data-offset-x="75" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-x="75"></div></div>
+  <div class="third" data-expected-width="75" data-offset-x="525" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 
 <div style="position: relative;">
 <div class="flexbox column">
   <div class="first" data-expected-height="150" data-offset-y="0" style="flex: 1 0 0; margin: auto 200px auto 150px;"></div>
-  <div class="second" data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-y="150" data-offset-x="200"></div></div>
-  <div class="third" data-expected-height="150" data-offset-y="450" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div class="second" data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-y="150" data-offset-x="200"></div></div>
+  <div class="third" data-expected-height="150" data-offset-y="450" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 </div>
 
 <div style="position: relative;">
 <div class="flexbox column-reverse">
   <div class="first" data-expected-height="150" data-offset-y="450" style="flex: 1 0 0; margin: auto 200px auto 150px;"></div>
-  <div class="second" data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-y="150" data-offset-x="200"></div></div>
-  <div class="third" data-expected-height="150" data-offset-y="0" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div class="second" data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-y="150" data-offset-x="200"></div></div>
+  <div class="third" data-expected-height="150" data-offset-y="0" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 </div>
 
 <div style="position: relative;">
 <div class="flexbox column rtl">
   <div class="first" data-expected-height="150" data-offset-y="0" data-offset-x="480" style="flex: 1 0 0; margin: auto 100px auto 50px;"></div>
-  <div class="second" data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-y="150" data-offset-x="380"></div></div>
-  <div class="third" data-expected-height="150" data-offset-y="450" data-offset-x="580" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div class="second" data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-y="150" data-offset-x="380"></div></div>
+  <div class="third" data-expected-height="150" data-offset-y="450" data-offset-x="580" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 </div>
 
 <div style="position: relative;">
 <div class="flexbox column-reverse rtl">
   <div class="first" data-expected-height="150" data-offset-y="450" data-offset-x="480" style="flex: 1 0 0; margin: auto 100px auto 50px;"></div>
-  <div class="second" data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-y="150" data-offset-x="380"></div></div>
-  <div class="third" data-expected-height="150" data-offset-y="0" data-offset-x="580" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div class="second" data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-y="150" data-offset-x="380"></div></div>
+  <div class="third" data-expected-height="150" data-offset-y="0" data-offset-x="580" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 </div>
 
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-auto-margins.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-auto-margins.html
index fcb7c51..3979711 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-auto-margins.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-auto-margins.html
@@ -53,16 +53,16 @@
     margin: 13px auto 17px auto;
 }
 .logical {
-    -webkit-margin-before: 10px;
-    -webkit-margin-after: 30px;
-    -webkit-margin-start: 40px;
-    -webkit-margin-end: 20px;
+    margin-block-start: 10px;
+    margin-block-end: 30px;
+    margin-inline-start: 40px;
+    margin-inline-end: 20px;
 }
 .logical > div {
-    -webkit-margin-before: auto;
-    -webkit-margin-after: 17px;
-    -webkit-margin-start: auto;
-    -webkit-margin-end: 2px;
+    margin-block-start: auto;
+    margin-block-end: 17px;
+    margin-inline-start: auto;
+    margin-inline-end: 2px;
 }
 .flexbox > :nth-child(1) {
     background-color: blue;
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-border.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-border.html
index eba0bb4..cc86577 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-border.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-border.html
@@ -55,16 +55,16 @@
     border-width: 13px 2px 17px 8px;
 }
 .logical {
-    -webkit-border-before-width: 10px;
-    -webkit-border-after-width: 30px;
-    -webkit-border-start-width: 40px;
-    -webkit-border-end-width: 20px;
+    border-block-start-width: 10px;
+    border-block-end-width: 30px;
+    border-inline-start-width: 40px;
+    border-inline-end-width: 20px;
 }
 .logical > div {
-    -webkit-border-before-width: 13px;
-    -webkit-border-after-width: 17px;
-    -webkit-border-start-width: 8px;
-    -webkit-border-end-width: 2px;
+    border-block-start-width: 13px;
+    border-block-end-width: 17px;
+    border-inline-start-width: 8px;
+    border-inline-end-width: 2px;
 }
 .flexbox > :nth-child(1) {
     background-color: blue;
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-margins.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-margins.html
index cb3f930f..2bc8a06 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-margins.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-margins.html
@@ -50,16 +50,16 @@
     margin: 13px 2px 17px 8px;
 }
 .logical {
-    -webkit-margin-before: 10px;
-    -webkit-margin-after: 30px;
-    -webkit-margin-start: 40px;
-    -webkit-margin-end: 20px;
+    margin-block-start: 10px;
+    margin-block-end: 30px;
+    margin-inline-start: 40px;
+    margin-inline-end: 20px;
 }
 .logical > div {
-    -webkit-margin-before: 13px;
-    -webkit-margin-after: 17px;
-    -webkit-margin-start: 8px;
-    -webkit-margin-end: 2px;
+    margin-block-start: 13px;
+    margin-block-end: 17px;
+    margin-inline-start: 8px;
+    margin-inline-end: 2px;
 }
 .flexbox > :nth-child(1) {
     background-color: blue;
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-padding.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-padding.html
index bf0119c..f9cd465 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-padding.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow-padding.html
@@ -50,16 +50,16 @@
     padding: 13px 2px 17px 8px;
 }
 .logical {
-    -webkit-padding-before: 10px;
-    -webkit-padding-after: 30px;
-    -webkit-padding-start: 40px;
-    -webkit-padding-end: 20px;
+    padding-block-start: 10px;
+    padding-block-end: 30px;
+    padding-inline-start: 40px;
+    padding-inline-end: 20px;
 }
 .logical > div {
-    -webkit-padding-before: 13px;
-    -webkit-padding-after: 17px;
-    -webkit-padding-start: 8px;
-    -webkit-padding-end: 2px;
+    padding-block-start: 13px;
+    padding-block-end: 17px;
+    padding-inline-start: 8px;
+    padding-inline-end: 2px;
 }
 .flexbox > :nth-child(1) {
     background-color: blue;
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow.html b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow.html
index b61463a..32938a28 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/flex-flow.html
@@ -66,57 +66,57 @@
 
 <div class="flexbox">
   <div data-expected-width="75" data-offset-x="0" style="flex: 1 0 0; margin: 0 auto;"></div>
-  <div data-expected-width="350" data-offset-x="75" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-x="275"></div></div>
-  <div data-expected-width="75" data-offset-x="425" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div data-expected-width="350" data-offset-x="75" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-x="275"></div></div>
+  <div data-expected-width="75" data-offset-x="425" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 
 <div class="flexbox rtl">
   <div data-expected-width="75" data-offset-x="525" style="flex: 1 0 0; margin: 0 auto;"></div>
-  <div data-expected-width="350" data-offset-x="175" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-x="175"></div></div>
-  <div data-expected-width="75" data-offset-x="100" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div data-expected-width="350" data-offset-x="175" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-x="175"></div></div>
+  <div data-expected-width="75" data-offset-x="100" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 
 <div class="flexbox row-reverse">
   <div data-expected-width="75" data-offset-x="525" style="flex: 1 0 0; margin: 0 auto;"></div>
-  <div data-expected-width="350" data-offset-x="175" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-x="375"></div></div>
-  <div data-expected-width="75" data-offset-x="0" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div data-expected-width="350" data-offset-x="175" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-x="375"></div></div>
+  <div data-expected-width="75" data-offset-x="0" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 
 <div class="flexbox rtl row-reverse">
   <div data-expected-width="75" data-offset-x="0" style="flex: 1 0 0; margin: 0 auto;"></div>
-  <div data-expected-width="350" data-offset-x="75" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-x="75"></div></div>
-  <div data-expected-width="75" data-offset-x="525" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div data-expected-width="350" data-offset-x="75" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-x="75"></div></div>
+  <div data-expected-width="75" data-offset-x="525" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 
 <div style="position: relative;">
 <div class="flexbox column">
   <div data-expected-height="150" data-offset-y="0" style="flex: 1 0 0; margin: auto 200px auto 150px;"></div>
-  <div data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-y="150" data-offset-x="200"></div></div>
-  <div data-expected-height="150" data-offset-y="450" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-y="150" data-offset-x="200"></div></div>
+  <div data-expected-height="150" data-offset-y="450" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 </div>
 
 <div style="position: relative;">
 <div class="flexbox column-reverse">
   <div data-expected-height="150" data-offset-y="450" style="flex: 1 0 0; margin: auto 200px auto 150px;"></div>
-  <div data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-y="150" data-offset-x="200"></div></div>
-  <div data-expected-height="150" data-offset-y="0" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-y="150" data-offset-x="200"></div></div>
+  <div data-expected-height="150" data-offset-y="0" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 </div>
 
 <div style="position: relative;">
 <div class="flexbox column rtl">
   <div data-expected-height="150" data-offset-y="0" data-offset-x="480" style="flex: 1 0 0; margin: auto 100px auto 50px;"></div>
-  <div data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-y="150" data-offset-x="380"></div></div>
-  <div data-expected-height="150" data-offset-y="450" data-offset-x="580" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-y="150" data-offset-x="380"></div></div>
+  <div data-expected-height="150" data-offset-y="450" data-offset-x="580" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 </div>
 
 <div style="position: relative;">
 <div class="flexbox column-reverse rtl">
   <div data-expected-height="150" data-offset-y="450" data-offset-x="480" style="flex: 1 0 0; margin: auto 100px auto 50px;"></div>
-  <div data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; -webkit-padding-start: 200px"><div data-offset-y="150" data-offset-x="380"></div></div>
-  <div data-expected-height="150" data-offset-y="0" data-offset-x="580" style="flex: 1 0 0; -webkit-margin-end: 100px;"></div>
+  <div data-expected-height="300" data-offset-y="150" style="flex: 2 0 0; padding-inline-start: 200px"><div data-offset-y="150" data-offset-x="380"></div></div>
+  <div data-expected-height="150" data-offset-y="0" data-offset-x="580" style="flex: 1 0 0; margin-inline-end: 100px;"></div>
 </div>
 </div>
 
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/multiline-align-self.html b/third_party/WebKit/LayoutTests/css3/flexbox/multiline-align-self.html
index 6ccfdd55..09d2054 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/multiline-align-self.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/multiline-align-self.html
@@ -1037,7 +1037,7 @@
                 flexbox.className = 'flexbox ' + flexboxClassName;
                 flexbox.setAttribute('style', mainAxis + ': 70px');
 
-                var baselineMargin = (flexDirection.indexOf('row') != -1) ? '-webkit-margin-before: 5px;' : '-webkit-margin-start: 5px;';
+                var baselineMargin = (flexDirection.indexOf('row') != -1) ? 'margin-block-start: 5px;' : 'margin-inline-start: 5px;';
 
                 var testExpectations = expectations[writingMode][flexDirection][direction][wrap];
                 addChild(flexbox, mainAxis, crossAxis, 10, '10px', 'flex-start', testExpectations['child1']);
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/multiline-justify-content.html b/third_party/WebKit/LayoutTests/css3/flexbox/multiline-justify-content.html
index dd91223f..a5e18c1 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/multiline-justify-content.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/multiline-justify-content.html
@@ -1985,7 +1985,7 @@
                     flexbox.className = 'flexbox ' + flexboxClassName;
                     flexbox.setAttribute('style', mainAxis + ': 80px');
 
-                    var baselineMargin = (flexDirection.indexOf('row') != -1) ? '-webkit-margin-before: 5px' : '-webkit-margin-start: 5px';
+                    var baselineMargin = (flexDirection.indexOf('row') != -1) ? 'margin-block-start: 5px' : 'margin-inline-start: 5px';
 
                     var testExpectations = expectations[writingMode][flexDirection][direction][wrap][justifyContent];
                     addChild(flexbox, mainAxis, crossAxis, 40, '10', testExpectations['child1']);
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/negative-flex-rounding-assert.html b/third_party/WebKit/LayoutTests/css3/flexbox/negative-flex-rounding-assert.html
index 1daafb9..12abe30 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/negative-flex-rounding-assert.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/negative-flex-rounding-assert.html
@@ -12,10 +12,10 @@
     flex-direction: column;
 }
 .mfrac > :first-child {
-    -webkit-margin-after: 0.2em;
+    margin-block-end: 0.2em;
 }
 .mfrac > :last-child {
-    -webkit-margin-before: 0.2em;
+    margin-block-start: 0.2em;
 }
 .x {
     line-height: 9px;
diff --git a/third_party/WebKit/LayoutTests/css3/flexbox/writing-modes.html b/third_party/WebKit/LayoutTests/css3/flexbox/writing-modes.html
index edfc353c..a819051 100644
--- a/third_party/WebKit/LayoutTests/css3/flexbox/writing-modes.html
+++ b/third_party/WebKit/LayoutTests/css3/flexbox/writing-modes.html
@@ -63,13 +63,13 @@
 <div class="flexbox rtl">
   <div data-expected-width="75" data-offset-x="525" style="flex: 1 0 0; margin: 0 auto;"></div>
   <div data-expected-width="350" data-offset-x="175" style="flex: 2 0 0; padding: 0 100px;"></div>
-  <div data-expected-width="75" data-offset-x="0" style="flex: 1 0 0; -webkit-margin-start: 100px;"></div>
+  <div data-expected-width="75" data-offset-x="0" style="flex: 1 0 0; margin-inline-start: 100px;"></div>
 </div>
 
-<div class="flexbox rtl" style="-webkit-margin-start: 20px;-webkit-margin-end: 50px;">
+<div class="flexbox rtl" style="margin-inline-start: 20px;margin-inline-end: 50px;">
   <div data-expected-width="75" data-offset-x="575" style="flex: 1 0 0; margin: 0 auto;"></div>
   <div data-expected-width="350" data-offset-x="225" style="flex: 2 0 0; padding: 0 100px;"></div>
-  <div data-expected-width="75" data-offset-x="50" style="flex: 1 0 0; -webkit-margin-start: 100px;"></div>
+  <div data-expected-width="75" data-offset-x="50" style="flex: 1 0 0; margin-inline-start: 100px;"></div>
 </div>
 
 <div style="position:relative">
@@ -98,7 +98,7 @@
 
 <div style="position:relative">
 <div class="flexbox vertical-lr">
-  <div data-expected-height="450" data-offset-y="0" style="flex: 1 0 0;-webkit-padding-start:200px;-webkit-padding-end:200px;-webkit-padding-before:100px;-webkit-padding-after:100px;"></div>
+  <div data-expected-height="450" data-offset-y="0" style="flex: 1 0 0;padding-inline-start:200px;padding-inline-end:200px;padding-block-start:100px;padding-block-end:100px;"></div>
   <div data-expected-height="100" data-offset-y="450" style="flex: 2 0 0;"></div>
   <div data-expected-height="50" data-offset-y="550" style="flex: 1 0 0;"></div>
 </div>
@@ -106,7 +106,7 @@
 
 <div style="position:relative">
 <div class="flexbox vertical-lr">
-  <div data-expected-height="300" data-offset-y="0" class="horizontal-tb" style="flex: 1 0 0;-webkit-padding-start:200px;-webkit-padding-end:200px;-webkit-padding-before:100px;-webkit-padding-after:100px;"></div>
+  <div data-expected-height="300" data-offset-y="0" class="horizontal-tb" style="flex: 1 0 0;padding-inline-start:200px;padding-inline-end:200px;padding-block-start:100px;padding-block-end:100px;"></div>
   <div data-expected-height="200" data-offset-y="300" style="flex: 2 0 0;"></div>
   <div data-expected-height="100" data-offset-y="500" style="flex: 1 0 0;"></div>
 </div>
@@ -139,7 +139,7 @@
 
 <div style="position:relative">
 <div class="flexbox vertical-lr">
-  <div data-expected-height="150" data-offset-y="0" style="flex: 1 0 0;-webkit-margin-start:auto;-webkit-margin-end:auto;-webkit-margin-before:0;-webkit-margin-after:0;;"></div>
+  <div data-expected-height="150" data-offset-y="0" style="flex: 1 0 0;margin-inline-start:auto;margin-inline-end:auto;margin-block-start:0;margin-block-end:0;;"></div>
   <div data-expected-height="300" data-offset-y="150" style="flex: 2 0 0;"></div>
   <div data-expected-height="150" data-offset-y="450" style="flex: 1 0 0;"></div>
 </div>
@@ -147,7 +147,7 @@
 
 <div style="position:relative">
 <div class="flexbox vertical-lr">
-  <div data-expected-height="150" data-offset-y="0" class="horizontal-tb" style="flex: 1 0 0;-webkit-margin-start:auto;-webkit-margin-end:auto;-webkit-margin-before:0;-webkit-margin-after:0;;"></div>
+  <div data-expected-height="150" data-offset-y="0" class="horizontal-tb" style="flex: 1 0 0;margin-inline-start:auto;margin-inline-end:auto;margin-block-start:0;margin-block-end:0;;"></div>
   <div data-expected-height="300" data-offset-y="150" style="flex: 2 0 0;"></div>
   <div data-expected-height="150" data-offset-y="450" style="flex: 1 0 0;"></div>
 </div>
@@ -157,7 +157,7 @@
 <div class="flexbox vertical-lr rtl">
   <div data-expected-height="75" data-offset-y="525" style="flex: 1 0 0; margin: auto 0;"></div>
   <div data-expected-height="350" data-offset-y="175" class="horizontal-tb" style="flex: 2 0 0; padding: 100px 0;"></div>
-  <div data-expected-height="75" data-offset-y="0" style="flex: 1 0 0; -webkit-margin-start: 100px;"></div>
+  <div data-expected-height="75" data-offset-y="0" style="flex: 1 0 0; margin-inline-start: 100px;"></div>
 </div>
 </div>
 
diff --git a/third_party/WebKit/LayoutTests/editing/deleting/delete-blockquote-large-offsets.html b/third_party/WebKit/LayoutTests/editing/deleting/delete-blockquote-large-offsets.html
index 7ea982e..991b5cd 100644
--- a/third_party/WebKit/LayoutTests/editing/deleting/delete-blockquote-large-offsets.html
+++ b/third_party/WebKit/LayoutTests/editing/deleting/delete-blockquote-large-offsets.html
@@ -3,7 +3,7 @@
 <body>
 This tests setting caret inside a blockquote with a large offset and running execCommand('Delete').  WebKit should not crash and you should see PASS below:
 <div id="test" contentEditable="true">
-<blockquote type="cite" id="blockquote" style="font-size: 0px; -webkit-min-logical-height: 4px;"><br></blockquote>
+<blockquote type="cite" id="blockquote" style="font-size: 0px; min-block-size: 4px;"><br></blockquote>
 </div>
 <script>
 if (window.testRunner)
diff --git a/third_party/WebKit/LayoutTests/editing/selection/modify_move/move-by-word-visually-crash-test-5.html b/third_party/WebKit/LayoutTests/editing/selection/modify_move/move-by-word-visually-crash-test-5.html
index 5606a3d..e7a6276f 100644
--- a/third_party/WebKit/LayoutTests/editing/selection/modify_move/move-by-word-visually-crash-test-5.html
+++ b/third_party/WebKit/LayoutTests/editing/selection/modify_move/move-by-word-visually-crash-test-5.html
@@ -12,4 +12,4 @@
 <div dir=ltr title="test_for_crash"
 class="test_move_by_word"
 ><plaintext>class="test_move_by_word"
-style="-wap-marquee-style:mix; marker:sliderthumb-vertical; position:-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001; border-top-style:rl-tb; -webkit-padding-after:absolute; position:destination-atop; border:ethiopic-halehame-ti-et; clip-rule:absolute; position:menulist-text; color-profile:-webkit-activelink; position:reset-size; margin-right:message-box; filter:absolute; position:no-punctuation; -webkit-border-end:no-punctuation; border-bottom-style:absolute; position:line-through; text-underline-mode:repeat-y; clip-rule:absolute; position:amharic-abegede; -webkit-text-fill-color:nowrap; -webkit-text-decorations-in-effect:absolute; position:sliderthumb-horizontal; border-top-right-radius:wave; border-top:absolute; position:up; border-right:not-allowed; enable-background:absolute; position:caption; max-height:ne-resize;
+style="-wap-marquee-style:mix; marker:sliderthumb-vertical; position:-0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001; border-top-style:rl-tb; padding-block-end:absolute; position:destination-atop; border:ethiopic-halehame-ti-et; clip-rule:absolute; position:menulist-text; color-profile:-webkit-activelink; position:reset-size; margin-right:message-box; filter:absolute; position:no-punctuation; border-inline-end:no-punctuation; border-bottom-style:absolute; position:line-through; text-underline-mode:repeat-y; clip-rule:absolute; position:amharic-abegede; -webkit-text-fill-color:nowrap; -webkit-text-decorations-in-effect:absolute; position:sliderthumb-horizontal; border-top-right-radius:wave; border-top:absolute; position:up; border-right:not-allowed; enable-background:absolute; position:caption; max-height:ne-resize;
diff --git a/third_party/WebKit/LayoutTests/editing/text-iterator/first_letter_find_string_crash.html b/third_party/WebKit/LayoutTests/editing/text-iterator/first_letter_find_string_crash.html
index 9e84c9270..17155e1 100644
--- a/third_party/WebKit/LayoutTests/editing/text-iterator/first_letter_find_string_crash.html
+++ b/third_party/WebKit/LayoutTests/editing/text-iterator/first_letter_find_string_crash.html
@@ -12,7 +12,7 @@
 
 * {
   -webkit-rtl-ordering: visual;
-  -webkit-margin-end: -1px
+  margin-inline-end: -1px
 }
 </style>
 <font dir="rtl">iC <q></q></font>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 5a010e31..3325142 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -6375,6 +6375,18 @@
      {}
     ]
    ],
+   "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self.html": [
+    [
+     "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self.html",
+     [
+      [
+       "/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self_ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "2dcontext/line-styles/canvas_linestyles_linecap_001.htm": [
     [
      "/2dcontext/line-styles/canvas_linestyles_linecap_001.htm",
@@ -47107,6 +47119,150 @@
      {}
     ]
    ],
+   "css/css-lists/content-property/marker-text-matches-armenian.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-armenian.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-armenian-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-circle.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-circle.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-circle-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-decimal-leading-zero.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-decimal-leading-zero.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-decimal-leading-zero-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-decimal.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-decimal.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-decimal-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-disc.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-disc.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-disc-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-georgian.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-georgian.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-georgian-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-lower-greek.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-lower-greek.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-lower-greek-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-lower-latin.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-lower-latin.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-lower-latin-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-lower-roman.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-lower-roman.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-lower-roman-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-square.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-square.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-square-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-upper-latin.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-upper-latin.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-upper-latin-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-upper-roman.html": [
+    [
+     "/css/css-lists/content-property/marker-text-matches-upper-roman.html",
+     [
+      [
+       "/css/css-lists/content-property/marker-text-matches-upper-roman-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-lists/counter-increment-inside-display-contents.html": [
     [
      "/css/css-lists/counter-increment-inside-display-contents.html",
@@ -52279,6 +52435,18 @@
      {}
     ]
    ],
+   "css/css-pseudo/marker-inherit-line-height.html": [
+    [
+     "/css/css-pseudo/marker-inherit-line-height.html",
+     [
+      [
+       "/css/css-pseudo/marker-inherit-line-height-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-pseudo/marker-inherit-values.html": [
     [
      "/css/css-pseudo/marker-inherit-values.html",
@@ -57595,18 +57763,6 @@
      {}
     ]
    ],
-   "css/css-text/overflow-wrap/overflow-wrap-break-word-004.html": [
-    [
-     "/css/css-text/overflow-wrap/overflow-wrap-break-word-004.html",
-     [
-      [
-       "/css/css-text/overflow-wrap/reference/overflow-wrap-break-word-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-text/overflow-wrap/overflow-wrap-break-word-fit-content-001.html": [
     [
      "/css/css-text/overflow-wrap/overflow-wrap-break-word-fit-content-001.html",
@@ -59587,30 +59743,6 @@
      {}
     ]
    ],
-   "css/css-text/word-break/word-break-break-all-010.html": [
-    [
-     "/css/css-text/word-break/word-break-break-all-010.html",
-     [
-      [
-       "/css/css-text/word-break/reference/word-break-break-all-010-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-text/word-break/word-break-break-all-011.html": [
-    [
-     "/css/css-text/word-break/word-break-break-all-011.html",
-     [
-      [
-       "/css/css-text/word-break/reference/word-break-break-all-010-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-text/word-break/word-break-keep-all-000.html": [
     [
      "/css/css-text/word-break/word-break-keep-all-000.html",
@@ -95871,6 +96003,18 @@
      {}
     ]
    ],
+   "svg/linking/reftests/use-descendant-combinator-003.html": [
+    [
+     "/svg/linking/reftests/use-descendant-combinator-003.html",
+     [
+      [
+       "/svg/linking/reftests/use-descendant-combinator-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "svg/painting/currentColor-override-pserver-fallback.svg": [
     [
      "/svg/painting/currentColor-override-pserver-fallback.svg",
@@ -96063,6 +96207,30 @@
      {}
     ]
    ],
+   "svg/render/reftests/blending-001.svg": [
+    [
+     "/svg/render/reftests/blending-001.svg",
+     [
+      [
+       "/svg/render/reftests/blending-001-ref.svg",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "svg/render/reftests/blending-002.svg": [
+    [
+     "/svg/render/reftests/blending-002.svg",
+     [
+      [
+       "/svg/render/reftests/blending-002-ref.svg",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "svg/rendering/order/z-index.svg": [
     [
      "/svg/rendering/order/z-index.svg",
@@ -100904,6 +101072,11 @@
      {}
     ]
    ],
+   "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self_ref.html": [
+    [
+     {}
+    ]
+   ],
    "2dcontext/drawing-model/.gitkeep": [
     [
      {}
@@ -102559,6 +102732,11 @@
      {}
     ]
    ],
+   "accelerometer/idlharness.https.window-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "accname/description_from_content_of_describedby_element-manual-expected.txt": [
     [
      {}
@@ -103454,6 +103632,26 @@
      {}
     ]
    ],
+   "background-fetch/idlharness.any-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "background-fetch/idlharness.any.sharedworker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "background-fetch/idlharness.any.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "background-fetch/idlharness.https.any.serviceworker-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "background-fetch/interfaces-worker.https-expected.txt": [
     [
      {}
@@ -123129,6 +123327,11 @@
      {}
     ]
    ],
+   "css/css-images/idlharness-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "css/css-images/linear-gradient-ref.html": [
     [
      {}
@@ -123504,6 +123707,66 @@
      {}
     ]
    ],
+   "css/css-lists/content-property/marker-text-matches-armenian-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-circle-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-decimal-leading-zero-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-decimal-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-disc-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-georgian-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-lower-greek-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-lower-latin-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-lower-roman-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-square-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-upper-latin-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-lists/content-property/marker-text-matches-upper-roman-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-lists/counter-7-ref.html": [
     [
      {}
@@ -123534,6 +123797,11 @@
      {}
     ]
    ],
+   "css/css-logical/animation-003.tentative-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "css/css-logical/cascading-001-ref.html": [
     [
      {}
@@ -125059,6 +125327,11 @@
      {}
     ]
    ],
+   "css/css-pseudo/marker-inherit-line-height-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-pseudo/marker-inherit-values-ref.html": [
     [
      {}
@@ -128444,11 +128717,6 @@
      {}
     ]
    ],
-   "css/css-text/word-break/reference/word-break-break-all-010-ref.html": [
-    [
-     {}
-    ]
-   ],
    "css/css-text/word-break/reference/word-break-break-all-ref-000.html": [
     [
      {}
@@ -158309,11 +158577,6 @@
      {}
     ]
    ],
-   "infrastructure/server/wpt-server-http.sub-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "infrastructure/testdriver/send_keys-expected.txt": [
     [
      {}
@@ -158509,6 +158772,11 @@
      {}
     ]
    ],
+   "interfaces/css-counter-styles.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/css-font-loading.idl": [
     [
      {}
@@ -158519,6 +158787,11 @@
      {}
     ]
    ],
+   "interfaces/css-images.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/css-masking.idl": [
     [
      {}
@@ -158529,6 +158802,11 @@
      {}
     ]
    ],
+   "interfaces/css-regions.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/css-transitions.idl": [
     [
      {}
@@ -158669,6 +158947,11 @@
      {}
     ]
    ],
+   "interfaces/media-source.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/mediacapture-depth.idl": [
     [
      {}
@@ -159209,6 +159492,16 @@
      {}
     ]
    ],
+   "media-source/idlharness.any-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "media-source/idlharness.any.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "media-source/import_tests.sh": [
     [
      {}
@@ -161029,11 +161322,6 @@
      {}
     ]
    ],
-   "payment-method-basic-card/idlharness.window-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "payment-method-basic-card/payment-request-canmakepayment-method.https-expected.txt": [
     [
      {}
@@ -164624,6 +164912,11 @@
      {}
     ]
    ],
+   "resize-observer/idlharness.window-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "resize-observer/resources/iframe.html": [
     [
      {}
@@ -165009,6 +165302,11 @@
      {}
     ]
    ],
+   "selection/idlharness.window-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "selection/interfaces-expected.txt": [
     [
      {}
@@ -165899,6 +166197,16 @@
      {}
     ]
    ],
+   "server-timing/resources/parsing/84.js": [
+    [
+     {}
+    ]
+   ],
+   "server-timing/resources/parsing/84.js.sub.headers": [
+    [
+     {}
+    ]
+   ],
    "server-timing/resources/parsing/9.js": [
     [
      {}
@@ -167134,11 +167442,6 @@
      {}
     ]
    ],
-   "service-workers/service-worker/resources/interfaces-idls.js": [
-    [
-     {}
-    ]
-   ],
    "service-workers/service-worker/resources/interfaces-worker.sub.js": [
     [
      {}
@@ -169019,6 +169322,16 @@
      {}
     ]
    ],
+   "svg/render/reftests/blending-001-ref.svg": [
+    [
+     {}
+    ]
+   ],
+   "svg/render/reftests/blending-002-ref.svg": [
+    [
+     {}
+    ]
+   ],
    "svg/rendering/order/z-index-ref.svg": [
     [
      {}
@@ -170434,6 +170747,11 @@
      {}
     ]
    ],
+   "webaudio/idlharness.https.window-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "webaudio/js/buffer-loader.js": [
     [
      {}
@@ -171024,7 +171342,7 @@
      {}
     ]
    ],
-   "webrtc/RTCPeerConnection-addTransceiver-expected.txt": [
+   "webrtc/RTCPeerConnection-addTransceiver.https-expected.txt": [
     [
      {}
     ]
@@ -183901,9 +184219,9 @@
      {}
     ]
    ],
-   "accelerometer/idlharness.https.html": [
+   "accelerometer/idlharness.https.window.js": [
     [
-     "/accelerometer/idlharness.https.html",
+     "/accelerometer/idlharness.https.window.html",
      {}
     ]
    ],
@@ -183979,13 +184297,21 @@
      {}
     ]
    ],
-   "background-fetch/interfaces.https.any.js": [
+   "background-fetch/idlharness.any.js": [
     [
-     "/background-fetch/interfaces.https.any.html",
+     "/background-fetch/idlharness.any.html",
      {}
     ],
     [
-     "/background-fetch/interfaces.https.any.worker.html",
+     "/background-fetch/idlharness.any.sharedworker.html",
+     {}
+    ],
+    [
+     "/background-fetch/idlharness.any.worker.html",
+     {}
+    ],
+    [
+     "/background-fetch/idlharness.https.any.serviceworker.html",
      {}
     ]
    ],
@@ -192021,6 +192347,12 @@
      {}
     ]
    ],
+   "css/css-images/idlharness.html": [
+    [
+     "/css/css-images/idlharness.html",
+     {}
+    ]
+   ],
    "css/css-images/parsing/gradient-position-invalid.html": [
     [
      "/css/css-images/parsing/gradient-position-invalid.html",
@@ -192135,9 +192467,9 @@
      {}
     ]
    ],
-   "css/css-logical/animation-003.tenative.html": [
+   "css/css-logical/animation-003.tentative.html": [
     [
-     "/css/css-logical/animation-003.tenative.html",
+     "/css/css-logical/animation-003.tentative.html",
      {}
     ]
    ],
@@ -216011,15 +216343,15 @@
      {}
     ]
    ],
-   "html/rendering/non-replaced-elements/tables/form-in-tables.html": [
+   "html/rendering/non-replaced-elements/tables/form-in-tables-xhtml.xhtml": [
     [
-     "/html/rendering/non-replaced-elements/tables/form-in-tables.html",
+     "/html/rendering/non-replaced-elements/tables/form-in-tables-xhtml.xhtml",
      {}
     ]
    ],
-   "html/rendering/non-replaced-elements/tables/form-in-tables.xhtml": [
+   "html/rendering/non-replaced-elements/tables/form-in-tables.html": [
     [
-     "/html/rendering/non-replaced-elements/tables/form-in-tables.xhtml",
+     "/html/rendering/non-replaced-elements/tables/form-in-tables.html",
      {}
     ]
    ],
@@ -218979,6 +219311,14 @@
      }
     ]
    ],
+   "html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach.html": [
+    [
+     "/html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach.html",
+     {
+      "timeout": "long"
+     }
+    ]
+   ],
    "html/semantics/embedded-content/the-img-element/decode/image-decode.html": [
     [
      "/html/semantics/embedded-content/the-img-element/decode/image-decode.html",
@@ -220253,18 +220593,42 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-textarea-element/textarea-maxlength.html": [
+    [
+     "/html/semantics/forms/the-textarea-element/textarea-maxlength.html",
+     {}
+    ]
+   ],
+   "html/semantics/forms/the-textarea-element/textarea-minlength.html": [
+    [
+     "/html/semantics/forms/the-textarea-element/textarea-minlength.html",
+     {}
+    ]
+   ],
    "html/semantics/forms/the-textarea-element/textarea-setcustomvalidity.html": [
     [
      "/html/semantics/forms/the-textarea-element/textarea-setcustomvalidity.html",
      {}
     ]
    ],
+   "html/semantics/forms/the-textarea-element/textarea-textLength.html": [
+    [
+     "/html/semantics/forms/the-textarea-element/textarea-textLength.html",
+     {}
+    ]
+   ],
    "html/semantics/forms/the-textarea-element/textarea-type.html": [
     [
      "/html/semantics/forms/the-textarea-element/textarea-type.html",
      {}
     ]
    ],
+   "html/semantics/forms/the-textarea-element/textarea-validity-clone.html": [
+    [
+     "/html/semantics/forms/the-textarea-element/textarea-validity-clone.html",
+     {}
+    ]
+   ],
    "html/semantics/forms/the-textarea-element/value-defaultValue-textContent-xhtml.xhtml": [
     [
      "/html/semantics/forms/the-textarea-element/value-defaultValue-textContent-xhtml.xhtml",
@@ -225895,9 +226259,13 @@
      {}
     ]
    ],
-   "media-source/interfaces.html": [
+   "media-source/idlharness.any.js": [
     [
-     "/media-source/interfaces.html",
+     "/media-source/idlharness.any.html",
+     {}
+    ],
+    [
+     "/media-source/idlharness.any.worker.html",
      {}
     ]
    ],
@@ -247621,9 +247989,9 @@
      {}
     ]
    ],
-   "resize-observer/idlharness.html": [
+   "resize-observer/idlharness.window.js": [
     [
-     "/resize-observer/idlharness.html",
+     "/resize-observer/idlharness.window.html",
      {}
     ]
    ],
@@ -248205,9 +248573,9 @@
      {}
     ]
    ],
-   "selection/interfaces.html": [
+   "selection/idlharness.window.js": [
     [
-     "/selection/interfaces.html",
+     "/selection/idlharness.window.html",
      {}
     ]
    ],
@@ -253789,9 +254157,9 @@
      {}
     ]
    ],
-   "web-share/idlharness.https.html": [
+   "web-share/idlharness.https.window.js": [
     [
-     "/web-share/idlharness.https.html",
+     "/web-share/idlharness.https.window.html",
      {}
     ]
    ],
@@ -253825,9 +254193,9 @@
      {}
     ]
    ],
-   "webaudio/idlharness.https.html": [
+   "webaudio/idlharness.https.window.js": [
     [
-     "/webaudio/idlharness.https.html",
+     "/webaudio/idlharness.https.window.html",
      {
       "timeout": "long"
      }
@@ -255701,9 +256069,9 @@
      {}
     ]
    ],
-   "webrtc/RTCPeerConnection-addTransceiver.html": [
+   "webrtc/RTCPeerConnection-addTransceiver.https.html": [
     [
-     "/webrtc/RTCPeerConnection-addTransceiver.html",
+     "/webrtc/RTCPeerConnection-addTransceiver.https.html",
      {}
     ]
    ],
@@ -258275,9 +258643,9 @@
      }
     ]
    ],
-   "webstorage/idlharness.html": [
+   "webstorage/idlharness.window.js": [
     [
-     "/webstorage/idlharness.html",
+     "/webstorage/idlharness.window.html",
      {}
     ]
    ],
@@ -268664,6 +269032,14 @@
    "3b15af010f2ce13316fed6fcab9d85e05484b60d",
    "testharness"
   ],
+  "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self.html": [
+   "ec6a6d1111aae9ce051cd1a2503a5b01149ceca6",
+   "reftest"
+  ],
+  "2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self_ref.html": [
+   "f09c2922fc630872519fc37de47f232ecc8cc677",
+   "support"
+  ],
   "2dcontext/drawing-images-to-the-canvas/drawimage_html_image.html": [
    "ec86f8f5c84628cd5f3b8673de8dde34dc372fd9",
    "testharness"
@@ -274600,8 +274976,12 @@
    "fccd52aeb8ce8476e31cd5a881c3284fa5c16556",
    "support"
   ],
-  "accelerometer/idlharness.https.html": [
-   "93a78732bf63dcdd30ca1004f7ab850d5e7faaae",
+  "accelerometer/idlharness.https.window-expected.txt": [
+   "b613fec755d4ffdd89b73e672ad6ad85f93a1a07",
+   "support"
+  ],
+  "accelerometer/idlharness.https.window.js": [
+   "80f5c68be13e93686b4851871cc115bad160b633",
    "testharness"
   ],
   "accname/description_from_content_of_describedby_element-manual-expected.txt": [
@@ -275380,6 +275760,26 @@
    "6177ea08e069fd1aca85fd3d772a53022b07f519",
    "support"
   ],
+  "background-fetch/idlharness.any-expected.txt": [
+   "6d0c8ed4939faa52b94fede0968b379edca7daa5",
+   "support"
+  ],
+  "background-fetch/idlharness.any.js": [
+   "5c0eebc307b9cdb534003593248b03004352dacd",
+   "testharness"
+  ],
+  "background-fetch/idlharness.any.sharedworker-expected.txt": [
+   "d3818aef8b559e61186ed89c5343601e8f8164f3",
+   "support"
+  ],
+  "background-fetch/idlharness.any.worker-expected.txt": [
+   "d3818aef8b559e61186ed89c5343601e8f8164f3",
+   "support"
+  ],
+  "background-fetch/idlharness.https.any.serviceworker-expected.txt": [
+   "bc0333837b7e504edcc444ef0e41fcf6d97d6baf",
+   "support"
+  ],
   "background-fetch/interfaces-worker.https-expected.txt": [
    "88211a0d44012d229af146366440ced5d12b0988",
    "support"
@@ -275392,10 +275792,6 @@
    "8a5cf2119205440349c364ccdeaa65ce3cf42791",
    "support"
   ],
-  "background-fetch/interfaces.https.any.js": [
-   "34a07e3b0425cb5a1b940c9581573e2b3322724f",
-   "testharness"
-  ],
   "background-fetch/interfaces.https.any.worker-expected.txt": [
    "66d01d6b1e71e7381f1a1b87b56372ffe850b27f",
    "support"
@@ -277205,7 +277601,7 @@
    "testharness"
   ],
   "content-security-policy/embedded-enforcement/idlharness.window.js": [
-   "e009d639fbb4ede1085c365038fb79d1e0625143",
+   "a64a6a47127c3a770d9190df2d0a3ad570e32427",
    "testharness"
   ],
   "content-security-policy/embedded-enforcement/iframe-csp-attribute.html": [
@@ -313964,6 +314360,14 @@
    "4b49a6bc4cfef048f3a4ac1d62feeb604e0d28a5",
    "reftest"
   ],
+  "css/css-images/idlharness-expected.txt": [
+   "deb34377105c08e4511c5a4c8b90c58972679287",
+   "support"
+  ],
+  "css/css-images/idlharness.html": [
+   "43a0b8582221d2cd3838fcf6ba93bc7198cbdbf1",
+   "testharness"
+  ],
   "css/css-images/image-fit-001.xht": [
    "868d9469f57e6013a024efa5e04ef2455d97296e",
    "visual"
@@ -314688,6 +315092,102 @@
    "3ddf25363a61baa64374747cdfadeb9329e87f81",
    "support"
   ],
+  "css/css-lists/content-property/marker-text-matches-armenian-ref.html": [
+   "36a124835188ab9172d59dcf8615d050f3b4b37d",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-armenian.html": [
+   "08e07d745f07a15806d532ab2b859a528ea58f0b",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-circle-ref.html": [
+   "5cf7f2cb8c066d220dfd441bb50aeec2f514bf25",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-circle.html": [
+   "3191e867c0d1a02840977838fd13e25e12cdb491",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-decimal-leading-zero-ref.html": [
+   "428d093039a3e489e0b5765b0dfe1a3587d1bf92",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-decimal-leading-zero.html": [
+   "648d651fce939501916074632c5704764115fcd5",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-decimal-ref.html": [
+   "f7c2fcd3655546e3d8e6d5fdd82523db81c69927",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-decimal.html": [
+   "c00f56ab58e7fd3ce8a2fc281543ddcde05d26fb",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-disc-ref.html": [
+   "6eee62533f2d54b12a5c9b39e93c3224cb2ffafb",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-disc.html": [
+   "876d93ca33eac5044084c7a5d0e5e445f3770a98",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-georgian-ref.html": [
+   "60f3e664d51a2a71df464f470cb644904f21f612",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-georgian.html": [
+   "192b49e24f250a1b403ab4b4f815c2d916a17abd",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-lower-greek-ref.html": [
+   "4f2732719698d51272bb5cccf891e64a016cef8d",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-lower-greek.html": [
+   "967b17032b21f3a041fd69b00a7b10a78d6743e6",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-lower-latin-ref.html": [
+   "0b9981e525a3bcfe86a1b837d32c70af5355f7c0",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-lower-latin.html": [
+   "258697c2a8b72849da7e99db6fcb1e18bed313b1",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-lower-roman-ref.html": [
+   "d0c2e9b1b84254e32956f9f26461f7d8751e17b8",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-lower-roman.html": [
+   "8507450cf81d498202277ad20f47d9047b82803c",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-square-ref.html": [
+   "1b69ce33b9dd6e674407f78937e47b3aa4d012af",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-square.html": [
+   "198deb47052925b046d8b9f37ddb2b2109d29c25",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-upper-latin-ref.html": [
+   "f2b5bb160a67b42add362f0bdd3d492f1992b3ff",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-upper-latin.html": [
+   "5640698b5296d42d403591796cb35984d4f44e3a",
+   "reftest"
+  ],
+  "css/css-lists/content-property/marker-text-matches-upper-roman-ref.html": [
+   "188a77cab595081eac21b18005a911cf2c3c53ec",
+   "support"
+  ],
+  "css/css-lists/content-property/marker-text-matches-upper-roman.html": [
+   "5b66ea59ac497741a1501c3c6d91764fb8d99e0d",
+   "reftest"
+  ],
   "css/css-lists/counter-7-ref.html": [
    "6391e214ad5262afaab7cd6caaf57e7f2506fb4d",
    "support"
@@ -314748,7 +315248,11 @@
    "ff44f2aadd8f274135c40ffc70a94b71df022718",
    "support"
   ],
-  "css/css-logical/animation-003.tenative.html": [
+  "css/css-logical/animation-003.tentative-expected.txt": [
+   "ff44f2aadd8f274135c40ffc70a94b71df022718",
+   "support"
+  ],
+  "css/css-logical/animation-003.tentative.html": [
    "bdb7e952eb7fecf402f64129a00b511d89470195",
    "testharness"
   ],
@@ -317940,6 +318444,14 @@
    "7d4739f2252956461b38d8b8566a84ead3c1d8b1",
    "reftest"
   ],
+  "css/css-pseudo/marker-inherit-line-height-ref.html": [
+   "e0b76bc582df84e630c911cd45a77bd714ae3727",
+   "support"
+  ],
+  "css/css-pseudo/marker-inherit-line-height.html": [
+   "d6da862bc43db77db9e22a1fd1090a26a497e8cc",
+   "reftest"
+  ],
   "css/css-pseudo/marker-inherit-values-ref.html": [
    "92bdc9d8f482c34ad389f27c957d4024a7e05b43",
    "support"
@@ -323280,10 +323792,6 @@
    "63bbe4f7fb67f33217876af58c1de4d032c369f4",
    "reftest"
   ],
-  "css/css-text/overflow-wrap/overflow-wrap-break-word-004.html": [
-   "ca2b98f9db6ac13da149380dab3311301d741045",
-   "reftest"
-  ],
   "css/css-text/overflow-wrap/overflow-wrap-break-word-fit-content-001.html": [
    "9f88a667825f8cb725dc348e17081e1a25b3f4de",
    "reftest"
@@ -324820,10 +325328,6 @@
    "5ad54c7b9197746f66fa30628b6059a369f5bd36",
    "support"
   ],
-  "css/css-text/word-break/reference/word-break-break-all-010-ref.html": [
-   "0b16a0bdb25ddd647ad96dd82e3430274667ee87",
-   "support"
-  ],
   "css/css-text/word-break/reference/word-break-break-all-ref-000.html": [
    "765afbeeede3d3dd8ad33b88927d6eb8e5435463",
    "support"
@@ -325000,14 +325504,6 @@
    "fd5f0cf9f57152d3c6df7c4b59c0fe70733bf9f4",
    "manual"
   ],
-  "css/css-text/word-break/word-break-break-all-010.html": [
-   "f9eedfe8e72bcf6693f8049bfdf2e1efdf3084ef",
-   "reftest"
-  ],
-  "css/css-text/word-break/word-break-break-all-011.html": [
-   "047e950374d902e426287900a2d03c63726420a2",
-   "reftest"
-  ],
   "css/css-text/word-break/word-break-keep-all-000.html": [
    "219e6b0435541a834ebbee114b0dd40e15956f75",
    "reftest"
@@ -366836,12 +367332,12 @@
    "1732dc6dd595354e21c7fb6006c32b844ceedf18",
    "reftest"
   ],
-  "html/rendering/non-replaced-elements/tables/form-in-tables.html": [
-   "8319c136723513a019d48f66c663ce3673777bcd",
+  "html/rendering/non-replaced-elements/tables/form-in-tables-xhtml.xhtml": [
+   "610932708cb18b8022ca64b8c9f3f59d8cf1ae56",
    "testharness"
   ],
-  "html/rendering/non-replaced-elements/tables/form-in-tables.xhtml": [
-   "610932708cb18b8022ca64b8c9f3f59d8cf1ae56",
+  "html/rendering/non-replaced-elements/tables/form-in-tables.html": [
+   "8319c136723513a019d48f66c663ce3673777bcd",
    "testharness"
   ],
   "html/rendering/non-replaced-elements/tables/hidden-attr-expected.txt": [
@@ -370668,6 +371164,10 @@
    "9405efb65176096957438cbdcc59109b488d80e6",
    "testharness"
   ],
+  "html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach.html": [
+   "cd7e495a854d848712b46cddec40e3ebffe9d3ba",
+   "testharness"
+  ],
   "html/semantics/embedded-content/the-img-element/decode/image-decode.html": [
    "5368b62bf6c950e8d57b16b36148e5695ce16fd8",
    "testharness"
@@ -371992,6 +372492,14 @@
    "b61235681689807b5d46b8aaca9ae6c7a18039f7",
    "testharness"
   ],
+  "html/semantics/forms/the-textarea-element/textarea-maxlength.html": [
+   "fb2796fe7e542bd9551c18c0176a4f822ee347cd",
+   "testharness"
+  ],
+  "html/semantics/forms/the-textarea-element/textarea-minlength.html": [
+   "fcccb00d0db7222af1fb03e7481ccf31e51ec924",
+   "testharness"
+  ],
   "html/semantics/forms/the-textarea-element/textarea-newline-bidi-ref.html": [
    "26eb3e615f8b0e15cf02b7ee18d39fd71b04da70",
    "support"
@@ -372012,10 +372520,18 @@
    "5f5932aeba8a0a7da66ee006a6e604780210d57b",
    "testharness"
   ],
+  "html/semantics/forms/the-textarea-element/textarea-textLength.html": [
+   "0f9b8cdaace12d4f4e7fbd57a90fcba7e826ced5",
+   "testharness"
+  ],
   "html/semantics/forms/the-textarea-element/textarea-type.html": [
    "81a270bc3c9304f8b2e7dd526519f4eab7d94f45",
    "testharness"
   ],
+  "html/semantics/forms/the-textarea-element/textarea-validity-clone.html": [
+   "d0334cee779937e5d800e478013e5c8ffeaa6a1c",
+   "testharness"
+  ],
   "html/semantics/forms/the-textarea-element/value-defaultValue-textContent-expected.txt": [
    "4f2f22b676dea822e14a2073fa9ea727488fdc95",
    "support"
@@ -377936,10 +378452,6 @@
    "d1220af2e8cc4fab720497311064666393eea7c8",
    "testharness"
   ],
-  "infrastructure/server/wpt-server-http.sub-expected.txt": [
-   "f43e81e2a389b59723ff9787014c6d96a030e13b",
-   "support"
-  ],
   "infrastructure/server/wpt-server-http.sub.html": [
    "2a400478de23a6aecf31bdc08b187784c36be629",
    "testharness"
@@ -378089,7 +378601,7 @@
    "support"
   ],
   "interfaces/background-fetch.idl": [
-   "272d5ef66a2df3a6c3fefaf9688802ed93a9ad5f",
+   "4f744971f4eb6fc90bfb5fa4cc7514230e5e57dd",
    "support"
   ],
   "interfaces/battery-status.idl": [
@@ -378140,6 +378652,10 @@
    "0019e54201874e5d2a2b10c887e44b8c42199c32",
    "support"
   ],
+  "interfaces/css-counter-styles.idl": [
+   "437dd5859385f5a17f9b9b2509b8f50eeb42a717",
+   "support"
+  ],
   "interfaces/css-font-loading.idl": [
    "9f2f252c5b63c159d9680de46a932bfa4335bf11",
    "support"
@@ -378148,6 +378664,10 @@
    "ff2d83e9468c743993c9b4a1ecf3fab09684dc16",
    "support"
   ],
+  "interfaces/css-images.idl": [
+   "29ff2de2d9dac38494a4e2b7cfc6dfc2947f16c1",
+   "support"
+  ],
   "interfaces/css-masking.idl": [
    "5f4ed3d8922e30ab3ddb714d185c6e6f794e5a29",
    "support"
@@ -378156,6 +378676,10 @@
    "9939fb7f08cab0f167e6e0762eac6ad94b2dfd9f",
    "support"
   ],
+  "interfaces/css-regions.idl": [
+   "23d01fa1c91539c443b2227df6a89e377b65a393",
+   "support"
+  ],
   "interfaces/css-transitions.idl": [
    "54dd701233a71187c8b675ebbf7336f852a7cace",
    "support"
@@ -378268,6 +378792,10 @@
    "dad6123e39feca39ec620de51307e56823cc5408",
    "support"
   ],
+  "interfaces/media-source.idl": [
+   "a3c8e49db54b906ae99e2aa2cc385c0e4d949a80",
+   "support"
+  ],
   "interfaces/mediacapture-depth.idl": [
    "2ac0dcf83f5afb227f24c9063d738dd22e941fe9",
    "support"
@@ -378373,7 +378901,7 @@
    "support"
   ],
   "interfaces/resource-timing.idl": [
-   "75fcdf5c6ac811254e1a025cd58d958f27ab5b5b",
+   "d500e42e860b94614c0efeeb0b46d2ad7e8d79f9",
    "support"
   ],
   "interfaces/screen-orientation.idl": [
@@ -378389,7 +378917,7 @@
    "support"
   ],
   "interfaces/selection-api.idl": [
-   "10e7cdeb0e3c5e3871c81e30e89e72412d3f572f",
+   "622e064c826b3d25618e0bd6041e4297f9939d78",
    "support"
   ],
   "interfaces/server-timing.idl": [
@@ -378397,7 +378925,7 @@
    "support"
   ],
   "interfaces/service-workers.idl": [
-   "979a3b43c2db10f5a93213f46f1abf90082da22b",
+   "d219b474e3981be9cdeed598046e8002b4b48ddf",
    "support"
   ],
   "interfaces/shape-detection-api.idl": [
@@ -378409,7 +378937,7 @@
    "support"
   ],
   "interfaces/touch-events.idl": [
-   "00811ff421c7ecafb8070d1a3d17310e1228c725",
+   "4e456ecce04a5f8fb19a7be5ae0d9e5bd69a1ec1",
    "support"
   ],
   "interfaces/touchevents.idl": [
@@ -378976,6 +379504,18 @@
    "fefa39b93290d8d97b18f606c5166d7792193251",
    "support"
   ],
+  "media-source/idlharness.any-expected.txt": [
+   "5d955cd235b47e9a85ec1992410b576835e88040",
+   "support"
+  ],
+  "media-source/idlharness.any.js": [
+   "d9b97ca6d0883ef11491723a5db5b9e92e32a380",
+   "testharness"
+  ],
+  "media-source/idlharness.any.worker-expected.txt": [
+   "8abee7dbcb3581e009040a8b4cab306a0f5e7f4c",
+   "support"
+  ],
   "media-source/import_tests.sh": [
    "943d26f264d59f2a7c01db30f5d91e72dafa9935",
    "support"
@@ -378984,10 +379524,6 @@
    "f7122a377e6ceb667a42f978dc549457d8c301e1",
    "support"
   ],
-  "media-source/interfaces.html": [
-   "f836da38e12662cd56590d5a0534ad555dbf249e",
-   "testharness"
-  ],
   "media-source/manifest.txt": [
    "d1e89d132c19294d2c7bb677668c03f3309b475e",
    "support"
@@ -388640,10 +389176,6 @@
    "01e6ebc11174b8de17212aaf004890685bd90fae",
    "manual"
   ],
-  "payment-method-basic-card/idlharness.window-expected.txt": [
-   "d6c9c468cebdcd639c1d1d17beba93b3808751b1",
-   "support"
-  ],
   "payment-method-basic-card/idlharness.window.js": [
    "0219c2651ea2bd20d1c694f4f450646a38b8513f",
    "testharness"
@@ -389101,7 +389633,7 @@
    "support"
   ],
   "picture-in-picture/disable-picture-in-picture.html": [
-   "d97bf03a6e2f991c173248f9e28bd713da19a6f4",
+   "f80cdccd1c6edcf6a859a1ae2315a9f65188d812",
    "testharness"
   ],
   "picture-in-picture/enter-picture-in-picture.html": [
@@ -389113,11 +389645,11 @@
    "testharness"
   ],
   "picture-in-picture/idlharness.window-expected.txt": [
-   "a048d5c50c8e843efdfb66389f95f16b3e1bca6a",
+   "a9cf0a080146f82378696b5732b1d56da3b10368",
    "support"
   ],
   "picture-in-picture/idlharness.window.js": [
-   "a2a5c08651d42ef14d4ffd1ac0fa0c56a7a2eb37",
+   "8861876d089790497afb99496c118ac24f43eadd",
    "testharness"
   ],
   "picture-in-picture/leave-picture-in-picture.html": [
@@ -389133,7 +389665,7 @@
    "testharness"
   ],
   "picture-in-picture/request-picture-in-picture-twice.html": [
-   "289c2decddd418722b3d5345b31706b4fad59ed3",
+   "c45cc223ec4336916d46c3d4db8bc4decbbd3332",
    "testharness"
   ],
   "picture-in-picture/request-picture-in-picture.html": [
@@ -389141,7 +389673,7 @@
    "testharness"
   ],
   "picture-in-picture/resources/picture-in-picture-helpers.js": [
-   "1d4f14127753148c7dfc4a79d2beec34410e416b",
+   "b41a3c97a777a69ab28eea3b33f464379303da3d",
    "support"
   ],
   "picture-in-picture/shadow-dom.html": [
@@ -389849,7 +390381,7 @@
    "testharness"
   ],
   "presentation-api/controlling-ua/idlharness.https.html": [
-   "75dca68e8398772129feacc28bfe574e9c8d402b",
+   "b369c2a6001fa89daffbee9dc588388c74c6badc",
    "testharness"
   ],
   "presentation-api/controlling-ua/reconnectToPresentation_notfound_error.https.html": [
@@ -398392,8 +398924,12 @@
    "369f73cd032f618992d1746184927d0e78a920e8",
    "support"
   ],
-  "resize-observer/idlharness.html": [
-   "2b1960834f7164e351cdbba119694830055dcf17",
+  "resize-observer/idlharness.window-expected.txt": [
+   "50f625b9289202a2da470abb4b42c2e3a119a6a3",
+   "support"
+  ],
+  "resize-observer/idlharness.window.js": [
+   "678952851933ad07531c0bebe6b9dc7be52dcdc3",
    "testharness"
   ],
   "resize-observer/notify.html": [
@@ -398433,7 +398969,7 @@
    "testharness"
   ],
   "resource-timing/idlharness.any.js": [
-   "a1bb5ee0f67683b42035fa683e9a984b0cf4d5dc",
+   "2065b03393c21199e49553ec99902aaddec74ce0",
    "testharness"
   ],
   "resource-timing/iframe-setdomain.sub.html": [
@@ -399056,14 +399592,18 @@
    "4b5b638ae5cdaab02fbe9cca255a119134238a7d",
    "testharness"
   ],
+  "selection/idlharness.window-expected.txt": [
+   "1bdfe84569e3607508422c62bc7b03ecfc2df38a",
+   "support"
+  ],
+  "selection/idlharness.window.js": [
+   "2a89076946fd12a1629ef962c2e459accba952df",
+   "testharness"
+  ],
   "selection/interfaces-expected.txt": [
    "8a53b2e46fc24e712365a3e1484acdca85752864",
    "support"
   ],
-  "selection/interfaces.html": [
-   "78e92642e2562da8040c791e4c3a7ad1de53e600",
-   "testharness"
-  ],
   "selection/isCollapsed.html": [
    "d1984a9359d880dfb81197e7ec31b2456833809d",
    "testharness"
@@ -399820,6 +400360,14 @@
    "ba24e1d89104fb25d5100dfa0b38388ca19ee9c1",
    "support"
   ],
+  "server-timing/resources/parsing/84.js": [
+   "aa4b60a397c4704689621874403329c705598c9c",
+   "support"
+  ],
+  "server-timing/resources/parsing/84.js.sub.headers": [
+   "94fd8cac84f6fdc22d8b46786ac690f788e657f4",
+   "support"
+  ],
   "server-timing/resources/parsing/9.js": [
    "5660bb21eb42f322a58f80c6c001d14c6e0fc0c9",
    "support"
@@ -399829,19 +400377,19 @@
    "support"
   ],
   "server-timing/server_timing_header-parsing-expected.txt": [
-   "87ae6268c574b3305a79fc1376d7a62aa7587f2d",
+   "3fb854f9b672fcac8995d77ba7d23e996c8f3485",
    "support"
   ],
   "server-timing/server_timing_header-parsing.html": [
-   "10f756bbf749b7ad8f7c6eb4efe752ee79c44b4a",
+   "8df39d7b393cb0ae6dac1997b2d8755210a97ea5",
    "testharness"
   ],
   "server-timing/server_timing_header-parsing.https-expected.txt": [
-   "ef70b0cf8dbcb0090957b0bba170ee610b11a39d",
+   "531ef8b2e35dc7b7984fb6ce4a84eead76fb3a12",
    "support"
   ],
   "server-timing/server_timing_header-parsing.https.html": [
-   "10f756bbf749b7ad8f7c6eb4efe752ee79c44b4a",
+   "8df39d7b393cb0ae6dac1997b2d8755210a97ea5",
    "testharness"
   ],
   "server-timing/service_worker_idl.https.html": [
@@ -400685,7 +401233,7 @@
    "testharness"
   ],
   "service-workers/service-worker/interfaces-window.https.html": [
-   "71c0e09861863b9f36571137d2398fa8af516601",
+   "18b96c6b13d9b561e2fdb1eca32872d6596c76b0",
    "testharness"
   ],
   "service-workers/service-worker/invalid-blobtype.https.html": [
@@ -401580,12 +402128,8 @@
    "0f2d441a80fb4641af35ad851e86690b7c02d1f7",
    "support"
   ],
-  "service-workers/service-worker/resources/interfaces-idls.js": [
-   "2d3ae3bdd1be17a2871aa3af2009daaacf43d3db",
-   "support"
-  ],
   "service-workers/service-worker/resources/interfaces-worker.sub.js": [
-   "694568194185de15fb912b3e4b4655ea3f65420d",
+   "cd067da4cc6683916037aaf13d71f6309f04460b",
    "support"
   ],
   "service-workers/service-worker/resources/invalid-blobtype-iframe.https.html": [
@@ -404892,6 +405436,10 @@
    "3d51ca0fc007d52147e7ea03493cac7ee1bb7903",
    "reftest"
   ],
+  "svg/linking/reftests/use-descendant-combinator-003.html": [
+   "d9155d3b92ecf0735f82ed9a0f2a8fd3fc380d55",
+   "reftest"
+  ],
   "svg/linking/reftests/use-descendant-combinator-ref.html": [
    "fb8aec792684b97151d2964b85d1e70829e141ad",
    "support"
@@ -405048,6 +405596,22 @@
    "03751dba3c2dfc7b4d478879dc94878b0dffcc99",
    "reftest"
   ],
+  "svg/render/reftests/blending-001-ref.svg": [
+   "2eab909f1ad53777522f75b968e73879236573f9",
+   "support"
+  ],
+  "svg/render/reftests/blending-001.svg": [
+   "5503dc3d96e7fa0c5884f6692469010fe28e4527",
+   "reftest"
+  ],
+  "svg/render/reftests/blending-002-ref.svg": [
+   "cf08e0892c32439a738b1eef93683702b6139990",
+   "support"
+  ],
+  "svg/render/reftests/blending-002.svg": [
+   "f77800e686cee3007fb7c40574c61b22d65217ef",
+   "reftest"
+  ],
   "svg/rendering/order/z-index-ref.svg": [
    "955f465ece3132da0bdd1e3b832e97db84f22b55",
    "support"
@@ -405449,7 +406013,7 @@
    "support"
   ],
   "touch-events/idlharness.window.js": [
-   "c5bcdd44381f6f49f0e653c48d05cc14c93f424a",
+   "8a4eee7d4002836a205a1cd0aceb3a8008a1a929",
    "testharness"
   ],
   "touch-events/multi-touch-interactions.js": [
@@ -407608,8 +408172,8 @@
    "07eb3c26df43537e0735d741c8bdc8c041b91175",
    "support"
   ],
-  "web-share/idlharness.https.html": [
-   "17e370aefd324ffac6a6f4b0211fbaecd1781ad4",
+  "web-share/idlharness.https.window.js": [
+   "cd9160bc9790e6e734a73a1f0656f70f8583e246",
    "testharness"
   ],
   "web-share/resources/manual-helper.js": [
@@ -407705,15 +408269,19 @@
    "support"
   ],
   "webaudio/historical.html": [
-   "93068df297042344669093ce899f0230c87ebf54",
+   "c6e3c7d6751731c708edfb0f4e32df8a6a3b80b0",
    "testharness"
   ],
   "webaudio/idlharness.https-expected.txt": [
    "451ba6e7843b5bc4e64983f0ac2aac11467f91e4",
    "support"
   ],
-  "webaudio/idlharness.https.html": [
-   "0403de985b3346240ba1d4b465a8e0838f3860bc",
+  "webaudio/idlharness.https.window-expected.txt": [
+   "77fb40fa0aeedc7f4d8e90d1d51f847895128fbf",
+   "support"
+  ],
+  "webaudio/idlharness.https.window.js": [
+   "cadc212b4ecb16e95581e34886f49f0357c593bc",
    "testharness"
   ],
   "webaudio/js/buffer-loader.js": [
@@ -409432,11 +410000,11 @@
    "74096ec62288029bf7aea81008e63e43a5f40549",
    "testharness"
   ],
-  "webrtc/RTCPeerConnection-addTransceiver-expected.txt": [
+  "webrtc/RTCPeerConnection-addTransceiver.https-expected.txt": [
    "f081cfd4da18191f04c211a70735b7142907e61f",
    "support"
   ],
-  "webrtc/RTCPeerConnection-addTransceiver.html": [
+  "webrtc/RTCPeerConnection-addTransceiver.https.html": [
    "3d1531048c244d0f3391d6fe30e7c8bc7e13ef35",
    "testharness"
   ],
@@ -409537,7 +410105,7 @@
    "testharness"
   ],
   "webrtc/RTCPeerConnection-helper.js": [
-   "e92d33cfb3fdacc6a2f172ecfe3444a1ced5680e",
+   "4c2699a8df315a475f1037a3ac8dcbb313f2757b",
    "support"
   ],
   "webrtc/RTCPeerConnection-iceConnectionState-expected.txt": [
@@ -409829,11 +410397,11 @@
    "testharness"
   ],
   "webrtc/RTCRtpSender-replaceTrack.https-expected.txt": [
-   "a6b5ff94414685af0bb1f94f914c47270f26f7b5",
+   "0addd08af3b15ccf95020bdcd609732d37535a50",
    "support"
   ],
   "webrtc/RTCRtpSender-replaceTrack.https.html": [
-   "ea6ff719d0939e22fd5af2c72af009a1c9602c93",
+   "c73569cdd7272bdda237661599f6c1f62b4c1f0c",
    "testharness"
   ],
   "webrtc/RTCRtpSender-setParameters-expected.txt": [
@@ -411152,8 +411720,8 @@
    "6ba7d14a894e782495d818e43f4b0901607c207e",
    "support"
   ],
-  "webstorage/idlharness.html": [
-   "9bbb03ed7a846411183963fba16241a107652c0f",
+  "webstorage/idlharness.window.js": [
+   "4aeab6abb761637eeb0d03e6f95dcc5c8a9e00c1",
    "testharness"
   ],
   "webstorage/missing_arguments.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self.html b/third_party/WebKit/LayoutTests/external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self.html
new file mode 100644
index 0000000..83cf535
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self.html
@@ -0,0 +1,17 @@
+<link rel="match" href="drawimage_canvas_self_ref.html">
+<canvas id="dest" height="100" width="100"></canvas>
+<script>
+var canvasWidth = canvasHeight = 100;
+var destWidth = canvasWidth / 4;
+var destHeight = canvasHeight / 4;
+var destCanvas = document.getElementById('dest');
+var destCtx = destCanvas.getContext('2d');
+
+destCtx.fillStyle = 'red';
+destCtx.fillRect(0, 0,  canvasWidth, canvasHeight);
+destCtx.fillStyle = 'green';
+destCtx.fillRect(0, 0, canvasWidth / 2, canvasHeight / 2);
+destCtx.drawImage(destCanvas,
+                  0, 0, destWidth, destHeight,
+                  canvasWidth / 2, canvasHeight / 2, destWidth, destHeight);
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self_ref.html b/third_party/WebKit/LayoutTests/external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self_ref.html
new file mode 100644
index 0000000..9f297ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_canvas_self_ref.html
@@ -0,0 +1,11 @@
+<canvas id="dest" height="100" width="100"></canvas>
+<script>
+var canvasWidth = canvasHeight = 100;
+var destCanvas = document.getElementById('dest');
+var destCtx = destCanvas.getContext('2d');
+destCtx.fillStyle = 'red';
+destCtx.fillRect(0, 0,  canvasWidth, canvasHeight);
+destCtx.fillStyle = 'green';
+destCtx.fillRect(0, 0, canvasWidth / 2, canvasHeight / 2);
+destCtx.fillRect(canvasWidth / 2, canvasHeight / 2, canvasWidth / 4, canvasHeight / 4);
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https.html
deleted file mode 100644
index 1f32be9..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>Accelerometer Sensor IDL tests</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<link rel="help" href="https://w3c.github.io/accelerometer/">
-<link rel="help" href="https://w3c.github.io/sensors/">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-<script>
-"use strict";
-
-function doTest([dom, generic_sensor, accelerometer]) {
-  const idl_array = new IdlArray();
-  idl_array.add_untested_idls(dom);
-  idl_array.add_untested_idls('interface EventHandler {};');
-  idl_array.add_idls(generic_sensor, { only: ['Sensor', 'SensorOptions'] });
-  idl_array.add_idls(accelerometer);
-  idl_array.add_objects({
-    Accelerometer: ['new Accelerometer();'],
-    LinearAccelerationSensor: ['new LinearAccelerationSensor();'],
-    GravitySensor: ['new GravitySensor();']
-  });
-  idl_array.test();
-}
-
-function fetchText(url) {
-  return fetch(url).then((response) => response.text());
-}
-
-promise_test(() => {
-  return Promise.all([
-    "/interfaces/dom.idl",
-    "/interfaces/sensors.idl",
-    "/interfaces/accelerometer.idl",
-  ].map(fetchText)).then(doTest);
-}, "Test IDL implementation of Accelerometer Sensor");
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https.window-expected.txt
new file mode 100644
index 0000000..cacfccf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https.window-expected.txt
@@ -0,0 +1,43 @@
+This is a testharness.js-based test.
+PASS Test IDL implementation of Accelerometer Sensor
+PASS Accelerometer interface: existence and properties of interface object
+PASS Accelerometer interface object length
+PASS Accelerometer interface object name
+PASS Accelerometer interface: existence and properties of interface prototype object
+PASS Accelerometer interface: existence and properties of interface prototype object's "constructor" property
+PASS Accelerometer interface: existence and properties of interface prototype object's @@unscopables property
+PASS Accelerometer interface: attribute x
+PASS Unscopable handled correctly for x property on Accelerometer
+PASS Accelerometer interface: attribute y
+PASS Unscopable handled correctly for y property on Accelerometer
+PASS Accelerometer interface: attribute z
+PASS Unscopable handled correctly for z property on Accelerometer
+PASS Accelerometer must be primary interface of new Accelerometer();
+PASS Stringification of new Accelerometer();
+PASS Accelerometer interface: new Accelerometer(); must inherit property "x" with the proper type
+PASS Accelerometer interface: new Accelerometer(); must inherit property "y" with the proper type
+PASS Accelerometer interface: new Accelerometer(); must inherit property "z" with the proper type
+PASS LinearAccelerationSensor interface: existence and properties of interface object
+PASS LinearAccelerationSensor interface object length
+PASS LinearAccelerationSensor interface object name
+PASS LinearAccelerationSensor interface: existence and properties of interface prototype object
+PASS LinearAccelerationSensor interface: existence and properties of interface prototype object's "constructor" property
+PASS LinearAccelerationSensor interface: existence and properties of interface prototype object's @@unscopables property
+PASS LinearAccelerationSensor must be primary interface of new LinearAccelerationSensor();
+PASS Stringification of new LinearAccelerationSensor();
+PASS Accelerometer interface: new LinearAccelerationSensor(); must inherit property "x" with the proper type
+PASS Accelerometer interface: new LinearAccelerationSensor(); must inherit property "y" with the proper type
+PASS Accelerometer interface: new LinearAccelerationSensor(); must inherit property "z" with the proper type
+FAIL GravitySensor interface: existence and properties of interface object assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor interface object length assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor interface object name assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor interface: existence and properties of interface prototype object assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor must be primary interface of new GravitySensor(); assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Stringification of new GravitySensor(); assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Accelerometer interface: new GravitySensor(); must inherit property "x" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Accelerometer interface: new GravitySensor(); must inherit property "y" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Accelerometer interface: new GravitySensor(); must inherit property "z" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https.window.js
new file mode 100644
index 0000000..f6cbcd96
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https.window.js
@@ -0,0 +1,19 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://w3c.github.io/accelerometer/
+
+"use strict";
+
+idl_test(
+  ['accelerometer'],
+  ['generic-sensor', 'dom'],
+  idl_array => {
+    idl_array.add_objects({
+      Accelerometer: ['new Accelerometer();'],
+      LinearAccelerationSensor: ['new LinearAccelerationSensor();'],
+      GravitySensor: ['new GravitySensor();']
+    });
+  },
+  'Test IDL implementation of Accelerometer Sensor'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any-expected.txt
new file mode 100644
index 0000000..6faed0f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any-expected.txt
@@ -0,0 +1,80 @@
+This is a testharness.js-based test.
+Found 76 tests; 58 PASS, 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS background-fetch interfaces
+PASS Partial interface ServiceWorkerGlobalScope: original interface defined
+PASS Partial interface ServiceWorkerRegistration: original interface defined
+PASS BackgroundFetchManager interface: existence and properties of interface object
+PASS BackgroundFetchManager interface object length
+PASS BackgroundFetchManager interface object name
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchManager interface: operation fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions)
+PASS Unscopable handled correctly for fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions) on BackgroundFetchManager
+PASS BackgroundFetchManager interface: operation get(DOMString)
+PASS Unscopable handled correctly for get(DOMString) on BackgroundFetchManager
+PASS BackgroundFetchManager interface: operation getIds()
+PASS Unscopable handled correctly for getIds() on BackgroundFetchManager
+PASS BackgroundFetchRegistration interface: existence and properties of interface object
+PASS BackgroundFetchRegistration interface object length
+PASS BackgroundFetchRegistration interface object name
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchRegistration interface: attribute id
+PASS Unscopable handled correctly for id property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute uploadTotal
+PASS Unscopable handled correctly for uploadTotal property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute uploaded
+PASS Unscopable handled correctly for uploaded property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute downloadTotal
+PASS Unscopable handled correctly for downloadTotal property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute downloaded
+PASS Unscopable handled correctly for downloaded property on BackgroundFetchRegistration
+FAIL BackgroundFetchRegistration interface: attribute activeFetches assert_true: The prototype object must have a property "activeFetches" expected true got false
+PASS Unscopable handled correctly for activeFetches property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute onprogress
+PASS Unscopable handled correctly for onprogress property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: operation abort()
+PASS Unscopable handled correctly for abort() on BackgroundFetchRegistration
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: operation match(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for match(RequestInfo, CacheQueryOptions) on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetches interface: operation matchAll(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for matchAll(RequestInfo, CacheQueryOptions) on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetches interface: operation values() assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for values() on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: attribute responseReady assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+PASS Unscopable handled correctly for responseReady property on BackgroundFetchActiveFetch
+PASS BackgroundFetchFetch interface: existence and properties of interface object
+PASS BackgroundFetchFetch interface object length
+PASS BackgroundFetchFetch interface object name
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchFetch interface: attribute request
+PASS Unscopable handled correctly for request property on BackgroundFetchFetch
+PASS BackgroundFetchEvent interface: existence and properties of interface object
+PASS BackgroundFetchSettledEvent interface: existence and properties of interface object
+PASS BackgroundFetchSettledFetches interface: existence and properties of interface object
+PASS BackgroundFetchSettledFetch interface: existence and properties of interface object
+PASS BackgroundFetchUpdateEvent interface: existence and properties of interface object
+PASS BackgroundFetchClickEvent interface: existence and properties of interface object
+FAIL ServiceWorkerRegistration interface: attribute backgroundFetch assert_own_property: self does not have own property "ServiceWorkerRegistration" expected property "ServiceWorkerRegistration" missing
+PASS Unscopable handled correctly for backgroundFetch property on ServiceWorkerRegistration
+PASS ServiceWorkerGlobalScope interface: existence and properties of interface object
+PASS ExtendableEvent interface: existence and properties of interface object
+PASS WorkerGlobalScope interface: existence and properties of interface object
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.js
new file mode 100644
index 0000000..ad20477
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.js
@@ -0,0 +1,25 @@
+// META: global=window,worker
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+'use strict';
+
+// https://wicg.github.io/background-fetch/
+
+idl_test(
+  ['background-fetch'],
+  ['service-workers', 'dedicated-workers', 'dom'],
+  idl_array => {
+    const isServiceWorker = location.pathname.includes('.serviceworker.');
+    if (isServiceWorker) {
+      idl_array.add_objects({
+        ServiceWorkerGlobalScope: ['self'],
+        ServiceWorkerRegistration: ['registration'],
+        BackgroundFetchManager: ['registration.backgroundFetch'],
+        BackgroundFetchEvent: ['new BackgroundFetchEvent("type")'],
+        BackgroundFetchUpdateEvent: ['new BackgroundFetchUpdateEvent("type")'],
+      });
+    }
+  },
+  'background-fetch interfaces'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.sharedworker-expected.txt
new file mode 100644
index 0000000..5f3ed505
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.sharedworker-expected.txt
@@ -0,0 +1,79 @@
+This is a testharness.js-based test.
+Found 75 tests; 57 PASS, 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS background-fetch interfaces
+PASS Partial interface ServiceWorkerGlobalScope: original interface defined
+PASS Partial interface ServiceWorkerRegistration: original interface defined
+PASS BackgroundFetchManager interface: existence and properties of interface object
+PASS BackgroundFetchManager interface object length
+PASS BackgroundFetchManager interface object name
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchManager interface: operation fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions)
+PASS Unscopable handled correctly for fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions) on BackgroundFetchManager
+PASS BackgroundFetchManager interface: operation get(DOMString)
+PASS Unscopable handled correctly for get(DOMString) on BackgroundFetchManager
+PASS BackgroundFetchManager interface: operation getIds()
+PASS Unscopable handled correctly for getIds() on BackgroundFetchManager
+PASS BackgroundFetchRegistration interface: existence and properties of interface object
+PASS BackgroundFetchRegistration interface object length
+PASS BackgroundFetchRegistration interface object name
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchRegistration interface: attribute id
+PASS Unscopable handled correctly for id property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute uploadTotal
+PASS Unscopable handled correctly for uploadTotal property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute uploaded
+PASS Unscopable handled correctly for uploaded property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute downloadTotal
+PASS Unscopable handled correctly for downloadTotal property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute downloaded
+PASS Unscopable handled correctly for downloaded property on BackgroundFetchRegistration
+FAIL BackgroundFetchRegistration interface: attribute activeFetches assert_true: The prototype object must have a property "activeFetches" expected true got false
+PASS Unscopable handled correctly for activeFetches property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute onprogress
+PASS Unscopable handled correctly for onprogress property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: operation abort()
+PASS Unscopable handled correctly for abort() on BackgroundFetchRegistration
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: operation match(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for match(RequestInfo, CacheQueryOptions) on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetches interface: operation matchAll(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for matchAll(RequestInfo, CacheQueryOptions) on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetches interface: operation values() assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for values() on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: attribute responseReady assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+PASS Unscopable handled correctly for responseReady property on BackgroundFetchActiveFetch
+PASS BackgroundFetchFetch interface: existence and properties of interface object
+PASS BackgroundFetchFetch interface object length
+PASS BackgroundFetchFetch interface object name
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchFetch interface: attribute request
+PASS Unscopable handled correctly for request property on BackgroundFetchFetch
+PASS BackgroundFetchEvent interface: existence and properties of interface object
+PASS BackgroundFetchSettledEvent interface: existence and properties of interface object
+PASS BackgroundFetchSettledFetches interface: existence and properties of interface object
+PASS BackgroundFetchSettledFetch interface: existence and properties of interface object
+PASS BackgroundFetchUpdateEvent interface: existence and properties of interface object
+PASS BackgroundFetchClickEvent interface: existence and properties of interface object
+FAIL ServiceWorkerRegistration interface: attribute backgroundFetch assert_own_property: self does not have own property "ServiceWorkerRegistration" expected property "ServiceWorkerRegistration" missing
+PASS Unscopable handled correctly for backgroundFetch property on ServiceWorkerRegistration
+PASS ServiceWorkerGlobalScope interface: existence and properties of interface object
+PASS ExtendableEvent interface: existence and properties of interface object
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.worker-expected.txt
new file mode 100644
index 0000000..5f3ed505
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.any.worker-expected.txt
@@ -0,0 +1,79 @@
+This is a testharness.js-based test.
+Found 75 tests; 57 PASS, 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS background-fetch interfaces
+PASS Partial interface ServiceWorkerGlobalScope: original interface defined
+PASS Partial interface ServiceWorkerRegistration: original interface defined
+PASS BackgroundFetchManager interface: existence and properties of interface object
+PASS BackgroundFetchManager interface object length
+PASS BackgroundFetchManager interface object name
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchManager interface: operation fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions)
+PASS Unscopable handled correctly for fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions) on BackgroundFetchManager
+PASS BackgroundFetchManager interface: operation get(DOMString)
+PASS Unscopable handled correctly for get(DOMString) on BackgroundFetchManager
+PASS BackgroundFetchManager interface: operation getIds()
+PASS Unscopable handled correctly for getIds() on BackgroundFetchManager
+PASS BackgroundFetchRegistration interface: existence and properties of interface object
+PASS BackgroundFetchRegistration interface object length
+PASS BackgroundFetchRegistration interface object name
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchRegistration interface: attribute id
+PASS Unscopable handled correctly for id property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute uploadTotal
+PASS Unscopable handled correctly for uploadTotal property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute uploaded
+PASS Unscopable handled correctly for uploaded property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute downloadTotal
+PASS Unscopable handled correctly for downloadTotal property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute downloaded
+PASS Unscopable handled correctly for downloaded property on BackgroundFetchRegistration
+FAIL BackgroundFetchRegistration interface: attribute activeFetches assert_true: The prototype object must have a property "activeFetches" expected true got false
+PASS Unscopable handled correctly for activeFetches property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute onprogress
+PASS Unscopable handled correctly for onprogress property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: operation abort()
+PASS Unscopable handled correctly for abort() on BackgroundFetchRegistration
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: operation match(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for match(RequestInfo, CacheQueryOptions) on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetches interface: operation matchAll(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for matchAll(RequestInfo, CacheQueryOptions) on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetches interface: operation values() assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for values() on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: attribute responseReady assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+PASS Unscopable handled correctly for responseReady property on BackgroundFetchActiveFetch
+PASS BackgroundFetchFetch interface: existence and properties of interface object
+PASS BackgroundFetchFetch interface object length
+PASS BackgroundFetchFetch interface object name
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchFetch interface: attribute request
+PASS Unscopable handled correctly for request property on BackgroundFetchFetch
+PASS BackgroundFetchEvent interface: existence and properties of interface object
+PASS BackgroundFetchSettledEvent interface: existence and properties of interface object
+PASS BackgroundFetchSettledFetches interface: existence and properties of interface object
+PASS BackgroundFetchSettledFetch interface: existence and properties of interface object
+PASS BackgroundFetchUpdateEvent interface: existence and properties of interface object
+PASS BackgroundFetchClickEvent interface: existence and properties of interface object
+FAIL ServiceWorkerRegistration interface: attribute backgroundFetch assert_own_property: self does not have own property "ServiceWorkerRegistration" expected property "ServiceWorkerRegistration" missing
+PASS Unscopable handled correctly for backgroundFetch property on ServiceWorkerRegistration
+PASS ServiceWorkerGlobalScope interface: existence and properties of interface object
+PASS ExtendableEvent interface: existence and properties of interface object
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.serviceworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.serviceworker-expected.txt
new file mode 100644
index 0000000..d897833
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/idlharness.https.any.serviceworker-expected.txt
@@ -0,0 +1,130 @@
+This is a testharness.js-based test.
+PASS background-fetch interfaces
+PASS Partial interface ServiceWorkerGlobalScope: original interface defined
+PASS Partial interface ServiceWorkerRegistration: original interface defined
+PASS BackgroundFetchManager interface: existence and properties of interface object
+PASS BackgroundFetchManager interface object length
+PASS BackgroundFetchManager interface object name
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchManager interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchManager interface: operation fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions)
+PASS Unscopable handled correctly for fetch(DOMString, [object Object],[object Object], BackgroundFetchOptions) on BackgroundFetchManager
+PASS BackgroundFetchManager interface: operation get(DOMString)
+PASS Unscopable handled correctly for get(DOMString) on BackgroundFetchManager
+PASS BackgroundFetchManager interface: operation getIds()
+PASS Unscopable handled correctly for getIds() on BackgroundFetchManager
+PASS BackgroundFetchRegistration interface: existence and properties of interface object
+PASS BackgroundFetchRegistration interface object length
+PASS BackgroundFetchRegistration interface object name
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchRegistration interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchRegistration interface: attribute id
+PASS Unscopable handled correctly for id property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute uploadTotal
+PASS Unscopable handled correctly for uploadTotal property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute uploaded
+PASS Unscopable handled correctly for uploaded property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute downloadTotal
+PASS Unscopable handled correctly for downloadTotal property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute downloaded
+PASS Unscopable handled correctly for downloaded property on BackgroundFetchRegistration
+FAIL BackgroundFetchRegistration interface: attribute activeFetches assert_true: The prototype object must have a property "activeFetches" expected true got false
+PASS Unscopable handled correctly for activeFetches property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: attribute onprogress
+PASS Unscopable handled correctly for onprogress property on BackgroundFetchRegistration
+PASS BackgroundFetchRegistration interface: operation abort()
+PASS Unscopable handled correctly for abort() on BackgroundFetchRegistration
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+FAIL BackgroundFetchActiveFetches interface: operation match(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for match(RequestInfo, CacheQueryOptions) on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetches interface: operation matchAll(RequestInfo, CacheQueryOptions) assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for matchAll(RequestInfo, CacheQueryOptions) on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetches interface: operation values() assert_own_property: self does not have own property "BackgroundFetchActiveFetches" expected property "BackgroundFetchActiveFetches" missing
+PASS Unscopable handled correctly for values() on BackgroundFetchActiveFetches
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface object length assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface object name assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+FAIL BackgroundFetchActiveFetch interface: attribute responseReady assert_own_property: self does not have own property "BackgroundFetchActiveFetch" expected property "BackgroundFetchActiveFetch" missing
+PASS Unscopable handled correctly for responseReady property on BackgroundFetchActiveFetch
+PASS BackgroundFetchFetch interface: existence and properties of interface object
+PASS BackgroundFetchFetch interface object length
+PASS BackgroundFetchFetch interface object name
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchFetch interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchFetch interface: attribute request
+PASS Unscopable handled correctly for request property on BackgroundFetchFetch
+PASS BackgroundFetchEvent interface: existence and properties of interface object
+PASS BackgroundFetchEvent interface object length
+PASS BackgroundFetchEvent interface object name
+PASS BackgroundFetchEvent interface: existence and properties of interface prototype object
+PASS BackgroundFetchEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchEvent interface: attribute id
+PASS Unscopable handled correctly for id property on BackgroundFetchEvent
+PASS BackgroundFetchSettledEvent interface: existence and properties of interface object
+PASS BackgroundFetchSettledEvent interface object length
+PASS BackgroundFetchSettledEvent interface object name
+PASS BackgroundFetchSettledEvent interface: existence and properties of interface prototype object
+PASS BackgroundFetchSettledEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchSettledEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchSettledEvent interface: attribute fetches
+PASS Unscopable handled correctly for fetches property on BackgroundFetchSettledEvent
+PASS BackgroundFetchSettledFetches interface: existence and properties of interface object
+PASS BackgroundFetchSettledFetches interface object length
+PASS BackgroundFetchSettledFetches interface object name
+PASS BackgroundFetchSettledFetches interface: existence and properties of interface prototype object
+PASS BackgroundFetchSettledFetches interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchSettledFetches interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchSettledFetches interface: operation match(RequestInfo, CacheQueryOptions)
+PASS Unscopable handled correctly for match(RequestInfo, CacheQueryOptions) on BackgroundFetchSettledFetches
+FAIL BackgroundFetchSettledFetches interface: operation matchAll(RequestInfo, CacheQueryOptions) assert_own_property: interface prototype object missing non-static operation expected property "matchAll" missing
+PASS Unscopable handled correctly for matchAll(RequestInfo, CacheQueryOptions) on BackgroundFetchSettledFetches
+PASS BackgroundFetchSettledFetches interface: operation values()
+PASS Unscopable handled correctly for values() on BackgroundFetchSettledFetches
+PASS BackgroundFetchSettledFetch interface: existence and properties of interface object
+FAIL BackgroundFetchSettledFetch interface object length assert_equals: wrong value for BackgroundFetchSettledFetch.length expected 0 but got 2
+PASS BackgroundFetchSettledFetch interface object name
+PASS BackgroundFetchSettledFetch interface: existence and properties of interface prototype object
+PASS BackgroundFetchSettledFetch interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchSettledFetch interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchSettledFetch interface: attribute response
+PASS Unscopable handled correctly for response property on BackgroundFetchSettledFetch
+PASS BackgroundFetchUpdateEvent interface: existence and properties of interface object
+PASS BackgroundFetchUpdateEvent interface object length
+PASS BackgroundFetchUpdateEvent interface object name
+PASS BackgroundFetchUpdateEvent interface: existence and properties of interface prototype object
+PASS BackgroundFetchUpdateEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchUpdateEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchUpdateEvent interface: operation updateUI(DOMString)
+PASS Unscopable handled correctly for updateUI(DOMString) on BackgroundFetchUpdateEvent
+PASS BackgroundFetchClickEvent interface: existence and properties of interface object
+PASS BackgroundFetchClickEvent interface object length
+PASS BackgroundFetchClickEvent interface object name
+PASS BackgroundFetchClickEvent interface: existence and properties of interface prototype object
+PASS BackgroundFetchClickEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS BackgroundFetchClickEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS BackgroundFetchClickEvent interface: attribute state
+PASS Unscopable handled correctly for state property on BackgroundFetchClickEvent
+PASS ServiceWorkerRegistration interface: attribute backgroundFetch
+PASS Unscopable handled correctly for backgroundFetch property on ServiceWorkerRegistration
+PASS ServiceWorkerGlobalScope interface: attribute onbackgroundfetched
+PASS Unscopable handled correctly for onbackgroundfetched property on ServiceWorkerGlobalScope
+PASS ServiceWorkerGlobalScope interface: attribute onbackgroundfetchfail
+PASS Unscopable handled correctly for onbackgroundfetchfail property on ServiceWorkerGlobalScope
+PASS ServiceWorkerGlobalScope interface: attribute onbackgroundfetchabort
+PASS Unscopable handled correctly for onbackgroundfetchabort property on ServiceWorkerGlobalScope
+PASS ServiceWorkerGlobalScope interface: attribute onbackgroundfetchclick
+PASS Unscopable handled correctly for onbackgroundfetchclick property on ServiceWorkerGlobalScope
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.https.any.js b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.https.any.js
deleted file mode 100644
index b95b856..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.https.any.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// META: script=/resources/WebIDLParser.js
-// META: script=/resources/idlharness.js
-
-'use strict';
-
-// https://wicg.github.io/background-fetch/
-
-promise_test(async () => {
-  const srcs = [
-    'background-fetch',
-    'dedicated-workers',
-    'service-workers',
-    'dom'
-  ];
-  const [idls, worker, serviceWorker, dom] = await Promise.all(
-      srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
-
-  var idlArray = new IdlArray();
-  idlArray.add_idls(idls);
-  idlArray.add_dependency_idls(serviceWorker);
-  idlArray.add_dependency_idls(worker);
-  idlArray.add_dependency_idls(dom);
-  idlArray.test();
-}, 'background-fetch interfaces');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/idlharness.window.js
index 38fa663..6ac306c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/idlharness.window.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/embedded-enforcement/idlharness.window.js
@@ -5,17 +5,13 @@
 
 'use strict';
 
-promise_test(async () => {
-  const idl = await fetch('/interfaces/csp-embedded-enforcement.idl').then(r => r.text());
-  const html = await fetch('/interfaces/html.idl').then(r => r.text());
-  const dom = await fetch('/interfaces/dom.idl').then(r => r.text());
-
-  const idl_array = new IdlArray();
-  idl_array.add_idls(idl);
-  idl_array.add_dependency_idls(html);
-  idl_array.add_dependency_idls(dom);
-  idl_array.add_objects({
-    HTMLIFrameElement: ['document.createElement("iframe")'],
-  });
-  idl_array.test();
-}, 'csp-embedded-enforcement IDL');
+idl_test(
+  ['csp-embedded-enforcement'],
+  ['html', 'dom'],
+  idl_array => {
+    idl_array.add_objects({
+      HTMLIFrameElement: ['document.createElement("iframe")'],
+    });
+  },
+  'csp-embedded-enforcement IDL'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/position-absolute-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/position-absolute-001.html
index 3c3d593..f601740 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/position-absolute-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-flexbox/position-absolute-001.html
@@ -692,7 +692,7 @@
                 flexbox.className = 'flexbox ' + flexboxClassName;
                 flexbox.setAttribute('style', mainAxis + ': 80px;' + crossAxis + ': 20px');
 
-                var baselineMargin = (flexDirection.indexOf('row') != -1) ? '-webkit-margin-before: 5px' : '-webkit-margin-start: 5px';
+                var baselineMargin = (flexDirection.indexOf('row') != -1) ? 'margin-block-start: 5px' : 'margin-inline-start: 5px';
 
                 var testExpectations = expectations[writingMode][flexDirection][direction][justifyContent];
                 addChild(flexbox, mainAxis, crossAxis, 40, 10, testExpectations['child1']);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-images/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-images/idlharness-expected.txt
new file mode 100644
index 0000000..594163a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-images/idlharness-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS Test IDL implementation of css-masking
+FAIL Partial namespace CSS: original namespace defined assert_true: Original CSS definition should have type namespace expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-images/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-images/idlharness.html
new file mode 100644
index 0000000..ec9c358
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-images/idlharness.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>css-images IDL tests</title>
+<link rel="help" href="https://drafts.csswg.org/css-images-4/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script>
+  'use strict';
+
+  idl_test(
+    ['css-images'],
+    ['cssom'],
+    idl_array => {
+      // No objects,
+    },
+    'Test IDL implementation of css-masking'
+  );
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-armenian-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-armenian-ref.html
new file mode 100644
index 0000000..f21dfff
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-armenian-ref.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset=utf8>
+<title>Reference: Inside list marker and normal text render identically: armenian</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+</style>
+<p>Ա. Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-armenian.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-armenian.html
new file mode 100644
index 0000000..fd0df63
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-armenian.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: armenian</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-armenian-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: armenian inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-circle-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-circle-ref.html
new file mode 100644
index 0000000..60a342f1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-circle-ref.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>Reference: Inside list marker and normal text render identically: circle</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+p::before {
+    content: counter(test, circle);
+}
+</style>
+<p> Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-circle.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-circle.html
new file mode 100644
index 0000000..138f73c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-circle.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: circle</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-circle-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: circle inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal-leading-zero-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal-leading-zero-ref.html
new file mode 100644
index 0000000..997801d5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal-leading-zero-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Reference: Inside list marker and normal text render identically: decimal-leading-zero</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+</style>
+<p>01. Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal-leading-zero.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal-leading-zero.html
new file mode 100644
index 0000000..5044d4e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal-leading-zero.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: decimal-leading-zero</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-decimal-leading-zero-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: decimal-leading-zero inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal-ref.html
new file mode 100644
index 0000000..8f97cc36
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Reference: Inside list marker and normal text render identically: decimal</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+</style>
+<p>1. Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal.html
new file mode 100644
index 0000000..8c991bc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-decimal.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: decimal</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-decimal-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: decimal inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-disc-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-disc-ref.html
new file mode 100644
index 0000000..e34a900
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-disc-ref.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>Reference: Inside list marker and normal text render identically: disc</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+p::before {
+    content: counter(test, disc);
+}
+</style>
+<p> Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-disc.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-disc.html
new file mode 100644
index 0000000..e2456cb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-disc.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: disc</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-disc-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: disc inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-georgian-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-georgian-ref.html
new file mode 100644
index 0000000..c400aca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-georgian-ref.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset=utf8>
+<title>Reference: Inside list marker and normal text render identically: georgian</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+</style>
+<p>ა. Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-georgian.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-georgian.html
new file mode 100644
index 0000000..ef7615f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-georgian.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: georgian</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-georgian-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: georgian inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-greek-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-greek-ref.html
new file mode 100644
index 0000000..f28db82
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-greek-ref.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset=utf8>
+<title>Reference: Inside list marker and normal text render identically: lower-greek</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+</style>
+<p>α. Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-greek.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-greek.html
new file mode 100644
index 0000000..96b5d811
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-greek.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: lower-greek</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-lower-greek-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: lower-greek inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-latin-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-latin-ref.html
new file mode 100644
index 0000000..b86fe8ec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-latin-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Reference: Inside list marker and normal text render identically: lower-latin</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+</style>
+<p>a. Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-latin.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-latin.html
new file mode 100644
index 0000000..0f6f242
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-latin.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: lower-latin</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-lower-latin-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: lower-latin inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-roman-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-roman-ref.html
new file mode 100644
index 0000000..92dfa3d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-roman-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Reference: Inside list marker and normal text render identically: lower-roman</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+</style>
+<p>i. Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-roman.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-roman.html
new file mode 100644
index 0000000..db7301b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-lower-roman.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: lower-roman</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-lower-roman-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: lower-roman inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-square-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-square-ref.html
new file mode 100644
index 0000000..99b64a54
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-square-ref.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>Reference: Inside list marker and normal text render identically: square</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+p::before {
+    content: counter(test, square);
+}
+</style>
+<p> Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-square.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-square.html
new file mode 100644
index 0000000..9095017
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-square.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: square</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-square-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: square inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-latin-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-latin-ref.html
new file mode 100644
index 0000000..6cbb712
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-latin-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Reference: Inside list marker and normal text render identically: upper-latin</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+</style>
+<p>A. Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-latin.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-latin.html
new file mode 100644
index 0000000..903ef8f5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-latin.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: upper-latin</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-upper-latin-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: upper-latin inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-roman-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-roman-ref.html
new file mode 100644
index 0000000..6fca49f2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-roman-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Reference: Inside list marker and normal text render identically: upper-roman</title>
+<style>
+* {
+    margin: 0;
+    padding: 0;
+}
+</style>
+<p>I. Filler Text
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-roman.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-roman.html
new file mode 100644
index 0000000..69f34d74
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-lists/content-property/marker-text-matches-upper-roman.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Inside list marker and normal text render identically: upper-roman</title>
+<link rel=help href="https://drafts.csswg.org/css-lists-3/#content-property">
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=787382">
+<link rel=match href="marker-text-matches-upper-roman-ref.html">
+<style>
+* {
+    padding: 0;
+    margin: 0;
+}
+ol {
+    list-style: upper-roman inside;
+}
+</style>
+
+<ol>
+  <li>Filler Text</li>
+</ol>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-logical/animation-003.tentative-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-logical/animation-003.tentative-expected.txt
new file mode 100644
index 0000000..24c710be
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-logical/animation-003.tentative-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Logical properties are represented as physical properties in keyframes assert_own_property: expected property "height" missing
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-logical/animation-003.tenative.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-logical/animation-003.tentative.html
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/css/css-logical/animation-003.tenative.html
rename to third_party/WebKit/LayoutTests/external/wpt/css/css-logical/animation-003.tentative.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-pseudo/marker-inherit-line-height-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-pseudo/marker-inherit-line-height-ref.html
new file mode 100644
index 0000000..fe57a281f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-pseudo/marker-inherit-line-height-ref.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>Reference: Check that :marker inherits line-height</title>
+<style>
+div {
+  font: 128px/1 Ahem;
+  border: 2px solid blue;
+  background: orange;
+  color: black;
+}
+</style>
+
+<p>There should be two black rectangles below with no space between them and
+  the border above/below.</p>
+<div>
+  1. X
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-pseudo/marker-inherit-line-height.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-pseudo/marker-inherit-line-height.html
new file mode 100644
index 0000000..145aedcb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-pseudo/marker-inherit-line-height.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>Check that :marker inherits line-height</title>
+<link rel=help href="https://drafts.csswg.org/css-pseudo-4/#tree-abiding">
+<link rel=help href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
+<link rel=help href="https://drafts.csswg.org/css-display-3/#list-items">
+<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1415759">
+<link rel=match href=marker-inherit-line-height-ref.html>
+<style>
+div {
+  font: 128px/1 Ahem;
+  border: 2px solid blue;
+  background: orange;
+  color: black;
+}
+ol {
+  margin: 0;
+  padding: 0;
+  list-style-position: inside;
+  list-style-type: decimal;
+}
+</style>
+
+<p>There should be two black rectangles below with no space between them and
+  the border above/below.</p>
+<div>
+  <ol>
+    <li>X
+  </ol>
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-maxlength.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-maxlength.html
new file mode 100644
index 0000000..ff4e8f1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-maxlength.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>textarea maxlength</title>
+  <link rel="author" title="tigercosmos" href="mailto:phy.tiger@gmail.com">
+  <link rel=help href="https://html.spec.whatwg.org/multipage/#attr-textarea-maxlength">
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+
+  <textarea id="none"></textarea>
+  <textarea id="negative" maxlength="-5"></textarea>
+  <textarea id="non-numeric" maxlength="not-a-number"></textarea>
+  <textarea id="assign-negative"></textarea>
+  <textarea id="assign-non-numeric"></textarea>
+
+  <script>
+    test(
+      function () {
+        assert_equals(document.getElementById("none").maxLength, -1);
+      }, "Unset maxlength is -1");
+
+    test(
+      function () {
+        assert_equals(document.getElementById("negative").maxLength, -1);
+      }, "Negative maxlength is always -1");
+
+    test(
+      function () {
+        assert_equals(document.getElementById("non-numeric").maxLength, -1);
+      }, "Non-numeric maxlength is -1");
+
+    test(
+      function () {
+        assert_throws("INDEX_SIZE_ERR", function () {
+          document.getElementById("assign-negative").maxLength = -5;
+        });
+      }, "Assigning negative integer throws IndexSizeError");
+
+    test(
+      function () {
+        document.getElementById("assign-non-numeric").maxLength = "not-a-number";
+        assert_equals(document.getElementById("assign-non-numeric").maxLength, 0);
+      }, "Assigning non-numeric to maxlength sets maxlength to 0");
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-minlength.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-minlength.html
new file mode 100644
index 0000000..9a15a12
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-minlength.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+  <title>textarea minlength</title>
+  <link rel="author" title="tigercosmos" href="mailto:phy.tiger@gmail.com">
+  <link rel=help href="https://html.spec.whatwg.org/multipage/#attr-textarea-minlength">
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+
+  <textarea id="none"></textarea>
+  <textarea id="negative" minlength=-5></textarea>
+  <textarea id="non-numeric" minlength="not-a-number"></textarea>
+  <textarea id="assign-negative"></textarea>
+  <textarea id="assign-non-numeric"></textarea>
+
+  <script>
+    test(
+      function () {
+        assert_equals(document.getElementById("none").minLength, -1);
+      }, "Unset minlength is -1");
+
+    test(
+      function () {
+        assert_equals(document.getElementById("negative").minLength, -1);
+      }, "Negative minlength is always -1");
+
+    test(
+      function () {
+        assert_equals(document.getElementById("non-numeric").minLength, -1);
+      }, "Non-numeric minlength is -1");
+
+    test(
+      function () {
+        assert_throws("INDEX_SIZE_ERR", function () {
+          document.getElementById("assign-negative").minLength = -5;
+        });
+      }, "Assigning negative integer throws IndexSizeError");
+
+    test(
+      function () {
+        document.getElementById("assign-non-numeric").minLength = "not-a-number";
+        assert_equals(document.getElementById("assign-non-numeric").minLength, 0);
+      }, "Assigning non-numeric to minlength sets minlength to 0");
+  </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-textLength.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-textLength.html
new file mode 100644
index 0000000..d249278
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-textLength.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<title>The textLengh IDL attribute</title>
+<meta content="charset=utf-16">
+<link rel="author" title="tigercosmos" href="mailto:phy.tiger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-textarea-textlength">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<textarea id="textarea"></textarea>
+<script>
+    var textarea = document.getElementById("textarea");
+
+    test(function () {
+        textarea.value= "Hello, World!";
+        assert_equals(textarea.textLength, 13);
+
+        textarea.value = "\u4f60\u597d\uff0c\u4e16\u754c\uff01"; //你好,世界!
+        assert_equals(textarea.textLength, 6);
+    }, "Textarea's 'testLength' should work for utf-16.");
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-validity-clone.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-validity-clone.html
new file mode 100644
index 0000000..23d90e7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-textarea-element/textarea-validity-clone.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>HTML Test: &lt;textarea&gt; validity state is correct after a clone</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-textarea-element">
+<link rel="help" href="https://bugzil.la/1472169">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+  let form = document.createElement("form");
+  let textarea = document.createElement("textarea");
+  textarea.required = true;
+
+  textarea.appendChild(document.createTextNode("A"));
+  form.appendChild(textarea);
+
+  assert_true(textarea.validity.valid);
+
+  let formClone = form.cloneNode(true);
+  assert_equals(
+    formClone.querySelector('textarea').validity.valid,
+    textarea.validity.valid,
+    "Validity state should be preserved after a clone"
+  );
+}, "<textarea> validity state should be preserved after a clone");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/wpt-server-http.sub-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/wpt-server-http.sub-expected.txt
deleted file mode 100644
index 776d0af5..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/wpt-server-http.sub-expected.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-This is a testharness.js-based test.
-PASS HTTP protocol, no subdomain, port #1
-PASS HTTP protocol, no subdomain, port #2
-PASS HTTP protocol, www subdomain #1, port #1
-PASS HTTP protocol, www subdomain #1, port #2
-PASS HTTP protocol, www subdomain #2, port #1
-PASS HTTP protocol, www subdomain #2, port #2
-PASS HTTP protocol, www subdomain #3, port #1
-PASS HTTP protocol, www subdomain #3, port #2
-PASS HTTP protocol, punycode subdomain #1, port #1
-PASS HTTP protocol, punycode subdomain #1, port #2
-PASS HTTP protocol, punycode subdomain #2, port #1
-PASS HTTP protocol, punycode subdomain #2, port #2
-FAIL HTTP protocol, non-existent domain, port #1 assert_false: expected false got true
-FAIL HTTP protocol, non-existent domain, port #2 assert_false: expected false got true
-PASS HTTPS protocol, no subdomain
-PASS HTTPS protocol, www subdomain #1
-PASS HTTPS protocol, www subdomain #2
-PASS HTTPS protocol, www subdomain #3
-PASS HTTPS protocol, punycode subdomain #1
-PASS HTTPS protocol, punycode subdomain #2
-PASS HTTPS protocol, non-existent domain, port #1
-PASS HTTPS protocol, non-existent domain, port #2
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/background-fetch.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/background-fetch.idl
index 68509fc1a..fc3ed8d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/background-fetch.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/background-fetch.idl
@@ -18,7 +18,7 @@
 interface BackgroundFetchManager {
   Promise<BackgroundFetchRegistration> fetch(DOMString id, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options);
   Promise<BackgroundFetchRegistration?> get(DOMString id);
-  Promise<FrozenArray<DOMString>> getIds();
+  Promise<sequence<DOMString>> getIds();
   // TODO: in future this should become an async iterator for BackgroundFetchRegistration objects
 };
 
@@ -51,14 +51,10 @@
 };
 
 [Exposed=(Window,Worker)]
-interface BackgroundFetchFetch {
-  readonly attribute Request request;
-};
-
-[Exposed=(Window,Worker)]
 interface BackgroundFetchActiveFetches {
-  Promise<BackgroundFetchActiveFetch> match(RequestInfo request);
-  Promise<FrozenArray<BackgroundFetchActiveFetch>> values();
+  Promise<BackgroundFetchActiveFetch> match(RequestInfo request, optional CacheQueryOptions options);
+  Promise<sequence<BackgroundFetchActiveFetch>> matchAll(RequestInfo request, optional CacheQueryOptions options);
+  Promise<sequence<BackgroundFetchActiveFetch>> values();
 };
 
 [Exposed=(Window,Worker)]
@@ -67,6 +63,11 @@
   // In future this will include a fetch observer
 };
 
+[Exposed=(Window,Worker)]
+interface BackgroundFetchFetch {
+  readonly attribute Request request;
+};
+
 [Constructor(DOMString type, BackgroundFetchEventInit init), Exposed=ServiceWorker]
 interface BackgroundFetchEvent : ExtendableEvent {
   readonly attribute DOMString id;
@@ -87,8 +88,9 @@
 
 [Exposed=ServiceWorker]
 interface BackgroundFetchSettledFetches {
-  Promise<BackgroundFetchSettledFetch> match(RequestInfo request);
-  Promise<FrozenArray<BackgroundFetchSettledFetch>> values();
+  Promise<BackgroundFetchSettledFetch> match(RequestInfo request, optional CacheQueryOptions options);
+  Promise<sequence<BackgroundFetchSettledFetch>> matchAll(RequestInfo request, optional CacheQueryOptions options);
+  Promise<sequence<BackgroundFetchSettledFetch>> values();
 };
 
 [Exposed=ServiceWorker]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-counter-styles.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-counter-styles.idl
new file mode 100644
index 0000000..b1c3663
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-counter-styles.idl
@@ -0,0 +1,23 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "CSS Counter Styles Level 3" spec.
+// See: https://drafts.csswg.org/css-counter-styles/
+
+partial interface CSSRule {
+    const unsigned short COUNTER_STYLE_RULE = 11;
+};
+
+[Exposed=Window]
+interface CSSCounterStyleRule : CSSRule {
+  attribute CSSOMString name;
+  attribute CSSOMString system;
+  attribute CSSOMString symbols;
+  attribute CSSOMString additiveSymbols;
+  attribute CSSOMString negative;
+  attribute CSSOMString prefix;
+  attribute CSSOMString suffix;
+  attribute CSSOMString range;
+  attribute CSSOMString pad;
+  attribute CSSOMString speakAs;
+  attribute CSSOMString fallback;
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-images.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-images.idl
new file mode 100644
index 0000000..0dbac1c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-images.idl
@@ -0,0 +1,8 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "CSS Images Module Level 4" spec.
+// See: https://drafts.csswg.org/css-images-4/
+
+partial namespace CSS {
+  // [SameObject] readonly attribute Map elementSources;
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-regions.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-regions.idl
new file mode 100644
index 0000000..546c21ad
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-regions.idl
@@ -0,0 +1,35 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "CSS Regions Module Level 1" spec.
+// See: https://drafts.csswg.org/css-regions/
+
+partial interface Document {
+  readonly attribute NamedFlowMap namedFlows;
+};
+
+[Exposed=Window,
+ MapClass=(CSSOMString, NamedFlow)] interface NamedFlowMap {
+  NamedFlow? get(CSSOMString flowName);
+  boolean has(CSSOMString flowName);
+  NamedFlowMap set(CSSOMString flowName, NamedFlow flowValue);
+  boolean delete(CSSOMString flowName);
+};
+
+[Exposed=Window]
+interface NamedFlow : EventTarget {
+  readonly attribute CSSOMString name;
+  readonly attribute boolean overset;
+  sequence<Region> getRegions();
+  readonly attribute short firstEmptyRegionIndex;
+  sequence<Node> getContent();
+  sequence<Region> getRegionsByContent(Node node);
+};
+
+[Exposed=Window,
+ NoInterfaceObject]
+interface Region {
+  readonly attribute CSSOMString regionOverset;
+  sequence<Range>? getRegionFlowRanges();
+};
+
+Element implements Region;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/media-source.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/media-source.idl
new file mode 100644
index 0000000..6476794
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/media-source.idl
@@ -0,0 +1,72 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "Media Source Extensions™" spec.
+// See: https://w3c.github.io/media-source/
+
+enum ReadyState {
+    "closed",
+    "open",
+    "ended"
+};
+enum EndOfStreamError {
+    "network",
+    "decode"
+};
+[Constructor]
+interface MediaSource : EventTarget {
+    readonly attribute SourceBufferList    sourceBuffers;
+    readonly attribute SourceBufferList    activeSourceBuffers;
+    readonly attribute ReadyState          readyState;
+             attribute unrestricted double duration;
+             attribute EventHandler        onsourceopen;
+             attribute EventHandler        onsourceended;
+             attribute EventHandler        onsourceclose;
+    SourceBuffer addSourceBuffer(DOMString type);
+    void         removeSourceBuffer(SourceBuffer sourceBuffer);
+    void         endOfStream(optional EndOfStreamError error);
+    void         setLiveSeekableRange(double start, double end);
+    void         clearLiveSeekableRange();
+    static boolean isTypeSupported(DOMString type);
+};
+enum AppendMode {
+    "segments",
+    "sequence"
+};
+interface SourceBuffer : EventTarget {
+             attribute AppendMode          mode;
+    readonly attribute boolean             updating;
+    readonly attribute TimeRanges          buffered;
+             attribute double              timestampOffset;
+    readonly attribute AudioTrackList      audioTracks;
+    readonly attribute VideoTrackList      videoTracks;
+    readonly attribute TextTrackList       textTracks;
+             attribute double              appendWindowStart;
+             attribute unrestricted double appendWindowEnd;
+             attribute EventHandler        onupdatestart;
+             attribute EventHandler        onupdate;
+             attribute EventHandler        onupdateend;
+             attribute EventHandler        onerror;
+             attribute EventHandler        onabort;
+    void appendBuffer(BufferSource data);
+    void abort();
+    void remove(double start, unrestricted double end);
+};
+interface SourceBufferList : EventTarget {
+    readonly attribute unsigned long length;
+             attribute EventHandler  onaddsourcebuffer;
+             attribute EventHandler  onremovesourcebuffer;
+    getter SourceBuffer (unsigned long index);
+};
+[Exposed=Window]
+partial interface URL {
+    static DOMString createObjectURL(MediaSource mediaSource);
+};
+partial interface AudioTrack {
+    readonly attribute SourceBuffer? sourceBuffer;
+};
+partial interface VideoTrack {
+    readonly attribute SourceBuffer? sourceBuffer;
+};
+partial interface TextTrack {
+    readonly attribute SourceBuffer? sourceBuffer;
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/resource-timing.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/resource-timing.idl
index 3f041e1..2668f91 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/resource-timing.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/resource-timing.idl
@@ -5,27 +5,28 @@
 
 [Exposed=(Window,Worker)]
 interface PerformanceResourceTiming : PerformanceEntry {
-    readonly attribute DOMString           initiatorType;
-    readonly attribute DOMString           nextHopProtocol;
-    readonly attribute DOMHighResTimeStamp workerStart;
-    readonly attribute DOMHighResTimeStamp redirectStart;
-    readonly attribute DOMHighResTimeStamp redirectEnd;
-    readonly attribute DOMHighResTimeStamp fetchStart;
-    readonly attribute DOMHighResTimeStamp domainLookupStart;
-    readonly attribute DOMHighResTimeStamp domainLookupEnd;
-    readonly attribute DOMHighResTimeStamp connectStart;
-    readonly attribute DOMHighResTimeStamp connectEnd;
-    readonly attribute DOMHighResTimeStamp secureConnectionStart;
-    readonly attribute DOMHighResTimeStamp requestStart;
-    readonly attribute DOMHighResTimeStamp responseStart;
-    readonly attribute DOMHighResTimeStamp responseEnd;
-    readonly attribute unsigned long long  transferSize;
-    readonly attribute unsigned long long  encodedBodySize;
-    readonly attribute unsigned long long  decodedBodySize;
+    readonly        attribute DOMString initiatorType;
+    readonly        attribute DOMString nextHopProtocol;
+    readonly        attribute DOMHighResTimeStamp workerStart;
+    readonly        attribute DOMHighResTimeStamp redirectStart;
+    readonly        attribute DOMHighResTimeStamp redirectEnd;
+    readonly        attribute DOMHighResTimeStamp fetchStart;
+    readonly        attribute DOMHighResTimeStamp domainLookupStart;
+    readonly        attribute DOMHighResTimeStamp domainLookupEnd;
+    readonly        attribute DOMHighResTimeStamp connectStart;
+    readonly        attribute DOMHighResTimeStamp connectEnd;
+    readonly        attribute DOMHighResTimeStamp secureConnectionStart;
+    readonly        attribute DOMHighResTimeStamp requestStart;
+    readonly        attribute DOMHighResTimeStamp responseStart;
+    readonly        attribute DOMHighResTimeStamp responseEnd;
+    readonly        attribute unsigned long long transferSize;
+    readonly        attribute unsigned long long encodedBodySize;
+    readonly        attribute unsigned long long decodedBodySize;
     [Default] object toJSON();
 };
+
 partial interface Performance {
-    void clearResourceTimings();
-    void setResourceTimingBufferSize(unsigned long maxSize);
-    attribute EventHandler onresourcetimingbufferfull;
+  void clearResourceTimings();
+  void setResourceTimingBufferSize(unsigned long maxSize);
+              attribute EventHandler onresourcetimingbufferfull;
 };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/selection-api.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/selection-api.idl
index b2d2f86..6e814ea 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/selection-api.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/selection-api.idl
@@ -4,42 +4,40 @@
 // See: https://w3c.github.io/selection-api/
 
 interface Selection {
-    readonly attribute Node?         anchorNode;
-    readonly attribute unsigned long anchorOffset;
-    readonly attribute Node?         focusNode;
-    readonly attribute unsigned long focusOffset;
-    readonly attribute boolean       isCollapsed;
-    readonly attribute unsigned long rangeCount;
-    readonly attribute DOMString     type;
-    Range                 getRangeAt(unsigned long index);
-    void                  addRange(Range range);
-    void                  removeRange(Range range);
-    void                  removeAllRanges();
-    void                  empty();
-    void                  collapse(Node? node,
-                                   optional unsigned long offset = 0);
-    void                  setPosition(Node? node,
-                                      optional unsigned long offset = 0);
-    void                  collapseToStart();
-    void                  collapseToEnd();
-    void                  extend(Node node, optional unsigned long offset = 0);
-    void                  setBaseAndExtent(Node anchorNode,
-                                           unsigned long anchorOffset,
-                                           Node focusNode,
-                                           unsigned long focusOffset);
-    void                  selectAllChildren(Node node);
-    [CEReactions] void                  deleteFromDocument();
-    boolean               containsNode(Node node,
-                                       optional boolean allowPartialContainment = false);
-    stringifier DOMString ();
+  readonly attribute Node? anchorNode;
+  readonly attribute unsigned long anchorOffset;
+  readonly attribute Node? focusNode;
+  readonly attribute unsigned long focusOffset;
+  readonly attribute boolean isCollapsed;
+  readonly attribute unsigned long rangeCount;
+  readonly attribute DOMString type;
+  Range getRangeAt(unsigned long index);
+  void addRange(Range range);
+  void removeRange(Range range);
+  void removeAllRanges();
+  void empty();
+  void collapse(Node? node, optional unsigned long offset = 0);
+  void setPosition(Node? node, optional unsigned long offset = 0);
+  void collapseToStart();
+  void collapseToEnd();
+  void extend(Node node, optional unsigned long offset = 0);
+  void setBaseAndExtent(Node anchorNode, unsigned long anchorOffset, Node focusNode, unsigned long focusOffset);
+  void selectAllChildren(Node node);
+  [CEReactions]
+  void deleteFromDocument();
+  boolean containsNode(Node node, optional boolean allowPartialContainment = false);
+  stringifier DOMString ();
 };
+
 partial interface Document {
-    Selection? getSelection();
+  Selection? getSelection();
 };
+
 partial interface Window {
-    Selection? getSelection();
+  Selection? getSelection();
 };
+
 partial interface GlobalEventHandlers {
-    attribute EventHandler onselectstart;
-    attribute EventHandler onselectionchange;
+  attribute EventHandler onselectstart;
+  attribute EventHandler onselectionchange;
 };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/service-workers.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/service-workers.idl
index edf2985bd..38d22c6 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/service-workers.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/service-workers.idl
@@ -12,7 +12,7 @@
   // event
   attribute EventHandler onstatechange;
 };
-ServiceWorker implements AbstractWorker;
+ServiceWorker includes AbstractWorker;
 
 enum ServiceWorkerState {
   "installing",
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/touch-events.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/touch-events.idl
index 5c5a3ef..097b0e9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/touch-events.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/touch-events.idl
@@ -9,78 +9,74 @@
 };
 
 dictionary TouchInit {
-    required long        identifier;
+    required long identifier;
     required EventTarget target;
-             double      clientX = 0;
-             double      clientY = 0;
-             double      screenX = 0;
-             double      screenY = 0;
-             double      pageX = 0;
-             double      pageY = 0;
-             float       radiusX = 0;
-             float       radiusY = 0;
-             float       rotationAngle = 0;
-             float       force = 0;
-             double      altitudeAngle = 0;
-             double      azimuthAngle = 0;
-             TouchType   touchType = "direct";
+             double clientX = 0;
+             double clientY = 0;
+             double screenX = 0;
+             double screenY = 0;
+             double pageX = 0;
+             double pageY = 0;
+             float radiusX = 0;
+             float radiusY = 0;
+             float rotationAngle = 0;
+             float force = 0;
+             double altitudeAngle = 0;
+             double azimuthAngle = 0;
+             TouchType touchType = "direct";
 };
 
-[Constructor(TouchInit touchInitDict),
- Exposed=Window]
+[Constructor(TouchInit touchInitDict), Exposed=Window]
 interface Touch {
-    readonly attribute long        identifier;
-    readonly attribute EventTarget target;
-    readonly attribute double      screenX;
-    readonly attribute double      screenY;
-    readonly attribute double      clientX;
-    readonly attribute double      clientY;
-    readonly attribute double      pageX;
-    readonly attribute double      pageY;
-    readonly attribute float       radiusX;
-    readonly attribute float       radiusY;
-    readonly attribute float       rotationAngle;
-    readonly attribute float       force;
-    readonly attribute float       altitudeAngle;
-    readonly attribute float       azimuthAngle;
-    readonly attribute TouchType   touchType;
+    readonly        attribute long identifier;
+    readonly        attribute EventTarget target;
+    readonly        attribute double screenX;
+    readonly        attribute double screenY;
+    readonly        attribute double clientX;
+    readonly        attribute double clientY;
+    readonly        attribute double pageX;
+    readonly        attribute double pageY;
+    readonly        attribute float radiusX;
+    readonly        attribute float radiusY;
+    readonly        attribute float rotationAngle;
+    readonly        attribute float force;
+    readonly        attribute float altitudeAngle;
+    readonly        attribute float azimuthAngle;
+    readonly        attribute TouchType touchType;
 };
+
 interface TouchList {
-    readonly attribute unsigned long length;
+    readonly        attribute unsigned long length;
     getter Touch? item(unsigned long index);
 };
+
 dictionary TouchEventInit : EventModifierInit {
-    sequence<Touch> touches = [];
-    sequence<Touch> targetTouches = [];
-    sequence<Touch> changedTouches = [];
+             sequence<Touch> touches = [];
+             sequence<Touch> targetTouches = [];
+             sequence<Touch> changedTouches = [];
 };
 
-[Constructor(DOMString type, optional TouchEventInit eventInitDict),
- Exposed=Window]
+[Constructor(DOMString type, optional TouchEventInit eventInitDict), Exposed=Window]
 interface TouchEvent : UIEvent {
-    readonly attribute TouchList touches;
-    readonly attribute TouchList targetTouches;
-    readonly attribute TouchList changedTouches;
-    readonly attribute boolean   altKey;
-    readonly attribute boolean   metaKey;
-    readonly attribute boolean   ctrlKey;
-    readonly attribute boolean   shiftKey;
+    readonly        attribute TouchList touches;
+    readonly        attribute TouchList targetTouches;
+    readonly        attribute TouchList changedTouches;
+    readonly        attribute boolean altKey;
+    readonly        attribute boolean metaKey;
+    readonly        attribute boolean ctrlKey;
+    readonly        attribute boolean shiftKey;
 };
+
 partial interface GlobalEventHandlers {
-    attribute EventHandler ontouchstart;
-    attribute EventHandler ontouchend;
-    attribute EventHandler ontouchmove;
-    attribute EventHandler ontouchcancel;
+                    attribute EventHandler ontouchstart;
+                    attribute EventHandler ontouchend;
+                    attribute EventHandler ontouchmove;
+                    attribute EventHandler ontouchcancel;
 };
+
 partial interface Document {
-    // Deprecated in this specification
-    Touch     createTouch(WindowProxy view,
-                          EventTarget target,
-                          long identifier,
-                          double pageX,
-                          double pageY,
-                          double screenX,
-                          double screenY);
-    // Deprecated in this specification
-    TouchList createTouchList(Touch... touches);
+  // Deprecated in this specification
+  Touch createTouch(WindowProxy view, EventTarget target, long identifier, double pageX, double pageY, double screenX, double screenY);
+  // Deprecated in this specification
+  TouchList createTouchList(Touch... touches);
 };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/media-source/idlharness.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/media-source/idlharness.any-expected.txt
new file mode 100644
index 0000000..4d85278
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/media-source/idlharness.any-expected.txt
@@ -0,0 +1,148 @@
+This is a testharness.js-based test.
+Found 144 tests; 141 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS media-source interfaces
+PASS Partial interface URL: original interface defined
+PASS Partial interface URL: valid exposure set
+PASS Partial interface AudioTrack: original interface defined
+PASS Partial interface VideoTrack: original interface defined
+PASS Partial interface TextTrack: original interface defined
+PASS MediaSource interface: existence and properties of interface object
+PASS MediaSource interface object length
+PASS MediaSource interface object name
+PASS MediaSource interface: existence and properties of interface prototype object
+PASS MediaSource interface: existence and properties of interface prototype object's "constructor" property
+PASS MediaSource interface: existence and properties of interface prototype object's @@unscopables property
+PASS MediaSource interface: attribute sourceBuffers
+PASS Unscopable handled correctly for sourceBuffers property on MediaSource
+PASS MediaSource interface: attribute activeSourceBuffers
+PASS Unscopable handled correctly for activeSourceBuffers property on MediaSource
+PASS MediaSource interface: attribute readyState
+PASS Unscopable handled correctly for readyState property on MediaSource
+PASS MediaSource interface: attribute duration
+PASS Unscopable handled correctly for duration property on MediaSource
+PASS MediaSource interface: attribute onsourceopen
+PASS Unscopable handled correctly for onsourceopen property on MediaSource
+PASS MediaSource interface: attribute onsourceended
+PASS Unscopable handled correctly for onsourceended property on MediaSource
+PASS MediaSource interface: attribute onsourceclose
+PASS Unscopable handled correctly for onsourceclose property on MediaSource
+PASS MediaSource interface: operation addSourceBuffer(DOMString)
+PASS Unscopable handled correctly for addSourceBuffer(DOMString) on MediaSource
+PASS MediaSource interface: operation removeSourceBuffer(SourceBuffer)
+PASS Unscopable handled correctly for removeSourceBuffer(SourceBuffer) on MediaSource
+PASS MediaSource interface: operation endOfStream(EndOfStreamError)
+PASS Unscopable handled correctly for endOfStream(EndOfStreamError) on MediaSource
+PASS MediaSource interface: operation setLiveSeekableRange(double, double)
+PASS Unscopable handled correctly for setLiveSeekableRange(double, double) on MediaSource
+PASS MediaSource interface: operation clearLiveSeekableRange()
+PASS Unscopable handled correctly for clearLiveSeekableRange() on MediaSource
+PASS MediaSource interface: operation isTypeSupported(DOMString)
+PASS Unscopable handled correctly for isTypeSupported(DOMString) on MediaSource
+PASS MediaSource must be primary interface of mediaSource
+PASS Stringification of mediaSource
+PASS MediaSource interface: mediaSource must inherit property "sourceBuffers" with the proper type
+PASS MediaSource interface: mediaSource must inherit property "activeSourceBuffers" with the proper type
+PASS MediaSource interface: mediaSource must inherit property "readyState" with the proper type
+PASS MediaSource interface: mediaSource must inherit property "duration" with the proper type
+PASS MediaSource interface: mediaSource must inherit property "onsourceopen" with the proper type
+PASS MediaSource interface: mediaSource must inherit property "onsourceended" with the proper type
+PASS MediaSource interface: mediaSource must inherit property "onsourceclose" with the proper type
+PASS MediaSource interface: mediaSource must inherit property "addSourceBuffer(DOMString)" with the proper type
+PASS MediaSource interface: calling addSourceBuffer(DOMString) on mediaSource with too few arguments must throw TypeError
+PASS MediaSource interface: mediaSource must inherit property "removeSourceBuffer(SourceBuffer)" with the proper type
+PASS MediaSource interface: calling removeSourceBuffer(SourceBuffer) on mediaSource with too few arguments must throw TypeError
+PASS MediaSource interface: mediaSource must inherit property "endOfStream(EndOfStreamError)" with the proper type
+PASS MediaSource interface: calling endOfStream(EndOfStreamError) on mediaSource with too few arguments must throw TypeError
+PASS MediaSource interface: mediaSource must inherit property "setLiveSeekableRange(double, double)" with the proper type
+PASS MediaSource interface: calling setLiveSeekableRange(double, double) on mediaSource with too few arguments must throw TypeError
+PASS MediaSource interface: mediaSource must inherit property "clearLiveSeekableRange()" with the proper type
+PASS MediaSource interface: mediaSource must inherit property "isTypeSupported(DOMString)" with the proper type
+PASS MediaSource interface: calling isTypeSupported(DOMString) on mediaSource with too few arguments must throw TypeError
+PASS SourceBuffer interface: existence and properties of interface object
+PASS SourceBuffer interface object length
+PASS SourceBuffer interface object name
+PASS SourceBuffer interface: existence and properties of interface prototype object
+PASS SourceBuffer interface: existence and properties of interface prototype object's "constructor" property
+PASS SourceBuffer interface: existence and properties of interface prototype object's @@unscopables property
+PASS SourceBuffer interface: attribute mode
+PASS Unscopable handled correctly for mode property on SourceBuffer
+PASS SourceBuffer interface: attribute updating
+PASS Unscopable handled correctly for updating property on SourceBuffer
+PASS SourceBuffer interface: attribute buffered
+PASS Unscopable handled correctly for buffered property on SourceBuffer
+PASS SourceBuffer interface: attribute timestampOffset
+PASS Unscopable handled correctly for timestampOffset property on SourceBuffer
+PASS SourceBuffer interface: attribute audioTracks
+PASS Unscopable handled correctly for audioTracks property on SourceBuffer
+PASS SourceBuffer interface: attribute videoTracks
+PASS Unscopable handled correctly for videoTracks property on SourceBuffer
+FAIL SourceBuffer interface: attribute textTracks assert_true: The prototype object must have a property "textTracks" expected true got false
+PASS Unscopable handled correctly for textTracks property on SourceBuffer
+PASS SourceBuffer interface: attribute appendWindowStart
+PASS Unscopable handled correctly for appendWindowStart property on SourceBuffer
+PASS SourceBuffer interface: attribute appendWindowEnd
+PASS Unscopable handled correctly for appendWindowEnd property on SourceBuffer
+PASS SourceBuffer interface: attribute onupdatestart
+PASS Unscopable handled correctly for onupdatestart property on SourceBuffer
+PASS SourceBuffer interface: attribute onupdate
+PASS Unscopable handled correctly for onupdate property on SourceBuffer
+PASS SourceBuffer interface: attribute onupdateend
+PASS Unscopable handled correctly for onupdateend property on SourceBuffer
+PASS SourceBuffer interface: attribute onerror
+PASS Unscopable handled correctly for onerror property on SourceBuffer
+PASS SourceBuffer interface: attribute onabort
+PASS Unscopable handled correctly for onabort property on SourceBuffer
+PASS SourceBuffer interface: operation appendBuffer(BufferSource)
+PASS Unscopable handled correctly for appendBuffer(BufferSource) on SourceBuffer
+PASS SourceBuffer interface: operation abort()
+PASS Unscopable handled correctly for abort() on SourceBuffer
+PASS SourceBuffer interface: operation remove(double, unrestricted double)
+PASS Unscopable handled correctly for remove(double, unrestricted double) on SourceBuffer
+PASS SourceBuffer must be primary interface of sourceBuffer
+PASS Stringification of sourceBuffer
+PASS SourceBuffer interface: sourceBuffer must inherit property "mode" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "updating" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "buffered" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "timestampOffset" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "audioTracks" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "videoTracks" with the proper type
+FAIL SourceBuffer interface: sourceBuffer must inherit property "textTracks" with the proper type assert_inherits: property "textTracks" not found in prototype chain
+PASS SourceBuffer interface: sourceBuffer must inherit property "appendWindowStart" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "appendWindowEnd" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "onupdatestart" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "onupdate" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "onupdateend" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "onerror" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "onabort" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "appendBuffer(BufferSource)" with the proper type
+PASS SourceBuffer interface: calling appendBuffer(BufferSource) on sourceBuffer with too few arguments must throw TypeError
+PASS SourceBuffer interface: sourceBuffer must inherit property "abort()" with the proper type
+PASS SourceBuffer interface: sourceBuffer must inherit property "remove(double, unrestricted double)" with the proper type
+PASS SourceBuffer interface: calling remove(double, unrestricted double) on sourceBuffer with too few arguments must throw TypeError
+PASS SourceBufferList interface: existence and properties of interface object
+PASS SourceBufferList interface object length
+PASS SourceBufferList interface object name
+PASS SourceBufferList interface: existence and properties of interface prototype object
+PASS SourceBufferList interface: existence and properties of interface prototype object's "constructor" property
+PASS SourceBufferList interface: existence and properties of interface prototype object's @@unscopables property
+PASS SourceBufferList interface: attribute length
+PASS Unscopable handled correctly for length property on SourceBufferList
+PASS SourceBufferList interface: attribute onaddsourcebuffer
+PASS Unscopable handled correctly for onaddsourcebuffer property on SourceBufferList
+PASS SourceBufferList interface: attribute onremovesourcebuffer
+PASS Unscopable handled correctly for onremovesourcebuffer property on SourceBufferList
+PASS SourceBufferList must be primary interface of mediaSource.sourceBuffers
+PASS Stringification of mediaSource.sourceBuffers
+PASS SourceBufferList interface: mediaSource.sourceBuffers must inherit property "length" with the proper type
+PASS SourceBufferList interface: mediaSource.sourceBuffers must inherit property "onaddsourcebuffer" with the proper type
+PASS SourceBufferList interface: mediaSource.sourceBuffers must inherit property "onremovesourcebuffer" with the proper type
+PASS AudioTrack interface: attribute sourceBuffer
+PASS Unscopable handled correctly for sourceBuffer property on AudioTrack
+PASS VideoTrack interface: attribute sourceBuffer
+PASS Unscopable handled correctly for sourceBuffer property on VideoTrack
+FAIL TextTrack interface: attribute sourceBuffer assert_true: The prototype object must have a property "sourceBuffer" expected true got false
+PASS Unscopable handled correctly for sourceBuffer property on TextTrack
+PASS URL interface: operation createObjectURL(MediaSource)
+PASS Unscopable handled correctly for createObjectURL(MediaSource) on URL
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/media-source/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/media-source/idlharness.any.js
new file mode 100644
index 0000000..7992b11
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/media-source/idlharness.any.js
@@ -0,0 +1,59 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://w3c.github.io/media-source/
+
+'use strict';
+
+var mediaSource;
+var sourceBuffer;
+var video = document.createElement("video");
+
+promise_test(async t => {
+  const srcs = ['media-source', 'dom', 'html', 'url'];
+  const [idl, dom, html, url] = await Promise.all(
+      srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
+
+  var idlArray = new IdlArray();
+  idlArray.add_idls(idl);
+  idlArray.add_dependency_idls(dom);
+  idlArray.add_dependency_idls(html);
+  idlArray.add_dependency_idls(url);
+
+  const testIdls = new Promise(resolve => {
+    try {
+      mediaSource = new MediaSource();
+      video.src = URL.createObjectURL(mediaSource);
+      mediaSource.addEventListener("sourceopen", function () {
+        var defaultType ='video/webm;codecs="vp8,vorbis"';
+        if (MediaSource.isTypeSupported(defaultType)) {
+          sourceBuffer = mediaSource.addSourceBuffer(defaultType);
+        } else {
+          sourceBuffer = mediaSource.addSourceBuffer('video/mp4');
+        }
+        sourceBuffer.addEventListener("updateend", function (e) {
+          mediaSource.endOfStream();
+          resolve();
+        });
+        sourceBuffer.appendBuffer(new ArrayBuffer());
+      });
+    } catch (e) {
+      // Will be surfaced in idlharness.js's test_object below.
+    }
+  })
+
+  idlArray.add_objects({
+    MediaSource: ['mediaSource'],
+    SourceBuffer: ['sourceBuffer'],
+    SourceBufferList: ['mediaSource.sourceBuffers']
+  });
+
+  const timeout = new Promise((_, reject) => t.step_timeout(reject, 3000));
+  return Promise
+      .race([testIdls, timeout])
+      .then(() => { idlArray.test(); })
+      .catch(() => {
+        idlArray.test();
+        return Promise.reject('Failed to create media-source objects')
+      });
+}, 'media-source interfaces');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/media-source/idlharness.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/media-source/idlharness.any.worker-expected.txt
new file mode 100644
index 0000000..b86bc74
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/media-source/idlharness.any.worker-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL idlharness Uncaught ReferenceError: document is not defined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/media-source/interfaces.html b/third_party/WebKit/LayoutTests/external/wpt/media-source/interfaces.html
deleted file mode 100644
index 13e3148..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/media-source/interfaces.html
+++ /dev/null
@@ -1,144 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<title>Media Source Extensions IDL tests</title>
-<div id=log></div>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/WebIDLParser.js></script>
-<script src=/resources/idlharness.js></script>
-<script type=text/plain class=untested>
-interface EventTarget {
-  void addEventListener(DOMString type, EventListener? callback, optional boolean capture /* = false */);
-  void removeEventListener(DOMString type, EventListener? callback, optional boolean capture /* = false */);
-  boolean dispatchEvent(Event event);
-};
-interface EventHandler {};
-interface URL {};
-interface HTMLVideoElement {};
-interface AudioTrack {};
-interface AudioTrackList {};
-interface VideoTrack {};
-interface VideoTrackList {};
-interface TextTrack {};
-interface TextTrackList {};
-interface TimeRanges {};
-typedef double DOMHighResTimeStamp;
-</script>
-<script type=text/plain>
-[Constructor]
-interface MediaSource : EventTarget {
-    readonly attribute SourceBufferList    sourceBuffers;
-    readonly attribute SourceBufferList    activeSourceBuffers;
-    readonly attribute ReadyState          readyState;
-             attribute unrestricted double duration;
-             attribute EventHandler        onsourceopen;
-             attribute EventHandler        onsourceended;
-             attribute EventHandler        onsourceclose;
-    SourceBuffer addSourceBuffer(DOMString type);
-    void         removeSourceBuffer(SourceBuffer sourceBuffer);
-    void         endOfStream(optional EndOfStreamError error);
-    void         setLiveSeekableRange(double start, double end);
-    void         clearLiveSeekableRange();
-    static boolean isTypeSupported(DOMString type);
-};
-
-interface SourceBuffer : EventTarget {
-             attribute AppendMode          mode;
-    readonly attribute boolean             updating;
-    readonly attribute TimeRanges          buffered;
-             attribute double              timestampOffset;
-    readonly attribute AudioTrackList      audioTracks;
-    readonly attribute VideoTrackList      videoTracks;
-    readonly attribute TextTrackList       textTracks;
-             attribute double              appendWindowStart;
-             attribute unrestricted double appendWindowEnd;
-             attribute EventHandler        onupdatestart;
-             attribute EventHandler        onupdate;
-             attribute EventHandler        onupdateend;
-             attribute EventHandler        onerror;
-             attribute EventHandler        onabort;
-    void appendBuffer(BufferSource data);
-    void abort();
-    void changeType(DOMString type);
-    void remove(double start, unrestricted double end);
-};
-
-interface SourceBufferList : EventTarget {
-    readonly attribute unsigned long length;
-             attribute EventHandler  onaddsourcebuffer;
-             attribute EventHandler  onremovesourcebuffer;
-    getter SourceBuffer (unsigned long index);
-};
-
-[Exposed=Window,DedicatedWorker,SharedWorker]
-partial interface URL {
-    static DOMString createObjectURL(MediaSource mediaSource);
-};
-
-partial interface AudioTrack {
-    readonly attribute SourceBuffer? sourceBuffer;
-};
-
-partial interface VideoTrack {
-    readonly attribute SourceBuffer? sourceBuffer;
-};
-
-partial interface TextTrack {
-    readonly attribute SourceBuffer? sourceBuffer;
-};
-
-enum EndOfStreamError {
-    "network",
-    "decode"
-};
-
-enum AppendMode {
-    "segments",
-    "sequence"
-};
-
-enum ReadyState {
-    "closed",
-    "open",
-    "ended"
-};
-</script>
-<script>
-"use strict";
-setup({ explicit_done: true });
-var mediaSource;
-var sourceBuffer;
-var video = document.createElement("video");
-var idlCheck = function() {
-  var idlArray = new IdlArray();
-  [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
-    if (node.className == "untested") {
-      idlArray.add_untested_idls(node.textContent);
-    } else {
-      idlArray.add_idls(node.textContent);
-    }
-  });
-  idlArray.add_objects({
-    MediaSource: ['mediaSource'],
-    SourceBuffer: ['sourceBuffer'],
-    SourceBufferList: ['mediaSource.sourceBuffers']
-  });
-  idlArray.test();
-  done();
-}
-mediaSource = new MediaSource();
-video.src = URL.createObjectURL(mediaSource);
-mediaSource.addEventListener("sourceopen", function () {
-  var defaultType ='video/webm;codecs="vp8,vorbis"';
-  if (MediaSource.isTypeSupported(defaultType)) {
-    sourceBuffer = mediaSource.addSourceBuffer(defaultType);
-  } else {
-    sourceBuffer = mediaSource.addSourceBuffer('video/mp4');
-  }
-  sourceBuffer.addEventListener("updateend", function (e) {
-    mediaSource.endOfStream();
-    idlCheck();
-  });
-  sourceBuffer.appendBuffer(new ArrayBuffer());
-});
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/idlharness.window-expected.txt
deleted file mode 100644
index d29913a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-method-basic-card/idlharness.window-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL payment-method-basic-card interfaces. promise_test: Unhandled rejection with value: object "TypeError: idl_setup_func is not a function"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/disable-picture-in-picture.html b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/disable-picture-in-picture.html
index 1a59b7a3..fdd8e97 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/disable-picture-in-picture.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/disable-picture-in-picture.html
@@ -33,7 +33,7 @@
 
 promise_test(async t => {
   const video = await loadVideo();
-  return callWithTrustedClick(async () => {
+  return test_driver.bless('request picture in picture', async () => {
     const promise = video.requestPictureInPicture();
     video.disablePictureInPicture = true;
     await promise_rejects(t, 'InvalidStateError', promise);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window-expected.txt
index 5f0cb84..ed8f389 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window-expected.txt
@@ -1,6 +1,5 @@
 This is a testharness.js-based test.
-PASS idlharness
-PASS picture-in-picture interfaces.
+FAIL picture-in-picture interfaces. promise_test: Unhandled rejection with value: object "NotSupportedError: Picture-in-Picture is not available."
 PASS Partial interface HTMLVideoElement: original interface defined
 PASS Partial interface Document: original interface defined
 PASS Partial interface DocumentOrShadowRoot: original interface defined
diff --git a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window.js
index 6ada0fe..ac4c0bf 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window.js
@@ -8,24 +8,19 @@
 
 // https://wicg.github.io/picture-in-picture/
 
-promise_test(async () => {
-  try {
+idl_test(
+  ['picture-in-picture'],
+  ['html', 'dom'],
+  async idl_array => {
+    idl_array.add_objects({
+      Document: ['document'],
+      DocumentOrShadowRoot: ['document'],
+      HTMLVideoElement: ['video'],
+      PictureInPictureWindow: ['pipw'],
+    });
+
     self.video = await loadVideo();
     self.pipw = await requestPictureInPictureWithTrustedClick(video);
-  } catch (e) {
-    // Will be surfaced when video/pipw are undefined below.
-  }
-
-  idl_test(
-    ['picture-in-picture'],
-    ['html', 'dom'],
-    idl_array => {
-      idl_array.add_objects({
-        Document: ['document'],
-        DocumentOrShadowRoot: ['document'],
-        HTMLVideoElement: ['video'],
-        PictureInPictureWindow: ['pipw'],
-      });
-    },
-    'picture-in-picture interfaces.');
-})
+  },
+  'picture-in-picture interfaces.'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/request-picture-in-picture-twice.html b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/request-picture-in-picture-twice.html
index 7f1f81f8..556cf83 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/request-picture-in-picture-twice.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/request-picture-in-picture-twice.html
@@ -10,13 +10,12 @@
 promise_test(async t => {
   const video1 = await loadVideo();
   const video2 = await loadVideo();
-  return callWithTrustedClick(() => {
-    const first = video1.requestPictureInPicture();
-    const second = video2.requestPictureInPicture();
-    return Promise.all([
-      first,
-      promise_rejects(t, 'NotAllowedError', second)
-    ]);
-  });
+  return test_driver.bless(
+    'request picture in picture',
+    async () => {
+      await video1.requestPictureInPicture();
+      promise_rejects(t, 'NotAllowedError', video2.requestPictureInPicture());
+    }
+  );
 }, 'request Picture-in-Picture consumes user gesture');
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/resources/picture-in-picture-helpers.js b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/resources/picture-in-picture-helpers.js
index 4514edf..86b9f29 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/resources/picture-in-picture-helpers.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/resources/picture-in-picture-helpers.js
@@ -4,38 +4,19 @@
   }
 }
 
-function callWithTrustedClick(callback) {
-  return new Promise((resolve, reject) => {
-    let button = document.createElement('button');
-    button.textContent = 'click to continue test';
-    button.style.display = 'block';
-    button.style.fontSize = '20px';
-    button.style.padding = '10px';
-    button.onclick = () => {
-      document.body.removeChild(button);
-      resolve(callback());
-    };
-    document.body.appendChild(button);
-    test_driver.click(button).catch(_ => reject('Click failed'));
-  });
-}
-
 function loadVideo(activeDocument, sourceUrl) {
   return new Promise((resolve, reject) => {
     const document = activeDocument || window.document;
     const video = document.createElement('video');
     video.src = sourceUrl || '/media/movie_5.ogv';
-    video.onloadedmetadata = () => {
-      resolve(video);
-    };
-    video.onerror = error => {
-      reject(error);
-    };
+    video.onloadedmetadata = () => { resolve(video); };
+    video.onerror = error => { reject(error); };
   });
 }
 
 // Calls requestPictureInPicture() in a context that's 'allowed to request PiP'.
 function requestPictureInPictureWithTrustedClick(videoElement) {
-  return callWithTrustedClick(
-      () => videoElement.requestPictureInPicture());
+  return test_driver.bless(
+    'request picture in picture',
+    () => videoElement.requestPictureInPicture());
 }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/idlharness.https.html
index 04d1741..52aa8c5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/idlharness.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/idlharness.https.html
@@ -26,16 +26,24 @@
     idl_array.add_dependency_idls(dom);
     idl_array.add_dependency_idls(html);
 
-    window.presentation_request = new PresentationRequest("/presentation-api/receiving-ua/idlharness.html");
-    window.presentation_request_urls = new PresentationRequest([
-      "/presentation-api/receiving-ua/idlharness.html",
-      "https://www.example.com/presentation.html"
-    ]);
-    navigator.presentation.defaultRequest = presentation_request;
+    try {
+      window.presentation_request = new PresentationRequest("/presentation-api/receiving-ua/idlharness.html");
+      window.presentation_request_urls = new PresentationRequest([
+        "/presentation-api/receiving-ua/idlharness.html",
+        "https://www.example.com/presentation.html"
+      ]);
+      navigator.presentation.defaultRequest = window.presentation_request;
+    } catch (e) {
+      // Will be surfaced in idlharness.js's test_object below.
+    }
 
     idl_array.add_objects({
-        Presentation: ['navigator.presentation'],
-        PresentationRequest: ['navigator.presentation.defaultRequest', 'presentation_request', 'presentation_request_urls']
+      Presentation: ['navigator.presentation'],
+      PresentationRequest: [
+        'navigator.presentation.defaultRequest',
+        'presentation_request',
+        'presentation_request_urls'
+      ],
     });
     idl_array.test();
   }, "Test IDL implementation of Presentation API");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.html
deleted file mode 100644
index 51ab4fd..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!doctype html>
-<title>ResizeObserver IDL tests</title>
-<link rel="help" href="https://wicg.github.io/ResizeObserver/">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-<script>
-  "use strict";
-
-  promise_test(async () => {
-    const idl_array = new IdlArray();
-    const idl = await fetch("/interfaces/ResizeObserver.idl").then(r => r.text());
-    idl_array.add_idls(idl);
-    idl_array.add_objects({
-      ResizeObserver: ["new ResizeObserver(entries => {})"],
-    });
-    idl_array.test();
-  }, "Test IDL implementation of ResizeObserver");
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.window-expected.txt
new file mode 100644
index 0000000..f07e46a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.window-expected.txt
@@ -0,0 +1,52 @@
+This is a testharness.js-based test.
+PASS Test IDL implementation of ResizeObserver
+PASS ResizeObserverEntry creator
+PASS ResizeObserver interface: existence and properties of interface object
+PASS ResizeObserver interface object length
+PASS ResizeObserver interface object name
+PASS ResizeObserver interface: existence and properties of interface prototype object
+PASS ResizeObserver interface: existence and properties of interface prototype object's "constructor" property
+PASS ResizeObserver interface: existence and properties of interface prototype object's @@unscopables property
+PASS ResizeObserver interface: operation observe(Element)
+PASS Unscopable handled correctly for observe(Element) on ResizeObserver
+PASS ResizeObserver interface: operation unobserve(Element)
+PASS Unscopable handled correctly for unobserve(Element) on ResizeObserver
+PASS ResizeObserver interface: operation disconnect()
+PASS Unscopable handled correctly for disconnect() on ResizeObserver
+PASS ResizeObserver must be primary interface of observer
+PASS Stringification of observer
+PASS ResizeObserver interface: observer must inherit property "observe(Element)" with the proper type
+PASS ResizeObserver interface: calling observe(Element) on observer with too few arguments must throw TypeError
+PASS ResizeObserver interface: observer must inherit property "unobserve(Element)" with the proper type
+PASS ResizeObserver interface: calling unobserve(Element) on observer with too few arguments must throw TypeError
+PASS ResizeObserver interface: observer must inherit property "disconnect()" with the proper type
+PASS ResizeObserverEntry interface: existence and properties of interface object
+FAIL ResizeObserverEntry interface object length assert_equals: wrong value for ResizeObserverEntry.length expected 1 but got 0
+PASS ResizeObserverEntry interface object name
+PASS ResizeObserverEntry interface: existence and properties of interface prototype object
+PASS ResizeObserverEntry interface: existence and properties of interface prototype object's "constructor" property
+PASS ResizeObserverEntry interface: existence and properties of interface prototype object's @@unscopables property
+PASS ResizeObserverEntry interface: attribute target
+PASS Unscopable handled correctly for target property on ResizeObserverEntry
+PASS ResizeObserverEntry interface: attribute contentRect
+PASS Unscopable handled correctly for contentRect property on ResizeObserverEntry
+PASS ResizeObserverEntry must be primary interface of entry
+PASS Stringification of entry
+PASS ResizeObserverEntry interface: entry must inherit property "target" with the proper type
+PASS ResizeObserverEntry interface: entry must inherit property "contentRect" with the proper type
+FAIL ResizeObservation interface: existence and properties of interface object assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface object length assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface object name assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface: existence and properties of interface prototype object assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface: attribute target assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+PASS Unscopable handled correctly for target property on ResizeObservation
+FAIL ResizeObservation interface: attribute broadcastWidth assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+PASS Unscopable handled correctly for broadcastWidth property on ResizeObservation
+FAIL ResizeObservation interface: attribute broadcastHeight assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+PASS Unscopable handled correctly for broadcastHeight property on ResizeObservation
+FAIL ResizeObservation interface: operation isActive() assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+PASS Unscopable handled correctly for isActive() on ResizeObservation
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.window.js
new file mode 100644
index 0000000..240f5ec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.window.js
@@ -0,0 +1,38 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+// META: script=resources/resizeTestHelper.js
+
+'use strict';
+
+// https://wicg.github.io/ResizeObserver/
+
+idl_test(
+  ['ResizeObserver'],
+  ['dom', 'geometry'],
+  async idl_array => {
+    idl_array.add_objects({
+      ResizeObserver: ['observer'],
+      ResizeObserverEntry: ['entry'],
+    });
+
+    const div = document.createElement('div');
+    document.body.appendChild(div);
+    let helper = new ResizeTestHelper(
+      "ResizeObserverEntry creator",
+      [
+        {
+          setup: observer => {
+            self.observer = observer;
+            observer.observe(div);
+            div.style.width = "5px";
+          },
+          notify: entries => {
+            self.entry = entries[0];
+            assert_equals(entries[0].contentRect.width, 5, "target width");
+          }
+        }
+      ]);
+    await helper.start();
+  },
+  'Test IDL implementation of ResizeObserver'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/idlharness.any.js
index d522aae..6dff5e85 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/idlharness.any.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/idlharness.any.js
@@ -5,24 +5,20 @@
 
 // https://w3c.github.io/resource-timing/
 
-promise_test(async () => {
-  const [idl, perf, hrtime, dom, html] = await Promise.all([
-    '/interfaces/resource-timing.idl',
-    '/interfaces/performance-timeline.idl',
-    '/interfaces/hr-time.idl',
-    '/interfaces/dom.idl',
-    '/interfaces/html.idl',
-  ].map(url => fetch(url).then(r => r.text())));
+idl_test(
+  ['resource-timing'],
+  ['performance-timeline', 'hr-time', 'dom', 'html'],
+  idl_array => {
+    try {
+      self.resource = performance.getEntriesByType('resource')[0];
+    } catch (e) {
+      // Will be surfaced when resource is undefined below.
+    }
 
-  const idl_array = new IdlArray();
-  idl_array.add_idls(idl);
-  idl_array.add_dependency_idls(perf);
-  idl_array.add_dependency_idls(hrtime);
-  idl_array.add_dependency_idls(dom);
-  idl_array.add_dependency_idls(html);
-  idl_array.add_objects({
-    Performance: ['performance'],
-    PerformanceResourceTiming: ["performance.getEntriesByType('resource')[0]"]
-  });
-  idl_array.test();
-}, 'Test server-timing IDL implementation');
+    idl_array.add_objects({
+      Performance: ['performance'],
+      PerformanceResourceTiming: ['resource']
+    });
+  },
+  'Test server-timing IDL implementation'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js
index 74be1f0..224befd 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js
@@ -62,11 +62,14 @@
 }
 
 // Implements both VRDisplayHost and VRMagicWindowProvider. Maintains a mock for
-// VRPresentationProvider.
+// XRPresentationProvider.
 class MockDevice {
   constructor(fakeDeviceInit, service) {
     this.displayClient_ = new device.mojom.VRDisplayClientPtr();
-    this.presentation_provider_ = new MockVRPresentationProvider();
+    this.presentation_provider_ = new MockXRPresentationProvider();
+
+    this.pose_ = null;
+    this.next_frame_id_ = 0;
 
     this.service_ = service;
 
@@ -101,7 +104,7 @@
     if (poseMatrix == null) {
       this.presentation_provider_.pose_ = null;
     } else {
-      this.presentation_provider_.setPoseFromMatrix(poseMatrix);
+      this.setPoseFromMatrix(poseMatrix);
     }
 
     if (views) {
@@ -122,6 +125,49 @@
     }
   }
 
+
+  setPoseFromMatrix(poseMatrix) {
+    this.pose_ = {
+      orientation: null,
+      position: null,
+      angularVelocity: null,
+      linearVelocity: null,
+      angularAcceleration: null,
+      linearAcceleration: null,
+      inputState: null,
+      poseIndex: 0
+    };
+
+    let pose = this.poseFromMatrix(poseMatrix);
+    for (let field in pose) {
+      if (this.pose_.hasOwnProperty(field)) {
+        this.pose_[field] = pose[field];
+      }
+    }
+  }
+
+  poseFromMatrix(m) {
+    let orientation = [];
+
+    let m00 = m[0];
+    let m11 = m[5];
+    let m22 = m[10];
+    // The max( 0, ... ) is just a safeguard against rounding error.
+    orientation[3] = Math.sqrt(Math.max(0, 1 + m00 + m11 + m22)) / 2;
+    orientation[0] = Math.sqrt(Math.max(0, 1 + m00 - m11 - m22)) / 2;
+    orientation[1] = Math.sqrt(Math.max(0, 1 - m00 + m11 - m22)) / 2;
+    orientation[2] = Math.sqrt(Math.max(0, 1 - m00 - m11 + m22)) / 2;
+
+    let position = [];
+    position[0] = m[12];
+    position[1] = m[13];
+    position[2] = m[14];
+
+    return {
+      orientation, position
+    }
+  }
+
   getNonImmersiveDisplayInfo() {
     let displayInfo = this.getImmersiveDisplayInfo();
 
@@ -202,158 +248,7 @@
 
   // Mojo function implementations.
 
-  // VRMagicWindowProvider implementation.
-
-  getFrameData() {
-    // Convert current document time to monotonic time.
-    let now = window.performance.now() / 1000.0;
-    let diff = now - internals.monotonicTimeToZeroBasedDocumentTime(now);
-    now += diff;
-    now *= 1000000;
-
-    return Promise.resolve({
-      frameData: {
-        pose: this.presentation_provider_.pose_,
-        bufferHolder: null,
-        bufferSize: {},
-        timeDelta: [],
-        projectionMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
-      }
-    });
-  }
-
-  updateSessionGeometry(frame_size, display_rotation) {
-    // This function must exist to ensure that calls to it do not crash, but we
-    // do not have any use for this data at present.
-  }
-
-  // VRDisplayHost implementation.
-
-  requestSession(sessionOptions, was_activation) {
-    return this.supportsSession(sessionOptions).then((result) => {
-      // The JavaScript bindings convert c_style_names to camelCase names.
-      let options = new device.mojom.VRDisplayFrameTransportOptions();
-      options.transportMethod =
-          device.mojom.VRDisplayFrameTransportMethod.SUBMIT_AS_MAILBOX_HOLDER;
-      options.waitForTransferNotification = true;
-      options.waitForRenderNotification = true;
-
-      let connection;
-      if (result.supportsSession) {
-        connection = {
-          clientRequest: this.presentation_provider_.getClientRequest(),
-          provider: this.presentation_provider_.bindProvider(sessionOptions),
-          transportOptions: options
-        };
-
-        let magicWindowPtr = new device.mojom.VRMagicWindowProviderPtr();
-        let magicWindowRequest = mojo.makeRequest(magicWindowPtr);
-        let magicWindowBinding = new mojo.Binding(
-            device.mojom.VRMagicWindowProvider, this, magicWindowRequest);
-
-        return Promise.resolve({
-          session:
-              {connection: connection, magicWindowProvider: magicWindowPtr}
-        });
-      } else {
-        return Promise.resolve({session: null});
-      }
-    });
-  }
-
-  supportsSession(options) {
-    return Promise.resolve({
-      supportsSession:
-          !options.exclusive || this.displayInfo_.capabilities.canPresent
-    });
-  };
-}
-
-class MockVRPresentationProvider {
-  constructor() {
-    this.binding_ = new mojo.Binding(device.mojom.VRPresentationProvider, this);
-    this.pose_ = null;
-    this.next_frame_id_ = 0;
-    this.submit_frame_count_ = 0;
-    this.missing_frame_count_ = 0;
-  }
-
-  bindProvider(request) {
-    let providerPtr = new device.mojom.VRPresentationProviderPtr();
-    let providerRequest = mojo.makeRequest(providerPtr);
-
-    this.binding_.close();
-
-    this.binding_ = new mojo.Binding(
-        device.mojom.VRPresentationProvider, this, providerRequest);
-
-    return providerPtr;
-  }
-
-  getClientRequest() {
-    this.submitFrameClient_ = new device.mojom.VRSubmitFrameClientPtr();
-    return mojo.makeRequest(this.submitFrameClient_);
-  }
-
-  setPoseFromMatrix(poseMatrix) {
-    this.pose_ = {
-      orientation: null,
-      position: null,
-      angularVelocity: null,
-      linearVelocity: null,
-      angularAcceleration: null,
-      linearAcceleration: null,
-      inputState: null,
-      poseIndex: 0
-    };
-
-    let pose = this.poseFromMatrix(poseMatrix);
-    for (let field in pose) {
-      if (this.pose_.hasOwnProperty(field)) {
-        this.pose_[field] = pose[field];
-      }
-    }
-  }
-
-  poseFromMatrix(m) {
-    let orientation = [];
-
-    let m00 = m[0];
-    let m11 = m[5];
-    let m22 = m[10];
-    // The max( 0, ... ) is just a safeguard against rounding error.
-    orientation[3] = Math.sqrt(Math.max(0, 1 + m00 + m11 + m22)) / 2;
-    orientation[0] = Math.sqrt(Math.max(0, 1 + m00 - m11 - m22)) / 2;
-    orientation[1] = Math.sqrt(Math.max(0, 1 - m00 + m11 - m22)) / 2;
-    orientation[2] = Math.sqrt(Math.max(0, 1 - m00 - m11 + m22)) / 2;
-
-    let position = [];
-    position[0] = m[12];
-    position[1] = m[13];
-    position[2] = m[14];
-
-    return {
-      orientation, position
-    }
-  }
-
-  // VRPresentationProvider mojo implementation
-  submitFrameMissing(frameId, mailboxHolder, timeWaited) {
-    this.missing_frame_count_++;
-  }
-
-  submitFrame(frameId, mailboxHolder, timeWaited) {
-    this.submit_frame_count_++;
-
-    // Trigger the submit completion callbacks here. WARNING: The
-    // Javascript-based mojo mocks are *not* re-entrant. It's OK to
-    // wait for these notifications on the next frame, but waiting
-    // within the current frame would never finish since the incoming
-    // calls would be queued until the current execution context finishes.
-    this.submitFrameClient_.onSubmitFrameTransferred(true);
-    this.submitFrameClient_.onSubmitFrameRendered();
-  }
-
+  // XRFrameDataProvider implementation.
   getFrameData() {
     if (this.pose_) {
       this.pose_.poseIndex++;
@@ -378,6 +273,105 @@
       }
     });
   }
+
+  updateSessionGeometry(frame_size, display_rotation) {
+    // This function must exist to ensure that calls to it do not crash, but we
+    // do not have any use for this data at present.
+  }
+
+  // VRDisplayHost implementation.
+
+  requestSession(sessionOptions, was_activation) {
+    return this.supportsSession(sessionOptions).then((result) => {
+      // The JavaScript bindings convert c_style_names to camelCase names.
+      let options = new device.mojom.XRPresentationTransportOptions();
+      options.transportMethod =
+          device.mojom.XRPresentationTransportMethod.SUBMIT_AS_MAILBOX_HOLDER;
+      options.waitForTransferNotification = true;
+      options.waitForRenderNotification = true;
+
+      let submit_frame_sink;
+      if (result.supportsSession) {
+        submit_frame_sink = {
+          clientRequest: this.presentation_provider_.getClientRequest(),
+          provider: this.presentation_provider_.bindProvider(sessionOptions),
+          transportOptions: options
+        };
+
+        let dataProviderPtr = new device.mojom.XRFrameDataProviderPtr();
+        let dataProviderRequest = mojo.makeRequest(dataProviderPtr);
+        let dataProviderBinding = new mojo.Binding(
+            device.mojom.XRFrameDataProvider, this, dataProviderRequest);
+
+        let enviromentProviderPtr =
+            new device.mojom.XREnviromentIntegrationProviderPtr();
+        let enviromentProviderRequest = mojo.makeRequest(enviromentProviderPtr);
+        let enviromentProviderBinding = new mojo.Binding(
+            device.mojom.XREnviromentIntegrationProvider, this,
+            enviromentProviderRequest);
+
+        return Promise.resolve({
+          session: {
+            submitFrameSink: submit_frame_sink,
+            dataProvider: dataProviderPtr,
+            enviromentProvider: enviromentProviderPtr
+          }
+        });
+      } else {
+        return Promise.resolve({session: null});
+      }
+    });
+  }
+
+  supportsSession(options) {
+    return Promise.resolve({
+      supportsSession:
+          !options.exclusive || this.displayInfo_.capabilities.canPresent
+    });
+  };
+}
+
+class MockXRPresentationProvider {
+  constructor() {
+    this.binding_ = new mojo.Binding(device.mojom.XRPresentationProvider, this);
+
+    this.submit_frame_count_ = 0;
+    this.missing_frame_count_ = 0;
+  }
+
+  bindProvider(request) {
+    let providerPtr = new device.mojom.XRPresentationProviderPtr();
+    let providerRequest = mojo.makeRequest(providerPtr);
+
+    this.binding_.close();
+
+    this.binding_ = new mojo.Binding(
+        device.mojom.XRPresentationProvider, this, providerRequest);
+
+    return providerPtr;
+  }
+
+  getClientRequest() {
+    this.submitFrameClient_ = new device.mojom.XRPresentationClientPtr();
+    return mojo.makeRequest(this.submitFrameClient_);
+  }
+
+  // XRPresentationProvider mojo implementation
+  submitFrameMissing(frameId, mailboxHolder, timeWaited) {
+    this.missing_frame_count_++;
+  }
+
+  submitFrame(frameId, mailboxHolder, timeWaited) {
+    this.submit_frame_count_++;
+
+    // Trigger the submit completion callbacks here. WARNING: The
+    // Javascript-based mojo mocks are *not* re-entrant. It's OK to
+    // wait for these notifications on the next frame, but waiting
+    // within the current frame would never finish since the incoming
+    // calls would be queued until the current execution context finishes.
+    this.submitFrameClient_.onSubmitFrameTransferred(true);
+    this.submitFrameClient_.onSubmitFrameRendered();
+  }
 }
 
 let XRTest = new ChromeXRTest();
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
index bfb2582..6f89a71 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
@@ -870,6 +870,16 @@
 
             test(function () {
                 assert_true(originalExists, `Original ${parsed_idl.type} should be defined`);
+
+                var expected = IdlInterface;
+                switch (parsed_idl.type) {
+                    case 'interface': expected = IdlInterface; break;
+                    case 'dictionary': expected = IdlDictionary; break;
+                    case 'namespace': expected = IdlNamespace; break;
+                }
+                assert_true(
+                    expected.prototype.isPrototypeOf(this.members[parsed_idl.name]),
+                    `Original ${parsed_idl.name} definition should have type ${parsed_idl.type}`);
             }.bind(this), `Partial ${parsed_idl.type} ${partialTestName}: original ${parsed_idl.type} defined`);
         }
         if (!originalExists) {
@@ -3187,7 +3197,9 @@
                 }
             })
             .then(function() {
-                return idl_setup_func(idl_array, t);
+                if (idl_setup_func) {
+                    return idl_setup_func(idl_array, t);
+                }
             })
             .then(function() { idl_array.test(); })
             .catch(function (reason) {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/selection/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/selection/idlharness.window-expected.txt
new file mode 100644
index 0000000..949a6b7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/selection/idlharness.window-expected.txt
@@ -0,0 +1,103 @@
+This is a testharness.js-based test.
+Found 99 tests; 93 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS selection-api interfaces
+PASS Partial interface Document: original interface defined
+PASS Partial interface Window: original interface defined
+PASS Partial interface GlobalEventHandlers: original interface defined
+PASS Selection interface: existence and properties of interface object
+PASS Selection interface object length
+PASS Selection interface object name
+PASS Selection interface: existence and properties of interface prototype object
+PASS Selection interface: existence and properties of interface prototype object's "constructor" property
+PASS Selection interface: existence and properties of interface prototype object's @@unscopables property
+PASS Selection interface: attribute anchorNode
+PASS Unscopable handled correctly for anchorNode property on Selection
+PASS Selection interface: attribute anchorOffset
+PASS Unscopable handled correctly for anchorOffset property on Selection
+PASS Selection interface: attribute focusNode
+PASS Unscopable handled correctly for focusNode property on Selection
+PASS Selection interface: attribute focusOffset
+PASS Unscopable handled correctly for focusOffset property on Selection
+PASS Selection interface: attribute isCollapsed
+PASS Unscopable handled correctly for isCollapsed property on Selection
+PASS Selection interface: attribute rangeCount
+PASS Unscopable handled correctly for rangeCount property on Selection
+PASS Selection interface: attribute type
+PASS Unscopable handled correctly for type property on Selection
+PASS Selection interface: operation getRangeAt(unsigned long)
+PASS Unscopable handled correctly for getRangeAt(unsigned long) on Selection
+PASS Selection interface: operation addRange(Range)
+PASS Unscopable handled correctly for addRange(Range) on Selection
+PASS Selection interface: operation removeRange(Range)
+PASS Unscopable handled correctly for removeRange(Range) on Selection
+PASS Selection interface: operation removeAllRanges()
+PASS Unscopable handled correctly for removeAllRanges() on Selection
+PASS Selection interface: operation empty()
+PASS Unscopable handled correctly for empty() on Selection
+PASS Selection interface: operation collapse(Node, unsigned long)
+PASS Unscopable handled correctly for collapse(Node, unsigned long) on Selection
+PASS Selection interface: operation setPosition(Node, unsigned long)
+PASS Unscopable handled correctly for setPosition(Node, unsigned long) on Selection
+PASS Selection interface: operation collapseToStart()
+PASS Unscopable handled correctly for collapseToStart() on Selection
+PASS Selection interface: operation collapseToEnd()
+PASS Unscopable handled correctly for collapseToEnd() on Selection
+PASS Selection interface: operation extend(Node, unsigned long)
+PASS Unscopable handled correctly for extend(Node, unsigned long) on Selection
+PASS Selection interface: operation setBaseAndExtent(Node, unsigned long, Node, unsigned long)
+PASS Unscopable handled correctly for setBaseAndExtent(Node, unsigned long, Node, unsigned long) on Selection
+PASS Selection interface: operation selectAllChildren(Node)
+PASS Unscopable handled correctly for selectAllChildren(Node) on Selection
+PASS Selection interface: operation deleteFromDocument()
+PASS Unscopable handled correctly for deleteFromDocument() on Selection
+PASS Selection interface: operation containsNode(Node, boolean)
+PASS Unscopable handled correctly for containsNode(Node, boolean) on Selection
+PASS Selection interface: stringifier
+PASS Selection must be primary interface of getSelection()
+PASS Stringification of getSelection()
+PASS Selection interface: getSelection() must inherit property "anchorNode" with the proper type
+PASS Selection interface: getSelection() must inherit property "anchorOffset" with the proper type
+PASS Selection interface: getSelection() must inherit property "focusNode" with the proper type
+PASS Selection interface: getSelection() must inherit property "focusOffset" with the proper type
+PASS Selection interface: getSelection() must inherit property "isCollapsed" with the proper type
+PASS Selection interface: getSelection() must inherit property "rangeCount" with the proper type
+PASS Selection interface: getSelection() must inherit property "type" with the proper type
+PASS Selection interface: getSelection() must inherit property "getRangeAt(unsigned long)" with the proper type
+PASS Selection interface: calling getRangeAt(unsigned long) on getSelection() with too few arguments must throw TypeError
+PASS Selection interface: getSelection() must inherit property "addRange(Range)" with the proper type
+PASS Selection interface: calling addRange(Range) on getSelection() with too few arguments must throw TypeError
+PASS Selection interface: getSelection() must inherit property "removeRange(Range)" with the proper type
+PASS Selection interface: calling removeRange(Range) on getSelection() with too few arguments must throw TypeError
+PASS Selection interface: getSelection() must inherit property "removeAllRanges()" with the proper type
+PASS Selection interface: getSelection() must inherit property "empty()" with the proper type
+PASS Selection interface: getSelection() must inherit property "collapse(Node, unsigned long)" with the proper type
+PASS Selection interface: calling collapse(Node, unsigned long) on getSelection() with too few arguments must throw TypeError
+PASS Selection interface: getSelection() must inherit property "setPosition(Node, unsigned long)" with the proper type
+PASS Selection interface: calling setPosition(Node, unsigned long) on getSelection() with too few arguments must throw TypeError
+PASS Selection interface: getSelection() must inherit property "collapseToStart()" with the proper type
+PASS Selection interface: getSelection() must inherit property "collapseToEnd()" with the proper type
+PASS Selection interface: getSelection() must inherit property "extend(Node, unsigned long)" with the proper type
+PASS Selection interface: calling extend(Node, unsigned long) on getSelection() with too few arguments must throw TypeError
+PASS Selection interface: getSelection() must inherit property "setBaseAndExtent(Node, unsigned long, Node, unsigned long)" with the proper type
+PASS Selection interface: calling setBaseAndExtent(Node, unsigned long, Node, unsigned long) on getSelection() with too few arguments must throw TypeError
+PASS Selection interface: getSelection() must inherit property "selectAllChildren(Node)" with the proper type
+PASS Selection interface: calling selectAllChildren(Node) on getSelection() with too few arguments must throw TypeError
+PASS Selection interface: getSelection() must inherit property "deleteFromDocument()" with the proper type
+PASS Selection interface: getSelection() must inherit property "containsNode(Node, boolean)" with the proper type
+PASS Selection interface: calling containsNode(Node, boolean) on getSelection() with too few arguments must throw TypeError
+PASS Document interface: operation getSelection()
+PASS Unscopable handled correctly for getSelection() on Document
+PASS Document interface: document must inherit property "getSelection()" with the proper type
+PASS Window interface: operation getSelection()
+PASS Unscopable handled correctly for getSelection() on Window
+FAIL Window interface: attribute onselectstart assert_own_property: The global object must have a property "onselectstart" expected property "onselectstart" missing
+PASS Unscopable handled correctly for onselectstart property on Window
+FAIL Window interface: attribute onselectionchange assert_own_property: The global object must have a property "onselectionchange" expected property "onselectionchange" missing
+PASS Unscopable handled correctly for onselectionchange property on Window
+PASS Window interface: window must inherit property "getSelection()" with the proper type
+FAIL Window interface: window must inherit property "onselectstart" with the proper type assert_own_property: expected property "onselectstart" missing
+FAIL Window interface: window must inherit property "onselectionchange" with the proper type assert_own_property: expected property "onselectionchange" missing
+FAIL GlobalEventHandlers interface: self must inherit property "onselectstart" with the proper type assert_inherits: property "onselectstart" not found in prototype chain
+FAIL GlobalEventHandlers interface: self must inherit property "onselectionchange" with the proper type assert_inherits: property "onselectionchange" not found in prototype chain
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/selection/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/selection/idlharness.window.js
new file mode 100644
index 0000000..d7b851d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/selection/idlharness.window.js
@@ -0,0 +1,20 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+'use strict';
+
+// https://w3c.github.io/selection-api/
+
+idl_test(
+  ['selection-api'],
+  ['dom', 'html'],
+  idlArray => {
+    idlArray.add_objects({
+      Window: ['window'],
+      Document: ['document'],
+      Selection: ['getSelection()'],
+      GlobalEventHandlers: ['self'],
+    });
+  },
+  'selection-api interfaces'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces.html b/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces.html
deleted file mode 100644
index 6b72f28..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!doctype html>
-<title>Selection interface tests</title>
-<div id=log></div>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/WebIDLParser.js></script>
-<script src=/resources/idlharness.js></script>
-<script>
-"use strict";
-
-function doTest([selection, dom, cssom, touchevents, uievents, html]) {
-  var idlArray = new IdlArray();
-  idlArray.add_untested_idls('interface SVGElement {};');
-  idlArray.add_untested_idls(dom + cssom + touchevents + uievents + html);
-  idlArray.add_idls(selection);
-  idlArray.add_objects({Selection: ['getSelection()']});
-  idlArray.test();
-}
-
-function fetchData(url) {
-  return fetch(url).then((response) => response.text());
-}
-
-promise_test(function() {
-  return Promise.all([fetchData("/interfaces/selection-api.idl"),
-                      fetchData("/interfaces/dom.idl"),
-                      fetchData("/interfaces/cssom.idl"),
-                      fetchData("/interfaces/touchevents.idl"),
-                      fetchData("/interfaces/uievents.idl"),
-                      fetchData("/interfaces/html.idl")])
-                .then(doTest);
-}, "Test driver");
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-window.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-window.https.html
index 8786b29..d3e85f2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-window.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-window.https.html
@@ -4,18 +4,16 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="/resources/WebIDLParser.js"></script>
 <script src="/resources/idlharness.js"></script>
-<script src="resources/interfaces-idls.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
 'use strict';
 
 promise_test(async (t) => {
-  const srcs = ['dom', 'service-workers'];
-  const [dom, serviceWorkerIdl] = await Promise.all(
+  const srcs = ['dom', 'html', 'service-workers', 'dedicated-workers'];
+  const [dom, html, serviceWorkerIdl, dedicated] = await Promise.all(
     srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
 
   var idlArray = new IdlArray();
-  idlArray.add_untested_idls(idls.untested);
   idlArray.add_idls(serviceWorkerIdl, { only: [
     'ServiceWorkerGlobalScope',
     'Client',
@@ -30,7 +28,9 @@
     'Cache',
     'CacheStorage',
   ]});
+  idlArray.add_dependency_idls(dedicated);
   idlArray.add_dependency_idls(dom);
+  idlArray.add_dependency_idls(html);
   idlArray.add_objects({
     ServiceWorkerContainer: ['navigator.serviceWorker']
   });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-idls.js b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-idls.js
deleted file mode 100644
index 3db45c6..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-idls.js
+++ /dev/null
@@ -1,14 +0,0 @@
-var idls = {};
-idls.untested = `
-[Exposed=Worker]
-interface WorkerGlobalScope {};
-
-[TreatNonObjectAsNull]
-callback EventHandlerNonNull = any (Event event);
-typedef EventHandlerNonNull? EventHandler;
-
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface AbstractWorker {
-  attribute EventHandler onerror;
-};
-`;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js
index 606ec07..10fe14d5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/interfaces-worker.sub.js
@@ -1,17 +1,15 @@
 'use strict';
 
-importScripts('interfaces-idls.js');
 importScripts('worker-testharness.js');
 importScripts('/resources/WebIDLParser.js');
 importScripts('/resources/idlharness.js');
 
 promise_test(async (t) => {
-  const srcs = ['dom', 'service-workers'];
-  const [dom, serviceWorkerIdl] = await Promise.all(
+  const srcs = ['dom', 'html', 'service-workers', 'dedicated-workers'];
+  const [dom, html, serviceWorkerIdl, dedicated] = await Promise.all(
     srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
 
   var idlArray = new IdlArray();
-  idlArray.add_untested_idls(idls.untested);
   idlArray.add_idls(serviceWorkerIdl, { only: [
     'ServiceWorkerGlobalScope',
     'Client',
@@ -26,7 +24,9 @@
     'Cache',
     'CacheStorage',
   ]});
+  idlArray.add_dependency_idls(dedicated);
   idlArray.add_dependency_idls(dom);
+  idlArray.add_dependency_idls(html);
   idlArray.add_objects({
     ServiceWorkerGlobalScope: ['self'],
     Clients: ['self.clients'],
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/linking/reftests/use-descendant-combinator-003.html b/third_party/WebKit/LayoutTests/external/wpt/svg/linking/reftests/use-descendant-combinator-003.html
new file mode 100644
index 0000000..14bf5bd1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/linking/reftests/use-descendant-combinator-003.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS Test: use element doesn't cross shadow tree boundaries in selector-matching, and is invalidated properly</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://svgwg.org/svg2-draft/struct.html#UseElement">
+<link rel="match" href="/svg/linking/reftests/use-descendant-combinator-ref.html">
+<style>
+#test rect {
+  stroke: red;
+  stroke-width: 10px;
+}
+.inside-use rect {
+  fill: red;
+}
+defs .inside-use rect {
+  fill: red;
+}
+</style>
+<p>
+  You should see a green square, and no red.
+</p>
+<svg>
+  <defs>
+    <g id="square">
+      <g class="inside-use">
+        <rect width="100" height="100"/>
+      </g>
+    </g>
+  </defs>
+  <g id="test">
+    <use href="#square" />
+  </g>
+</svg>
+<script>
+  document.body.offsetTop;
+  document.styleSheets[0].cssRules[1].style.fill = 'green';
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-001-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-001-ref.svg
new file mode 100644
index 0000000..dcd39a8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-001-ref.svg
@@ -0,0 +1,32 @@
+<svg id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>'mix-blend-mode' with 'isolation'</title>
+    <html:link rel="author"
+          title="Tavmjong Bah"
+          href="http://tavmjong.free.fr"/>
+  </g>
+
+  <g id="test-body-content">
+    <g>
+      <rect x="120" y="80"  width="160" height="160" fill="red"/>
+      <rect x="200" y="80"  width="160" height="160" fill="lime"/>
+      <rect x="160" y="160" width="160" height="160" fill="blue"/>
+      <rect x="200" y="160" width="80"  height="80"  fill="#ffffff"/>
+      <rect x="200" y="80"  width="80"  height="80"  fill="#ffff00"/>
+      <rect x="160" y="160" width="40"  height="80"  fill="#ff00ff"/>
+      <rect x="280" y="160" width="40"  height="80"  fill="#00ffff"/>
+    </g>
+
+    <!-- Stroke to prevent aliasing from effecting results. -->
+    <g style="fill:none;stroke:black;stroke-width:2px">
+      <rect x="120" y="80"  width="160" height="160"/>
+      <rect x="200" y="80"  width="160" height="160"/>
+      <rect x="160" y="160" width="160" height="160"/>
+    </g>
+  </g>
+
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-001.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-001.svg
new file mode 100644
index 0000000..2278019c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-001.svg
@@ -0,0 +1,43 @@
+<svg id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>'mix-blend-mode'</title>
+    <html:link rel="author"
+          title="Tavmjong Bah"
+          href="http://tavmjong.free.fr"/>
+    <html:link rel="help"
+          href="https://www.w3.org/TR/SVG2/render.html#PaintersModel"/>
+    <html:link rel="match"  href="blending-001-ref.svg" />
+  </g>
+
+  <style id="test-font" type="text/css">
+    rect {
+      mix-blend-mode: screen;
+    }
+
+    g {
+      isolation: isolate;
+    }
+  </style>
+
+  <g id="test-body-content">
+
+    <g>
+      <rect x="120" y="80"  width="160" height="160" fill="red"/>
+      <rect x="200" y="80"  width="160" height="160" fill="lime"/>
+      <rect x="160" y="160" width="160" height="160" fill="blue"/>
+    </g>
+
+    <!-- Stroke to prevent aliasing from effecting results. -->
+    <g style="mix-blend-mode:normal;fill:none;stroke:black;stroke-width:2px">
+      <rect x="120" y="80"  width="160" height="160"/>
+      <rect x="200" y="80"  width="160" height="160"/>
+      <rect x="160" y="160" width="160" height="160"/>
+    </g>
+
+  </g>
+
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-002-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-002-ref.svg
new file mode 100644
index 0000000..df6f29f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-002-ref.svg
@@ -0,0 +1,32 @@
+<svg id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>'mix-blend-mode' with 'isolation'</title>
+    <html:link rel="author"
+          title="Tavmjong Bah"
+          href="http://tavmjong.free.fr"/>
+  </g>
+
+  <g id="test-body-content">
+    <g>
+      <rect x="120" y="80"  width="160" height="160" fill="red"/>
+      <rect x="200" y="80"  width="160" height="160" fill="lime"/>
+      <rect x="160" y="160" width="160" height="160" fill="blue"/>
+      <rect x="200" y="160" width="80"  height="80"  fill="#00ffff"/>
+      <rect x="200" y="80"  width="80"  height="80"  fill="#00ff00"/>
+      <rect x="160" y="160" width="40"  height="80"  fill="#0000ff"/>
+      <rect x="280" y="160" width="40"  height="80"  fill="#00ffff"/>
+    </g>
+
+    <!-- Stroke to prevent aliasing from effecting results. -->
+    <g style="fill:none;stroke:black;stroke-width:2px">
+      <rect x="120" y="80"  width="160" height="160"/>
+      <rect x="200" y="80"  width="160" height="160"/>
+      <rect x="160" y="160" width="160" height="160"/>
+    </g>
+  </g>
+
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-002.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-002.svg
new file mode 100644
index 0000000..01e180f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/render/reftests/blending-002.svg
@@ -0,0 +1,43 @@
+<svg id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>'mix-blend-mode' with 'isolation'</title>
+    <html:link rel="author"
+          title="Tavmjong Bah"
+          href="http://tavmjong.free.fr"/>
+    <html:link rel="help"
+          href="https://www.w3.org/TR/SVG2/render.html#PaintersModel"/>
+    <html:link rel="match"  href="blending-002-ref.svg" />
+  </g>
+
+  <style id="test-font" type="text/css">
+    rect {
+      mix-blend-mode: screen;
+    }
+
+    g {
+      isolation: isolate;
+    }
+  </style>
+
+  <g id="test-body-content">
+
+    <rect x="120" y="80"  width="160" height="160" fill="red"/>
+    <g>
+      <rect x="200" y="80"  width="160" height="160" fill="lime"/>
+      <rect x="160" y="160" width="160" height="160" fill="blue"/>
+    </g>
+
+    <!-- Stroke to prevent aliasing from effecting results. -->
+    <g style="mix-blend-mode:normal;fill:none;stroke:black;stroke-width:2px">
+      <rect x="120" y="80"  width="160" height="160"/>
+      <rect x="200" y="80"  width="160" height="160"/>
+      <rect x="160" y="160" width="160" height="160"/>
+    </g>
+
+  </g>
+
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/touch-events/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/touch-events/idlharness.window.js
index 6a95892..dbea07a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/touch-events/idlharness.window.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/touch-events/idlharness.window.js
@@ -5,21 +5,16 @@
 
 'use strict';
 
-promise_test(async () => {
-  const srcs = ['touch-events', 'uievents', 'dom', 'html'];
-  const [idl, uievents, dom, html] = await Promise.all(
-      srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
-
-  const idl_array = new IdlArray();
-  idl_array.add_idls(idl);
-  idl_array.add_dependency_idls(uievents);
-  idl_array.add_dependency_idls(dom);
-  idl_array.add_dependency_idls(html);
-  idl_array.add_objects({
-    Document: ['document'],
-    GlobalEventHandlers: ['window', 'document', 'document.body'],
-    Touch: ['new Touch({identifier: 1, target: document})'],
-    TouchEvent: ['new TouchEvent("name")'],
-  });
-  idl_array.test();
-}, 'Test IDL implementation of touch-events API');
+idl_test(
+  ['touch-events'],
+  ['uievents', 'dom', 'html'],
+  idl_array => {
+    idl_array.add_objects({
+      Document: ['document'],
+      GlobalEventHandlers: ['window', 'document', 'document.body'],
+      Touch: ['new Touch({identifier: 1, target: document})'],
+      TouchEvent: ['new TouchEvent("name")'],
+    });
+  },
+  'Test IDL implementation of touch-events API'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-share/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/web-share/idlharness.https.html
deleted file mode 100644
index f68e51e5e..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/web-share/idlharness.https.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>WebShare IDL test</title>
-    <link rel="help" href="https://wicg.github.io/web-share/">
-    <script src=/resources/testharness.js></script>
-    <script src=/resources/testharnessreport.js></script>
-    <script src=/resources/WebIDLParser.js></script>
-    <script src=/resources/idlharness.js></script>
-  </head>
-  <body>
-    <script>
-        "use strict";
-        var idl_array = new IdlArray();
-
-        function doTest(idl) {
-          idl_array.add_untested_idls('interface Navigator {};');
-          idl_array.add_idls(idl);
-          idl_array.add_objects({
-            Navigator: ['navigator']
-          });
-          idl_array.test();
-        }
-
-        promise_test(async () => {
-          const response = await fetch('../interfaces/web-share.idl');
-          doTest(await response.text());
-        }, 'Test driver');
-    </script>
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-share/idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/web-share/idlharness.https.window.js
new file mode 100644
index 0000000..6a69c8d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-share/idlharness.https.window.js
@@ -0,0 +1,17 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://wicg.github.io/web-share/
+
+'use strict';
+
+idl_test(
+  ['web-share'],
+  ['html'],
+  idl_array => {
+    idl_array.add_objects({
+      Navigator: ['navigator']
+    });
+  },
+  'Test driver'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/historical.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/historical.html
index 2407a87..1f3146c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/historical.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/historical.html
@@ -12,4 +12,18 @@
     assert_false(name in window);
   }, name + " interface should not exist");
 });
+
+[
+  "dopplerFactor",
+  "speedOfSound",
+  "setVelocity"
+].forEach(name => {
+  test(function() {
+    assert_false(name in AudioListener.prototype);
+  }, name + " member should not exist on the AudioListener.");
+});
+
+test(function() {
+  assert_false("setVelocity" in PannerNode.prototype);
+}, "setVelocity should not exist on PannerNodes.");
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.html
deleted file mode 100644
index bd1df62..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.html
+++ /dev/null
@@ -1,97 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>WebAudio IDL tests</title>
-<link rel="help" href="https://webaudio.github.io/web-audio-api/"/>
-<meta name="timeout" content="long"><!-- Heavy computation of the idl_objects -->
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-<script>
-'use strict';
-
-let sample_rate, context, buffer, worklet_node;
-
-promise_test(async t => {
-  const srcs = ['cssom', 'dom', 'html', 'uievents', 'mediacapture-streams', 'webaudio'];
-  const [cssom, dom, html, uievents, mediacapture, webaudio] =
-      await Promise.all(
-          srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
-
-  const idl_array = new IdlArray();
-  idl_array.add_idls(webaudio);
-
-  // Dependencies of HTML
-  idl_array.add_dependency_idls(html);
-  idl_array.add_dependency_idls(uievents);
-  idl_array.add_dependency_idls(dom);
-  idl_array.add_dependency_idls(mediacapture);
-  idl_array.add_dependency_idls(cssom);
-
-  idl_array.add_untested_idls('interface SVGElement {};');
-  idl_array.add_untested_idls('interface WorkletGlobalScope {};');
-  idl_array.add_untested_idls('interface Worklet {};');
-
-  try {
-    sample_rate = 44100;
-    context = new AudioContext;
-    buffer = new AudioBuffer({length: 1, sampleRate: sample_rate});
-    await context.audioWorklet.addModule(
-      'the-audio-api/the-audioworklet-interface/processors/dummy-processor.js');
-    worklet_node = new AudioWorkletNode(context, 'dummy');
-  } catch (e) {
-    // Ignore - errors will surface in each test_object below.
-  }
-
-  idl_array.add_objects({
-    BaseAudioContext: [],
-    AudioContext: ['context'],
-    OfflineAudioContext: ['new OfflineAudioContext(1, 1, sample_rate)'],
-    OfflineAudioCompletionEvent: [
-      'new OfflineAudioCompletionEvent("", {renderedBuffer: buffer})'],
-    AudioBuffer: ['buffer'],
-    AudioNode: [],
-    AudioParam: ['new AudioBufferSourceNode(context).playbackRate'],
-    AudioScheduledSourceNode: [],
-    AnalyserNode: ['new AnalyserNode(context)'],
-    AudioBufferSourceNode: ['new AudioBufferSourceNode(context)'],
-    AudioDestinationNode: ['context.destination'],
-    AudioListener: ['context.listener'],
-    AudioProcessingEvent: [`new AudioProcessingEvent('', {
-      playbackTime: 0, inputBuffer: buffer, outputBuffer: buffer
-    })`],
-    BiquadFilterNode: ['new BiquadFilterNode(context)'],
-    ChannelMergerNode: ['new ChannelMergerNode(context)'],
-    ChannelSplitterNode: ['new ChannelSplitterNode(context)'],
-    ConstantSourceNode: ['new ConstantSourceNode(context)'],
-    ConvolverNode: ['new ConvolverNode(context)'],
-    DelayNode: ['new DelayNode(context)'],
-    DynamicsCompressorNode: ['new DynamicsCompressorNode(context)'],
-    GainNode: ['new GainNode(context)'],
-    IIRFilterNode: [
-      'new IIRFilterNode(context, {feedforward: [1], feedback: [1]})'
-    ],
-    MediaElementAudioSourceNode: [
-      'new MediaElementAudioSourceNode(context, {mediaElement: new Audio})'
-    ],
-    MediaStreamAudioDestinationNode: [
-      'new MediaStreamAudioDestinationNode(context)'
-    ],
-    MediaStreamAudioSourceNode: [],
-    MediaStreamTrackAudioSourceNode: [],
-    OscillatorNode: ['new OscillatorNode(context)'],
-    PannerNode: ['new PannerNode(context)'],
-    PeriodicWave: ['new PeriodicWave(context)'],
-    ScriptProcessorNode: ['context.createScriptProcessor()'],
-    StereoPannerNode: ['new StereoPannerNode(context)'],
-    WaveShaperNode: ['new WaveShaperNode(context)'],
-    AudioWorklet: ['context.audioWorklet'],
-    AudioWorkletGlobalScope: [],
-    AudioParamMap: ['worklet_node.parameters'],
-    AudioWorkletNode: ['worklet_node'],
-    AudioWorkletProcessor: [],
-  });
-  idl_array.test();
-
-}, 'Test driver');
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt
new file mode 100644
index 0000000..5bdb954
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window-expected.txt
@@ -0,0 +1,1285 @@
+This is a testharness.js-based test.
+PASS Test driver
+PASS BaseAudioContext interface: existence and properties of interface object
+PASS BaseAudioContext interface object length
+PASS BaseAudioContext interface object name
+PASS BaseAudioContext interface: existence and properties of interface prototype object
+PASS BaseAudioContext interface: existence and properties of interface prototype object's "constructor" property
+PASS BaseAudioContext interface: existence and properties of interface prototype object's @@unscopables property
+PASS BaseAudioContext interface: attribute destination
+PASS Unscopable handled correctly for destination property on BaseAudioContext
+PASS BaseAudioContext interface: attribute sampleRate
+PASS Unscopable handled correctly for sampleRate property on BaseAudioContext
+PASS BaseAudioContext interface: attribute currentTime
+PASS Unscopable handled correctly for currentTime property on BaseAudioContext
+PASS BaseAudioContext interface: attribute listener
+PASS Unscopable handled correctly for listener property on BaseAudioContext
+PASS BaseAudioContext interface: attribute state
+PASS Unscopable handled correctly for state property on BaseAudioContext
+PASS BaseAudioContext interface: attribute audioWorklet
+PASS Unscopable handled correctly for audioWorklet property on BaseAudioContext
+PASS BaseAudioContext interface: attribute onstatechange
+PASS Unscopable handled correctly for onstatechange property on BaseAudioContext
+PASS BaseAudioContext interface: operation createAnalyser()
+PASS Unscopable handled correctly for createAnalyser() on BaseAudioContext
+PASS BaseAudioContext interface: operation createBiquadFilter()
+PASS Unscopable handled correctly for createBiquadFilter() on BaseAudioContext
+PASS BaseAudioContext interface: operation createBuffer(unsigned long, unsigned long, float)
+PASS Unscopable handled correctly for createBuffer(unsigned long, unsigned long, float) on BaseAudioContext
+PASS BaseAudioContext interface: operation createBufferSource()
+PASS Unscopable handled correctly for createBufferSource() on BaseAudioContext
+PASS BaseAudioContext interface: operation createChannelMerger(unsigned long)
+PASS Unscopable handled correctly for createChannelMerger(unsigned long) on BaseAudioContext
+PASS BaseAudioContext interface: operation createChannelSplitter(unsigned long)
+PASS Unscopable handled correctly for createChannelSplitter(unsigned long) on BaseAudioContext
+PASS BaseAudioContext interface: operation createConstantSource()
+PASS Unscopable handled correctly for createConstantSource() on BaseAudioContext
+PASS BaseAudioContext interface: operation createConvolver()
+PASS Unscopable handled correctly for createConvolver() on BaseAudioContext
+PASS BaseAudioContext interface: operation createDelay(double)
+PASS Unscopable handled correctly for createDelay(double) on BaseAudioContext
+PASS BaseAudioContext interface: operation createDynamicsCompressor()
+PASS Unscopable handled correctly for createDynamicsCompressor() on BaseAudioContext
+PASS BaseAudioContext interface: operation createGain()
+PASS Unscopable handled correctly for createGain() on BaseAudioContext
+PASS BaseAudioContext interface: operation createIIRFilter([object Object], [object Object])
+PASS Unscopable handled correctly for createIIRFilter([object Object], [object Object]) on BaseAudioContext
+PASS BaseAudioContext interface: operation createOscillator()
+PASS Unscopable handled correctly for createOscillator() on BaseAudioContext
+PASS BaseAudioContext interface: operation createPanner()
+PASS Unscopable handled correctly for createPanner() on BaseAudioContext
+PASS BaseAudioContext interface: operation createPeriodicWave([object Object], [object Object], PeriodicWaveConstraints)
+PASS Unscopable handled correctly for createPeriodicWave([object Object], [object Object], PeriodicWaveConstraints) on BaseAudioContext
+PASS BaseAudioContext interface: operation createScriptProcessor(unsigned long, unsigned long, unsigned long)
+PASS Unscopable handled correctly for createScriptProcessor(unsigned long, unsigned long, unsigned long) on BaseAudioContext
+PASS BaseAudioContext interface: operation createStereoPanner()
+PASS Unscopable handled correctly for createStereoPanner() on BaseAudioContext
+PASS BaseAudioContext interface: operation createWaveShaper()
+PASS Unscopable handled correctly for createWaveShaper() on BaseAudioContext
+PASS BaseAudioContext interface: operation decodeAudioData(ArrayBuffer, DecodeSuccessCallback, DecodeErrorCallback)
+PASS Unscopable handled correctly for decodeAudioData(ArrayBuffer, DecodeSuccessCallback, DecodeErrorCallback) on BaseAudioContext
+PASS BaseAudioContext interface: operation resume()
+PASS Unscopable handled correctly for resume() on BaseAudioContext
+PASS AudioContext interface: existence and properties of interface object
+PASS AudioContext interface object length
+PASS AudioContext interface object name
+PASS AudioContext interface: existence and properties of interface prototype object
+PASS AudioContext interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioContext interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioContext interface: attribute baseLatency
+PASS Unscopable handled correctly for baseLatency property on AudioContext
+FAIL AudioContext interface: attribute outputLatency assert_true: The prototype object must have a property "outputLatency" expected true got false
+PASS Unscopable handled correctly for outputLatency property on AudioContext
+PASS AudioContext interface: operation getOutputTimestamp()
+PASS Unscopable handled correctly for getOutputTimestamp() on AudioContext
+PASS AudioContext interface: operation suspend()
+PASS Unscopable handled correctly for suspend() on AudioContext
+PASS AudioContext interface: operation close()
+PASS Unscopable handled correctly for close() on AudioContext
+FAIL AudioContext interface: operation createMediaElementSource(HTMLMediaElement) assert_own_property: interface prototype object missing non-static operation expected property "createMediaElementSource" missing
+PASS Unscopable handled correctly for createMediaElementSource(HTMLMediaElement) on AudioContext
+FAIL AudioContext interface: operation createMediaStreamSource(MediaStream) assert_own_property: interface prototype object missing non-static operation expected property "createMediaStreamSource" missing
+PASS Unscopable handled correctly for createMediaStreamSource(MediaStream) on AudioContext
+FAIL AudioContext interface: operation createMediaStreamTrackSource(MediaStreamTrack) assert_own_property: interface prototype object missing non-static operation expected property "createMediaStreamTrackSource" missing
+PASS Unscopable handled correctly for createMediaStreamTrackSource(MediaStreamTrack) on AudioContext
+FAIL AudioContext interface: operation createMediaStreamDestination() assert_own_property: interface prototype object missing non-static operation expected property "createMediaStreamDestination" missing
+PASS Unscopable handled correctly for createMediaStreamDestination() on AudioContext
+PASS AudioContext must be primary interface of context
+PASS Stringification of context
+PASS AudioContext interface: context must inherit property "baseLatency" with the proper type
+FAIL AudioContext interface: context must inherit property "outputLatency" with the proper type assert_inherits: property "outputLatency" not found in prototype chain
+PASS AudioContext interface: context must inherit property "getOutputTimestamp()" with the proper type
+PASS AudioContext interface: context must inherit property "suspend()" with the proper type
+PASS AudioContext interface: context must inherit property "close()" with the proper type
+PASS AudioContext interface: context must inherit property "createMediaElementSource(HTMLMediaElement)" with the proper type
+PASS AudioContext interface: calling createMediaElementSource(HTMLMediaElement) on context with too few arguments must throw TypeError
+PASS AudioContext interface: context must inherit property "createMediaStreamSource(MediaStream)" with the proper type
+PASS AudioContext interface: calling createMediaStreamSource(MediaStream) on context with too few arguments must throw TypeError
+FAIL AudioContext interface: context must inherit property "createMediaStreamTrackSource(MediaStreamTrack)" with the proper type assert_inherits: property "createMediaStreamTrackSource" not found in prototype chain
+FAIL AudioContext interface: calling createMediaStreamTrackSource(MediaStreamTrack) on context with too few arguments must throw TypeError assert_inherits: property "createMediaStreamTrackSource" not found in prototype chain
+PASS AudioContext interface: context must inherit property "createMediaStreamDestination()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "destination" with the proper type
+PASS BaseAudioContext interface: context must inherit property "sampleRate" with the proper type
+PASS BaseAudioContext interface: context must inherit property "currentTime" with the proper type
+PASS BaseAudioContext interface: context must inherit property "listener" with the proper type
+PASS BaseAudioContext interface: context must inherit property "state" with the proper type
+PASS BaseAudioContext interface: context must inherit property "audioWorklet" with the proper type
+PASS BaseAudioContext interface: context must inherit property "onstatechange" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createAnalyser()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createBiquadFilter()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createBuffer(unsigned long, unsigned long, float)" with the proper type
+PASS BaseAudioContext interface: calling createBuffer(unsigned long, unsigned long, float) on context with too few arguments must throw TypeError
+PASS BaseAudioContext interface: context must inherit property "createBufferSource()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createChannelMerger(unsigned long)" with the proper type
+PASS BaseAudioContext interface: calling createChannelMerger(unsigned long) on context with too few arguments must throw TypeError
+PASS BaseAudioContext interface: context must inherit property "createChannelSplitter(unsigned long)" with the proper type
+PASS BaseAudioContext interface: calling createChannelSplitter(unsigned long) on context with too few arguments must throw TypeError
+PASS BaseAudioContext interface: context must inherit property "createConstantSource()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createConvolver()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createDelay(double)" with the proper type
+PASS BaseAudioContext interface: calling createDelay(double) on context with too few arguments must throw TypeError
+PASS BaseAudioContext interface: context must inherit property "createDynamicsCompressor()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createGain()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createIIRFilter([object Object], [object Object])" with the proper type
+PASS BaseAudioContext interface: calling createIIRFilter([object Object], [object Object]) on context with too few arguments must throw TypeError
+PASS BaseAudioContext interface: context must inherit property "createOscillator()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createPanner()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createPeriodicWave([object Object], [object Object], PeriodicWaveConstraints)" with the proper type
+PASS BaseAudioContext interface: calling createPeriodicWave([object Object], [object Object], PeriodicWaveConstraints) on context with too few arguments must throw TypeError
+PASS BaseAudioContext interface: context must inherit property "createScriptProcessor(unsigned long, unsigned long, unsigned long)" with the proper type
+PASS BaseAudioContext interface: calling createScriptProcessor(unsigned long, unsigned long, unsigned long) on context with too few arguments must throw TypeError
+PASS BaseAudioContext interface: context must inherit property "createStereoPanner()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "createWaveShaper()" with the proper type
+PASS BaseAudioContext interface: context must inherit property "decodeAudioData(ArrayBuffer, DecodeSuccessCallback, DecodeErrorCallback)" with the proper type
+PASS BaseAudioContext interface: calling decodeAudioData(ArrayBuffer, DecodeSuccessCallback, DecodeErrorCallback) on context with too few arguments must throw TypeError
+PASS BaseAudioContext interface: context must inherit property "resume()" with the proper type
+PASS OfflineAudioContext interface: existence and properties of interface object
+PASS OfflineAudioContext interface object length
+PASS OfflineAudioContext interface object name
+PASS OfflineAudioContext interface: existence and properties of interface prototype object
+PASS OfflineAudioContext interface: existence and properties of interface prototype object's "constructor" property
+PASS OfflineAudioContext interface: existence and properties of interface prototype object's @@unscopables property
+PASS OfflineAudioContext interface: operation startRendering()
+PASS Unscopable handled correctly for startRendering() on OfflineAudioContext
+PASS OfflineAudioContext interface: operation suspend(double)
+PASS Unscopable handled correctly for suspend(double) on OfflineAudioContext
+PASS OfflineAudioContext interface: attribute length
+PASS Unscopable handled correctly for length property on OfflineAudioContext
+PASS OfflineAudioContext interface: attribute oncomplete
+PASS Unscopable handled correctly for oncomplete property on OfflineAudioContext
+PASS OfflineAudioContext must be primary interface of new OfflineAudioContext(1, 1, sample_rate)
+PASS Stringification of new OfflineAudioContext(1, 1, sample_rate)
+PASS OfflineAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "startRendering()" with the proper type
+PASS OfflineAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "suspend(double)" with the proper type
+PASS OfflineAudioContext interface: calling suspend(double) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError
+PASS OfflineAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "length" with the proper type
+PASS OfflineAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "oncomplete" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "destination" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "sampleRate" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "currentTime" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "listener" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "state" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "audioWorklet" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "onstatechange" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createAnalyser()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createBiquadFilter()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createBuffer(unsigned long, unsigned long, float)" with the proper type
+PASS BaseAudioContext interface: calling createBuffer(unsigned long, unsigned long, float) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createBufferSource()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createChannelMerger(unsigned long)" with the proper type
+PASS BaseAudioContext interface: calling createChannelMerger(unsigned long) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createChannelSplitter(unsigned long)" with the proper type
+PASS BaseAudioContext interface: calling createChannelSplitter(unsigned long) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createConstantSource()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createConvolver()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createDelay(double)" with the proper type
+PASS BaseAudioContext interface: calling createDelay(double) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createDynamicsCompressor()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createGain()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createIIRFilter([object Object], [object Object])" with the proper type
+PASS BaseAudioContext interface: calling createIIRFilter([object Object], [object Object]) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createOscillator()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createPanner()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createPeriodicWave([object Object], [object Object], PeriodicWaveConstraints)" with the proper type
+PASS BaseAudioContext interface: calling createPeriodicWave([object Object], [object Object], PeriodicWaveConstraints) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createScriptProcessor(unsigned long, unsigned long, unsigned long)" with the proper type
+PASS BaseAudioContext interface: calling createScriptProcessor(unsigned long, unsigned long, unsigned long) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createStereoPanner()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "createWaveShaper()" with the proper type
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "decodeAudioData(ArrayBuffer, DecodeSuccessCallback, DecodeErrorCallback)" with the proper type
+PASS BaseAudioContext interface: calling decodeAudioData(ArrayBuffer, DecodeSuccessCallback, DecodeErrorCallback) on new OfflineAudioContext(1, 1, sample_rate) with too few arguments must throw TypeError
+PASS BaseAudioContext interface: new OfflineAudioContext(1, 1, sample_rate) must inherit property "resume()" with the proper type
+PASS OfflineAudioCompletionEvent interface: existence and properties of interface object
+PASS OfflineAudioCompletionEvent interface object length
+PASS OfflineAudioCompletionEvent interface object name
+PASS OfflineAudioCompletionEvent interface: existence and properties of interface prototype object
+PASS OfflineAudioCompletionEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS OfflineAudioCompletionEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS OfflineAudioCompletionEvent interface: attribute renderedBuffer
+PASS Unscopable handled correctly for renderedBuffer property on OfflineAudioCompletionEvent
+PASS OfflineAudioCompletionEvent must be primary interface of new OfflineAudioCompletionEvent("", {renderedBuffer: buffer})
+PASS Stringification of new OfflineAudioCompletionEvent("", {renderedBuffer: buffer})
+PASS OfflineAudioCompletionEvent interface: new OfflineAudioCompletionEvent("", {renderedBuffer: buffer}) must inherit property "renderedBuffer" with the proper type
+PASS AudioBuffer interface: existence and properties of interface object
+PASS AudioBuffer interface object length
+PASS AudioBuffer interface object name
+PASS AudioBuffer interface: existence and properties of interface prototype object
+PASS AudioBuffer interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioBuffer interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioBuffer interface: attribute sampleRate
+PASS Unscopable handled correctly for sampleRate property on AudioBuffer
+PASS AudioBuffer interface: attribute length
+PASS Unscopable handled correctly for length property on AudioBuffer
+PASS AudioBuffer interface: attribute duration
+PASS Unscopable handled correctly for duration property on AudioBuffer
+PASS AudioBuffer interface: attribute numberOfChannels
+PASS Unscopable handled correctly for numberOfChannels property on AudioBuffer
+PASS AudioBuffer interface: operation getChannelData(unsigned long)
+PASS Unscopable handled correctly for getChannelData(unsigned long) on AudioBuffer
+PASS AudioBuffer interface: operation copyFromChannel(Float32Array, unsigned long, unsigned long)
+PASS Unscopable handled correctly for copyFromChannel(Float32Array, unsigned long, unsigned long) on AudioBuffer
+PASS AudioBuffer interface: operation copyToChannel(Float32Array, unsigned long, unsigned long)
+PASS Unscopable handled correctly for copyToChannel(Float32Array, unsigned long, unsigned long) on AudioBuffer
+PASS AudioBuffer must be primary interface of buffer
+PASS Stringification of buffer
+PASS AudioBuffer interface: buffer must inherit property "sampleRate" with the proper type
+PASS AudioBuffer interface: buffer must inherit property "length" with the proper type
+PASS AudioBuffer interface: buffer must inherit property "duration" with the proper type
+PASS AudioBuffer interface: buffer must inherit property "numberOfChannels" with the proper type
+PASS AudioBuffer interface: buffer must inherit property "getChannelData(unsigned long)" with the proper type
+PASS AudioBuffer interface: calling getChannelData(unsigned long) on buffer with too few arguments must throw TypeError
+PASS AudioBuffer interface: buffer must inherit property "copyFromChannel(Float32Array, unsigned long, unsigned long)" with the proper type
+PASS AudioBuffer interface: calling copyFromChannel(Float32Array, unsigned long, unsigned long) on buffer with too few arguments must throw TypeError
+PASS AudioBuffer interface: buffer must inherit property "copyToChannel(Float32Array, unsigned long, unsigned long)" with the proper type
+PASS AudioBuffer interface: calling copyToChannel(Float32Array, unsigned long, unsigned long) on buffer with too few arguments must throw TypeError
+PASS AudioNode interface: existence and properties of interface object
+PASS AudioNode interface object length
+PASS AudioNode interface object name
+PASS AudioNode interface: existence and properties of interface prototype object
+PASS AudioNode interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioNode interface: operation connect(AudioNode, unsigned long, unsigned long)
+PASS Unscopable handled correctly for connect(AudioNode, unsigned long, unsigned long) on AudioNode
+PASS AudioNode interface: operation connect(AudioParam, unsigned long)
+PASS Unscopable handled correctly for connect(AudioParam, unsigned long) on AudioNode
+PASS AudioNode interface: operation disconnect()
+PASS Unscopable handled correctly for disconnect() on AudioNode
+PASS AudioNode interface: operation disconnect(unsigned long)
+PASS Unscopable handled correctly for disconnect(unsigned long) on AudioNode
+PASS AudioNode interface: operation disconnect(AudioNode)
+PASS Unscopable handled correctly for disconnect(AudioNode) on AudioNode
+PASS AudioNode interface: operation disconnect(AudioNode, unsigned long)
+PASS Unscopable handled correctly for disconnect(AudioNode, unsigned long) on AudioNode
+PASS AudioNode interface: operation disconnect(AudioNode, unsigned long, unsigned long)
+PASS Unscopable handled correctly for disconnect(AudioNode, unsigned long, unsigned long) on AudioNode
+PASS AudioNode interface: operation disconnect(AudioParam)
+PASS Unscopable handled correctly for disconnect(AudioParam) on AudioNode
+PASS AudioNode interface: operation disconnect(AudioParam, unsigned long)
+PASS Unscopable handled correctly for disconnect(AudioParam, unsigned long) on AudioNode
+PASS AudioNode interface: attribute context
+PASS Unscopable handled correctly for context property on AudioNode
+PASS AudioNode interface: attribute numberOfInputs
+PASS Unscopable handled correctly for numberOfInputs property on AudioNode
+PASS AudioNode interface: attribute numberOfOutputs
+PASS Unscopable handled correctly for numberOfOutputs property on AudioNode
+PASS AudioNode interface: attribute channelCount
+PASS Unscopable handled correctly for channelCount property on AudioNode
+PASS AudioNode interface: attribute channelCountMode
+PASS Unscopable handled correctly for channelCountMode property on AudioNode
+PASS AudioNode interface: attribute channelInterpretation
+PASS Unscopable handled correctly for channelInterpretation property on AudioNode
+PASS AudioParam interface: existence and properties of interface object
+PASS AudioParam interface object length
+PASS AudioParam interface object name
+PASS AudioParam interface: existence and properties of interface prototype object
+PASS AudioParam interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioParam interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioParam interface: attribute value
+PASS Unscopable handled correctly for value property on AudioParam
+PASS AudioParam interface: attribute automationRate
+PASS Unscopable handled correctly for automationRate property on AudioParam
+PASS AudioParam interface: attribute defaultValue
+PASS Unscopable handled correctly for defaultValue property on AudioParam
+PASS AudioParam interface: attribute minValue
+PASS Unscopable handled correctly for minValue property on AudioParam
+PASS AudioParam interface: attribute maxValue
+PASS Unscopable handled correctly for maxValue property on AudioParam
+PASS AudioParam interface: operation setValueAtTime(float, double)
+PASS Unscopable handled correctly for setValueAtTime(float, double) on AudioParam
+PASS AudioParam interface: operation linearRampToValueAtTime(float, double)
+PASS Unscopable handled correctly for linearRampToValueAtTime(float, double) on AudioParam
+PASS AudioParam interface: operation exponentialRampToValueAtTime(float, double)
+PASS Unscopable handled correctly for exponentialRampToValueAtTime(float, double) on AudioParam
+PASS AudioParam interface: operation setTargetAtTime(float, double, float)
+PASS Unscopable handled correctly for setTargetAtTime(float, double, float) on AudioParam
+PASS AudioParam interface: operation setValueCurveAtTime([object Object], double, double)
+PASS Unscopable handled correctly for setValueCurveAtTime([object Object], double, double) on AudioParam
+PASS AudioParam interface: operation cancelScheduledValues(double)
+PASS Unscopable handled correctly for cancelScheduledValues(double) on AudioParam
+PASS AudioParam interface: operation cancelAndHoldAtTime(double)
+PASS Unscopable handled correctly for cancelAndHoldAtTime(double) on AudioParam
+PASS AudioParam must be primary interface of new AudioBufferSourceNode(context).playbackRate
+PASS Stringification of new AudioBufferSourceNode(context).playbackRate
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "value" with the proper type
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "automationRate" with the proper type
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "defaultValue" with the proper type
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "minValue" with the proper type
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "maxValue" with the proper type
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "setValueAtTime(float, double)" with the proper type
+PASS AudioParam interface: calling setValueAtTime(float, double) on new AudioBufferSourceNode(context).playbackRate with too few arguments must throw TypeError
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "linearRampToValueAtTime(float, double)" with the proper type
+PASS AudioParam interface: calling linearRampToValueAtTime(float, double) on new AudioBufferSourceNode(context).playbackRate with too few arguments must throw TypeError
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "exponentialRampToValueAtTime(float, double)" with the proper type
+PASS AudioParam interface: calling exponentialRampToValueAtTime(float, double) on new AudioBufferSourceNode(context).playbackRate with too few arguments must throw TypeError
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "setTargetAtTime(float, double, float)" with the proper type
+PASS AudioParam interface: calling setTargetAtTime(float, double, float) on new AudioBufferSourceNode(context).playbackRate with too few arguments must throw TypeError
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "setValueCurveAtTime([object Object], double, double)" with the proper type
+PASS AudioParam interface: calling setValueCurveAtTime([object Object], double, double) on new AudioBufferSourceNode(context).playbackRate with too few arguments must throw TypeError
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "cancelScheduledValues(double)" with the proper type
+PASS AudioParam interface: calling cancelScheduledValues(double) on new AudioBufferSourceNode(context).playbackRate with too few arguments must throw TypeError
+PASS AudioParam interface: new AudioBufferSourceNode(context).playbackRate must inherit property "cancelAndHoldAtTime(double)" with the proper type
+PASS AudioParam interface: calling cancelAndHoldAtTime(double) on new AudioBufferSourceNode(context).playbackRate with too few arguments must throw TypeError
+PASS AudioScheduledSourceNode interface: existence and properties of interface object
+PASS AudioScheduledSourceNode interface object length
+PASS AudioScheduledSourceNode interface object name
+PASS AudioScheduledSourceNode interface: existence and properties of interface prototype object
+PASS AudioScheduledSourceNode interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioScheduledSourceNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioScheduledSourceNode interface: attribute onended
+PASS Unscopable handled correctly for onended property on AudioScheduledSourceNode
+PASS AudioScheduledSourceNode interface: operation start(double)
+PASS Unscopable handled correctly for start(double) on AudioScheduledSourceNode
+PASS AudioScheduledSourceNode interface: operation stop(double)
+PASS Unscopable handled correctly for stop(double) on AudioScheduledSourceNode
+PASS AnalyserNode interface: existence and properties of interface object
+PASS AnalyserNode interface object length
+PASS AnalyserNode interface object name
+PASS AnalyserNode interface: existence and properties of interface prototype object
+PASS AnalyserNode interface: existence and properties of interface prototype object's "constructor" property
+PASS AnalyserNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS AnalyserNode interface: operation getFloatFrequencyData(Float32Array)
+PASS Unscopable handled correctly for getFloatFrequencyData(Float32Array) on AnalyserNode
+PASS AnalyserNode interface: operation getByteFrequencyData(Uint8Array)
+PASS Unscopable handled correctly for getByteFrequencyData(Uint8Array) on AnalyserNode
+PASS AnalyserNode interface: operation getFloatTimeDomainData(Float32Array)
+PASS Unscopable handled correctly for getFloatTimeDomainData(Float32Array) on AnalyserNode
+PASS AnalyserNode interface: operation getByteTimeDomainData(Uint8Array)
+PASS Unscopable handled correctly for getByteTimeDomainData(Uint8Array) on AnalyserNode
+PASS AnalyserNode interface: attribute fftSize
+PASS Unscopable handled correctly for fftSize property on AnalyserNode
+PASS AnalyserNode interface: attribute frequencyBinCount
+PASS Unscopable handled correctly for frequencyBinCount property on AnalyserNode
+PASS AnalyserNode interface: attribute minDecibels
+PASS Unscopable handled correctly for minDecibels property on AnalyserNode
+PASS AnalyserNode interface: attribute maxDecibels
+PASS Unscopable handled correctly for maxDecibels property on AnalyserNode
+PASS AnalyserNode interface: attribute smoothingTimeConstant
+PASS Unscopable handled correctly for smoothingTimeConstant property on AnalyserNode
+PASS AnalyserNode must be primary interface of new AnalyserNode(context)
+PASS Stringification of new AnalyserNode(context)
+PASS AnalyserNode interface: new AnalyserNode(context) must inherit property "getFloatFrequencyData(Float32Array)" with the proper type
+PASS AnalyserNode interface: calling getFloatFrequencyData(Float32Array) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AnalyserNode interface: new AnalyserNode(context) must inherit property "getByteFrequencyData(Uint8Array)" with the proper type
+PASS AnalyserNode interface: calling getByteFrequencyData(Uint8Array) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AnalyserNode interface: new AnalyserNode(context) must inherit property "getFloatTimeDomainData(Float32Array)" with the proper type
+PASS AnalyserNode interface: calling getFloatTimeDomainData(Float32Array) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AnalyserNode interface: new AnalyserNode(context) must inherit property "getByteTimeDomainData(Uint8Array)" with the proper type
+PASS AnalyserNode interface: calling getByteTimeDomainData(Uint8Array) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AnalyserNode interface: new AnalyserNode(context) must inherit property "fftSize" with the proper type
+PASS AnalyserNode interface: new AnalyserNode(context) must inherit property "frequencyBinCount" with the proper type
+PASS AnalyserNode interface: new AnalyserNode(context) must inherit property "minDecibels" with the proper type
+PASS AnalyserNode interface: new AnalyserNode(context) must inherit property "maxDecibels" with the proper type
+PASS AnalyserNode interface: new AnalyserNode(context) must inherit property "smoothingTimeConstant" with the proper type
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new AnalyserNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new AnalyserNode(context) must inherit property "channelInterpretation" with the proper type
+PASS AudioBufferSourceNode interface: existence and properties of interface object
+PASS AudioBufferSourceNode interface object length
+PASS AudioBufferSourceNode interface object name
+PASS AudioBufferSourceNode interface: existence and properties of interface prototype object
+PASS AudioBufferSourceNode interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioBufferSourceNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioBufferSourceNode interface: attribute buffer
+PASS Unscopable handled correctly for buffer property on AudioBufferSourceNode
+PASS AudioBufferSourceNode interface: attribute playbackRate
+PASS Unscopable handled correctly for playbackRate property on AudioBufferSourceNode
+PASS AudioBufferSourceNode interface: attribute detune
+PASS Unscopable handled correctly for detune property on AudioBufferSourceNode
+PASS AudioBufferSourceNode interface: attribute loop
+PASS Unscopable handled correctly for loop property on AudioBufferSourceNode
+PASS AudioBufferSourceNode interface: attribute loopStart
+PASS Unscopable handled correctly for loopStart property on AudioBufferSourceNode
+PASS AudioBufferSourceNode interface: attribute loopEnd
+PASS Unscopable handled correctly for loopEnd property on AudioBufferSourceNode
+PASS AudioBufferSourceNode interface: operation start(double, double, double)
+PASS Unscopable handled correctly for start(double, double, double) on AudioBufferSourceNode
+PASS AudioBufferSourceNode must be primary interface of new AudioBufferSourceNode(context)
+PASS Stringification of new AudioBufferSourceNode(context)
+PASS AudioBufferSourceNode interface: new AudioBufferSourceNode(context) must inherit property "buffer" with the proper type
+PASS AudioBufferSourceNode interface: new AudioBufferSourceNode(context) must inherit property "playbackRate" with the proper type
+PASS AudioBufferSourceNode interface: new AudioBufferSourceNode(context) must inherit property "detune" with the proper type
+PASS AudioBufferSourceNode interface: new AudioBufferSourceNode(context) must inherit property "loop" with the proper type
+PASS AudioBufferSourceNode interface: new AudioBufferSourceNode(context) must inherit property "loopStart" with the proper type
+PASS AudioBufferSourceNode interface: new AudioBufferSourceNode(context) must inherit property "loopEnd" with the proper type
+PASS AudioBufferSourceNode interface: new AudioBufferSourceNode(context) must inherit property "start(double, double, double)" with the proper type
+PASS AudioBufferSourceNode interface: calling start(double, double, double) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioScheduledSourceNode interface: new AudioBufferSourceNode(context) must inherit property "onended" with the proper type
+PASS AudioScheduledSourceNode interface: new AudioBufferSourceNode(context) must inherit property "start(double)" with the proper type
+PASS AudioScheduledSourceNode interface: calling start(double) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioScheduledSourceNode interface: new AudioBufferSourceNode(context) must inherit property "stop(double)" with the proper type
+PASS AudioScheduledSourceNode interface: calling stop(double) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new AudioBufferSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new AudioBufferSourceNode(context) must inherit property "channelInterpretation" with the proper type
+PASS AudioDestinationNode interface: existence and properties of interface object
+PASS AudioDestinationNode interface object length
+PASS AudioDestinationNode interface object name
+PASS AudioDestinationNode interface: existence and properties of interface prototype object
+PASS AudioDestinationNode interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioDestinationNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioDestinationNode interface: attribute maxChannelCount
+PASS Unscopable handled correctly for maxChannelCount property on AudioDestinationNode
+PASS AudioDestinationNode must be primary interface of context.destination
+PASS Stringification of context.destination
+PASS AudioDestinationNode interface: context.destination must inherit property "maxChannelCount" with the proper type
+PASS AudioNode interface: context.destination must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on context.destination with too few arguments must throw TypeError
+PASS AudioNode interface: context.destination must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on context.destination with too few arguments must throw TypeError
+PASS AudioNode interface: context.destination must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: context.destination must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on context.destination with too few arguments must throw TypeError
+PASS AudioNode interface: context.destination must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on context.destination with too few arguments must throw TypeError
+PASS AudioNode interface: context.destination must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on context.destination with too few arguments must throw TypeError
+PASS AudioNode interface: context.destination must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on context.destination with too few arguments must throw TypeError
+PASS AudioNode interface: context.destination must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on context.destination with too few arguments must throw TypeError
+PASS AudioNode interface: context.destination must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on context.destination with too few arguments must throw TypeError
+PASS AudioNode interface: context.destination must inherit property "context" with the proper type
+PASS AudioNode interface: context.destination must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: context.destination must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: context.destination must inherit property "channelCount" with the proper type
+PASS AudioNode interface: context.destination must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: context.destination must inherit property "channelInterpretation" with the proper type
+PASS AudioListener interface: existence and properties of interface object
+PASS AudioListener interface object length
+PASS AudioListener interface object name
+PASS AudioListener interface: existence and properties of interface prototype object
+PASS AudioListener interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioListener interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioListener interface: attribute positionX
+PASS Unscopable handled correctly for positionX property on AudioListener
+PASS AudioListener interface: attribute positionY
+PASS Unscopable handled correctly for positionY property on AudioListener
+PASS AudioListener interface: attribute positionZ
+PASS Unscopable handled correctly for positionZ property on AudioListener
+PASS AudioListener interface: attribute forwardX
+PASS Unscopable handled correctly for forwardX property on AudioListener
+PASS AudioListener interface: attribute forwardY
+PASS Unscopable handled correctly for forwardY property on AudioListener
+PASS AudioListener interface: attribute forwardZ
+PASS Unscopable handled correctly for forwardZ property on AudioListener
+PASS AudioListener interface: attribute upX
+PASS Unscopable handled correctly for upX property on AudioListener
+PASS AudioListener interface: attribute upY
+PASS Unscopable handled correctly for upY property on AudioListener
+PASS AudioListener interface: attribute upZ
+PASS Unscopable handled correctly for upZ property on AudioListener
+PASS AudioListener interface: operation setPosition(float, float, float)
+PASS Unscopable handled correctly for setPosition(float, float, float) on AudioListener
+PASS AudioListener interface: operation setOrientation(float, float, float, float, float, float)
+PASS Unscopable handled correctly for setOrientation(float, float, float, float, float, float) on AudioListener
+PASS AudioListener must be primary interface of context.listener
+PASS Stringification of context.listener
+PASS AudioListener interface: context.listener must inherit property "positionX" with the proper type
+PASS AudioListener interface: context.listener must inherit property "positionY" with the proper type
+PASS AudioListener interface: context.listener must inherit property "positionZ" with the proper type
+PASS AudioListener interface: context.listener must inherit property "forwardX" with the proper type
+PASS AudioListener interface: context.listener must inherit property "forwardY" with the proper type
+PASS AudioListener interface: context.listener must inherit property "forwardZ" with the proper type
+PASS AudioListener interface: context.listener must inherit property "upX" with the proper type
+PASS AudioListener interface: context.listener must inherit property "upY" with the proper type
+PASS AudioListener interface: context.listener must inherit property "upZ" with the proper type
+PASS AudioListener interface: context.listener must inherit property "setPosition(float, float, float)" with the proper type
+PASS AudioListener interface: calling setPosition(float, float, float) on context.listener with too few arguments must throw TypeError
+PASS AudioListener interface: context.listener must inherit property "setOrientation(float, float, float, float, float, float)" with the proper type
+PASS AudioListener interface: calling setOrientation(float, float, float, float, float, float) on context.listener with too few arguments must throw TypeError
+PASS AudioProcessingEvent interface: existence and properties of interface object
+PASS AudioProcessingEvent interface object length
+PASS AudioProcessingEvent interface object name
+PASS AudioProcessingEvent interface: existence and properties of interface prototype object
+PASS AudioProcessingEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioProcessingEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioProcessingEvent interface: attribute playbackTime
+PASS Unscopable handled correctly for playbackTime property on AudioProcessingEvent
+PASS AudioProcessingEvent interface: attribute inputBuffer
+PASS Unscopable handled correctly for inputBuffer property on AudioProcessingEvent
+PASS AudioProcessingEvent interface: attribute outputBuffer
+PASS Unscopable handled correctly for outputBuffer property on AudioProcessingEvent
+PASS AudioProcessingEvent must be primary interface of new AudioProcessingEvent('', {
+        playbackTime: 0, inputBuffer: buffer, outputBuffer: buffer
+      })
+PASS Stringification of new AudioProcessingEvent('', {
+        playbackTime: 0, inputBuffer: buffer, outputBuffer: buffer
+      })
+PASS AudioProcessingEvent interface: new AudioProcessingEvent('', {
+        playbackTime: 0, inputBuffer: buffer, outputBuffer: buffer
+      }) must inherit property "playbackTime" with the proper type
+PASS AudioProcessingEvent interface: new AudioProcessingEvent('', {
+        playbackTime: 0, inputBuffer: buffer, outputBuffer: buffer
+      }) must inherit property "inputBuffer" with the proper type
+PASS AudioProcessingEvent interface: new AudioProcessingEvent('', {
+        playbackTime: 0, inputBuffer: buffer, outputBuffer: buffer
+      }) must inherit property "outputBuffer" with the proper type
+PASS BiquadFilterNode interface: existence and properties of interface object
+PASS BiquadFilterNode interface object length
+PASS BiquadFilterNode interface object name
+PASS BiquadFilterNode interface: existence and properties of interface prototype object
+PASS BiquadFilterNode interface: existence and properties of interface prototype object's "constructor" property
+PASS BiquadFilterNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS BiquadFilterNode interface: attribute type
+PASS Unscopable handled correctly for type property on BiquadFilterNode
+PASS BiquadFilterNode interface: attribute frequency
+PASS Unscopable handled correctly for frequency property on BiquadFilterNode
+PASS BiquadFilterNode interface: attribute detune
+PASS Unscopable handled correctly for detune property on BiquadFilterNode
+PASS BiquadFilterNode interface: attribute Q
+PASS Unscopable handled correctly for Q property on BiquadFilterNode
+PASS BiquadFilterNode interface: attribute gain
+PASS Unscopable handled correctly for gain property on BiquadFilterNode
+PASS BiquadFilterNode interface: operation getFrequencyResponse(Float32Array, Float32Array, Float32Array)
+PASS Unscopable handled correctly for getFrequencyResponse(Float32Array, Float32Array, Float32Array) on BiquadFilterNode
+PASS BiquadFilterNode must be primary interface of new BiquadFilterNode(context)
+PASS Stringification of new BiquadFilterNode(context)
+PASS BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "type" with the proper type
+PASS BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "frequency" with the proper type
+PASS BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "detune" with the proper type
+PASS BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "Q" with the proper type
+PASS BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "gain" with the proper type
+PASS BiquadFilterNode interface: new BiquadFilterNode(context) must inherit property "getFrequencyResponse(Float32Array, Float32Array, Float32Array)" with the proper type
+PASS BiquadFilterNode interface: calling getFrequencyResponse(Float32Array, Float32Array, Float32Array) on new BiquadFilterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new BiquadFilterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new BiquadFilterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new BiquadFilterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new BiquadFilterNode(context) must inherit property "channelInterpretation" with the proper type
+PASS ChannelMergerNode interface: existence and properties of interface object
+PASS ChannelMergerNode interface object length
+PASS ChannelMergerNode interface object name
+PASS ChannelMergerNode interface: existence and properties of interface prototype object
+PASS ChannelMergerNode interface: existence and properties of interface prototype object's "constructor" property
+PASS ChannelMergerNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS ChannelMergerNode must be primary interface of new ChannelMergerNode(context)
+PASS Stringification of new ChannelMergerNode(context)
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new ChannelMergerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new ChannelMergerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new ChannelMergerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new ChannelMergerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new ChannelMergerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new ChannelMergerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new ChannelMergerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new ChannelMergerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new ChannelMergerNode(context) must inherit property "channelInterpretation" with the proper type
+PASS ChannelSplitterNode interface: existence and properties of interface object
+PASS ChannelSplitterNode interface object length
+PASS ChannelSplitterNode interface object name
+PASS ChannelSplitterNode interface: existence and properties of interface prototype object
+PASS ChannelSplitterNode interface: existence and properties of interface prototype object's "constructor" property
+PASS ChannelSplitterNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS ChannelSplitterNode must be primary interface of new ChannelSplitterNode(context)
+PASS Stringification of new ChannelSplitterNode(context)
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new ChannelSplitterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new ChannelSplitterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new ChannelSplitterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new ChannelSplitterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new ChannelSplitterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new ChannelSplitterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new ChannelSplitterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new ChannelSplitterNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new ChannelSplitterNode(context) must inherit property "channelInterpretation" with the proper type
+PASS ConstantSourceNode interface: existence and properties of interface object
+PASS ConstantSourceNode interface object length
+PASS ConstantSourceNode interface object name
+PASS ConstantSourceNode interface: existence and properties of interface prototype object
+PASS ConstantSourceNode interface: existence and properties of interface prototype object's "constructor" property
+PASS ConstantSourceNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS ConstantSourceNode interface: attribute offset
+PASS Unscopable handled correctly for offset property on ConstantSourceNode
+PASS ConstantSourceNode must be primary interface of new ConstantSourceNode(context)
+PASS Stringification of new ConstantSourceNode(context)
+PASS ConstantSourceNode interface: new ConstantSourceNode(context) must inherit property "offset" with the proper type
+PASS AudioScheduledSourceNode interface: new ConstantSourceNode(context) must inherit property "onended" with the proper type
+PASS AudioScheduledSourceNode interface: new ConstantSourceNode(context) must inherit property "start(double)" with the proper type
+PASS AudioScheduledSourceNode interface: calling start(double) on new ConstantSourceNode(context) with too few arguments must throw TypeError
+PASS AudioScheduledSourceNode interface: new ConstantSourceNode(context) must inherit property "stop(double)" with the proper type
+PASS AudioScheduledSourceNode interface: calling stop(double) on new ConstantSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new ConstantSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new ConstantSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new ConstantSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new ConstantSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new ConstantSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new ConstantSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new ConstantSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new ConstantSourceNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new ConstantSourceNode(context) must inherit property "channelInterpretation" with the proper type
+PASS ConvolverNode interface: existence and properties of interface object
+PASS ConvolverNode interface object length
+PASS ConvolverNode interface object name
+PASS ConvolverNode interface: existence and properties of interface prototype object
+PASS ConvolverNode interface: existence and properties of interface prototype object's "constructor" property
+PASS ConvolverNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS ConvolverNode interface: attribute buffer
+PASS Unscopable handled correctly for buffer property on ConvolverNode
+PASS ConvolverNode interface: attribute normalize
+PASS Unscopable handled correctly for normalize property on ConvolverNode
+PASS ConvolverNode must be primary interface of new ConvolverNode(context)
+PASS Stringification of new ConvolverNode(context)
+PASS ConvolverNode interface: new ConvolverNode(context) must inherit property "buffer" with the proper type
+PASS ConvolverNode interface: new ConvolverNode(context) must inherit property "normalize" with the proper type
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new ConvolverNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new ConvolverNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new ConvolverNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new ConvolverNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new ConvolverNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new ConvolverNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new ConvolverNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new ConvolverNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new ConvolverNode(context) must inherit property "channelInterpretation" with the proper type
+PASS DelayNode interface: existence and properties of interface object
+PASS DelayNode interface object length
+PASS DelayNode interface object name
+PASS DelayNode interface: existence and properties of interface prototype object
+PASS DelayNode interface: existence and properties of interface prototype object's "constructor" property
+PASS DelayNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS DelayNode interface: attribute delayTime
+PASS Unscopable handled correctly for delayTime property on DelayNode
+PASS DelayNode must be primary interface of new DelayNode(context)
+PASS Stringification of new DelayNode(context)
+PASS DelayNode interface: new DelayNode(context) must inherit property "delayTime" with the proper type
+PASS AudioNode interface: new DelayNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new DelayNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DelayNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new DelayNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DelayNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new DelayNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new DelayNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DelayNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new DelayNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DelayNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new DelayNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DelayNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new DelayNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DelayNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new DelayNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DelayNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new DelayNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DelayNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new DelayNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new DelayNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new DelayNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new DelayNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new DelayNode(context) must inherit property "channelInterpretation" with the proper type
+PASS DynamicsCompressorNode interface: existence and properties of interface object
+PASS DynamicsCompressorNode interface object length
+PASS DynamicsCompressorNode interface object name
+PASS DynamicsCompressorNode interface: existence and properties of interface prototype object
+PASS DynamicsCompressorNode interface: existence and properties of interface prototype object's "constructor" property
+PASS DynamicsCompressorNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS DynamicsCompressorNode interface: attribute threshold
+PASS Unscopable handled correctly for threshold property on DynamicsCompressorNode
+PASS DynamicsCompressorNode interface: attribute knee
+PASS Unscopable handled correctly for knee property on DynamicsCompressorNode
+PASS DynamicsCompressorNode interface: attribute ratio
+PASS Unscopable handled correctly for ratio property on DynamicsCompressorNode
+PASS DynamicsCompressorNode interface: attribute reduction
+PASS Unscopable handled correctly for reduction property on DynamicsCompressorNode
+PASS DynamicsCompressorNode interface: attribute attack
+PASS Unscopable handled correctly for attack property on DynamicsCompressorNode
+PASS DynamicsCompressorNode interface: attribute release
+PASS Unscopable handled correctly for release property on DynamicsCompressorNode
+PASS DynamicsCompressorNode must be primary interface of new DynamicsCompressorNode(context)
+PASS Stringification of new DynamicsCompressorNode(context)
+PASS DynamicsCompressorNode interface: new DynamicsCompressorNode(context) must inherit property "threshold" with the proper type
+PASS DynamicsCompressorNode interface: new DynamicsCompressorNode(context) must inherit property "knee" with the proper type
+PASS DynamicsCompressorNode interface: new DynamicsCompressorNode(context) must inherit property "ratio" with the proper type
+PASS DynamicsCompressorNode interface: new DynamicsCompressorNode(context) must inherit property "reduction" with the proper type
+PASS DynamicsCompressorNode interface: new DynamicsCompressorNode(context) must inherit property "attack" with the proper type
+PASS DynamicsCompressorNode interface: new DynamicsCompressorNode(context) must inherit property "release" with the proper type
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new DynamicsCompressorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new DynamicsCompressorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new DynamicsCompressorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new DynamicsCompressorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new DynamicsCompressorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new DynamicsCompressorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new DynamicsCompressorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new DynamicsCompressorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new DynamicsCompressorNode(context) must inherit property "channelInterpretation" with the proper type
+PASS GainNode interface: existence and properties of interface object
+PASS GainNode interface object length
+PASS GainNode interface object name
+PASS GainNode interface: existence and properties of interface prototype object
+PASS GainNode interface: existence and properties of interface prototype object's "constructor" property
+PASS GainNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS GainNode interface: attribute gain
+PASS Unscopable handled correctly for gain property on GainNode
+PASS GainNode must be primary interface of new GainNode(context)
+PASS Stringification of new GainNode(context)
+PASS GainNode interface: new GainNode(context) must inherit property "gain" with the proper type
+PASS AudioNode interface: new GainNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new GainNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new GainNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new GainNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new GainNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new GainNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new GainNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new GainNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new GainNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new GainNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new GainNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new GainNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new GainNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new GainNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new GainNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new GainNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new GainNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new GainNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new GainNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new GainNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new GainNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new GainNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new GainNode(context) must inherit property "channelInterpretation" with the proper type
+PASS IIRFilterNode interface: existence and properties of interface object
+PASS IIRFilterNode interface object length
+PASS IIRFilterNode interface object name
+PASS IIRFilterNode interface: existence and properties of interface prototype object
+PASS IIRFilterNode interface: existence and properties of interface prototype object's "constructor" property
+PASS IIRFilterNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS IIRFilterNode interface: operation getFrequencyResponse(Float32Array, Float32Array, Float32Array)
+PASS Unscopable handled correctly for getFrequencyResponse(Float32Array, Float32Array, Float32Array) on IIRFilterNode
+PASS IIRFilterNode must be primary interface of new IIRFilterNode(context, {feedforward: [1], feedback: [1]})
+PASS Stringification of new IIRFilterNode(context, {feedforward: [1], feedback: [1]})
+PASS IIRFilterNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "getFrequencyResponse(Float32Array, Float32Array, Float32Array)" with the proper type
+PASS IIRFilterNode interface: calling getFrequencyResponse(Float32Array, Float32Array, Float32Array) on new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) with too few arguments must throw TypeError
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) with too few arguments must throw TypeError
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) with too few arguments must throw TypeError
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) with too few arguments must throw TypeError
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) with too few arguments must throw TypeError
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) with too few arguments must throw TypeError
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) with too few arguments must throw TypeError
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) with too few arguments must throw TypeError
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) with too few arguments must throw TypeError
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "context" with the proper type
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new IIRFilterNode(context, {feedforward: [1], feedback: [1]}) must inherit property "channelInterpretation" with the proper type
+PASS MediaElementAudioSourceNode interface: existence and properties of interface object
+PASS MediaElementAudioSourceNode interface object length
+PASS MediaElementAudioSourceNode interface object name
+PASS MediaElementAudioSourceNode interface: existence and properties of interface prototype object
+PASS MediaElementAudioSourceNode interface: existence and properties of interface prototype object's "constructor" property
+PASS MediaElementAudioSourceNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS MediaElementAudioSourceNode interface: attribute mediaElement
+PASS Unscopable handled correctly for mediaElement property on MediaElementAudioSourceNode
+PASS MediaElementAudioSourceNode must be primary interface of new MediaElementAudioSourceNode(context, {mediaElement: new Audio})
+PASS Stringification of new MediaElementAudioSourceNode(context, {mediaElement: new Audio})
+PASS MediaElementAudioSourceNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "mediaElement" with the proper type
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "context" with the proper type
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new MediaElementAudioSourceNode(context, {mediaElement: new Audio}) must inherit property "channelInterpretation" with the proper type
+PASS MediaStreamAudioDestinationNode interface: existence and properties of interface object
+PASS MediaStreamAudioDestinationNode interface object length
+PASS MediaStreamAudioDestinationNode interface object name
+PASS MediaStreamAudioDestinationNode interface: existence and properties of interface prototype object
+PASS MediaStreamAudioDestinationNode interface: existence and properties of interface prototype object's "constructor" property
+PASS MediaStreamAudioDestinationNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS MediaStreamAudioDestinationNode interface: attribute stream
+PASS Unscopable handled correctly for stream property on MediaStreamAudioDestinationNode
+PASS MediaStreamAudioDestinationNode must be primary interface of new MediaStreamAudioDestinationNode(context)
+PASS Stringification of new MediaStreamAudioDestinationNode(context)
+PASS MediaStreamAudioDestinationNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "stream" with the proper type
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new MediaStreamAudioDestinationNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new MediaStreamAudioDestinationNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new MediaStreamAudioDestinationNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new MediaStreamAudioDestinationNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new MediaStreamAudioDestinationNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new MediaStreamAudioDestinationNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new MediaStreamAudioDestinationNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new MediaStreamAudioDestinationNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new MediaStreamAudioDestinationNode(context) must inherit property "channelInterpretation" with the proper type
+PASS MediaStreamAudioSourceNode interface: existence and properties of interface object
+PASS MediaStreamAudioSourceNode interface object length
+PASS MediaStreamAudioSourceNode interface object name
+PASS MediaStreamAudioSourceNode interface: existence and properties of interface prototype object
+PASS MediaStreamAudioSourceNode interface: existence and properties of interface prototype object's "constructor" property
+PASS MediaStreamAudioSourceNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS MediaStreamAudioSourceNode interface: attribute mediaStream
+PASS Unscopable handled correctly for mediaStream property on MediaStreamAudioSourceNode
+FAIL MediaStreamTrackAudioSourceNode interface: existence and properties of interface object assert_own_property: self does not have own property "MediaStreamTrackAudioSourceNode" expected property "MediaStreamTrackAudioSourceNode" missing
+FAIL MediaStreamTrackAudioSourceNode interface object length assert_own_property: self does not have own property "MediaStreamTrackAudioSourceNode" expected property "MediaStreamTrackAudioSourceNode" missing
+FAIL MediaStreamTrackAudioSourceNode interface object name assert_own_property: self does not have own property "MediaStreamTrackAudioSourceNode" expected property "MediaStreamTrackAudioSourceNode" missing
+FAIL MediaStreamTrackAudioSourceNode interface: existence and properties of interface prototype object assert_own_property: self does not have own property "MediaStreamTrackAudioSourceNode" expected property "MediaStreamTrackAudioSourceNode" missing
+FAIL MediaStreamTrackAudioSourceNode interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "MediaStreamTrackAudioSourceNode" expected property "MediaStreamTrackAudioSourceNode" missing
+FAIL MediaStreamTrackAudioSourceNode interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "MediaStreamTrackAudioSourceNode" expected property "MediaStreamTrackAudioSourceNode" missing
+PASS OscillatorNode interface: existence and properties of interface object
+PASS OscillatorNode interface object length
+PASS OscillatorNode interface object name
+PASS OscillatorNode interface: existence and properties of interface prototype object
+PASS OscillatorNode interface: existence and properties of interface prototype object's "constructor" property
+PASS OscillatorNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS OscillatorNode interface: attribute type
+PASS Unscopable handled correctly for type property on OscillatorNode
+PASS OscillatorNode interface: attribute frequency
+PASS Unscopable handled correctly for frequency property on OscillatorNode
+PASS OscillatorNode interface: attribute detune
+PASS Unscopable handled correctly for detune property on OscillatorNode
+PASS OscillatorNode interface: operation setPeriodicWave(PeriodicWave)
+PASS Unscopable handled correctly for setPeriodicWave(PeriodicWave) on OscillatorNode
+PASS OscillatorNode must be primary interface of new OscillatorNode(context)
+PASS Stringification of new OscillatorNode(context)
+PASS OscillatorNode interface: new OscillatorNode(context) must inherit property "type" with the proper type
+PASS OscillatorNode interface: new OscillatorNode(context) must inherit property "frequency" with the proper type
+PASS OscillatorNode interface: new OscillatorNode(context) must inherit property "detune" with the proper type
+PASS OscillatorNode interface: new OscillatorNode(context) must inherit property "setPeriodicWave(PeriodicWave)" with the proper type
+PASS OscillatorNode interface: calling setPeriodicWave(PeriodicWave) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioScheduledSourceNode interface: new OscillatorNode(context) must inherit property "onended" with the proper type
+PASS AudioScheduledSourceNode interface: new OscillatorNode(context) must inherit property "start(double)" with the proper type
+PASS AudioScheduledSourceNode interface: calling start(double) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioScheduledSourceNode interface: new OscillatorNode(context) must inherit property "stop(double)" with the proper type
+PASS AudioScheduledSourceNode interface: calling stop(double) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new OscillatorNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new OscillatorNode(context) must inherit property "channelInterpretation" with the proper type
+PASS PannerNode interface: existence and properties of interface object
+PASS PannerNode interface object length
+PASS PannerNode interface object name
+PASS PannerNode interface: existence and properties of interface prototype object
+PASS PannerNode interface: existence and properties of interface prototype object's "constructor" property
+PASS PannerNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS PannerNode interface: attribute panningModel
+PASS Unscopable handled correctly for panningModel property on PannerNode
+PASS PannerNode interface: attribute positionX
+PASS Unscopable handled correctly for positionX property on PannerNode
+PASS PannerNode interface: attribute positionY
+PASS Unscopable handled correctly for positionY property on PannerNode
+PASS PannerNode interface: attribute positionZ
+PASS Unscopable handled correctly for positionZ property on PannerNode
+PASS PannerNode interface: attribute orientationX
+PASS Unscopable handled correctly for orientationX property on PannerNode
+PASS PannerNode interface: attribute orientationY
+PASS Unscopable handled correctly for orientationY property on PannerNode
+PASS PannerNode interface: attribute orientationZ
+PASS Unscopable handled correctly for orientationZ property on PannerNode
+PASS PannerNode interface: attribute distanceModel
+PASS Unscopable handled correctly for distanceModel property on PannerNode
+PASS PannerNode interface: attribute refDistance
+PASS Unscopable handled correctly for refDistance property on PannerNode
+PASS PannerNode interface: attribute maxDistance
+PASS Unscopable handled correctly for maxDistance property on PannerNode
+PASS PannerNode interface: attribute rolloffFactor
+PASS Unscopable handled correctly for rolloffFactor property on PannerNode
+PASS PannerNode interface: attribute coneInnerAngle
+PASS Unscopable handled correctly for coneInnerAngle property on PannerNode
+PASS PannerNode interface: attribute coneOuterAngle
+PASS Unscopable handled correctly for coneOuterAngle property on PannerNode
+PASS PannerNode interface: attribute coneOuterGain
+PASS Unscopable handled correctly for coneOuterGain property on PannerNode
+PASS PannerNode interface: operation setPosition(float, float, float)
+PASS Unscopable handled correctly for setPosition(float, float, float) on PannerNode
+PASS PannerNode interface: operation setOrientation(float, float, float)
+PASS Unscopable handled correctly for setOrientation(float, float, float) on PannerNode
+PASS PannerNode must be primary interface of new PannerNode(context)
+PASS Stringification of new PannerNode(context)
+PASS PannerNode interface: new PannerNode(context) must inherit property "panningModel" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "positionX" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "positionY" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "positionZ" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "orientationX" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "orientationY" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "orientationZ" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "distanceModel" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "refDistance" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "maxDistance" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "rolloffFactor" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "coneInnerAngle" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "coneOuterAngle" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "coneOuterGain" with the proper type
+PASS PannerNode interface: new PannerNode(context) must inherit property "setPosition(float, float, float)" with the proper type
+PASS PannerNode interface: calling setPosition(float, float, float) on new PannerNode(context) with too few arguments must throw TypeError
+PASS PannerNode interface: new PannerNode(context) must inherit property "setOrientation(float, float, float)" with the proper type
+PASS PannerNode interface: calling setOrientation(float, float, float) on new PannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new PannerNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new PannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new PannerNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new PannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new PannerNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new PannerNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new PannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new PannerNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new PannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new PannerNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new PannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new PannerNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new PannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new PannerNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new PannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new PannerNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new PannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new PannerNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new PannerNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new PannerNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new PannerNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new PannerNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new PannerNode(context) must inherit property "channelInterpretation" with the proper type
+PASS PeriodicWave interface: existence and properties of interface object
+PASS PeriodicWave interface object length
+PASS PeriodicWave interface object name
+PASS PeriodicWave interface: existence and properties of interface prototype object
+PASS PeriodicWave interface: existence and properties of interface prototype object's "constructor" property
+PASS PeriodicWave interface: existence and properties of interface prototype object's @@unscopables property
+PASS PeriodicWave must be primary interface of new PeriodicWave(context)
+PASS Stringification of new PeriodicWave(context)
+PASS ScriptProcessorNode interface: existence and properties of interface object
+PASS ScriptProcessorNode interface object length
+PASS ScriptProcessorNode interface object name
+PASS ScriptProcessorNode interface: existence and properties of interface prototype object
+PASS ScriptProcessorNode interface: existence and properties of interface prototype object's "constructor" property
+PASS ScriptProcessorNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS ScriptProcessorNode interface: attribute onaudioprocess
+PASS Unscopable handled correctly for onaudioprocess property on ScriptProcessorNode
+PASS ScriptProcessorNode interface: attribute bufferSize
+PASS Unscopable handled correctly for bufferSize property on ScriptProcessorNode
+PASS ScriptProcessorNode must be primary interface of context.createScriptProcessor()
+PASS Stringification of context.createScriptProcessor()
+PASS ScriptProcessorNode interface: context.createScriptProcessor() must inherit property "onaudioprocess" with the proper type
+PASS ScriptProcessorNode interface: context.createScriptProcessor() must inherit property "bufferSize" with the proper type
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on context.createScriptProcessor() with too few arguments must throw TypeError
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on context.createScriptProcessor() with too few arguments must throw TypeError
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on context.createScriptProcessor() with too few arguments must throw TypeError
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on context.createScriptProcessor() with too few arguments must throw TypeError
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on context.createScriptProcessor() with too few arguments must throw TypeError
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on context.createScriptProcessor() with too few arguments must throw TypeError
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on context.createScriptProcessor() with too few arguments must throw TypeError
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on context.createScriptProcessor() with too few arguments must throw TypeError
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "context" with the proper type
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "channelCount" with the proper type
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: context.createScriptProcessor() must inherit property "channelInterpretation" with the proper type
+PASS StereoPannerNode interface: existence and properties of interface object
+PASS StereoPannerNode interface object length
+PASS StereoPannerNode interface object name
+PASS StereoPannerNode interface: existence and properties of interface prototype object
+PASS StereoPannerNode interface: existence and properties of interface prototype object's "constructor" property
+PASS StereoPannerNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS StereoPannerNode interface: attribute pan
+PASS Unscopable handled correctly for pan property on StereoPannerNode
+PASS StereoPannerNode must be primary interface of new StereoPannerNode(context)
+PASS Stringification of new StereoPannerNode(context)
+PASS StereoPannerNode interface: new StereoPannerNode(context) must inherit property "pan" with the proper type
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new StereoPannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new StereoPannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new StereoPannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new StereoPannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new StereoPannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new StereoPannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new StereoPannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new StereoPannerNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new StereoPannerNode(context) must inherit property "channelInterpretation" with the proper type
+PASS WaveShaperNode interface: existence and properties of interface object
+PASS WaveShaperNode interface object length
+PASS WaveShaperNode interface object name
+PASS WaveShaperNode interface: existence and properties of interface prototype object
+PASS WaveShaperNode interface: existence and properties of interface prototype object's "constructor" property
+PASS WaveShaperNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS WaveShaperNode interface: attribute curve
+PASS Unscopable handled correctly for curve property on WaveShaperNode
+PASS WaveShaperNode interface: attribute oversample
+PASS Unscopable handled correctly for oversample property on WaveShaperNode
+PASS WaveShaperNode must be primary interface of new WaveShaperNode(context)
+PASS Stringification of new WaveShaperNode(context)
+PASS WaveShaperNode interface: new WaveShaperNode(context) must inherit property "curve" with the proper type
+PASS WaveShaperNode interface: new WaveShaperNode(context) must inherit property "oversample" with the proper type
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on new WaveShaperNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on new WaveShaperNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on new WaveShaperNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on new WaveShaperNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on new WaveShaperNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on new WaveShaperNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on new WaveShaperNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on new WaveShaperNode(context) with too few arguments must throw TypeError
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "context" with the proper type
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "channelCount" with the proper type
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: new WaveShaperNode(context) must inherit property "channelInterpretation" with the proper type
+PASS AudioWorklet interface: existence and properties of interface object
+PASS AudioWorklet interface object length
+PASS AudioWorklet interface object name
+PASS AudioWorklet interface: existence and properties of interface prototype object
+PASS AudioWorklet interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioWorklet interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioWorklet must be primary interface of context.audioWorklet
+PASS Stringification of context.audioWorklet
+PASS AudioWorkletGlobalScope interface: existence and properties of interface object
+PASS AudioParamMap interface: existence and properties of interface object
+PASS AudioParamMap interface object length
+PASS AudioParamMap interface object name
+PASS AudioParamMap interface: existence and properties of interface prototype object
+PASS AudioParamMap interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioParamMap interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioParamMap must be primary interface of worklet_node.parameters
+PASS Stringification of worklet_node.parameters
+PASS AudioWorkletNode interface: existence and properties of interface object
+PASS AudioWorkletNode interface object length
+PASS AudioWorkletNode interface object name
+PASS AudioWorkletNode interface: existence and properties of interface prototype object
+PASS AudioWorkletNode interface: existence and properties of interface prototype object's "constructor" property
+PASS AudioWorkletNode interface: existence and properties of interface prototype object's @@unscopables property
+PASS AudioWorkletNode interface: attribute parameters
+PASS Unscopable handled correctly for parameters property on AudioWorkletNode
+PASS AudioWorkletNode interface: attribute port
+PASS Unscopable handled correctly for port property on AudioWorkletNode
+PASS AudioWorkletNode interface: attribute onprocessorerror
+PASS Unscopable handled correctly for onprocessorerror property on AudioWorkletNode
+PASS AudioWorkletNode must be primary interface of worklet_node
+PASS Stringification of worklet_node
+PASS AudioWorkletNode interface: worklet_node must inherit property "parameters" with the proper type
+PASS AudioWorkletNode interface: worklet_node must inherit property "port" with the proper type
+PASS AudioWorkletNode interface: worklet_node must inherit property "onprocessorerror" with the proper type
+PASS AudioNode interface: worklet_node must inherit property "connect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioNode, unsigned long, unsigned long) on worklet_node with too few arguments must throw TypeError
+PASS AudioNode interface: worklet_node must inherit property "connect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling connect(AudioParam, unsigned long) on worklet_node with too few arguments must throw TypeError
+PASS AudioNode interface: worklet_node must inherit property "disconnect()" with the proper type
+PASS AudioNode interface: worklet_node must inherit property "disconnect(unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(unsigned long) on worklet_node with too few arguments must throw TypeError
+PASS AudioNode interface: worklet_node must inherit property "disconnect(AudioNode)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode) on worklet_node with too few arguments must throw TypeError
+PASS AudioNode interface: worklet_node must inherit property "disconnect(AudioNode, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long) on worklet_node with too few arguments must throw TypeError
+PASS AudioNode interface: worklet_node must inherit property "disconnect(AudioNode, unsigned long, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioNode, unsigned long, unsigned long) on worklet_node with too few arguments must throw TypeError
+PASS AudioNode interface: worklet_node must inherit property "disconnect(AudioParam)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam) on worklet_node with too few arguments must throw TypeError
+PASS AudioNode interface: worklet_node must inherit property "disconnect(AudioParam, unsigned long)" with the proper type
+PASS AudioNode interface: calling disconnect(AudioParam, unsigned long) on worklet_node with too few arguments must throw TypeError
+PASS AudioNode interface: worklet_node must inherit property "context" with the proper type
+PASS AudioNode interface: worklet_node must inherit property "numberOfInputs" with the proper type
+PASS AudioNode interface: worklet_node must inherit property "numberOfOutputs" with the proper type
+PASS AudioNode interface: worklet_node must inherit property "channelCount" with the proper type
+PASS AudioNode interface: worklet_node must inherit property "channelCountMode" with the proper type
+PASS AudioNode interface: worklet_node must inherit property "channelInterpretation" with the proper type
+PASS AudioWorkletProcessor interface: existence and properties of interface object
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window.js
new file mode 100644
index 0000000..eb4734b0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.window.js
@@ -0,0 +1,75 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+// META: timeout=long
+
+// https://webaudio.github.io/web-audio-api/
+
+'use strict';
+
+idl_test(
+  ['webaudio'],
+  ['cssom', 'uievents', 'mediacapture-streams', 'html', 'dom'],
+  async idl_array => {
+    idl_array.add_untested_idls('interface SVGElement {};');
+    idl_array.add_untested_idls('interface WorkletGlobalScope {};');
+    idl_array.add_untested_idls('interface Worklet {};');
+
+    idl_array.add_objects({
+      BaseAudioContext: [],
+      AudioContext: ['context'],
+      OfflineAudioContext: ['new OfflineAudioContext(1, 1, sample_rate)'],
+      OfflineAudioCompletionEvent: [
+        'new OfflineAudioCompletionEvent("", {renderedBuffer: buffer})'
+      ],
+      AudioBuffer: ['buffer'],
+      AudioNode: [],
+      AudioParam: ['new AudioBufferSourceNode(context).playbackRate'],
+      AudioScheduledSourceNode: [],
+      AnalyserNode: ['new AnalyserNode(context)'],
+      AudioBufferSourceNode: ['new AudioBufferSourceNode(context)'],
+      AudioDestinationNode: ['context.destination'],
+      AudioListener: ['context.listener'],
+      AudioProcessingEvent: [`new AudioProcessingEvent('', {
+        playbackTime: 0, inputBuffer: buffer, outputBuffer: buffer
+      })`],
+      BiquadFilterNode: ['new BiquadFilterNode(context)'],
+      ChannelMergerNode: ['new ChannelMergerNode(context)'],
+      ChannelSplitterNode: ['new ChannelSplitterNode(context)'],
+      ConstantSourceNode: ['new ConstantSourceNode(context)'],
+      ConvolverNode: ['new ConvolverNode(context)'],
+      DelayNode: ['new DelayNode(context)'],
+      DynamicsCompressorNode: ['new DynamicsCompressorNode(context)'],
+      GainNode: ['new GainNode(context)'],
+      IIRFilterNode: [
+        'new IIRFilterNode(context, {feedforward: [1], feedback: [1]})'
+      ],
+      MediaElementAudioSourceNode: [
+        'new MediaElementAudioSourceNode(context, {mediaElement: new Audio})'
+      ],
+      MediaStreamAudioDestinationNode: [
+        'new MediaStreamAudioDestinationNode(context)'
+      ],
+      MediaStreamAudioSourceNode: [],
+      MediaStreamTrackAudioSourceNode: [],
+      OscillatorNode: ['new OscillatorNode(context)'],
+      PannerNode: ['new PannerNode(context)'],
+      PeriodicWave: ['new PeriodicWave(context)'],
+      ScriptProcessorNode: ['context.createScriptProcessor()'],
+      StereoPannerNode: ['new StereoPannerNode(context)'],
+      WaveShaperNode: ['new WaveShaperNode(context)'],
+      AudioWorklet: ['context.audioWorklet'],
+      AudioWorkletGlobalScope: [],
+      AudioParamMap: ['worklet_node.parameters'],
+      AudioWorkletNode: ['worklet_node'],
+      AudioWorkletProcessor: [],
+    });
+
+    self.sample_rate = 44100;
+    self.context = new AudioContext;
+    self.buffer = new AudioBuffer({length: 1, sampleRate: sample_rate});
+    await context.audioWorklet.addModule(
+      'the-audio-api/the-audioworklet-interface/processors/dummy-processor.js');
+    self.worklet_node = new AudioWorkletNode(context, 'dummy');
+  },
+  'Test driver'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webstorage/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/webstorage/idlharness.html
deleted file mode 100644
index efff8302..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/webstorage/idlharness.html
+++ /dev/null
@@ -1,83 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>Web Storage IDL tests</title>
-<link rel="author" title="W3C" href="http://www.w3.org/" />
-<link rel="help" href="http://www.w3.org/TR/webstorage/#storage"/>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-</head>
-<body>
-<h1>Web Storage IDL tests</h1>
-<div id="log"></div>
-
-<pre id='untested_idl' style='display:none'>
-[Global=Window, Exposed=Window]
-interface Window {
-};
-</pre>
-
-<pre id='idl'>
-interface Storage {
-  readonly attribute unsigned long length;
-  DOMString? key(unsigned long index);
-  getter DOMString? getItem(DOMString key);
-  setter void setItem(DOMString key, DOMString value);
-  deleter void removeItem(DOMString key);
-  void clear();
-};
-[NoInterfaceObject]
-interface WindowSessionStorage {
-  readonly attribute Storage sessionStorage;
-};
-Window implements WindowSessionStorage;
-[NoInterfaceObject]
-interface WindowLocalStorage {
-  readonly attribute Storage localStorage;
-};
-Window implements WindowLocalStorage;
-[Constructor(DOMString type, optional StorageEventInit eventInitDict)]
-interface StorageEvent : Event {
-  readonly attribute DOMString? key;
-  readonly attribute DOMString? oldValue;
-  readonly attribute DOMString? newValue;
-  readonly attribute DOMString url;
-  readonly attribute Storage? storageArea;
-};
-
-dictionary StorageEventInit : EventInit {
-  DOMString? key;
-  DOMString? oldValue;
-  DOMString? newValue;
-  DOMString url;
-  Storage? storageArea;
-};
-</pre>
-
-<script>
-function do_test([html, dom]) {
-  var idl_array = new IdlArray();
-
-  idl_array.add_untested_idls(dom, { only: ['Event', 'EventInit'] });
-  idl_array.add_untested_idls(html, { only: ['EventStorageInit'] });
-  idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
-  idl_array.add_idls(document.getElementById("idl").textContent);
-
-  idl_array.add_objects({Storage: ["window.localStorage"]});
-
-  idl_array.test();
-}
-
-function fetch_text(url) {
-  return fetch(url).then(response => response.text());
-}
-
-promise_test(function () {
-  return Promise.all(['/interfaces/html.idl', '/interfaces/dom.idl'].map(fetch_text)).then(do_test);
-}, 'webstorage interfaces');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webstorage/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/webstorage/idlharness.window.js
new file mode 100644
index 0000000..7a6f16a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webstorage/idlharness.window.js
@@ -0,0 +1,30 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// http://www.w3.org/TR/webstorage/#storage
+
+idl_test(
+  [], [], // Srcs + deps manually handled below.
+  async idl_array => {
+    const [html, dom] = await Promise.all(['html', 'dom']
+        .map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
+    idl_array.add_idls(html, {
+      only: [
+        'Storage',
+        'WindowSessionStorage',
+        'WindowLocalStorage',
+        'StorageEvent',
+        'StorageEventInit',
+      ]});
+    idl_array.add_dependency_idls(dom);
+
+    idl_array.add_objects({
+      Storage: [
+        'localStorage',
+        'sessionStorage',
+      ],
+      StorageEvent: ['new StorageEvent("storage")']
+    });
+  },
+  'webstorage interfaces'
+);
diff --git a/third_party/WebKit/LayoutTests/fast/backgrounds/bug420029.html b/third_party/WebKit/LayoutTests/fast/backgrounds/bug420029.html
index 20e5c0c..4bcfe4f 100644
--- a/third_party/WebKit/LayoutTests/fast/backgrounds/bug420029.html
+++ b/third_party/WebKit/LayoutTests/fast/backgrounds/bug420029.html
@@ -1,6 +1,6 @@
 <style>
 *{
-    -webkit-padding-start: 6801059;
+    padding-inline-start: 6801059;
     background-image:-webkit-cross-fade(url(foo1), url(foo2), 50%);
 }
 </style>
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/float-list-changed-before-layout-crash.html b/third_party/WebKit/LayoutTests/fast/block/float/float-list-changed-before-layout-crash.html
index ee2f26e..820e7bc8 100644
--- a/third_party/WebKit/LayoutTests/fast/block/float/float-list-changed-before-layout-crash.html
+++ b/third_party/WebKit/LayoutTests/fast/block/float/float-list-changed-before-layout-crash.html
@@ -26,7 +26,7 @@
         display: table-header-group;
       }
       #el6 {
-        -webkit-border-after: solid;
+        border-block-end: solid;
         float: left;
       }
       #el6:last-of-type {
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/intruding-float-not-removed-from-next-sibling-crash.html b/third_party/WebKit/LayoutTests/fast/block/float/intruding-float-not-removed-from-next-sibling-crash.html
index 544e62e..3960955f 100644
--- a/third_party/WebKit/LayoutTests/fast/block/float/intruding-float-not-removed-from-next-sibling-crash.html
+++ b/third_party/WebKit/LayoutTests/fast/block/float/intruding-float-not-removed-from-next-sibling-crash.html
@@ -9,7 +9,7 @@
     padding-top: 1em;
     padding-bottom: 1em;
     margin-bottom: 1em;
-    -webkit-margin-before: -100px; 
+    margin-block-start: -100px; 
 }
 </style>
 <script>
diff --git a/third_party/WebKit/LayoutTests/fast/block/float/overhanging-float-crashes-when-sibling-becomes-formatting-context.html b/third_party/WebKit/LayoutTests/fast/block/float/overhanging-float-crashes-when-sibling-becomes-formatting-context.html
index 1e39e89..7216f0e8 100644
--- a/third_party/WebKit/LayoutTests/fast/block/float/overhanging-float-crashes-when-sibling-becomes-formatting-context.html
+++ b/third_party/WebKit/LayoutTests/fast/block/float/overhanging-float-crashes-when-sibling-becomes-formatting-context.html
@@ -20,7 +20,7 @@
         document.documentElement.style.webkitWritingMode='vertical-rl';
         iframe.style.all='unset';
         document.documentElement.clientWidth;
-        iframe.style.webkitMarginAfter='22vmin';
+        iframe.style.marginBlockEnd='22vmin';
         if (window.testRunner)
             testRunner.notifyDone();
     }
diff --git a/third_party/WebKit/LayoutTests/fast/block/margin-collapse/self-collapsing-block-discards-margin.html b/third_party/WebKit/LayoutTests/fast/block/margin-collapse/self-collapsing-block-discards-margin.html
index 2b73efef..0ea6273 100644
--- a/third_party/WebKit/LayoutTests/fast/block/margin-collapse/self-collapsing-block-discards-margin.html
+++ b/third_party/WebKit/LayoutTests/fast/block/margin-collapse/self-collapsing-block-discards-margin.html
@@ -3,7 +3,7 @@
 <style>
 * { clear:both; }
 .discard { clear:none; -webkit-margin-after-collapse:discard; }
-.float { display:inherit; -webkit-border-before-style:dashed; float:left; margin-top:2%; }
+.float { display:inherit; border-block-start-style:dashed; float:left; margin-top:2%; }
 </style>
 <div class="float"></div>
 <div class="discard"></div>
diff --git a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/003.html b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/003.html
index 9ace83e2f..c8f83de 100644
--- a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/003.html
+++ b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/003.html
@@ -24,7 +24,7 @@
 
     div#two {
         background: green;
-        -webkit-margin-before: -100px;
+        margin-block-start: -100px;
     }
 
     body { -webkit-writing-mode: vertical-lr }
diff --git a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/004.html b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/004.html
index 77c51fa..fffcdb2 100644
--- a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/004.html
+++ b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-lr/004.html
@@ -24,7 +24,7 @@
 
     div#two {
         background: green;
-        -webkit-margin-before: -100px;
+        margin-block-start: -100px;
     }
 
     body { -webkit-writing-mode: vertical-lr }
diff --git a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/003.html b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/003.html
index ff29337..b938d603 100644
--- a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/003.html
+++ b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/003.html
@@ -24,7 +24,7 @@
 
     div#two {
         background: green;
-        -webkit-margin-before: -100px;
+        margin-block-start: -100px;
     }
 
     body { -webkit-writing-mode: vertical-rl }
diff --git a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/004.html b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/004.html
index 74757f8..31c3618 100644
--- a/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/004.html
+++ b/third_party/WebKit/LayoutTests/fast/block/positioning/vertical-rl/004.html
@@ -24,7 +24,7 @@
 
     div#two {
         background: green;
-        -webkit-margin-before: -100px;
+        margin-block-start: -100px;
     }
 
     body { -webkit-writing-mode: vertical-rl }
diff --git a/third_party/WebKit/LayoutTests/fast/borders/border-image-border-radius.html b/third_party/WebKit/LayoutTests/fast/borders/border-image-border-radius.html
index 1504fc1..ef3bf20 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/border-image-border-radius.html
+++ b/third_party/WebKit/LayoutTests/fast/borders/border-image-border-radius.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <html>
 <head>
     <style>
diff --git a/third_party/WebKit/LayoutTests/fast/borders/border-styles-split.html b/third_party/WebKit/LayoutTests/fast/borders/border-styles-split.html
index 6a71032..427ca95 100644
--- a/third_party/WebKit/LayoutTests/fast/borders/border-styles-split.html
+++ b/third_party/WebKit/LayoutTests/fast/borders/border-styles-split.html
@@ -3,7 +3,7 @@
     display: inline-block;
   }
   span {
-    -webkit-padding-start: 15px; -webkit-padding-end:15px;
+    padding-inline-start: 15px; padding-inline-end:15px;
     font-size: 48px;
     background-color: #DDD;
     line-height: 2em;
diff --git a/third_party/WebKit/LayoutTests/fast/css/border-start-end-expected.txt b/third_party/WebKit/LayoutTests/fast/css/border-start-end-expected.txt
index fe7f945..da92363 100644
--- a/third_party/WebKit/LayoutTests/fast/css/border-start-end-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/border-start-end-expected.txt
@@ -3,46 +3,46 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS testWidth("ltr", "-webkit-border-start-width: 10px; -webkit-border-start-style: solid") is 110
-PASS testWidth("ltr", "-webkit-border-end-width: 20px; -webkit-border-end-style:  solid") is 120
-PASS testWidth("rtl", "-webkit-border-start-width: 10px; -webkit-border-start-style:  solid") is 110
-PASS testWidth("rtl", "-webkit-border-end-width: 20px; -webkit-border-end-style:  solid") is 120
-PASS test("ltr", "-webkit-border-start-color: rgb(255, 0, 0)", "border-left-color") is "rgb(255, 0, 0)"
-PASS test("ltr", "border-left-color: rgb(255, 0, 0)", "-webkit-border-start-color") is "rgb(255, 0, 0)"
-PASS test("ltr", "-webkit-border-end-color: rgb(255, 0, 0)", "border-right-color") is "rgb(255, 0, 0)"
-PASS test("ltr", "border-right-color: rgb(255, 0, 0)", "-webkit-border-end-color") is "rgb(255, 0, 0)"
-PASS test("rtl", "-webkit-border-start-color: rgb(255, 0, 0)", "border-right-color") is "rgb(255, 0, 0)"
-PASS test("rtl", "border-right-color: rgb(255, 0, 0)", "-webkit-border-start-color") is "rgb(255, 0, 0)"
-PASS test("rtl", "-webkit-border-end-color: rgb(255, 0, 0)", "border-left-color") is "rgb(255, 0, 0)"
-PASS test("rtl", "border-left-color: rgb(255, 0, 0)", "-webkit-border-end-color") is "rgb(255, 0, 0)"
-PASS test("ltr", "-webkit-border-start-style: dotted", "border-left-style") is "dotted"
-PASS test("ltr", "border-left-style: dotted", "-webkit-border-start-style") is "dotted"
-PASS test("ltr", "-webkit-border-end-style: dotted", "border-right-style") is "dotted"
-PASS test("ltr", "border-right-style: dotted", "-webkit-border-end-style") is "dotted"
-PASS test("rtl", "-webkit-border-start-style: dotted", "border-right-style") is "dotted"
-PASS test("rtl", "border-right-style: dotted", "-webkit-border-start-style") is "dotted"
-PASS test("rtl", "-webkit-border-end-style: dotted", "border-left-style") is "dotted"
-PASS test("rtl", "border-left-style: dotted", "-webkit-border-end-style") is "dotted"
-PASS test("ltr", "-webkit-border-start-width: 10px; -webkit-border-start-style: solid", "border-left-width") is "10px"
-PASS test("ltr", "-webkit-border-end-width: 10px; -webkit-border-end-style: solid", "border-right-width") is "10px"
-PASS test("rtl", "-webkit-border-start-width: 10px; -webkit-border-start-style: solid", "border-right-width") is "10px"
-PASS test("rtl", "-webkit-border-end-width: 10px; -webkit-border-end-style: solid", "border-left-width") is "10px"
-PASS test("ltr", "border-left: 10px solid", "-webkit-border-start-width") is "10px"
-PASS test("ltr", "border-right: 10px solid", "-webkit-border-end-width") is "10px"
-PASS test("rtl", "border-left: 10px solid", "-webkit-border-end-width") is "10px"
-PASS test("rtl", "border-right: 10px solid", "-webkit-border-start-width") is "10px"
-PASS test("ltr", "-webkit-border-start: 10px solid red", "border-left-color") is "rgb(255, 0, 0)"
-PASS test("ltr", "-webkit-border-start: 10px solid red", "border-left-style") is "solid"
-PASS test("ltr", "-webkit-border-start: 10px solid red", "border-left-width") is "10px"
-PASS test("rtl", "-webkit-border-start: 10px solid red", "border-right-color") is "rgb(255, 0, 0)"
-PASS test("rtl", "-webkit-border-start: 10px solid red", "border-right-style") is "solid"
-PASS test("rtl", "-webkit-border-start: 10px solid red", "border-right-width") is "10px"
-PASS test("ltr", "-webkit-border-end: 10px solid red", "border-right-color") is "rgb(255, 0, 0)"
-PASS test("ltr", "-webkit-border-end: 10px solid red", "border-right-style") is "solid"
-PASS test("ltr", "-webkit-border-end: 10px solid red", "border-right-width") is "10px"
-PASS test("rtl", "-webkit-border-end: 10px solid red", "border-left-color") is "rgb(255, 0, 0)"
-PASS test("rtl", "-webkit-border-end: 10px solid red", "border-left-style") is "solid"
-PASS test("rtl", "-webkit-border-end: 10px solid red", "border-left-width") is "10px"
+PASS testWidth("ltr", "border-inline-start-width: 10px; border-inline-start-style: solid") is 110
+PASS testWidth("ltr", "border-inline-end-width: 20px; border-inline-end-style:  solid") is 120
+PASS testWidth("rtl", "border-inline-start-width: 10px; border-inline-start-style:  solid") is 110
+PASS testWidth("rtl", "border-inline-end-width: 20px; border-inline-end-style:  solid") is 120
+PASS test("ltr", "border-inline-start-color: rgb(255, 0, 0)", "border-left-color") is "rgb(255, 0, 0)"
+PASS test("ltr", "border-left-color: rgb(255, 0, 0)", "border-inline-start-color") is "rgb(255, 0, 0)"
+PASS test("ltr", "border-inline-end-color: rgb(255, 0, 0)", "border-right-color") is "rgb(255, 0, 0)"
+PASS test("ltr", "border-right-color: rgb(255, 0, 0)", "border-inline-end-color") is "rgb(255, 0, 0)"
+PASS test("rtl", "border-inline-start-color: rgb(255, 0, 0)", "border-right-color") is "rgb(255, 0, 0)"
+PASS test("rtl", "border-right-color: rgb(255, 0, 0)", "border-inline-start-color") is "rgb(255, 0, 0)"
+PASS test("rtl", "border-inline-end-color: rgb(255, 0, 0)", "border-left-color") is "rgb(255, 0, 0)"
+PASS test("rtl", "border-left-color: rgb(255, 0, 0)", "border-inline-end-color") is "rgb(255, 0, 0)"
+PASS test("ltr", "border-inline-start-style: dotted", "border-left-style") is "dotted"
+PASS test("ltr", "border-left-style: dotted", "border-inline-start-style") is "dotted"
+PASS test("ltr", "border-inline-end-style: dotted", "border-right-style") is "dotted"
+PASS test("ltr", "border-right-style: dotted", "border-inline-end-style") is "dotted"
+PASS test("rtl", "border-inline-start-style: dotted", "border-right-style") is "dotted"
+PASS test("rtl", "border-right-style: dotted", "border-inline-start-style") is "dotted"
+PASS test("rtl", "border-inline-end-style: dotted", "border-left-style") is "dotted"
+PASS test("rtl", "border-left-style: dotted", "border-inline-end-style") is "dotted"
+PASS test("ltr", "border-inline-start-width: 10px; border-inline-start-style: solid", "border-left-width") is "10px"
+PASS test("ltr", "border-inline-end-width: 10px; border-inline-end-style: solid", "border-right-width") is "10px"
+PASS test("rtl", "border-inline-start-width: 10px; border-inline-start-style: solid", "border-right-width") is "10px"
+PASS test("rtl", "border-inline-end-width: 10px; border-inline-end-style: solid", "border-left-width") is "10px"
+PASS test("ltr", "border-left: 10px solid", "border-inline-start-width") is "10px"
+PASS test("ltr", "border-right: 10px solid", "border-inline-end-width") is "10px"
+PASS test("rtl", "border-left: 10px solid", "border-inline-end-width") is "10px"
+PASS test("rtl", "border-right: 10px solid", "border-inline-start-width") is "10px"
+PASS test("ltr", "border-inline-start: 10px solid red", "border-left-color") is "rgb(255, 0, 0)"
+PASS test("ltr", "border-inline-start: 10px solid red", "border-left-style") is "solid"
+PASS test("ltr", "border-inline-start: 10px solid red", "border-left-width") is "10px"
+PASS test("rtl", "border-inline-start: 10px solid red", "border-right-color") is "rgb(255, 0, 0)"
+PASS test("rtl", "border-inline-start: 10px solid red", "border-right-style") is "solid"
+PASS test("rtl", "border-inline-start: 10px solid red", "border-right-width") is "10px"
+PASS test("ltr", "border-inline-end: 10px solid red", "border-right-color") is "rgb(255, 0, 0)"
+PASS test("ltr", "border-inline-end: 10px solid red", "border-right-style") is "solid"
+PASS test("ltr", "border-inline-end: 10px solid red", "border-right-width") is "10px"
+PASS test("rtl", "border-inline-end: 10px solid red", "border-left-color") is "rgb(255, 0, 0)"
+PASS test("rtl", "border-inline-end: 10px solid red", "border-left-style") is "solid"
+PASS test("rtl", "border-inline-end: 10px solid red", "border-left-width") is "10px"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/css/crash-inherit-value-font-family.html b/third_party/WebKit/LayoutTests/fast/css/crash-inherit-value-font-family.html
index 100a041..48a6bae 100644
--- a/third_party/WebKit/LayoutTests/fast/css/crash-inherit-value-font-family.html
+++ b/third_party/WebKit/LayoutTests/fast/css/crash-inherit-value-font-family.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <body>
-<var style="float: right; -webkit-border-before: groove; font-family: inherit"></var>
+<var style="float: right; border-block-start: groove; font-family: inherit"></var>
 
 <script>
     if (window.testRunner)
diff --git a/third_party/WebKit/LayoutTests/fast/css/fontMetric-webkit-border-end-width-null-crash.html b/third_party/WebKit/LayoutTests/fast/css/fontMetric-webkit-border-end-width-null-crash.html
index a3aa5d4..b0538f8 100644
--- a/third_party/WebKit/LayoutTests/fast/css/fontMetric-webkit-border-end-width-null-crash.html
+++ b/third_party/WebKit/LayoutTests/fast/css/fontMetric-webkit-border-end-width-null-crash.html
@@ -2,7 +2,7 @@
     if (window.testRunner)
         testRunner.dumpAsText();
     document.writeln("<v>");
-    document.body.innerHTML="<style>*{-webkit-border-end-width:0ex;}</style>";
+    document.body.innerHTML="<style>*{border-inline-end-width:0ex;}</style>";
     document.write("<title>x");
     document.body.innerHTML = "<a href='https://bugs.webkit.org/show_bug.cgi?id=57756'>chrome.dll!WebCore::ComputedStyle::fontMetrics ReadAV@NULL (two crashes)<br>PASSED: This test did not crash!";
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/css/identical-logical-height-decl.html b/third_party/WebKit/LayoutTests/fast/css/identical-logical-height-decl.html
index 20888a1..bd5d8910 100644
--- a/third_party/WebKit/LayoutTests/fast/css/identical-logical-height-decl.html
+++ b/third_party/WebKit/LayoutTests/fast/css/identical-logical-height-decl.html
@@ -5,9 +5,9 @@
   </head>
   <body style="overflow:hidden;">
     <p>There should be no red on this page.</p>
-    <div style="-webkit-logical-height:10px;"></div> <!-- set height -->
+    <div style="block-size:10px;"></div> <!-- set height -->
     <div style="-webkit-writing-mode:vertical-lr; width:100px; height:100px; background:red;">
-      <div style="-webkit-logical-height:10px;"> <!-- set width! -->
+      <div style="block-size:10px;"> <!-- set width! -->
         <div style="width:100px; background:white;"></div>
       </div>
     </div>
diff --git a/third_party/WebKit/LayoutTests/fast/css/inherit-initial-shorthand-values-expected.txt b/third_party/WebKit/LayoutTests/fast/css/inherit-initial-shorthand-values-expected.txt
index 83374a0..adda70d8 100644
--- a/third_party/WebKit/LayoutTests/fast/css/inherit-initial-shorthand-values-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/inherit-initial-shorthand-values-expected.txt
@@ -2,8 +2,12 @@
 PASS test('background-position') is "inherit, initial"
 PASS test('background-repeat') is "inherit, initial"
 PASS test('border') is "inherit, initial"
+PASS test('border-block-end') is "inherit, initial"
+PASS test('border-block-start') is "inherit, initial"
 PASS test('border-bottom') is "inherit, initial"
 PASS test('border-color') is "inherit, initial"
+PASS test('border-inline-end') is "inherit, initial"
+PASS test('border-inline-start') is "inherit, initial"
 PASS test('border-left') is "inherit, initial"
 PASS test('border-radius') is "inherit, initial"
 PASS test('border-right') is "inherit, initial"
@@ -18,10 +22,6 @@
 PASS test('overflow') is "inherit, initial"
 PASS test('padding') is "inherit, initial"
 PASS test('webkit-animation') is "inherit, initial"
-PASS test('webkit-border-after') is "inherit, initial"
-PASS test('webkit-border-before') is "inherit, initial"
-PASS test('webkit-border-end') is "inherit, initial"
-PASS test('webkit-border-start') is "inherit, initial"
 PASS test('webkit-columns') is "inherit, initial"
 PASS test('webkit-column-rule') is "inherit, initial"
 PASS test('webkit-flex-flow') is "inherit, initial"
diff --git a/third_party/WebKit/LayoutTests/fast/css/inherit-initial-shorthand-values.html b/third_party/WebKit/LayoutTests/fast/css/inherit-initial-shorthand-values.html
index fbc93530..6e49ec44 100644
--- a/third_party/WebKit/LayoutTests/fast/css/inherit-initial-shorthand-values.html
+++ b/third_party/WebKit/LayoutTests/fast/css/inherit-initial-shorthand-values.html
@@ -18,10 +18,14 @@
     "background-position",
     "background-repeat",
     "border",
+    "border-block-end",
+    "border-block-start",
     "border-bottom",
     "border-color",
     // getPropertyValue() functionality not supported, see http://webkit.org/b/103245.
     // "border-image",
+    "border-inline-end",
+    "border-inline-start",
     "border-left",
     "border-radius",
     "border-right",
@@ -36,10 +40,6 @@
     "overflow",
     "padding",
     "webkit-animation",
-    "webkit-border-after",
-    "webkit-border-before",
-    "webkit-border-end",
-    "webkit-border-start",
     "webkit-columns",
     "webkit-column-rule",
     "webkit-flex-flow",
diff --git a/third_party/WebKit/LayoutTests/fast/css/logical-property-resolution-webkit-prefix-expected.txt b/third_party/WebKit/LayoutTests/fast/css/logical-property-resolution-webkit-prefix-expected.txt
new file mode 100644
index 0000000..88f7c87
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css/logical-property-resolution-webkit-prefix-expected.txt
@@ -0,0 +1,38 @@
+This test has incorrect results but reflects what's happening as we bring block-flow online.
+Block #1:
+Margins: 1px 2px 3px 4px
+Padding: 4px 3px 2px 1px
+Borders: 1px solid rgb(0, 0, 0), 2px dotted rgb(0, 128, 0), 3px dashed rgb(255, 255, 0), 4px double rgb(128, 0, 128)
+Width: 100px
+Height: 50px
+Block #2:
+Margins: 4px 3px 2px 1px
+Padding: 1px 2px 3px 4px
+Borders: 4px double rgb(128, 0, 128), 3px dashed rgb(255, 255, 0), 2px dotted rgb(0, 128, 0), 1px solid rgb(0, 0, 0)
+Width: 50px
+Height: 100px
+Block #3:
+Margins: 4px 1px 2px 3px
+Padding: 1px 4px 3px 2px
+Borders: 4px double rgb(128, 0, 128), 1px solid rgb(0, 0, 0), 2px dotted rgb(0, 128, 0), 3px dashed rgb(255, 255, 0)
+Width: 50px
+Height: 100px
+Block #4:
+Margins: 1px 4px 3px 2px
+Padding: 4px 1px 2px 3px
+Borders: 1px solid rgb(0, 0, 0), 4px double rgb(128, 0, 128), 3px dashed rgb(255, 255, 0), 2px dotted rgb(0, 128, 0)
+Width: 100px
+Height: 50px
+Block #5:
+Margins: 2px 3px 4px 1px
+Padding: 3px 2px 1px 4px
+Borders: 2px dotted rgb(0, 128, 0), 3px dashed rgb(255, 255, 0), 4px double rgb(128, 0, 128), 1px solid rgb(0, 0, 0)
+Width: 50px
+Height: 100px
+Block #6:
+Margins: 2px 1px 4px 3px
+Padding: 3px 4px 1px 2px
+Borders: 2px dotted rgb(0, 128, 0), 1px solid rgb(0, 0, 0), 4px double rgb(128, 0, 128), 3px dashed rgb(255, 255, 0)
+Width: 50px
+Height: 100px
+
diff --git a/third_party/WebKit/LayoutTests/fast/css/logical-property-resolution-webkit-prefix.html b/third_party/WebKit/LayoutTests/fast/css/logical-property-resolution-webkit-prefix.html
new file mode 100644
index 0000000..48d1570
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css/logical-property-resolution-webkit-prefix.html
@@ -0,0 +1,93 @@
+<html>
+<head>
+<style>
+.ltr-text {
+  direction: ltr
+}
+
+.rtl-text {
+  direction: rtl
+}
+
+.tb-block {
+  -webkit-writing-mode: horizontal-tb;
+}
+
+.lr-block {
+  -webkit-writing-mode: vertical-lr
+}
+
+.rl-block {
+  -webkit-writing-mode: vertical-rl
+}
+
+.test {
+  -webkit-margin-before: 1px;
+  -webkit-margin-end: 2px;
+  -webkit-margin-after: 3px;
+  -webkit-margin-start: 4px;
+  -webkit-padding-before:4px;
+  -webkit-padding-end:3px;
+  -webkit-padding-after:2px;
+  -webkit-padding-start:1px;
+  -webkit-logical-width:100px;
+  -webkit-logical-height:50px;
+  -webkit-border-before: 1px solid black;
+  -webkit-border-end: 2px dotted green;
+  -webkit-border-after: 3px dashed yellow;
+  -webkit-border-start: 4px double purple;
+  float:left;
+}
+</style>
+<script>
+if (window.testRunner)
+  testRunner.dumpAsText()
+  
+function dumpBlockProperties()
+{
+   result = document.getElementById('result');
+   blocks = document.getElementsByTagName('div');
+   resultStr = "This test has incorrect results but reflects what's happening as we bring block-flow online.<br>";
+   for (i = 0; i < blocks.length; ++i) {
+        resultStr += "<b>Block #" + (i+1) + ":</b><br>";
+        resultStr += "Margins: ";
+        c = getComputedStyle(blocks[i], null);
+        resultStr += c.getPropertyValue("margin-top") + " "
+                     + c.getPropertyValue("margin-right") + " "
+                     + c.getPropertyValue("margin-bottom") + " "
+                     + c.getPropertyValue("margin-left") + "<br>";
+                     
+        resultStr += "Padding: ";
+        c = getComputedStyle(blocks[i], null);
+        resultStr += c.getPropertyValue("padding-top") + " "
+                     + c.getPropertyValue("padding-right") + " "
+                     + c.getPropertyValue("padding-bottom") + " "
+                     + c.getPropertyValue("padding-left") + "<br>";
+        
+        resultStr += "Borders: "
+        resultStr += c.getPropertyValue("border-top-width") + " " + c.getPropertyValue("border-top-style") + " " + c.getPropertyValue("border-top-color") + ", "
+                     + c.getPropertyValue("border-right-width") + " " + c.getPropertyValue("border-right-style") + " " + c.getPropertyValue("border-right-color") + ", "
+                     + c.getPropertyValue("border-bottom-width") + " " + c.getPropertyValue("border-bottom-style") + " " + c.getPropertyValue("border-bottom-color") + ", "
+                     + c.getPropertyValue("border-left-width") + " " + c.getPropertyValue("border-left-style") + " " + c.getPropertyValue("border-left-color") + "<br>"
+                     
+        resultStr += "Width: "
+        resultStr += c.getPropertyValue("width") + "<br>";
+        
+        resultStr += "Height: "
+        resultStr += c.getPropertyValue("height") + "<br>";
+   }
+   result.innerHTML = resultStr;
+}
+</script>
+</head>
+<body onload="dumpBlockProperties()">
+<div class="ltr-text tb-block test"></div>
+<div class="ltr-text lr-block test"></div>
+<div class="ltr-text rl-block test"></div>
+<div class="rtl-text tb-block test"></div>
+<div class="rtl-text lr-block test"></div>
+<div class="rtl-text rl-block test"></div>
+<p style="clear:both" id="result"></p>
+</body>
+</html>
+
diff --git a/third_party/WebKit/LayoutTests/fast/css/logical-property-resolution.html b/third_party/WebKit/LayoutTests/fast/css/logical-property-resolution.html
index 48d1570..2257b34 100644
--- a/third_party/WebKit/LayoutTests/fast/css/logical-property-resolution.html
+++ b/third_party/WebKit/LayoutTests/fast/css/logical-property-resolution.html
@@ -22,20 +22,20 @@
 }
 
 .test {
-  -webkit-margin-before: 1px;
-  -webkit-margin-end: 2px;
-  -webkit-margin-after: 3px;
-  -webkit-margin-start: 4px;
-  -webkit-padding-before:4px;
-  -webkit-padding-end:3px;
-  -webkit-padding-after:2px;
-  -webkit-padding-start:1px;
-  -webkit-logical-width:100px;
-  -webkit-logical-height:50px;
-  -webkit-border-before: 1px solid black;
-  -webkit-border-end: 2px dotted green;
-  -webkit-border-after: 3px dashed yellow;
-  -webkit-border-start: 4px double purple;
+  margin-block-start: 1px;
+  margin-inline-end: 2px;
+  margin-block-end: 3px;
+  margin-inline-start: 4px;
+  padding-block-start:4px;
+  padding-inline-end:3px;
+  padding-block-end:2px;
+  padding-inline-start:1px;
+  inline-size:100px;
+  block-size:50px;
+  border-block-start: 1px solid black;
+  border-inline-end: 2px dotted green;
+  border-block-end: 3px dashed yellow;
+  border-inline-start: 4px double purple;
   float:left;
 }
 </style>
diff --git a/third_party/WebKit/LayoutTests/fast/css/margin-start-end-expected.txt b/third_party/WebKit/LayoutTests/fast/css/margin-start-end-expected.txt
index 121c5c33..def03d1f 100644
--- a/third_party/WebKit/LayoutTests/fast/css/margin-start-end-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/margin-start-end-expected.txt
@@ -3,18 +3,18 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS test("ltr", "-webkit-margin-start", "10px", "width") is "90px"
-PASS test("ltr", "-webkit-margin-end", "20px", "width") is "80px"
-PASS test("ltr", "-webkit-margin-start", "10px", "margin-left") is "10px"
-PASS test("ltr", "-webkit-margin-end", "20px", "margin-right") is "20px"
-PASS test("ltr", "margin-left", "10px", "-webkit-margin-start") is "10px"
-PASS test("ltr", "margin-right", "20px", "-webkit-margin-end") is "20px"
-PASS test("rtl", "-webkit-margin-start", "10px", "width") is "90px"
-PASS test("rtl", "-webkit-margin-end", "20px", "width") is "80px"
-PASS test("rtl", "-webkit-margin-start", "10px", "margin-right") is "10px"
-PASS test("rtl", "-webkit-margin-end", "20px", "margin-left") is "20px"
-PASS test("rtl", "margin-right", "10px", "-webkit-margin-start") is "10px"
-PASS test("rtl", "margin-left", "20px", "-webkit-margin-end") is "20px"
+PASS test("ltr", "margin-inline-start", "10px", "width") is "90px"
+PASS test("ltr", "margin-inline-end", "20px", "width") is "80px"
+PASS test("ltr", "margin-inline-start", "10px", "margin-left") is "10px"
+PASS test("ltr", "margin-inline-end", "20px", "margin-right") is "20px"
+PASS test("ltr", "margin-left", "10px", "margin-inline-start") is "10px"
+PASS test("ltr", "margin-right", "20px", "margin-inline-end") is "20px"
+PASS test("rtl", "margin-inline-start", "10px", "width") is "90px"
+PASS test("rtl", "margin-inline-end", "20px", "width") is "80px"
+PASS test("rtl", "margin-inline-start", "10px", "margin-right") is "10px"
+PASS test("rtl", "margin-inline-end", "20px", "margin-left") is "20px"
+PASS test("rtl", "margin-right", "10px", "margin-inline-start") is "10px"
+PASS test("rtl", "margin-left", "20px", "margin-inline-end") is "20px"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/css/padding-start-end-expected.txt b/third_party/WebKit/LayoutTests/fast/css/padding-start-end-expected.txt
index 8dce0c4..f80303c 100644
--- a/third_party/WebKit/LayoutTests/fast/css/padding-start-end-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/padding-start-end-expected.txt
@@ -3,18 +3,18 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS testWidth("ltr", "-webkit-padding-start", "10px") is 110
-PASS testWidth("ltr", "-webkit-padding-end", "20px") is 120
-PASS test("ltr", "-webkit-padding-start", "10px", "padding-left") is "10px"
-PASS test("ltr", "-webkit-padding-end", "20px", "padding-right") is "20px"
-PASS test("ltr", "padding-left", "10px", "-webkit-padding-start") is "10px"
-PASS test("ltr", "padding-right", "20px", "-webkit-padding-end") is "20px"
-PASS testWidth("rtl", "-webkit-padding-start", "10px") is 110
-PASS testWidth("rtl", "-webkit-padding-end", "20px") is 120
-PASS test("rtl", "-webkit-padding-start", "10px", "padding-right") is "10px"
-PASS test("rtl", "-webkit-padding-end", "20px", "padding-left") is "20px"
-PASS test("rtl", "padding-right", "10px", "-webkit-padding-start") is "10px"
-PASS test("rtl", "padding-left", "20px", "-webkit-padding-end") is "20px"
+PASS testWidth("ltr", "padding-inline-start", "10px") is 110
+PASS testWidth("ltr", "padding-inline-end", "20px") is 120
+PASS test("ltr", "padding-inline-start", "10px", "padding-left") is "10px"
+PASS test("ltr", "padding-inline-end", "20px", "padding-right") is "20px"
+PASS test("ltr", "padding-left", "10px", "padding-inline-start") is "10px"
+PASS test("ltr", "padding-right", "20px", "padding-inline-end") is "20px"
+PASS testWidth("rtl", "padding-inline-start", "10px") is 110
+PASS testWidth("rtl", "padding-inline-end", "20px") is 120
+PASS test("rtl", "padding-inline-start", "10px", "padding-right") is "10px"
+PASS test("rtl", "padding-inline-end", "20px", "padding-left") is "20px"
+PASS test("rtl", "padding-right", "10px", "padding-inline-start") is "10px"
+PASS test("rtl", "padding-left", "20px", "padding-inline-end") is "20px"
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/fast/css/parsing-color-quirk-expected.txt b/third_party/WebKit/LayoutTests/fast/css/parsing-color-quirk-expected.txt
index 63567ae3..c33ec5bb 100644
--- a/third_party/WebKit/LayoutTests/fast/css/parsing-color-quirk-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css/parsing-color-quirk-expected.txt
@@ -13,10 +13,10 @@
 PASS No hashless color quirk for text-shadow color
 PASS No hashless color quirk for box-shadow color
 PASS No hashless color quirk for linear-gradient colors
-PASS No hashless color quirk for -webkit-border-start-color property
-PASS No hashless color quirk for -webkit-border-end-color property
-PASS No hashless color quirk for -webkit-border-before-property
-PASS No hashless color quirk for -webkit-border-after-color property
+PASS No hashless color quirk for border-inline-start-color property
+PASS No hashless color quirk for border-inline-end-color property
+PASS No hashless color quirk for border-block-start-property
+PASS No hashless color quirk for border-block-end-color property
 PASS No hashless color quirk for -webkit-column-rule-color property
 PASS No hashless color quirk for -webkit-text-emphasis-color property
 PASS No hashless color quirk for -webkit-text-fill-color property
diff --git a/third_party/WebKit/LayoutTests/fast/css/parsing-color-quirk.html b/third_party/WebKit/LayoutTests/fast/css/parsing-color-quirk.html
index a77f9438..c0efa1e 100644
--- a/third_party/WebKit/LayoutTests/fast/css/parsing-color-quirk.html
+++ b/third_party/WebKit/LayoutTests/fast/css/parsing-color-quirk.html
@@ -14,10 +14,10 @@
 #t10 { box-shadow: 1px 1px ff0000 }
 #t11 { background-image: linear-gradient(ff0000, blue); }
 
-#t12 { -webkit-border-start-color: ff0000 }
-#t13 { -webkit-border-end-color: ff0000 }
-#t14 { -webkit-border-before-color: ff0000 }
-#t15 { -webkit-border-after-color: ff0000 }
+#t12 { border-inline-start-color: ff0000 }
+#t13 { border-inline-end-color: ff0000 }
+#t14 { border-block-start-color: ff0000 }
+#t15 { border-block-end-color: ff0000 }
 
 #t16 { -webkit-column-rule-color: ff0000 }
 
@@ -113,20 +113,20 @@
 }, "No hashless color quirk for linear-gradient colors");
 
 test(function(){
-    assert_equals(sheet.cssRules[11].style.WebkitBorderStartColor, "");
-}, "No hashless color quirk for -webkit-border-start-color property");
+    assert_equals(sheet.cssRules[11].style.borderInlineStartColor, "");
+}, "No hashless color quirk for border-inline-start-color property");
 
 test(function(){
-    assert_equals(sheet.cssRules[12].style.WebkitBorderEndColor, "");
-}, "No hashless color quirk for -webkit-border-end-color property");
+    assert_equals(sheet.cssRules[12].style.borderInlineEndColor, "");
+}, "No hashless color quirk for border-inline-end-color property");
 
 test(function(){
-    assert_equals(sheet.cssRules[13].style.WebkitBorderBeforeColor, "");
-}, "No hashless color quirk for -webkit-border-before-property");
+    assert_equals(sheet.cssRules[13].style.borderBlockStartColor, "");
+}, "No hashless color quirk for border-block-start-property");
 
 test(function(){
-    assert_equals(sheet.cssRules[14].style.WebkitBorderAfterColor, "");
-}, "No hashless color quirk for -webkit-border-after-color property");
+    assert_equals(sheet.cssRules[14].style.borderBlockEndColor, "");
+}, "No hashless color quirk for border-block-end-color property");
 
 test(function(){
     assert_equals(sheet.cssRules[15].style.WebkitColumnRuleColor, "");
diff --git a/third_party/WebKit/LayoutTests/fast/css/script-tests/border-start-end.js b/third_party/WebKit/LayoutTests/fast/css/script-tests/border-start-end.js
index 0ed26443..ddc6d672 100644
--- a/third_party/WebKit/LayoutTests/fast/css/script-tests/border-start-end.js
+++ b/third_party/WebKit/LayoutTests/fast/css/script-tests/border-start-end.js
@@ -30,43 +30,43 @@
     return result;
 }
 
-shouldBe('testWidth("ltr", "-webkit-border-start-width: 10px; -webkit-border-start-style: solid")', '110');
-shouldBe('testWidth("ltr", "-webkit-border-end-width: 20px; -webkit-border-end-style:  solid")', '120');
-shouldBe('testWidth("rtl", "-webkit-border-start-width: 10px; -webkit-border-start-style:  solid")', '110');
-shouldBe('testWidth("rtl", "-webkit-border-end-width: 20px; -webkit-border-end-style:  solid")', '120');
+shouldBe('testWidth("ltr", "border-inline-start-width: 10px; border-inline-start-style: solid")', '110');
+shouldBe('testWidth("ltr", "border-inline-end-width: 20px; border-inline-end-style:  solid")', '120');
+shouldBe('testWidth("rtl", "border-inline-start-width: 10px; border-inline-start-style:  solid")', '110');
+shouldBe('testWidth("rtl", "border-inline-end-width: 20px; border-inline-end-style:  solid")', '120');
 
-testSame('ltr', '-webkit-border-start-color', 'border-left-color', 'rgb(255, 0, 0)');
-testSame('ltr', '-webkit-border-end-color', 'border-right-color', 'rgb(255, 0, 0)');
-testSame('rtl', '-webkit-border-start-color', 'border-right-color', 'rgb(255, 0, 0)');
-testSame('rtl', '-webkit-border-end-color', 'border-left-color', 'rgb(255, 0, 0)');
+testSame('ltr', 'border-inline-start-color', 'border-left-color', 'rgb(255, 0, 0)');
+testSame('ltr', 'border-inline-end-color', 'border-right-color', 'rgb(255, 0, 0)');
+testSame('rtl', 'border-inline-start-color', 'border-right-color', 'rgb(255, 0, 0)');
+testSame('rtl', 'border-inline-end-color', 'border-left-color', 'rgb(255, 0, 0)');
 
-testSame('ltr', '-webkit-border-start-style', 'border-left-style', 'dotted');
-testSame('ltr', '-webkit-border-end-style', 'border-right-style', 'dotted');
-testSame('rtl', '-webkit-border-start-style', 'border-right-style', 'dotted');
-testSame('rtl', '-webkit-border-end-style', 'border-left-style', 'dotted');
+testSame('ltr', 'border-inline-start-style', 'border-left-style', 'dotted');
+testSame('ltr', 'border-inline-end-style', 'border-right-style', 'dotted');
+testSame('rtl', 'border-inline-start-style', 'border-right-style', 'dotted');
+testSame('rtl', 'border-inline-end-style', 'border-left-style', 'dotted');
 
-shouldBeEqualToString('test("ltr", "-webkit-border-start-width: 10px; -webkit-border-start-style: solid", "border-left-width")', '10px');
-shouldBeEqualToString('test("ltr", "-webkit-border-end-width: 10px; -webkit-border-end-style: solid", "border-right-width")', '10px');
-shouldBeEqualToString('test("rtl", "-webkit-border-start-width: 10px; -webkit-border-start-style: solid", "border-right-width")', '10px');
-shouldBeEqualToString('test("rtl", "-webkit-border-end-width: 10px; -webkit-border-end-style: solid", "border-left-width")', '10px');
+shouldBeEqualToString('test("ltr", "border-inline-start-width: 10px; border-inline-start-style: solid", "border-left-width")', '10px');
+shouldBeEqualToString('test("ltr", "border-inline-end-width: 10px; border-inline-end-style: solid", "border-right-width")', '10px');
+shouldBeEqualToString('test("rtl", "border-inline-start-width: 10px; border-inline-start-style: solid", "border-right-width")', '10px');
+shouldBeEqualToString('test("rtl", "border-inline-end-width: 10px; border-inline-end-style: solid", "border-left-width")', '10px');
 
-shouldBeEqualToString('test("ltr", "border-left: 10px solid", "-webkit-border-start-width")', '10px');
-shouldBeEqualToString('test("ltr", "border-right: 10px solid", "-webkit-border-end-width")', '10px');
-shouldBeEqualToString('test("rtl", "border-left: 10px solid", "-webkit-border-end-width")', '10px');
-shouldBeEqualToString('test("rtl", "border-right: 10px solid", "-webkit-border-start-width")', '10px');
+shouldBeEqualToString('test("ltr", "border-left: 10px solid", "border-inline-start-width")', '10px');
+shouldBeEqualToString('test("ltr", "border-right: 10px solid", "border-inline-end-width")', '10px');
+shouldBeEqualToString('test("rtl", "border-left: 10px solid", "border-inline-end-width")', '10px');
+shouldBeEqualToString('test("rtl", "border-right: 10px solid", "border-inline-start-width")', '10px');
 
-shouldBeEqualToString('test("ltr", "-webkit-border-start: 10px solid red", "border-left-color")', 'rgb(255, 0, 0)');
-shouldBeEqualToString('test("ltr", "-webkit-border-start: 10px solid red", "border-left-style")', 'solid');
-shouldBeEqualToString('test("ltr", "-webkit-border-start: 10px solid red", "border-left-width")', '10px');
+shouldBeEqualToString('test("ltr", "border-inline-start: 10px solid red", "border-left-color")', 'rgb(255, 0, 0)');
+shouldBeEqualToString('test("ltr", "border-inline-start: 10px solid red", "border-left-style")', 'solid');
+shouldBeEqualToString('test("ltr", "border-inline-start: 10px solid red", "border-left-width")', '10px');
 
-shouldBeEqualToString('test("rtl", "-webkit-border-start: 10px solid red", "border-right-color")', 'rgb(255, 0, 0)');
-shouldBeEqualToString('test("rtl", "-webkit-border-start: 10px solid red", "border-right-style")', 'solid');
-shouldBeEqualToString('test("rtl", "-webkit-border-start: 10px solid red", "border-right-width")', '10px');
+shouldBeEqualToString('test("rtl", "border-inline-start: 10px solid red", "border-right-color")', 'rgb(255, 0, 0)');
+shouldBeEqualToString('test("rtl", "border-inline-start: 10px solid red", "border-right-style")', 'solid');
+shouldBeEqualToString('test("rtl", "border-inline-start: 10px solid red", "border-right-width")', '10px');
 
-shouldBeEqualToString('test("ltr", "-webkit-border-end: 10px solid red", "border-right-color")', 'rgb(255, 0, 0)');
-shouldBeEqualToString('test("ltr", "-webkit-border-end: 10px solid red", "border-right-style")', 'solid');
-shouldBeEqualToString('test("ltr", "-webkit-border-end: 10px solid red", "border-right-width")', '10px');
+shouldBeEqualToString('test("ltr", "border-inline-end: 10px solid red", "border-right-color")', 'rgb(255, 0, 0)');
+shouldBeEqualToString('test("ltr", "border-inline-end: 10px solid red", "border-right-style")', 'solid');
+shouldBeEqualToString('test("ltr", "border-inline-end: 10px solid red", "border-right-width")', '10px');
 
-shouldBeEqualToString('test("rtl", "-webkit-border-end: 10px solid red", "border-left-color")', 'rgb(255, 0, 0)');
-shouldBeEqualToString('test("rtl", "-webkit-border-end: 10px solid red", "border-left-style")', 'solid');
-shouldBeEqualToString('test("rtl", "-webkit-border-end: 10px solid red", "border-left-width")', '10px');
+shouldBeEqualToString('test("rtl", "border-inline-end: 10px solid red", "border-left-color")', 'rgb(255, 0, 0)');
+shouldBeEqualToString('test("rtl", "border-inline-end: 10px solid red", "border-left-style")', 'solid');
+shouldBeEqualToString('test("rtl", "border-inline-end: 10px solid red", "border-left-width")', '10px');
diff --git a/third_party/WebKit/LayoutTests/fast/css/script-tests/margin-start-end.js b/third_party/WebKit/LayoutTests/fast/css/script-tests/margin-start-end.js
index 970f1ef..df26c3c 100644
--- a/third_party/WebKit/LayoutTests/fast/css/script-tests/margin-start-end.js
+++ b/third_party/WebKit/LayoutTests/fast/css/script-tests/margin-start-end.js
@@ -17,16 +17,16 @@
     return result;
 }
 
-shouldBeEqualToString('test("ltr", "-webkit-margin-start", "10px", "width")', '90px');
-shouldBeEqualToString('test("ltr", "-webkit-margin-end", "20px", "width")', '80px');
-shouldBeEqualToString('test("ltr", "-webkit-margin-start", "10px", "margin-left")', '10px');
-shouldBeEqualToString('test("ltr", "-webkit-margin-end", "20px", "margin-right")', '20px');
-shouldBeEqualToString('test("ltr", "margin-left", "10px", "-webkit-margin-start")', '10px');
-shouldBeEqualToString('test("ltr", "margin-right", "20px", "-webkit-margin-end")', '20px');
+shouldBeEqualToString('test("ltr", "margin-inline-start", "10px", "width")', '90px');
+shouldBeEqualToString('test("ltr", "margin-inline-end", "20px", "width")', '80px');
+shouldBeEqualToString('test("ltr", "margin-inline-start", "10px", "margin-left")', '10px');
+shouldBeEqualToString('test("ltr", "margin-inline-end", "20px", "margin-right")', '20px');
+shouldBeEqualToString('test("ltr", "margin-left", "10px", "margin-inline-start")', '10px');
+shouldBeEqualToString('test("ltr", "margin-right", "20px", "margin-inline-end")', '20px');
 
-shouldBeEqualToString('test("rtl", "-webkit-margin-start", "10px", "width")', '90px');
-shouldBeEqualToString('test("rtl", "-webkit-margin-end", "20px", "width")', '80px');
-shouldBeEqualToString('test("rtl", "-webkit-margin-start", "10px", "margin-right")', '10px');
-shouldBeEqualToString('test("rtl", "-webkit-margin-end", "20px", "margin-left")', '20px');
-shouldBeEqualToString('test("rtl", "margin-right", "10px", "-webkit-margin-start")', '10px');
-shouldBeEqualToString('test("rtl", "margin-left", "20px", "-webkit-margin-end")', '20px');
+shouldBeEqualToString('test("rtl", "margin-inline-start", "10px", "width")', '90px');
+shouldBeEqualToString('test("rtl", "margin-inline-end", "20px", "width")', '80px');
+shouldBeEqualToString('test("rtl", "margin-inline-start", "10px", "margin-right")', '10px');
+shouldBeEqualToString('test("rtl", "margin-inline-end", "20px", "margin-left")', '20px');
+shouldBeEqualToString('test("rtl", "margin-right", "10px", "margin-inline-start")', '10px');
+shouldBeEqualToString('test("rtl", "margin-left", "20px", "margin-inline-end")', '20px');
diff --git a/third_party/WebKit/LayoutTests/fast/css/script-tests/padding-start-end.js b/third_party/WebKit/LayoutTests/fast/css/script-tests/padding-start-end.js
index 91c07b3..0e2bd0e4 100644
--- a/third_party/WebKit/LayoutTests/fast/css/script-tests/padding-start-end.js
+++ b/third_party/WebKit/LayoutTests/fast/css/script-tests/padding-start-end.js
@@ -24,16 +24,16 @@
     return result;
 }
 
-shouldBe('testWidth("ltr", "-webkit-padding-start", "10px")', '110');
-shouldBe('testWidth("ltr", "-webkit-padding-end", "20px")', '120');
-shouldBeEqualToString('test("ltr", "-webkit-padding-start", "10px", "padding-left")', '10px');
-shouldBeEqualToString('test("ltr", "-webkit-padding-end", "20px", "padding-right")', '20px');
-shouldBeEqualToString('test("ltr", "padding-left", "10px", "-webkit-padding-start")', '10px');
-shouldBeEqualToString('test("ltr", "padding-right", "20px", "-webkit-padding-end")', '20px');
+shouldBe('testWidth("ltr", "padding-inline-start", "10px")', '110');
+shouldBe('testWidth("ltr", "padding-inline-end", "20px")', '120');
+shouldBeEqualToString('test("ltr", "padding-inline-start", "10px", "padding-left")', '10px');
+shouldBeEqualToString('test("ltr", "padding-inline-end", "20px", "padding-right")', '20px');
+shouldBeEqualToString('test("ltr", "padding-left", "10px", "padding-inline-start")', '10px');
+shouldBeEqualToString('test("ltr", "padding-right", "20px", "padding-inline-end")', '20px');
 
-shouldBe('testWidth("rtl", "-webkit-padding-start", "10px")', '110');
-shouldBe('testWidth("rtl", "-webkit-padding-end", "20px")', '120');
-shouldBeEqualToString('test("rtl", "-webkit-padding-start", "10px", "padding-right")', '10px');
-shouldBeEqualToString('test("rtl", "-webkit-padding-end", "20px", "padding-left")', '20px');
-shouldBeEqualToString('test("rtl", "padding-right", "10px", "-webkit-padding-start")', '10px');
-shouldBeEqualToString('test("rtl", "padding-left", "20px", "-webkit-padding-end")', '20px');
+shouldBe('testWidth("rtl", "padding-inline-start", "10px")', '110');
+shouldBe('testWidth("rtl", "padding-inline-end", "20px")', '120');
+shouldBeEqualToString('test("rtl", "padding-inline-start", "10px", "padding-right")', '10px');
+shouldBeEqualToString('test("rtl", "padding-inline-end", "20px", "padding-left")', '20px');
+shouldBeEqualToString('test("rtl", "padding-right", "10px", "padding-inline-start")', '10px');
+shouldBeEqualToString('test("rtl", "padding-left", "20px", "padding-inline-end")', '20px');
diff --git a/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-1.html b/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-1.html
index 94fcfd38..70eaf2e 100644
--- a/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-1.html
+++ b/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-1.html
@@ -22,21 +22,21 @@
     <p>This test the style is not copied from the wrong source when the direction is defined.</p>
     <!-- The inline style strings must be strictly equal. Each tested div must also match the exact same set of rules. -->
     <div class="ltr">
-        <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+        <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         <div>
-            <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+            <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         </div>
     </div>
     <div class="rtl">
-        <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+        <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         <div>
-            <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+            <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         </div>
     </div>
     <div class="default">
-        <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+        <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         <div>
-            <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+            <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         </div>
     </div>
 </body>
diff --git a/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-2.html b/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-2.html
index fa774d49..6d7db5d 100644
--- a/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-2.html
+++ b/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-2.html
@@ -22,21 +22,21 @@
     <p>This test the style is not copied from the wrong source when the direction is defined.</p>
     <!-- The inline style strings must be strictly equal. Each tested div must also match the exact same set of rules. -->
     <div class="rtl">
-        <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+        <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         <div>
-            <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+            <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         </div>
     </div>
     <div class="ltr">
-        <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+        <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         <div>
-            <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+            <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         </div>
     </div>
     <div class="default">
-        <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+        <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         <div>
-            <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+            <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         </div>
     </div>
 </body>
diff --git a/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-3.html b/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-3.html
index 121316e..3a0dd3ed 100644
--- a/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-3.html
+++ b/third_party/WebKit/LayoutTests/fast/css/style-resolver-cache-direction-3.html
@@ -22,21 +22,21 @@
     <p>This test the style is not copied from the wrong source when the direction is defined.</p>
     <!-- The inline style strings must be strictly equal. Each tested div must also match the exact same set of rules. -->
     <div class="default">
-        <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+        <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         <div>
-            <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+            <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         </div>
     </div>
     <div class="ltr">
-        <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+        <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         <div>
-            <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+            <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         </div>
     </div>
     <div class="rtl">
-        <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+        <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         <div>
-            <div style="height: 25px; width: 50px; background-color: red; -webkit-margin-start: 200px; -moz-margin-start: 200px;"></div>
+            <div style="height: 25px; width: 50px; background-color: red; margin-inline-start: 200px; -moz-margin-start: 200px;"></div>
         </div>
     </div>
 </body>
diff --git a/third_party/WebKit/LayoutTests/fast/css/window-internals-isCSSPropertyUseCounted.html b/third_party/WebKit/LayoutTests/fast/css/window-internals-isCSSPropertyUseCounted.html
index 65356b6..a47559cb 100644
--- a/third_party/WebKit/LayoutTests/fast/css/window-internals-isCSSPropertyUseCounted.html
+++ b/third_party/WebKit/LayoutTests/fast/css/window-internals-isCSSPropertyUseCounted.html
@@ -11,7 +11,7 @@
 	opacity: invalid value;
 	border: black solid 5px;
 	border-left: thick dashed lightgreen;
-	-webkit-border-end-color: pink;
+	border-inline-end-color: pink;
 }
 #target2 {
   -webkit-align-content: space-between;
@@ -28,7 +28,7 @@
 	assert_true(internals.isCSSPropertyUseCounted(document, "background-color"));
 	assert_true(internals.isCSSPropertyUseCounted(document, "padding-bottom"));
 	assert_true(internals.isCSSPropertyUseCounted(document, "padding-left"));
-	assert_true(internals.isCSSPropertyUseCounted(document, "-webkit-border-end-color"));
+	assert_true(internals.isCSSPropertyUseCounted(document, "border-inline-end-color"));
 }, "Test setting and reading css properties");
 
 test(function() {
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-before-text-node.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-before-text-node.html
index 81630fba..4ef84a0 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-before-text-node.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-before-text-node.html
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="../../../resources/js-test.js"></script>
 <style>
-.testDiv {-webkit-border-start: 5px solid green; -webkit-border-end: 5px solid red; }
+.testDiv {border-inline-start: 5px solid green; border-inline-end: 5px solid red; }
 </style>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-child-node.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-child-node.html
index 3b20976..65d5c43 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-child-node.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-child-node.html
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="../../../resources/js-test.js"></script>
 <style>
-.testDiv {-webkit-border-start: 5px solid green; -webkit-border-end: 5px solid red; }
+.testDiv {border-inline-start: 5px solid green; border-inline-end: 5px solid red; }
 </style>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-text-form-control.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-text-form-control.html
index 65586c9..9838e1c 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-text-form-control.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-text-form-control.html
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="../../../resources/js-test.js"></script>
 <style>
-.testElement {-webkit-border-start: 5px solid green; -webkit-border-end: 5px solid red; }
+.testElement {border-inline-start: 5px solid green; border-inline-end: 5px solid red; }
 </style>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-text.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-text.html
index 05729e1..a7e1d2c 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-text.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-change-text.html
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="../../../resources/js-test.js"></script>
 <style>
-.testDiv {-webkit-border-start: 5px solid green; -webkit-border-end: 5px solid red; }
+.testDiv {border-inline-start: 5px solid green; border-inline-end: 5px solid red; }
 </style>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-children.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-children.html
index 9017f02..b66a6ba3 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-children.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-children.html
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="../../../resources/js-test.js"></script>
 <style>
-.testDiv {-webkit-border-start: 5px solid green; -webkit-border-end: 5px solid red; }
+.testDiv {border-inline-start: 5px solid green; border-inline-end: 5px solid red; }
 </style>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-remove-add-children.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-remove-add-children.html
index 757c2d4..5fa80e17 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-remove-add-children.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-remove-add-children.html
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="../../../resources/js-test.js"></script>
 <style>
-.testDiv {-webkit-border-start: 5px solid green; -webkit-border-end: 5px solid red; }
+.testDiv {border-inline-start: 5px solid green; border-inline-end: 5px solid red; }
 </style>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-text-form-control-child.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-text-form-control-child.html
index 5d7f9c8..6a1f22b 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-text-form-control-child.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-text-form-control-child.html
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="../../../resources/js-test.js"></script>
 <style>
-.testElement {-webkit-border-start: 5px solid green; -webkit-border-end: 5px solid red; }
+.testElement {border-inline-start: 5px solid green; border-inline-end: 5px solid red; }
 </style>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-text-form-control.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-text-form-control.html
index 429174e1f..0d08bd8 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-text-form-control.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto-text-form-control.html
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="../../../resources/js-test.js"></script>
 <style>
-.testElement {-webkit-border-start: 5px solid green; -webkit-border-end: 5px solid red; }
+.testElement {border-inline-start: 5px solid green; border-inline-end: 5px solid red; }
 </style>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto.html
index 1c419af..3a3de45 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-auto.html
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="../../../resources/js-test.js"></script>
 <style>
-.testDiv {-webkit-border-start: 5px solid green; -webkit-border-end: 5px solid red; }
+.testDiv {border-inline-start: 5px solid green; border-inline-end: 5px solid red; }
 </style>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-value-change.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-value-change.html
index 10a12b1..8df849a 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-value-change.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLElement/attr-dir-value-change.html
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <script src="../../../resources/js-test.js"></script>
 <style>
-.testDiv {-webkit-border-start: 5px solid green; -webkit-border-end: 5px solid red; }
+.testDiv {border-inline-start: 5px solid green; border-inline-end: 5px solid red; }
 </style>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/attr-dir-inherit.html b/third_party/WebKit/LayoutTests/fast/dom/shadow/attr-dir-inherit.html
index 608067b..477d17a 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/shadow/attr-dir-inherit.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/shadow/attr-dir-inherit.html
@@ -115,8 +115,8 @@
 }, "dir=auto the first character in the distributed content with multiple levels of shadow roots");
 
 function assert_direction(description, elementToTest) {
-    elementToTest.style.webkitBorderStart = "5px solid green";
-    elementToTest.style.webkitBorderEnd = "5px solid red";
+    elementToTest.style.borderInlineStart = "5px solid green";
+    elementToTest.style.borderInlineEnd = "5px solid red";
     var actualColor = document.defaultView.getComputedStyle(elementToTest).getPropertyValue("border-right-color");
     var dirExpected = elementToTest.dataset.dirExpected;
     switch (dirExpected) {
diff --git a/third_party/WebKit/LayoutTests/fast/dynamic/crash-paint-no-documentElement-renderer-expected.txt b/third_party/WebKit/LayoutTests/fast/dynamic/crash-paint-no-documentElement-renderer-expected.txt
index ff24d7c..24ab3b4 100644
--- a/third_party/WebKit/LayoutTests/fast/dynamic/crash-paint-no-documentElement-renderer-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dynamic/crash-paint-no-documentElement-renderer-expected.txt
@@ -1 +1 @@
-*{-webkit-border-before-style:groove}
+*{border-block-start-style:groove}
diff --git a/third_party/WebKit/LayoutTests/fast/dynamic/crash-paint-no-documentElement-renderer.html-disabled b/third_party/WebKit/LayoutTests/fast/dynamic/crash-paint-no-documentElement-renderer.html-disabled
index 080e4c4..37c8660 100644
--- a/third_party/WebKit/LayoutTests/fast/dynamic/crash-paint-no-documentElement-renderer.html-disabled
+++ b/third_party/WebKit/LayoutTests/fast/dynamic/crash-paint-no-documentElement-renderer.html-disabled
@@ -11,7 +11,7 @@
         document.open();
         var oUElement = document.createElement("U");
         oUElement.hidden=true;
-        oUElement.innerHTML="<style>*{-webkit-border-before-style:groove}";
+        oUElement.innerHTML="<style>*{border-block-start-style:groove}";
         document.appendChild(oUElement);
         document.close();
     }
diff --git a/third_party/WebKit/LayoutTests/fast/html/layout-runs-and-floats-crash.html b/third_party/WebKit/LayoutTests/fast/html/layout-runs-and-floats-crash.html
index 9d35e5a..6ab355e 100644
--- a/third_party/WebKit/LayoutTests/fast/html/layout-runs-and-floats-crash.html
+++ b/third_party/WebKit/LayoutTests/fast/html/layout-runs-and-floats-crash.html
@@ -1,7 +1,7 @@
 <style>
 * {
     -webkit-columns: 10ex;
-    -webkit-margin-after: 60;
+    margin-block-end: 60;
 }
 </style>
 <main></main>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/hit-test-end-of-column-with-line-height.html b/third_party/WebKit/LayoutTests/fast/multicol/hit-test-end-of-column-with-line-height.html
index aaec74f5a..49b6f63 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/hit-test-end-of-column-with-line-height.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/hit-test-end-of-column-with-line-height.html
@@ -6,8 +6,8 @@
     columns: 2;
     column-gap: 0;
     column-fill: auto;
-    -webkit-logical-width: 400px;
-    -webkit-logical-height: 80px;
+    inline-size: 400px;
+    block-size: 80px;
     font: 20px Ahem;
     line-height: 2;
 ">Lorem ipsum dolor sit amet</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-lr-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-lr-expected.html
index 3c360e6..b9253cc 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-lr-expected.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-lr-expected.html
@@ -7,9 +7,9 @@
         <p>The word PASS should be seen below.</p>
         <div style="position:relative; width:30em; background:black;">
             <div style="width:20em; height:20em; -webkit-writing-mode:vertical-lr;">
-                <div style="-webkit-logical-height:6em; line-height:2em; background:cyan;">
+                <div style="block-size:6em; line-height:2em; background:cyan;">
                     <br>
-                    <span style="-webkit-margin-start:5em;">&nbsp;PASS</span>
+                    <span style="margin-inline-start:5em;">&nbsp;PASS</span>
                 </div>
             </div>
         </div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-lr.html b/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-lr.html
index 62cf792..dc0c86e 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-lr.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-lr.html
@@ -22,7 +22,7 @@
         <div style="position:relative; width:30em; background:black;">
             <div id="hider" style="position:absolute; z-index:1; top:5.1em; left:2em; width:3em; height:3em; background:red;"></div>
             <div style="width:20em; height:20em; -webkit-writing-mode:vertical-lr;">
-                <div style="-webkit-columns:4; -webkit-column-gap:0; columns:4; column-fill:auto; column-gap:0; orphans:1; widows:1; -webkit-logical-height:6em; line-height:2em; background:cyan;">
+                <div style="-webkit-columns:4; -webkit-column-gap:0; columns:4; column-fill:auto; column-gap:0; orphans:1; widows:1; block-size:6em; line-height:2em; background:cyan;">
                     <br>
                     <br>
                     <br>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-rl-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-rl-expected.html
index 4f86922..76e7190 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-rl-expected.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-rl-expected.html
@@ -7,9 +7,9 @@
         <p>The word PASS should be seen below.</p>
         <div style="position:relative; width:30em; background:black;">
             <div style="width:20em; height:20em; -webkit-writing-mode:vertical-rl;">
-                <div style="-webkit-logical-height:6em; line-height:2em; background:cyan;">
+                <div style="block-size:6em; line-height:2em; background:cyan;">
                     <br>
-                    <span style="-webkit-margin-start:5em;">&nbsp;PASS</span>
+                    <span style="margin-inline-start:5em;">&nbsp;PASS</span>
                 </div>
             </div>
         </div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-rl.html b/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-rl.html
index f1b96d8..950c20af 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-rl.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/newmulticol/hide-box-vertical-rl.html
@@ -22,7 +22,7 @@
         <div style="position:relative; width:30em; background:black;">
             <div id="hider" style="position:absolute; z-index:1; top:5.1em; right:12em; width:3em; height:3em; background:red;"></div>
             <div style="width:20em; height:20em; -webkit-writing-mode:vertical-rl;">
-                <div style="-webkit-columns:4; -webkit-column-gap:0; columns:4; column-fill:auto; column-gap:0; orphans:1; widows:1; -webkit-logical-height:6em; line-height:2em; background:cyan;">
+                <div style="-webkit-columns:4; -webkit-column-gap:0; columns:4; column-fill:auto; column-gap:0; orphans:1; widows:1; block-size:6em; line-height:2em; background:cyan;">
                     <br>
                     <br>
                     <br>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/overflow-content-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/overflow-content-expected.html
index 1fb1979e..11ce40d 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/overflow-content-expected.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/overflow-content-expected.html
@@ -1,8 +1,8 @@
 <style>
     div.test {
-        -webkit-logical-width: 100px;
-        -webkit-border-before: 5px solid;
-        -webkit-border-after: 15px solid;
+        inline-size: 100px;
+        border-block-start: 5px solid;
+        border-block-end: 15px solid;
         -webkit-column-count: 2;
         -webkit-column-gap: 0;
         column-count: 2;
@@ -11,17 +11,17 @@
         background-color: lightblue;
     }
     div.container {
-        -webkit-logical-height: 120px;
+        block-size: 120px;
         background-color: red;
-        -webkit-logical-width: 100px;
-        -webkit-margin-after: 8px;
+        inline-size: 100px;
+        margin-block-end: 8px;
     }
 </style>
 <div>
     <div class="container">
-        <div class="test" style="-webkit-logical-height: 100px;">
+        <div class="test" style="block-size: 100px;">
             <div>
-                <div style="-webkit-logical-height: 300px; background-color: yellow;"></div>
+                <div style="block-size: 300px; background-color: yellow;"></div>
             </div>
         </div>
     </div>
@@ -29,16 +29,16 @@
     <div class="container">
         <div class="test">
             <div>
-                <div style="-webkit-logical-height: 200px; background-color: yellow;"></div>
+                <div style="block-size: 200px; background-color: yellow;"></div>
             </div>
         </div>
     </div>
 
     <div class="container">
         <div class="test">
-            <div style="-webkit-logical-height: 10px;"></div>
+            <div style="block-size: 10px;"></div>
             <div style="-webkit-column-break-before: always;">
-                <div style="-webkit-logical-height: 100px; background-color: yellow;"></div>
+                <div style="block-size: 100px; background-color: yellow;"></div>
             </div>
             <div></div>
         </div>
@@ -46,9 +46,9 @@
 </div>
 <div style="-webkit-writing-mode: vertical-rl;">
     <div class="container">
-        <div class="test" style="-webkit-logical-height: 100px;">
+        <div class="test" style="block-size: 100px;">
             <div>
-                <div style="-webkit-logical-height: 300px; background-color: yellow;"></div>
+                <div style="block-size: 300px; background-color: yellow;"></div>
             </div>
         </div>
     </div>
@@ -56,16 +56,16 @@
     <div class="container">
         <div class="test">
             <div>
-                <div style="-webkit-logical-height: 200px; background-color: yellow;"></div>
+                <div style="block-size: 200px; background-color: yellow;"></div>
             </div>
         </div>
     </div>
 
     <div class="container">
         <div class="test">
-            <div style="-webkit-logical-height: 10px;"></div>
+            <div style="block-size: 10px;"></div>
             <div style="-webkit-column-break-before: always;">
-                <div style="-webkit-logical-height: 100px; background-color: yellow;"></div>
+                <div style="block-size: 100px; background-color: yellow;"></div>
             </div>
             <div></div>
         </div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/overflow-content.html b/third_party/WebKit/LayoutTests/fast/multicol/overflow-content.html
index fc5de7b..65d090d 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/overflow-content.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/overflow-content.html
@@ -1,8 +1,8 @@
 <style>
     div.test {
-        -webkit-logical-width: 100px;
-        -webkit-border-before: 5px solid;
-        -webkit-border-after: 15px solid;
+        inline-size: 100px;
+        border-block-start: 5px solid;
+        border-block-end: 15px solid;
         -webkit-column-count: 2;
         -webkit-column-gap: 0;
         column-count: 2;
@@ -11,63 +11,63 @@
         background-color: lightblue;
     }
     div.container {
-        -webkit-logical-height: 120px;
+        block-size: 120px;
         background-color: red;
-        -webkit-logical-width: 100px;
-        -webkit-margin-after: 8px;
+        inline-size: 100px;
+        margin-block-end: 8px;
     }
 </style>
 <div>
     <div class="container">
-        <div class="test" style="-webkit-logical-height: 100px;">
-            <div style="-webkit-logical-height: 20px;">
-                <div style="-webkit-logical-height: 300px; background-color: yellow;"></div>
+        <div class="test" style="block-size: 100px;">
+            <div style="block-size: 20px;">
+                <div style="block-size: 300px; background-color: yellow;"></div>
             </div>
         </div>
     </div>
 
     <div class="container">
         <div class="test">
-            <div style="-webkit-logical-height: 20px;">
-                <div style="-webkit-logical-height: 200px; background-color: yellow;"></div>
+            <div style="block-size: 20px;">
+                <div style="block-size: 200px; background-color: yellow;"></div>
             </div>
         </div>
     </div>
 
     <div class="container">
         <div class="test">
-            <div style="-webkit-logical-height: 10px;"></div>
-            <div style="-webkit-column-break-before: always; -webkit-logical-height: 10px;">
-                <div style="-webkit-logical-height: 100px; background-color: yellow;"></div>
+            <div style="block-size: 10px;"></div>
+            <div style="-webkit-column-break-before: always; block-size: 10px;">
+                <div style="block-size: 100px; background-color: yellow;"></div>
             </div>
-            <div style="-webkit-logical-height: 20px;"></div>
+            <div style="block-size: 20px;"></div>
         </div>
     </div>
 </div>
 <div style="-webkit-writing-mode: vertical-rl;">
     <div class="container">
-        <div class="test" style="-webkit-logical-height: 100px;">
-            <div style="-webkit-logical-height: 20px;">
-                <div style="-webkit-logical-height: 300px; background-color: yellow;"></div>
+        <div class="test" style="block-size: 100px;">
+            <div style="block-size: 20px;">
+                <div style="block-size: 300px; background-color: yellow;"></div>
             </div>
         </div>
     </div>
 
     <div class="container">
         <div class="test">
-            <div style="-webkit-logical-height: 20px;">
-                <div style="-webkit-logical-height: 200px; background-color: yellow;"></div>
+            <div style="block-size: 20px;">
+                <div style="block-size: 200px; background-color: yellow;"></div>
             </div>
         </div>
     </div>
 
     <div class="container">
         <div class="test">
-            <div style="-webkit-logical-height: 10px;"></div>
-            <div style="-webkit-column-break-before: always; -webkit-logical-height: 10px;">
-                <div style="-webkit-logical-height: 100px; background-color: yellow;"></div>
+            <div style="block-size: 10px;"></div>
+            <div style="-webkit-column-break-before: always; block-size: 10px;">
+                <div style="block-size: 100px; background-color: yellow;"></div>
             </div>
-            <div style="-webkit-logical-height: 20px;"></div>
+            <div style="block-size: 20px;"></div>
         </div>
     </div>
 </div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/pageLogicalOffset-vertical.html b/third_party/WebKit/LayoutTests/fast/multicol/pageLogicalOffset-vertical.html
index c3fe08b..2c53bfbb3 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/pageLogicalOffset-vertical.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/pageLogicalOffset-vertical.html
@@ -12,7 +12,7 @@
     }
 
     .margin-before {
-        -webkit-margin-before: 30px;
+        margin-block-start: 30px;
         width: 60px;
     }
 
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/float-truncation.html b/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/float-truncation.html
index 6e96866..20f1643 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/float-truncation.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/float-truncation.html
@@ -19,7 +19,7 @@
     div.float {
         float: left;
         height: 51px;
-        -webkit-margin-before: 5px;
+        margin-block-start: 5px;
         color: silver;
     }
 </style>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/rules-with-border-before.html b/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/rules-with-border-before.html
index 9a364acf..9421a96 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/rules-with-border-before.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/vertical-lr/rules-with-border-before.html
@@ -9,8 +9,8 @@
         -webkit-column-gap: 50px;
     }
 
-    .before { -webkit-border-before: 50px solid blue; }
-    .after { -webkit-border-after: 50px solid blue; }
+    .before { border-block-start: 50px solid blue; }
+    .after { border-block-end: 50px solid blue; }
 
     .test div { width: 200px; }
 </style>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/float-truncation.html b/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/float-truncation.html
index 4ac1f46..f82e8759 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/float-truncation.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/float-truncation.html
@@ -20,7 +20,7 @@
     div.float {
         float: left;
         height: 51px;
-        -webkit-margin-before: 5px;
+        margin-block-start: 5px;
         color: silver;
     }
 </style>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/rules-with-border-before.html b/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/rules-with-border-before.html
index e5b536d..900714f 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/rules-with-border-before.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/vertical-rl/rules-with-border-before.html
@@ -9,8 +9,8 @@
         -webkit-column-gap: 50px;
     }
 
-    .before { -webkit-border-before: 50px solid blue; }
-    .after { -webkit-border-after: 50px solid blue; }
+    .before { border-block-start: 50px solid blue; }
+    .after { border-block-end: 50px solid blue; }
 
     .test div { width: 200px; }
 </style>
diff --git a/third_party/WebKit/LayoutTests/fast/ruby/position-after.html b/third_party/WebKit/LayoutTests/fast/ruby/position-after.html
index 5b32ff0..df6e570f 100644
--- a/third_party/WebKit/LayoutTests/fast/ruby/position-after.html
+++ b/third_party/WebKit/LayoutTests/fast/ruby/position-after.html
@@ -1,7 +1,7 @@
 <script src="../../resources/ahem.js"></script>
 <style>
     div.container {
-        -webkit-logical-width: 8em;
+        inline-size: 8em;
         font: 20px Ahem;
         -webkit-font-smoothing: none;
         outline: thin dashed lightblue;
diff --git a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/001-vertical.html b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/001-vertical.html
index 2f655b0..e094f83 100644
--- a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/001-vertical.html
+++ b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/001-vertical.html
@@ -10,6 +10,6 @@
 </div>
 
 
-<div style="border:1px solid green; -webkit-margin-before:10em;">
+<div style="border:1px solid green; margin-block-start:10em;">
 <table style="border-collapse:collapse;"><tr><td style="border:2px solid black">Test</td></tr></table>
 </div>
diff --git a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/border-collapsing-head-foot-vertical.html b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/border-collapsing-head-foot-vertical.html
index a14d63a5..fb2454c1 100644
--- a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/border-collapsing-head-foot-vertical.html
+++ b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/border-collapsing-head-foot-vertical.html
@@ -7,12 +7,12 @@
         .test table { border-collapse: collapse; margin: 10px; }
         .test td, th { border: 1px lightgray solid; }
         
-        .example1 tfoot { -webkit-border-before: 2px solid blue;
-            -webkit-border-after: 2px solid green;
+        .example1 tfoot { border-block-start: 2px solid blue;
+            border-block-end: 2px solid green;
         }
 
-        .example2 thead { -webkit-border-before: 2px solid blue;
-            -webkit-border-after: 2px solid green;
+        .example2 thead { border-block-start: 2px solid blue;
+            border-block-end: 2px solid green;
         }
 
         table table { -webkit-writing-mode: vertical-rl; }
diff --git a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/equal-precedence-resolution-vertical.html b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/equal-precedence-resolution-vertical.html
index a3ba34d..32963794 100644
--- a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/equal-precedence-resolution-vertical.html
+++ b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/equal-precedence-resolution-vertical.html
@@ -5,50 +5,50 @@
 </style>
 <div style="-webkit-writing-mode: vertical-rl; height: 200px; border: solid;">
 <table>
-    <colgroup span="2"><colgroup span="1" style="-webkit-border-end: 5px solid rgba(0, 127, 0, 0.5);"><colgroup span="1" style="-webkit-border-start: 5px solid red">
+    <colgroup span="2"><colgroup span="1" style="border-inline-end: 5px solid rgba(0, 127, 0, 0.5);"><colgroup span="1" style="border-inline-start: 5px solid red">
     <tr>
-        <td style="-webkit-border-end: 5px solid rgba(0, 127, 0, 0.5); -webkit-border-after: 5px solid rgba(0, 127, 0, 0.5);"></td>
-        <td style="-webkit-border-start: 5px solid red;"></td>
+        <td style="border-inline-end: 5px solid rgba(0, 127, 0, 0.5); border-block-end: 5px solid rgba(0, 127, 0, 0.5);"></td>
+        <td style="border-inline-start: 5px solid red;"></td>
         <td></td>
         <td></td>
     </tr>
     <tr>
-        <td style="-webkit-border-before: 5px solid red;"></td>
+        <td style="border-block-start: 5px solid red;"></td>
         <td></td>
         <td></td>
         <td></td>
     </tr>
 </table>
 <table style="direction: rtl;">
-    <colgroup span="2"><colgroup span="1" style="-webkit-border-end: 5px solid rgba(0, 127, 0, 0.5);"><colgroup span="1" style="-webkit-border-start: 5px solid red">
+    <colgroup span="2"><colgroup span="1" style="border-inline-end: 5px solid rgba(0, 127, 0, 0.5);"><colgroup span="1" style="border-inline-start: 5px solid red">
     <tr>
-        <td style="-webkit-border-end: 5px solid rgba(0, 127, 0, 0.5); -webkit-border-after: 5px solid rgba(0, 127, 0, 0.5);"></td>
-        <td style="-webkit-border-start: 5px solid red;"></td>
+        <td style="border-inline-end: 5px solid rgba(0, 127, 0, 0.5); border-block-end: 5px solid rgba(0, 127, 0, 0.5);"></td>
+        <td style="border-inline-start: 5px solid red;"></td>
         <td></td>
         <td></td>
     </tr>
     <tr>
-        <td style="-webkit-border-before: 5px solid red;"></td>
+        <td style="border-block-start: 5px solid red;"></td>
         <td></td>
         <td></td>
         <td></td>
     </tr>
 </table>
 <table>
-    <tr style="-webkit-border-after: 5px solid rgba(0, 127, 0, 0.5);">
+    <tr style="border-block-end: 5px solid rgba(0, 127, 0, 0.5);">
         <td></td>
     </tr>
-    <tr style="-webkit-border-before: 5px solid red;">
+    <tr style="border-block-start: 5px solid red;">
         <td></td>
     </tr>
 </table>
 <table>
-    <tbody style="-webkit-border-after: 5px solid rgba(0, 127, 0, 0.5);">
+    <tbody style="border-block-end: 5px solid rgba(0, 127, 0, 0.5);">
         <tr>
             <td></td>
         </tr>
     </tbody>
-    <tbody style="-webkit-border-before: 5px solid red;">
+    <tbody style="border-block-start: 5px solid red;">
         <tr>
             <td></td>
         </tr>
@@ -57,50 +57,50 @@
 </div>
 <div style="-webkit-writing-mode: vertical-lr; height: 200px; border: solid;">
 <table>
-    <colgroup span="2"><colgroup span="1" style="-webkit-border-end: 5px solid rgba(0, 127, 0, 0.5);"><colgroup span="1" style="-webkit-border-start: 5px solid red">
+    <colgroup span="2"><colgroup span="1" style="border-inline-end: 5px solid rgba(0, 127, 0, 0.5);"><colgroup span="1" style="border-inline-start: 5px solid red">
     <tr>
-        <td style="-webkit-border-end: 5px solid rgba(0, 127, 0, 0.5); -webkit-border-after: 5px solid rgba(0, 127, 0, 0.5);"></td>
-        <td style="-webkit-border-start: 5px solid red;"></td>
+        <td style="border-inline-end: 5px solid rgba(0, 127, 0, 0.5); border-block-end: 5px solid rgba(0, 127, 0, 0.5);"></td>
+        <td style="border-inline-start: 5px solid red;"></td>
         <td></td>
         <td></td>
     </tr>
     <tr>
-        <td style="-webkit-border-before: 5px solid red;"></td>
+        <td style="border-block-start: 5px solid red;"></td>
         <td></td>
         <td></td>
         <td></td>
     </tr>
 </table>
 <table style="direction: rtl;">
-    <colgroup span="2"><colgroup span="1" style="-webkit-border-end: 5px solid rgba(0, 127, 0, 0.5);"><colgroup span="1" style="-webkit-border-start: 5px solid red">
+    <colgroup span="2"><colgroup span="1" style="border-inline-end: 5px solid rgba(0, 127, 0, 0.5);"><colgroup span="1" style="border-inline-start: 5px solid red">
     <tr>
-        <td style="-webkit-border-end: 5px solid rgba(0, 127, 0, 0.5); -webkit-border-after: 5px solid rgba(0, 127, 0, 0.5);"></td>
-        <td style="-webkit-border-start: 5px solid red;"></td>
+        <td style="border-inline-end: 5px solid rgba(0, 127, 0, 0.5); border-block-end: 5px solid rgba(0, 127, 0, 0.5);"></td>
+        <td style="border-inline-start: 5px solid red;"></td>
         <td></td>
         <td></td>
     </tr>
     <tr>
-        <td style="-webkit-border-before: 5px solid red;"></td>
+        <td style="border-block-start: 5px solid red;"></td>
         <td></td>
         <td></td>
         <td></td>
     </tr>
 </table>
 <table>
-    <tr style="-webkit-border-after: 5px solid rgba(0, 127, 0, 0.5);">
+    <tr style="border-block-end: 5px solid rgba(0, 127, 0, 0.5);">
         <td></td>
     </tr>
-    <tr style="-webkit-border-before: 5px solid red;">
+    <tr style="border-block-start: 5px solid red;">
         <td></td>
     </tr>
 </table>
 <table>
-    <tbody style="-webkit-border-after: 5px solid rgba(0, 127, 0, 0.5);">
+    <tbody style="border-block-end: 5px solid rgba(0, 127, 0, 0.5);">
         <tr>
             <td></td>
         </tr>
     </tbody>
-    <tbody style="-webkit-border-before: 5px solid red;">
+    <tbody style="border-block-start: 5px solid red;">
         <tr>
             <td></td>
         </tr>
diff --git a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/rtl-border-collapsing-vertical.html b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/rtl-border-collapsing-vertical.html
index 101790f..819235fa 100644
--- a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/rtl-border-collapsing-vertical.html
+++ b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/rtl-border-collapsing-vertical.html
@@ -9,15 +9,15 @@
 <hr>
 <table cellpadding="4" cellspacing="0" style="text-align: center; -webkit-writing-mode: vertical-rl;">
 <tr>
-<td style="-webkit-border-end: 1px solid black;">RTL</td>
+<td style="border-inline-end: 1px solid black;">RTL</td>
 <td>LTR</td>
 </tr>
 <tr>
-<td style="-webkit-border-end: 1px solid black;">
-    <table style="direction:rtl; border-collapse: collapse; -webkit-border-start: 2px solid red; -webkit-border-end: 2px solid blue;">
+<td style="border-inline-end: 1px solid black;">
+    <table style="direction:rtl; border-collapse: collapse; border-inline-start: 2px solid red; border-inline-end: 2px solid blue;">
         <col>
         <col>
-        <col style="background: yellow; -webkit-border-end: 2px green dotted; -webkit-border-start: solid 1px;">
+        <col style="background: yellow; border-inline-end: 2px green dotted; border-inline-start: solid 1px;">
         <col style="background: silver;">
         <tr>
             <td>&nbsp;&nbsp;</td>
@@ -26,7 +26,7 @@
             <td>&nbsp;&nbsp;</td>
         </tr>
         <tr>
-            <td style="-webkit-border-end: 4px solid maroon;">&nbsp;&nbsp;</td>
+            <td style="border-inline-end: 4px solid maroon;">&nbsp;&nbsp;</td>
             <td>&nbsp;&nbsp;</td>
             <td>&nbsp;&nbsp;</td>
             <td>&nbsp;&nbsp;</td>
@@ -35,10 +35,10 @@
     </table>
 </td>
 <td>    
-    <table style="direction:ltr; border-collapse: collapse; -webkit-border-start: 2px solid red; -webkit-border-end: 2px solid blue;">
+    <table style="direction:ltr; border-collapse: collapse; border-inline-start: 2px solid red; border-inline-end: 2px solid blue;">
         <col>
         <col>
-        <col style="background: yellow; -webkit-border-end: 2px green dotted; -webkit-border-start: solid 1px;">
+        <col style="background: yellow; border-inline-end: 2px green dotted; border-inline-start: solid 1px;">
         <col style="background: silver;">
         <tr>
             <td>&nbsp;&nbsp;</td>
@@ -47,7 +47,7 @@
             <td>&nbsp;&nbsp;</td>
         </tr>
         <tr>
-            <td style="-webkit-border-end: 4px solid maroon;">&nbsp;&nbsp;</td>
+            <td style="border-inline-end: 4px solid maroon;">&nbsp;&nbsp;</td>
             <td>&nbsp;&nbsp;</td>
             <td>&nbsp;&nbsp;</td>
             <td>&nbsp;&nbsp;</td>
diff --git a/third_party/WebKit/LayoutTests/fast/table/fixed-with-auto-with-colspan-vertical.html b/third_party/WebKit/LayoutTests/fast/table/fixed-with-auto-with-colspan-vertical.html
index be67a15..d4ee2746 100644
--- a/third_party/WebKit/LayoutTests/fast/table/fixed-with-auto-with-colspan-vertical.html
+++ b/third_party/WebKit/LayoutTests/fast/table/fixed-with-auto-with-colspan-vertical.html
@@ -1,5 +1,5 @@
 <style>
-    table { border-spacing: 5px 0; table-layout: fixed; height: 445px; -webkit-margin-before: 5px; }
+    table { border-spacing: 5px 0; table-layout: fixed; height: 445px; margin-block-start: 5px; }
     td { width: 50px; }
     #ref td { background-color: red; }
     #test td { background-color: green; }
diff --git a/third_party/WebKit/LayoutTests/fast/text/decorations-with-text-combine.html b/third_party/WebKit/LayoutTests/fast/text/decorations-with-text-combine.html
index 0dc1e6dce..732033a 100644
--- a/third_party/WebKit/LayoutTests/fast/text/decorations-with-text-combine.html
+++ b/third_party/WebKit/LayoutTests/fast/text/decorations-with-text-combine.html
@@ -7,7 +7,7 @@
     }
 
     div {
-        -webkit-margin-after: 10px;
+        margin-block-end: 10px;
     }
 
     .combine {
diff --git a/third_party/WebKit/LayoutTests/fast/text/dirty-inline-textbox-crash.html b/third_party/WebKit/LayoutTests/fast/text/dirty-inline-textbox-crash.html
index 6a861a9..0ea9cfe 100644
--- a/third_party/WebKit/LayoutTests/fast/text/dirty-inline-textbox-crash.html
+++ b/third_party/WebKit/LayoutTests/fast/text/dirty-inline-textbox-crash.html
@@ -4,7 +4,7 @@
             .box
             {
                 display: run-in; 
-                -webkit-padding-start: 10000;
+                padding-inline-start: 10000;
             }
         </style>
     </head>
diff --git a/third_party/WebKit/LayoutTests/fast/text/justify-vertical-expected.html b/third_party/WebKit/LayoutTests/fast/text/justify-vertical-expected.html
index b87fa976..a8c8f710 100644
--- a/third_party/WebKit/LayoutTests/fast/text/justify-vertical-expected.html
+++ b/third_party/WebKit/LayoutTests/fast/text/justify-vertical-expected.html
@@ -16,20 +16,20 @@
 </style>
 <dl>
 <dt>Ideographic, Kana, CJK symbols</dt>
-<dd style="-webkit-logical-width:9em;">&#x56FD; &#x56FD; &#x3042; &#xFF01; &#x56FD;<br>&#x56FD;&#xFEFF;WWWWWWWW</dd>
-<dd style="-webkit-logical-width:9em;">&#x56FD; &#x56FD; &#x3042; &#xFF01; &#x56FD;<br>WWWWWWWWW</dd>
-<dd style="-webkit-logical-width:9em;">&#x56FD; &#x56FD; &#x3042; &#xFF01; &#x56FD;<br>WWWWWWWWW</dd>
-<dd style="-webkit-logical-width:9em;">&#x56FD; &#x56FD; &#x3042; &#xFF01; W<br>WWWWWWWWW</dd>
-<dd style="-webkit-logical-width:9em;">&#x20B9F; &#x20B9F; &#x20B9F; &#x20B9F; &#x20B9F;<br>&#x20B9F;&#xFEFF;WWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x56FD; &#x56FD; &#x3042; &#xFF01; &#x56FD;<br>&#x56FD;&#xFEFF;WWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x56FD; &#x56FD; &#x3042; &#xFF01; &#x56FD;<br>WWWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x56FD; &#x56FD; &#x3042; &#xFF01; &#x56FD;<br>WWWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x56FD; &#x56FD; &#x3042; &#xFF01; W<br>WWWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x20B9F; &#x20B9F; &#x20B9F; &#x20B9F; &#x20B9F;<br>&#x20B9F;&#xFEFF;WWWWWWWW</dd>
 <dt>Ideographic, Kana, CJK symbols with spans</dt>
-<dd style="-webkit-logical-width:9em;">&#x56FD; &#x56FD; &#x3042; &#xFF01; &#x56FD;<br>&#x56FD;&#xFEFF;WWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x56FD; &#x56FD; &#x3042; &#xFF01; &#x56FD;<br>&#x56FD;&#xFEFF;WWWWWWWW</dd>
 <dt>Ideographic, Latin, and spaces</dt>
-<dd style="-webkit-logical-width:8em;">WW &#x56FD; W &#x56FD;<br>&#x56FD;&#xFEFF;WWWWWWW</dd>
-<dd style="-webkit-logical-width:11em;">WW &#x56FD;   W  &#x56FD;<br>&#x56FD;&#xFEFF;WWWWWWWWWW</dd>
-<dd style="-webkit-logical-width:11em;">WW &#x56FD;   W  &#x56FD;<br>WWWWWWWWWWW</dd>
-<dd style="-webkit-logical-width:11em;">WW &#x56FD;   W  &#x56FD;<br>WWWWWWWWWWW</dd>
-<dd style="-webkit-logical-width:8em;">WW &#x56FD;   W<br>&#x56FD;&#xFEFF;WWWWWWW</dd>
-<dd style="-webkit-logical-width:11em;">W.  W.  W &#x56FD;<br>WWWWWWWWWWW</dd>
+<dd style="inline-size:8em;">WW &#x56FD; W &#x56FD;<br>&#x56FD;&#xFEFF;WWWWWWW</dd>
+<dd style="inline-size:11em;">WW &#x56FD;   W  &#x56FD;<br>&#x56FD;&#xFEFF;WWWWWWWWWW</dd>
+<dd style="inline-size:11em;">WW &#x56FD;   W  &#x56FD;<br>WWWWWWWWWWW</dd>
+<dd style="inline-size:11em;">WW &#x56FD;   W  &#x56FD;<br>WWWWWWWWWWW</dd>
+<dd style="inline-size:8em;">WW &#x56FD;   W<br>&#x56FD;&#xFEFF;WWWWWWW</dd>
+<dd style="inline-size:11em;">W.  W.  W &#x56FD;<br>WWWWWWWWWWW</dd>
 </dl>
 <script>
 if (window.testRunner) {
diff --git a/third_party/WebKit/LayoutTests/fast/text/justify-vertical.html b/third_party/WebKit/LayoutTests/fast/text/justify-vertical.html
index e229385..15e7380a 100644
--- a/third_party/WebKit/LayoutTests/fast/text/justify-vertical.html
+++ b/third_party/WebKit/LayoutTests/fast/text/justify-vertical.html
@@ -16,24 +16,24 @@
 </style>
 <dl>
 <dt>Ideographic, Kana, CJK symbols</dt>
-<dd style="-webkit-logical-width:9em;">&#x56FD;&#x56FD;&#x3042;&#xFF01;&#x56FD;&#x56FD;&#xFEFF;WWWWWWWW</dd>
-<dd style="-webkit-logical-width:9em;">&#x56FD;&#x56FD;&#x3042;&#xFF01;&#x56FD;WWWWWWWWW</dd>
-<dd style="-webkit-logical-width:9em;">&#x56FD;&#x56FD;&#x3042;&#xFF01;&#x56FD; WWWWWWWWW</dd>
-<dd style="-webkit-logical-width:9em;">&#x56FD;&#x56FD;&#x3042;&#xFF01;W WWWWWWWWW</dd>
-<dd style="-webkit-logical-width:9em;">&#x20B9F;&#x20B9F;&#x20B9F;&#x20B9F;&#x20B9F;&#x20B9F;&#xFEFF;WWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x56FD;&#x56FD;&#x3042;&#xFF01;&#x56FD;&#x56FD;&#xFEFF;WWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x56FD;&#x56FD;&#x3042;&#xFF01;&#x56FD;WWWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x56FD;&#x56FD;&#x3042;&#xFF01;&#x56FD; WWWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x56FD;&#x56FD;&#x3042;&#xFF01;W WWWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x20B9F;&#x20B9F;&#x20B9F;&#x20B9F;&#x20B9F;&#x20B9F;&#xFEFF;WWWWWWWW</dd>
 <dt>Ideographic, Kana, CJK symbols with spans</dt>
-<dd style="-webkit-logical-width:9em;">&#x56FD;<span>&#x56FD;</span>&#x3042;&#xFF01;&#x56FD;&#x56FD;&#xFEFF;WWWWWWWW</dd>
+<dd style="inline-size:9em;">&#x56FD;<span>&#x56FD;</span>&#x3042;&#xFF01;&#x56FD;&#x56FD;&#xFEFF;WWWWWWWW</dd>
 <dt>Ideographic, Latin, and spaces</dt>
-<dd style="-webkit-logical-width:8em;">WW&#x56FD;W&#x56FD;&#x56FD;&#xFEFF;WWWWWWW</dd>
-<dd style="-webkit-logical-width:11em;">WW&#x56FD; W &#x56FD;&#x56FD;&#xFEFF;WWWWWWWWWW</dd>
-<dd style="-webkit-logical-width:11em;">WW&#x56FD; W &#x56FD;WWWWWWWWWWW</dd>
-<dd style="-webkit-logical-width:11em;">WW&#x56FD; W &#x56FD; WWWWWWWWWWW</dd>
-<dd style="-webkit-logical-width:8em;">WW&#x56FD; W &#x56FD;&#xFEFF;WWWWWWW</dd>
-<dd style="-webkit-logical-width:11em;">W. W. <span>W</span>&#x56FD;WWWWWWWWWWW</dd>
+<dd style="inline-size:8em;">WW&#x56FD;W&#x56FD;&#x56FD;&#xFEFF;WWWWWWW</dd>
+<dd style="inline-size:11em;">WW&#x56FD; W &#x56FD;&#x56FD;&#xFEFF;WWWWWWWWWW</dd>
+<dd style="inline-size:11em;">WW&#x56FD; W &#x56FD;WWWWWWWWWWW</dd>
+<dd style="inline-size:11em;">WW&#x56FD; W &#x56FD; WWWWWWWWWWW</dd>
+<dd style="inline-size:8em;">WW&#x56FD; W &#x56FD;&#xFEFF;WWWWWWW</dd>
+<dd style="inline-size:11em;">W. W. <span>W</span>&#x56FD;WWWWWWWWWWW</dd>
 <!-- These are not supported yet
 <dt>Combining and IVS</dt>
-<dd style="-webkit-logical-width:5em;">&#x304B;&#x3099;&#x304B;&#x3099;&#x304B;&#x3099;&#x304B;&#x3099;&#xFEFF;WWWW</dd>
-<dd style="-webkit-logical-width:5em;">&#x8FBA;&#xE0102;&#x8FBA;&#xE0102;&#x8FBA;&#xE0102;&#x8FBA;&#xFEFF;WWWW</dd>
+<dd style="inline-size:5em;">&#x304B;&#x3099;&#x304B;&#x3099;&#x304B;&#x3099;&#x304B;&#x3099;&#xFEFF;WWWW</dd>
+<dd style="inline-size:5em;">&#x8FBA;&#xE0102;&#x8FBA;&#xE0102;&#x8FBA;&#xE0102;&#x8FBA;&#xFEFF;WWWW</dd>
 -->
 </dl>
 <script>
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/Kusa-Makura-background-canvas.html b/third_party/WebKit/LayoutTests/fast/writing-mode/Kusa-Makura-background-canvas.html
index 58ffed1..2093b45 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/Kusa-Makura-background-canvas.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/Kusa-Makura-background-canvas.html
@@ -14,7 +14,7 @@
 /*body { font-family: HiraMinProN-W3;}		 to test the font vs fallback. */
 #div, h1, h2 { line-height: 150%; }			/* this line should make no difference for the line height as the default is 150 for the Japanese fonts. */
 
-.jisage_2 { -webkit-margin-start: 2em;}
+.jisage_2 { margin-inline-start: 2em;}
 body { margin: 8% 10%;}
 #ruby { line-height: 100%; }				/* hack to keep lines in conssitent positions. Should not be necessary. */
 #rt { line-height: 50%; }					/* hack to keep lines in conssitent positions. Should not be necessary. */
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/block-level-images.html b/third_party/WebKit/LayoutTests/fast/writing-mode/block-level-images.html
index 0722944..5e994ba9 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/block-level-images.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/block-level-images.html
@@ -1,14 +1,14 @@
 <!doctype html>
 <div style="margin:2px; float:left; height:300px;border:2px solid black;-webkit-writing-mode:vertical-lr">
 <div style="width:25px;background-color:green"></div>
-<img style="display:block;height:50%; -webkit-border-before:2px solid maroon; -webkit-border-after:2px solid maroon; -webkit-border-start: 1px solid purple; -webkit-border-end:5px dashed grey" src="resources/circle.svg">
-<img style="-webkit-margin-start: 40px; display:block;height:50px" src="resources/oval.png">
+<img style="display:block;height:50%; border-block-start:2px solid maroon; border-block-end:2px solid maroon; border-inline-start: 1px solid purple; border-inline-end:5px dashed grey" src="resources/circle.svg">
+<img style="margin-inline-start: 40px; display:block;height:50px" src="resources/oval.png">
 <div style="width:25px;background-color:green"></div>
 </div>
 
 <div style="margin:2px; float:left; height:300px;border:2px solid black;-webkit-writing-mode:vertical-lr; direction:rtl">
 <div style="width:25px;background-color:green"></div>
-<img style="display:block;height:50%; -webkit-border-before:2px solid maroon; -webkit-border-after:2px solid maroon; -webkit-border-start: 1px solid purple; -webkit-border-end:5px dashed grey" src="resources/circle.svg">
-<img style="-webkit-margin-start: 40px; display:block;height:50px" src="resources/oval.png">
+<img style="display:block;height:50%; border-block-start:2px solid maroon; border-block-end:2px solid maroon; border-inline-start: 1px solid purple; border-inline-end:5px dashed grey" src="resources/circle.svg">
+<img style="margin-inline-start: 40px; display:block;height:50px" src="resources/oval.png">
 <div style="width:25px;background-color:green"></div>
 </div>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/border-radius-clipping-vertical-lr.html b/third_party/WebKit/LayoutTests/fast/writing-mode/border-radius-clipping-vertical-lr.html
index 702bb42..23185bd 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/border-radius-clipping-vertical-lr.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/border-radius-clipping-vertical-lr.html
@@ -1,9 +1,9 @@
 <html style="-webkit-writing-mode: vertical-lr">
 <body>
-<div style="-webkit-logical-width: 600px; -webkit-margin-after:50px">
-    <span style="-webkit-padding-start: 15px; -webkit-padding-end:15px; -webkit-padding-before:5px; -webkit-padding-after: 5px; font-size: 48px; background-color:blue">
+<div style="inline-size: 600px; margin-block-end:50px">
+    <span style="padding-inline-start: 15px; padding-inline-end:15px; padding-block-start:5px; padding-block-end: 5px; font-size: 48px; background-color:blue">
     <span style="
-        -webkit-padding-start: 15px; -webkit-padding-end:15px;
+        padding-inline-start: 15px; padding-inline-end:15px;
         font-size: 48px;
         background-color: lightyellow;
         -webkit-border-radius: 10px;
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/border-styles-vertical-lr.html b/third_party/WebKit/LayoutTests/fast/writing-mode/border-styles-vertical-lr.html
index cba3c29e..7c18a76 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/border-styles-vertical-lr.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/border-styles-vertical-lr.html
@@ -9,7 +9,7 @@
       display: inline-block;
     }
     span {
-      -webkit-padding-start: 15px; -webkit-padding-end:15px;
+      padding-inline-start: 15px; padding-inline-end:15px;
       font-size: 48pt;
       background-color: #DDD;
       line-height: 2em;
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/border-styles-vertical-rl.html b/third_party/WebKit/LayoutTests/fast/writing-mode/border-styles-vertical-rl.html
index 85af6c5..f2b3ddb5 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/border-styles-vertical-rl.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/border-styles-vertical-rl.html
@@ -9,7 +9,7 @@
       display: inline-block;
     }
     span {
-      -webkit-padding-start: 15px; -webkit-padding-end:15px;
+      padding-inline-start: 15px; padding-inline-end:15px;
       font-size: 48pt;
       background-color: #DDD;
       line-height: 2em;
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/fieldsets.html b/third_party/WebKit/LayoutTests/fast/writing-mode/fieldsets.html
index 83762bb..0ade129 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/fieldsets.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/fieldsets.html
@@ -3,16 +3,16 @@
 <style>
 fieldset
 {
-    -webkit-logical-width:200px;
-    -webkit-logical-height:100px;
+    inline-size:200px;
+    block-size:100px;
     margin:1em;
     display:inline-block;
 }
 
 div
 {
-    -webkit-logical-width:100px;
-    -webkit-logical-height:25px;
+    inline-size:100px;
+    block-size:25px;
     background-color:orange;
 }
 
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/flipped-blocks-text-map-local-to-container.html b/third_party/WebKit/LayoutTests/fast/writing-mode/flipped-blocks-text-map-local-to-container.html
index ea0686b..216a4927 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/flipped-blocks-text-map-local-to-container.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/flipped-blocks-text-map-local-to-container.html
@@ -1,5 +1,5 @@
 <meta name=viewport content="width=device-width">
-<div style="border: solid; writing-mode: vertical-rl; -webkit-logical-width: 200px; -webkit-logical-height: 400px;
+<div style="border: solid; writing-mode: vertical-rl; inline-size: 200px; block-size: 400px;
     font-size: 36px; line-height: 2;
 ">
     Lorem ipsum dolor <span id="target">sit</span> amet consectetur adipiscing elit.
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/logical-height-after-clear-expected.html b/third_party/WebKit/LayoutTests/fast/writing-mode/logical-height-after-clear-expected.html
index 36518494..004d56e 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/logical-height-after-clear-expected.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/logical-height-after-clear-expected.html
@@ -1,13 +1,13 @@
 <style>
     div.test {
-        -webkit-logical-width: 50px;
-        -webkit-logical-height: 100px;
+        inline-size: 50px;
+        block-size: 100px;
         background-color: green;
     }
 
     div.green {
         background-color: blue;
-        -webkit-logical-height: 50px;
+        block-size: 50px;
     }
 
     div.lr {
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/logical-height-after-clear.html b/third_party/WebKit/LayoutTests/fast/writing-mode/logical-height-after-clear.html
index 30a187e..020d552 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/logical-height-after-clear.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/logical-height-after-clear.html
@@ -1,14 +1,14 @@
 <style>
     div.test {
-        -webkit-logical-width: 50px;
-        -webkit-logical-height: 100px;
+        inline-size: 50px;
+        block-size: 100px;
         background-color: red;
     }
 
     div.float {
         float: left;
-        -webkit-logical-height: 50px;
-        -webkit-logical-width: 50px;
+        block-size: 50px;
+        inline-size: 50px;
         background-color: blue;
     }
 
@@ -18,7 +18,7 @@
 
     div.green {
         background-color: green;
-        -webkit-logical-height: 25px;
+        block-size: 25px;
     }
 
     div.lr {
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/orthogonal-inline-block.html b/third_party/WebKit/LayoutTests/fast/writing-mode/orthogonal-inline-block.html
index b823218..392b5c7 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/orthogonal-inline-block.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/orthogonal-inline-block.html
@@ -46,46 +46,46 @@
   generate('margin-top: 1em', top);
   generate('margin-right: 1em', right);
   generate('margin-bottom: 1em', bottom);
-  generate('-webkit-margin-before: 1em', right);
-  generate('-webkit-margin-after: 1em', left);
-  generate('-webkit-margin-start: 1em', top);
-  generate('-webkit-margin-end: 1em', bottom);
+  generate('margin-block-start: 1em', right);
+  generate('margin-block-end: 1em', left);
+  generate('margin-inline-start: 1em', top);
+  generate('margin-inline-end: 1em', bottom);
 
   generate('border-left: 1em transparent solid', left);
   generate('border-top: 1em transparent solid', top);
   generate('border-right: 1em transparent solid', right);
   generate('border-bottom: 1em transparent solid', bottom);
-  generate('-webkit-border-before: 1em transparent solid', right);
-  generate('-webkit-border-after: 1em transparent solid', left);
-  generate('-webkit-border-start: 1em transparent solid', top);
-  generate('-webkit-border-end: 1em transparent solid', bottom);
+  generate('border-block-start: 1em transparent solid', right);
+  generate('border-block-end: 1em transparent solid', left);
+  generate('border-inline-start: 1em transparent solid', top);
+  generate('border-inline-end: 1em transparent solid', bottom);
 
   generate('padding-left: 1em', left);
   generate('padding-top: 1em', top);
   generate('padding-right: 1em', right);
   generate('padding-bottom: 1em', bottom);
-  generate('-webkit-padding-before: 1em', right);
-  generate('-webkit-padding-after: 1em', left);
-  generate('-webkit-padding-start: 1em', top);
-  generate('-webkit-padding-end: 1em', bottom);
+  generate('padding-block-start: 1em', right);
+  generate('padding-block-end: 1em', left);
+  generate('padding-inline-start: 1em', top);
+  generate('padding-inline-end: 1em', bottom);
 
   generate('margin-left: 20%', left);
   generate('margin-top: 20%', top);
   generate('margin-right: 20%', right);
   generate('margin-bottom: 20%', bottom);
-  generate('-webkit-margin-before: 20%', right);
-  generate('-webkit-margin-after: 20%', left);
-  generate('-webkit-margin-start: 20%', top);
-  generate('-webkit-margin-end: 20%', bottom);
+  generate('margin-block-start: 20%', right);
+  generate('margin-block-end: 20%', left);
+  generate('margin-inline-start: 20%', top);
+  generate('margin-inline-end: 20%', bottom);
 
   generate('padding-left: 20%', left);
   generate('padding-top: 20%', top);
   generate('padding-right: 20%', right);
   generate('padding-bottom: 20%', bottom);
-  generate('-webkit-padding-before: 20%', right);
-  generate('-webkit-padding-after: 20%', left);
-  generate('-webkit-padding-start: 20%', top);
-  generate('-webkit-padding-end: 20%', bottom);
+  generate('padding-block-start: 20%', right);
+  generate('padding-block-end: 20%', left);
+  generate('padding-inline-start: 20%', top);
+  generate('padding-inline-end: 20%', bottom);
 }
 
 function generate(inline_block_style, expected_direction) {
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/root-lr-basic.html b/third_party/WebKit/LayoutTests/fast/writing-mode/root-lr-basic.html
index 85d14ec..45c08e10 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/root-lr-basic.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/root-lr-basic.html
@@ -1,2 +1,2 @@
 <!doctype html>
-<html style="overflow:hidden; -webkit-writing-mode:vertical-lr; -webkit-logical-height:100px; border:2px solid black"></html>
+<html style="overflow:hidden; -webkit-writing-mode:vertical-lr; block-size:100px; border:2px solid black"></html>
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/vertical-lr-replaced-selection.html b/third_party/WebKit/LayoutTests/fast/writing-mode/vertical-lr-replaced-selection.html
index 16b7395..7a9b3e6 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/vertical-lr-replaced-selection.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/vertical-lr-replaced-selection.html
@@ -15,4 +15,4 @@
 </head>
 
 <body onload="selectStuff()" style="font-size:36px; -webkit-writing-mode:vertical-lr;-webkit-text-orientation:sideways-right;text-rendering:optimizeLegibility;">This is the first line of text.<br>
-<img style="-webkit-logical-width:20px;-webkit-logical-height:50px;background-color:green"> This is the second line of <img style="-webkit-logical-width:20px;-webkit-logical-height:100px;background-color:purple"> text.
\ No newline at end of file
+<img style="inline-size:20px;block-size:50px;background-color:green"> This is the second line of <img style="inline-size:20px;block-size:100px;background-color:purple"> text.
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/writing-mode/vertical-rl-replaced-selection.html b/third_party/WebKit/LayoutTests/fast/writing-mode/vertical-rl-replaced-selection.html
index 32d6428..0b640140 100644
--- a/third_party/WebKit/LayoutTests/fast/writing-mode/vertical-rl-replaced-selection.html
+++ b/third_party/WebKit/LayoutTests/fast/writing-mode/vertical-rl-replaced-selection.html
@@ -16,4 +16,4 @@
 </head>
 
 <body onload="selectStuff()" style="font-size:36px; -webkit-writing-mode:vertical-rl;-webkit-text-orientation:sideways-right;text-rendering:optimizeLegibility">This is the first line of text.<br>
-<img style="-webkit-logical-width:20px;-webkit-logical-height:50px;background-color:green"> This is the second line of <img style="-webkit-logical-width:20px;-webkit-logical-height:100px;background-color:purple"> text.
\ No newline at end of file
+<img style="inline-size:20px;block-size:50px;background-color:green"> This is the second line of <img style="inline-size:20px;block-size:100px;background-color:purple"> text.
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/csspaint/invalidation-background-image.html b/third_party/WebKit/LayoutTests/http/tests/csspaint/invalidation-background-image.html
index 86143c8b..6b3e32a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/csspaint/invalidation-background-image.html
+++ b/third_party/WebKit/LayoutTests/http/tests/csspaint/invalidation-background-image.html
@@ -46,6 +46,6 @@
     { property: '-webkit-border-radius', invalidationProperty: 'border-radius', prevValue: '', value: '25px' },
     { property: 'border-radius', invalidationProperty: '-webkit-border-radius', prevValue: '25px', value: '' },
     { property: '-webkit-border-radius', prevValue: '100px', value: 'calc(50px + 50px)', noInvalidation: true },
-    { property: '-webkit-margin-start', invalidationProperty: 'margin-left', prevValue: 'calc(50px + 50px)', value: '100px', noInvalidation: true },
+    { property: 'margin-inline-start', invalidationProperty: 'margin-left', prevValue: 'calc(50px + 50px)', value: '100px', noInvalidation: true },
 ]);
 </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/csspaint/resources/test-runner-invalidation-logging.js b/third_party/WebKit/LayoutTests/http/tests/csspaint/resources/test-runner-invalidation-logging.js
index f8ae42d7..cea64138 100644
--- a/third_party/WebKit/LayoutTests/http/tests/csspaint/resources/test-runner-invalidation-logging.js
+++ b/third_party/WebKit/LayoutTests/http/tests/csspaint/resources/test-runner-invalidation-logging.js
@@ -10,7 +10,7 @@
 // testRunnerInvalidationLogging('background-image', [
 //      { property: 'max-height', value: '100px' },
 //      { property: 'color', prevValue: '#00F', value: 'blue', noInvalidation: true },
-//      { property: '-webkit-margin-start', invalidationProperty: 'margin-left', prevValue: 'calc(50px + 50px)', value: '100px', noInvalidation: true }
+//      { property: 'margin-inline-start', invalidationProperty: 'margin-left', prevValue: 'calc(50px + 50px)', value: '100px', noInvalidation: true }
 // ]);
 
 function testRunnerInvalidationLogging(imageType, tests) {
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/test-helpers.js b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/test-helpers.js
index ecc94b7..240db09 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/test-helpers.js
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/test-helpers.js
@@ -210,3 +210,15 @@
                           'password2' + suffix, 'cookie2');
       });
 }
+
+function wait_for_port_message(port, handler) {
+  return new Promise((resolve, reject) => {
+    port.onmessage = (e) => {
+      try {
+        resolve(handler(e));
+      } catch (e) {
+        reject(e);
+      }
+    };
+  });
+}
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/update-no-controllee-worker.js b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/update-no-controllee-worker.js
new file mode 100644
index 0000000..0eeb286
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/resources/update-no-controllee-worker.js
@@ -0,0 +1,32 @@
+const rejectAfter = (timeout) => {
+  return new Promise((resolve, reject) => {
+    setTimeout(() => reject(), timeout);
+  });
+}
+
+const startUpdate = () => {
+  let p = [];
+  for (let i = 0; i < 10; i++) {
+    p.push(self.registration.update());
+  }
+  return Promise.all(p);
+};
+
+const update = () => {
+  // update() rejects in one of these cases:
+  //   1. at least one update() rejects, or
+  //   2. at least one update() does not resolve after 15 seconds.
+  return Promise.race([startUpdate(), rejectAfter(150000)]);
+};
+
+self.addEventListener('message', (e) => {
+  const port = e.data;
+
+  port.onmessage = (e) => {
+    update().then(() => {
+      port.postMessage('success');
+    }).catch((e) => {
+      port.postMessage('failure');
+    });
+  };
+});
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/update-no-controllee.https-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/update-no-controllee.https-expected.txt
new file mode 100644
index 0000000..3e0ec4b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/update-no-controllee.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Verify multiple updates from service workers without controllees do not resolve immediately assert_equals: update should not have succeeded expected "failure" but got "success"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/update-no-controllee.https.html b/third_party/WebKit/LayoutTests/http/tests/serviceworker/update-no-controllee.https.html
new file mode 100644
index 0000000..40740c6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/update-no-controllee.https.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- This is not a WPT test because it tests non-specified Chrome-specific behavior. It tests that self-updating service workers eventually fail to update. -->
+<title>Service Worker: update no controllee</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+  // Set up ServiceWorker and wait until it's |activated|.
+  const url = 'resources/update-no-controllee-worker.js';
+  const scope = 'resources/blank.html';
+  const registration = await service_worker_unregister_and_register(t, url, scope);
+  await wait_for_state(t, registration.installing, 'activated');
+
+  const frame = await with_iframe(scope);
+
+  const w = frame.contentWindow;
+  const sw = w.navigator.serviceWorker;
+  assert_true(sw.controller instanceof w.ServiceWorker,
+              'controller should be a ServiceWorker object');
+
+  const channel = new MessageChannel();
+  sw.controller.postMessage(channel.port1, [channel.port1]);
+
+  // Remove frame so our worker has no controller.
+  frame.remove();
+  assert_equals(
+      sw.controller, null, 'disconnected frame should not be controlled');
+
+  // Send a message to the worker to start updating and wait for its response.
+  // We expect at least one of the updates, and therefore the complete proccess,
+  // to fail immediately because the delay is too long.
+  const result = wait_for_port_message(channel.port2, (e) => {
+    assert_equals(e.data, 'failure', 'update should not have succeeded');
+  });
+  channel.port2.postMessage('');
+  await result;
+
+  // Cleanup.
+  await registration.unregister();
+}, 'Verify multiple updates from service workers without controllees ' +
+       'do not resolve immediately');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 68c12d00..759ccea 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -64,11 +64,6 @@
     attribute @@toStringTag
     method constructor
     method updateUI
-interface BackgroundFetchedEvent : BackgroundFetchEvent
-    attribute @@toStringTag
-    getter fetches
-    method constructor
-    method updateUI
 interface BarcodeDetector
     attribute @@toStringTag
     method constructor
diff --git a/third_party/WebKit/LayoutTests/http/tests/wasm_streaming/regression860637.html b/third_party/WebKit/LayoutTests/http/tests/wasm_streaming/regression860637.html
new file mode 100644
index 0000000..b0c9722b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/wasm_streaming/regression860637.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="wasm_response_apis.js"></script>
+<script src="../wasm/resources/wasm-constants.js"></script>
+<script src="../wasm/resources/wasm-module-builder.js"></script>
+<script>
+  promise_test(TestRegression837417, "Regression test");
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/wasm_streaming/wasm_response_apis.js b/third_party/WebKit/LayoutTests/http/tests/wasm_streaming/wasm_response_apis.js
index 4ee7579..316f37e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/wasm_streaming/wasm_response_apis.js
+++ b/third_party/WebKit/LayoutTests/http/tests/wasm_streaming/wasm_response_apis.js
@@ -255,3 +255,12 @@
   worker.addEventListener('message', e => resolve(e.data));
   return promise.then(exists => assert_true(exists));
 }
+
+function TestRegression837417() {
+  let old_then = WebAssembly.Module.prototype.then;
+  WebAssembly.Module.prototype.then = resolve => resolve(String.fromCharCode(
+      null, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41));
+
+  return WebAssembly.instantiateStreaming(fetch(incrementer_url))
+    .then(pair => assert_equals(5, pair.instance.exports.increment(4)));
+}
diff --git a/third_party/WebKit/LayoutTests/images/mask-box-image-crash.html b/third_party/WebKit/LayoutTests/images/mask-box-image-crash.html
index 35ced77..b491549 100644
--- a/third_party/WebKit/LayoutTests/images/mask-box-image-crash.html
+++ b/third_party/WebKit/LayoutTests/images/mask-box-image-crash.html
@@ -2,7 +2,7 @@
 if (window.testRunner)
     testRunner.dumpAsTextWithPixelResults();
 </script>
-<fieldset style="-webkit-margin-end: 99999px;
+<fieldset style="margin-inline-end: 99999px;
                  -webkit-mask-box-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE\
                  IAAABCAQAAAADLLz1FAAAACXZwQWcAAABCAAAAQgCVDTvpAAAAFElEQVQoz2P4DwUHGEZZo6xBwQI\
                  ANWY/j0PofaAAAAAASUVORK5CYII=') 10000% 10000 9999999999%;">
diff --git a/third_party/WebKit/LayoutTests/paint/transparency/compositing-alpha-fold-crash.html b/third_party/WebKit/LayoutTests/paint/transparency/compositing-alpha-fold-crash.html
index 7aae271..479e8e5 100644
--- a/third_party/WebKit/LayoutTests/paint/transparency/compositing-alpha-fold-crash.html
+++ b/third_party/WebKit/LayoutTests/paint/transparency/compositing-alpha-fold-crash.html
@@ -3,6 +3,6 @@
  <body style="opacity:0.5">
 <div style=" -webkit-mask-box-image-source: url();" >
 </div>
-<div style="box-shadow: 1px 1px black; -webkit-padding-before: 1px; isolation: isolate">
+<div style="box-shadow: 1px 1px black; padding-block-start: 1px; isolation: isolate">
 <div style="isolation: isolate"></div>
 </body>
diff --git a/third_party/WebKit/LayoutTests/scrollbars/scrollbar-part-created-with-no-parent-crash.html b/third_party/WebKit/LayoutTests/scrollbars/scrollbar-part-created-with-no-parent-crash.html
index 8ba9295d..8b34409 100644
--- a/third_party/WebKit/LayoutTests/scrollbars/scrollbar-part-created-with-no-parent-crash.html
+++ b/third_party/WebKit/LayoutTests/scrollbars/scrollbar-part-created-with-no-parent-crash.html
@@ -6,7 +6,7 @@
     margin: 0;
 }
 ::-webkit-scrollbar {
-    -webkit-logical-height: 65536;
+    block-size: 65536;
     -webkit-border-image: url(does_not_exist) 0 2 0 2;
 }
 
diff --git a/third_party/WebKit/LayoutTests/scrollbars/scrollbar-percent-padding-crash.html b/third_party/WebKit/LayoutTests/scrollbars/scrollbar-percent-padding-crash.html
index 808b25be..ef2c2789 100644
--- a/third_party/WebKit/LayoutTests/scrollbars/scrollbar-percent-padding-crash.html
+++ b/third_party/WebKit/LayoutTests/scrollbars/scrollbar-percent-padding-crash.html
@@ -3,7 +3,7 @@
 <head>
 <style>
 ::-webkit-scrollbar {
- -webkit-padding-start: 1%; background: #666 -webkit-gradient(linear, left top, right top, from(rgba(255,255,255,0.5)), color-stop(0.5, rgba(255,255,255,0.1)), color-stop(0.5, rgba(0,0,0,0)), to(rgba(0,0,0,0.01)));
+ padding-inline-start: 1%; background: #666 -webkit-gradient(linear, left top, right top, from(rgba(255,255,255,0.5)), color-stop(0.5, rgba(255,255,255,0.1)), color-stop(0.5, rgba(0,0,0,0)), to(rgba(0,0,0,0.01)));
 }
 </style>
 <script>
diff --git a/third_party/WebKit/LayoutTests/svg/as-image/svg-intrinsic-size-rectangular-vertical-expected.html b/third_party/WebKit/LayoutTests/svg/as-image/svg-intrinsic-size-rectangular-vertical-expected.html
index adde32e..39f6897 100644
--- a/third_party/WebKit/LayoutTests/svg/as-image/svg-intrinsic-size-rectangular-vertical-expected.html
+++ b/third_party/WebKit/LayoutTests/svg/as-image/svg-intrinsic-size-rectangular-vertical-expected.html
@@ -2,8 +2,8 @@
 <style>
     div.container {
         -webkit-writing-mode: vertical-rl;
-        -webkit-logical-width: 80px;
-        -webkit-logical-height: 200px;
+        inline-size: 80px;
+        block-size: 200px;
         outline: solid blue;
     }
 </style>
diff --git a/third_party/WebKit/LayoutTests/svg/as-image/svg-intrinsic-size-rectangular-vertical.html b/third_party/WebKit/LayoutTests/svg/as-image/svg-intrinsic-size-rectangular-vertical.html
index 77205ec..fa52028a 100644
--- a/third_party/WebKit/LayoutTests/svg/as-image/svg-intrinsic-size-rectangular-vertical.html
+++ b/third_party/WebKit/LayoutTests/svg/as-image/svg-intrinsic-size-rectangular-vertical.html
@@ -2,8 +2,8 @@
 <style>
     div.container {
         -webkit-writing-mode: vertical-rl;
-        -webkit-logical-width: 80px;
-        -webkit-logical-height: 200px;
+        inline-size: 80px;
+        block-size: 200px;
         outline: solid blue;
     }
 
diff --git a/third_party/WebKit/LayoutTests/svg/transforms/image-cull-rect-transform-change-expected.html b/third_party/WebKit/LayoutTests/svg/transforms/image-cull-rect-transform-change-expected.html
new file mode 100644
index 0000000..cfc2657
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/transforms/image-cull-rect-transform-change-expected.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<svg style="width: 400px; height: 400px">
+  <image xlink:href="../custom/resources/green-rect.svg" width="100" height="100" style="transform: translate(1px, 1px);"></image>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/svg/transforms/image-cull-rect-transform-change.html b/third_party/WebKit/LayoutTests/svg/transforms/image-cull-rect-transform-change.html
new file mode 100644
index 0000000..83eb337
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/transforms/image-cull-rect-transform-change.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<svg style="width: 400px; height: 400px">
+  <image id="image" xlink:href="../custom/resources/green-rect.svg" width="100" height="100"></image>
+</svg>
+<script>
+image.style.transform = "translate(-300px, -300px)";
+if (window.testRunner)
+  testRunner.waitUntilDone();
+onload = function() {
+  runAfterLayoutAndPaint(() => {
+    image.style.transform = "translate(1px, 1px)";
+    window.testRunner.notifyDone();
+  });
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/svg/transforms/rect-cull-rect-transform-change-expected.html b/third_party/WebKit/LayoutTests/svg/transforms/rect-cull-rect-transform-change-expected.html
new file mode 100644
index 0000000..397ddf7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/transforms/rect-cull-rect-transform-change-expected.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<svg style="width: 400px; height: 400px">
+  <rect width="100" height="100" fill="green" style="transform: translate(1px, 1px);"></rect>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/svg/transforms/rect-cull-rect-transform-change.html b/third_party/WebKit/LayoutTests/svg/transforms/rect-cull-rect-transform-change.html
new file mode 100644
index 0000000..0b2eb79
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/svg/transforms/rect-cull-rect-transform-change.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<svg style="width: 400px; height: 400px">
+  <rect id="rect" width="100" height="100" fill="green"></rect>
+</svg>
+<script>
+rect.style.transform = "translate(-300px, -300px)";
+if (window.testRunner)
+  testRunner.waitUntilDone();
+runAfterLayoutAndPaint(() => {
+  rect.style.transform = "translate(1px, 1px)";
+  window.testRunner.notifyDone();
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/touchadjustment/small-target-test.html b/third_party/WebKit/LayoutTests/touchadjustment/small-target-test.html
index 77ae0f8..2b96b28d 100644
--- a/third_party/WebKit/LayoutTests/touchadjustment/small-target-test.html
+++ b/third_party/WebKit/LayoutTests/touchadjustment/small-target-test.html
@@ -7,7 +7,7 @@
 
 <style>
   body {
-    -webkit-margin-start: 20px;
+    margin-inline-start: 20px;
     margin-top: 20px;
   }
   .control-pair {
diff --git a/third_party/WebKit/LayoutTests/xr/resources/xr-device-mocking.js b/third_party/WebKit/LayoutTests/xr/resources/xr-device-mocking.js
index 88b5719d..22058646 100644
--- a/third_party/WebKit/LayoutTests/xr/resources/xr-device-mocking.js
+++ b/third_party/WebKit/LayoutTests/xr/resources/xr-device-mocking.js
@@ -296,7 +296,13 @@
     this.displayClient_ = new device.mojom.VRDisplayClientPtr();
     this.displayInfo_ = displayInfo;
     this.service_ = service;
-    this.presentation_provider_ = new MockVRPresentationProvider();
+    this.presentation_provider_ = new MockXRPresentationProvider();
+
+    this.pose_ = null;
+    this.next_frame_id_ = 0;
+
+    this.input_sources_ = [];
+    this.next_input_source_index_ = 1;
 
     if (service.client_) {
       this.notifyClientOfDisplay();
@@ -306,28 +312,39 @@
   requestSession(sessionOptions, was_activation) {
     return this.supportsSession(sessionOptions).then((result) => {
       // The JavaScript bindings convert c_style_names to camelCase names.
-      var options = new device.mojom.VRDisplayFrameTransportOptions();
+      var options = new device.mojom.XRPresentationTransportOptions();
       options.transportMethod =
-          device.mojom.VRDisplayFrameTransportMethod.SUBMIT_AS_MAILBOX_HOLDER;
+          device.mojom.XRPresentationTransportMethod.SUBMIT_AS_MAILBOX_HOLDER;
       options.waitForTransferNotification = true;
       options.waitForRenderNotification = true;
 
-      let connection;
+      let submit_frame_sink;
       if (result.supportsSession) {
-        connection = {
+        submit_frame_sink = {
           clientRequest: this.presentation_provider_.getClientRequest(),
           provider: this.presentation_provider_.bindProvider(sessionOptions),
           transportOptions: options
         };
 
-        let magicWindowPtr = new device.mojom.VRMagicWindowProviderPtr();
-        let magicWindowRequest = mojo.makeRequest(magicWindowPtr);
-        let magicWindowBinding = new mojo.Binding(
-            device.mojom.VRMagicWindowProvider, this, magicWindowRequest);
+
+        let dataProviderPtr = new device.mojom.XRFrameDataProviderPtr();
+        let dataProviderRequest = mojo.makeRequest(dataProviderPtr);
+        let dataProviderBinding = new mojo.Binding(
+            device.mojom.XRFrameDataProvider, this, dataProviderRequest);
+
+        let enviromentProviderPtr =
+            new device.mojom.XREnviromentIntegrationProviderPtr();
+        let enviromentProviderRequest = mojo.makeRequest(enviromentProviderPtr);
+        let enviromentProviderBinding = new mojo.Binding(
+            device.mojom.XREnviromentIntegrationProvider, this,
+            enviromentProviderRequest);
 
         return Promise.resolve({
-          session:
-              {connection: connection, magicWindowProvider: magicWindowPtr}
+          session: {
+            submitFrameSink: submit_frame_sink,
+            dataProvider: dataProviderPtr,
+            enviromentProvider: enviromentProviderPtr
+          }
         });
       } else {
         return Promise.resolve({session: null});
@@ -344,10 +361,10 @@
 
   setPose(pose) {
     if (pose == null) {
-      this.presentation_provider_.pose_ = null;
+      this.pose_ = null;
     } else {
-      this.presentation_provider_.initPose();
-      this.presentation_provider_.fillPose(pose);
+      this.initPose();
+      this.fillPose(pose);
     }
   }
 
@@ -370,16 +387,33 @@
   }
 
   getFrameData() {
+    if (this.pose_) {
+      this.pose_.poseIndex++;
+
+      let input_states = [];
+      for (let i = 0; i < this.input_sources_.length; ++i) {
+        input_states.push(this.input_sources_[i].getInputSourceState());
+      }
+
+      this.pose_.inputState = input_states;
+    }
+
+    // Convert current document time to monotonic time.
+    var now = window.performance.now() / 1000.0;
+    var diff = now - internals.monotonicTimeToZeroBasedDocumentTime(now);
+    now += diff;
+    now *= 1000000;
+
     return Promise.resolve({
       frameData: {
-        pose: this.presentation_provider_.pose_,
+        pose: this.pose_,
         bufferHolder: null,
         bufferSize: {},
-        timeDelta: [],
-        projectionMatrix: [1, 0, 0, 0,
-                            0, 1, 0, 0,
-                            0, 0, 1, 0,
-                            0, 0, 0, 1]
+        timeDelta: {
+          microseconds: now,
+        },
+        frameId: this.next_frame_id_++,
+        projectionMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
       }
     });
   }
@@ -425,95 +459,6 @@
         displayPtr, clientRequest, this.displayInfo_);
   }
 
-  addInputSource(input_source) {
-    this.presentation_provider_.OnInputSourceAdded(input_source);
-  }
-
-  removeInputSource(input_source) {
-    this.presentation_provider_.OnInputSourceRemoved(input_source);
-  }
-}
-
-class MockVRPresentationProvider {
-  constructor() {
-    this.binding_ =
-        new mojo.Binding(device.mojom.VRPresentationProviderPtr, this);
-    this.pose_ = null;
-    this.next_frame_id_ = 0;
-    this.submit_frame_count_ = 0;
-    this.missing_frame_count_ = 0;
-
-    this.input_sources_ = [];
-    this.next_input_source_index_ = 1;
-  }
-
-  bindProvider(request) {
-    let providerPtr = new device.mojom.VRPresentationProviderPtr();
-    let providerRequest = mojo.makeRequest(providerPtr);
-
-    this.binding_.close();
-
-    this.binding_ = new mojo.Binding(
-        device.mojom.VRPresentationProvider, this, providerRequest);
-
-    return providerPtr;
-  }
-
-  getClientRequest() {
-    this.submitFrameClient_ = new device.mojom.VRSubmitFrameClientPtr();
-    return mojo.makeRequest(this.submitFrameClient_);
-  }
-
-
-  submitFrameMissing(frameId, mailboxHolder, timeWaited) {
-    this.missing_frame_count_++;
-  }
-
-  submitFrame(frameId, mailboxHolder, timeWaited) {
-    this.submit_frame_count_++;
-
-    // Trigger the submit completion callbacks here. WARNING: The
-    // Javascript-based mojo mocks are *not* re-entrant. It's OK to
-    // wait for these notifications on the next frame, but waiting
-    // within the current frame would never finish since the incoming
-    // calls would be queued until the current execution context finishes.
-    this.submitFrameClient_.onSubmitFrameTransferred(true);
-    this.submitFrameClient_.onSubmitFrameRendered();
-  }
-
-  getFrameData() {
-    if (this.pose_) {
-      this.pose_.poseIndex++;
-
-      let input_states = [];
-      for (let i = 0; i < this.input_sources_.length; ++i) {
-        input_states.push(this.input_sources_[i].getInputSourceState());
-      }
-
-      this.pose_.inputState = input_states;
-    }
-
-    // Convert current document time to monotonic time.
-    var now = window.performance.now() / 1000.0;
-    var diff = now - internals.monotonicTimeToZeroBasedDocumentTime(now);
-    now += diff;
-    now *= 1000000;
-
-    return Promise.resolve({
-      frameData: {
-        pose: this.pose_,
-        timeDelta: {
-          microseconds: now,
-        },
-        frameId: this.next_frame_id_++,
-        projectionMatrix : [1, 0, 0, 0,
-                            0, 1, 0, 0,
-                            0, 0, 1, 0,
-                            0, 0, 0, 1]
-      }
-    });
-  }
-
   initPose() {
     this.pose_ = {
       orientation: null,
@@ -536,14 +481,14 @@
     }
   }
 
-  OnInputSourceAdded(input_source) {
+  addInputSource(input_source) {
     let index = this.next_input_source_index_;
     input_source.source_id_ = index;
     this.next_input_source_index_++;
     this.input_sources_.push(input_source);
   }
 
-  OnInputSourceRemoved(input_source) {
+  removeInputSource(input_source) {
     for (let i = 0; i < this.input_sources_.length; ++i) {
       if (input_source.source_id_ == this.input_sources_[i].source_id_) {
         this.input_sources_.splice(i, 1);
@@ -553,6 +498,49 @@
   }
 }
 
+class MockXRPresentationProvider {
+  constructor() {
+    this.binding_ =
+        new mojo.Binding(device.mojom.XRPresentationProviderPtr, this);
+    this.submit_frame_count_ = 0;
+    this.missing_frame_count_ = 0;
+  }
+
+  bindProvider(request) {
+    let providerPtr = new device.mojom.XRPresentationProviderPtr();
+    let providerRequest = mojo.makeRequest(providerPtr);
+
+    this.binding_.close();
+
+    this.binding_ = new mojo.Binding(
+        device.mojom.XRPresentationProvider, this, providerRequest);
+
+    return providerPtr;
+  }
+
+  getClientRequest() {
+    this.submitFrameClient_ = new device.mojom.XRPresentationClientPtr();
+    return mojo.makeRequest(this.submitFrameClient_);
+  }
+
+
+  submitFrameMissing(frameId, mailboxHolder, timeWaited) {
+    this.missing_frame_count_++;
+  }
+
+  submitFrame(frameId, mailboxHolder, timeWaited) {
+    this.submit_frame_count_++;
+
+    // Trigger the submit completion callbacks here. WARNING: The
+    // Javascript-based mojo mocks are *not* re-entrant. It's OK to
+    // wait for these notifications on the next frame, but waiting
+    // within the current frame would never finish since the incoming
+    // calls would be queued until the current execution context finishes.
+    this.submitFrameClient_.onSubmitFrameTransferred(true);
+    this.submitFrameClient_.onSubmitFrameRendered();
+  }
+}
+
 class MockVRService {
   constructor() {
     this.bindingSet_ = new mojo.BindingSet(device.mojom.VRService);
diff --git a/third_party/abseil-cpp/BUILD.gn b/third_party/abseil-cpp/BUILD.gn
index 6005148..4d9f46c4 100644
--- a/third_party/abseil-cpp/BUILD.gn
+++ b/third_party/abseil-cpp/BUILD.gn
@@ -19,28 +19,7 @@
 }
 
 config("absl_include_config") {
-  # Using -isystem (with clang and GCC) and -imsvc (with clang-cl) instead of
-  # include_dirs (-I), so we don't need to suppress warnings coming from
-  # Abseil. Doing so would mask warnings in our own code.
-  if (is_win) {
-    if (is_clang) {
-      # clang-cl:
-      cflags = [
-        "-imsvc",
-        rebase_path(".", root_build_dir),
-      ]
-    } else {
-      # MSVC doesn't have -isystem, in that case we fallback to include_dirs and
-      # we use the warning suppression flags defined in :absl_default_cflags_cc.
-      include_dirs = [ "." ]
-    }
-  } else {
-    # GCC or clang:
-    cflags = [
-      "-isystem",
-      rebase_path(".", root_build_dir),
-    ]
-  }
+  include_dirs = [ "." ]
 }
 
 config("absl_define_config") {
diff --git a/third_party/abseil-cpp/absl/time/BUILD.gn b/third_party/abseil-cpp/absl/time/BUILD.gn
index 7f412bcc..24de31c 100644
--- a/third_party/abseil-cpp/absl/time/BUILD.gn
+++ b/third_party/abseil-cpp/absl/time/BUILD.gn
@@ -14,11 +14,21 @@
   visibility = [ "*" ]
 }
 
+config("suppress_unguarded_availability") {
+  # TODO(bugs.webrtc.org/9557): Remove -Wno-unguarded-availability when
+  # abseil will support Xcode 9.0+ (it currently supports Xcode 7.3.1+
+  # which doesn't have -Wunguarded-availability and __builtin_available).
+  cflags = [
+    "-Wno-unguarded-availability",
+  ]
+}
+
 source_set("time") {
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     "//build/config/compiler:no_chromium_code",
     "//third_party/abseil-cpp:absl_default_cflags_cc",
+    ":suppress_unguarded_availability",
   ]
   public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
   sources = [
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index c6c030a0..4ae8004 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -319,7 +319,6 @@
     "platform/web_native_scroll_behavior.h",
     "platform/web_network_state_notifier.h",
     "platform/web_platform_event_listener.h",
-    "platform/web_platform_event_type.h",
     "platform/web_point.h",
     "platform/web_pointer_event.h",
     "platform/web_pointer_properties.h",
diff --git a/third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom b/third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom
index af3a5239..fb00f88 100644
--- a/third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom
+++ b/third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom
@@ -73,7 +73,8 @@
   UpdateUI(int64 service_worker_registration_id,
            string developer_id,
            string unique_id,
-           string title)
+           string? title,
+           skia.mojom.Bitmap? icon)
       => (BackgroundFetchError error);
 
   // Aborts the Background Fetch registration identified by |unique_id| and
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index ff0d114..3c22845 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -55,7 +55,6 @@
 #include "third_party/blink/public/platform/web_gamepad_listener.h"
 #include "third_party/blink/public/platform/web_gesture_device.h"
 #include "third_party/blink/public/platform/web_localized_string.h"
-#include "third_party/blink/public/platform/web_platform_event_type.h"
 #include "third_party/blink/public/platform/web_rtc_api_name.h"
 #include "third_party/blink/public/platform/web_size.h"
 #include "third_party/blink/public/platform/web_speech_synthesizer.h"
diff --git a/third_party/blink/public/platform/web_platform_event_type.h b/third_party/blink/public/platform/web_platform_event_type.h
deleted file mode 100644
index 91c1e2f5..0000000
--- a/third_party/blink/public/platform/web_platform_event_type.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_PLATFORM_EVENT_TYPE_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_PLATFORM_EVENT_TYPE_H_
-
-namespace blink {
-
-enum WebPlatformEventType {
-  kWebPlatformEventTypeDeviceMotion,
-  kWebPlatformEventTypeDeviceOrientation,
-  kWebPlatformEventTypeDeviceOrientationAbsolute,
-  kWebPlatformEventTypeGamepad,
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_PLATFORM_EVENT_TYPE_H_
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h
index 895bd6cb..ea32357e 100644
--- a/third_party/blink/public/platform/web_runtime_features.h
+++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -191,6 +191,7 @@
   BLINK_PLATFORM_EXPORT static void EnableV8ContextSnapshot(bool);
   BLINK_PLATFORM_EXPORT static void EnableAutomationControlled(bool);
   BLINK_PLATFORM_EXPORT static void EnableWorkStealingInScriptRunner(bool);
+  BLINK_PLATFORM_EXPORT static void EnableScheduledScriptStreaming(bool);
   BLINK_PLATFORM_EXPORT static void EnableStopInBackground(bool);
   BLINK_PLATFORM_EXPORT static void EnableStopNonTimersInBackground(bool);
   BLINK_PLATFORM_EXPORT static void EnablePWAFullCodeCache(bool);
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
index 70f3cbd..9e56a7092 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -13,12 +13,15 @@
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
+#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
 #include "third_party/blink/renderer/core/script/classic_pending_script.h"
 #include "third_party/blink/renderer/platform/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/histogram.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/scheduler/public/background_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/shared_buffer.h"
 #include "third_party/blink/renderer/platform/wtf/deque.h"
@@ -392,6 +395,19 @@
   streaming_suppressed_ = true;
 }
 
+static void RunScriptStreamingTask(
+    std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task,
+    ScriptStreamer* streamer) {
+  TRACE_EVENT1(
+      "v8,devtools.timeline", "v8.parseOnBackground", "data",
+      InspectorParseScriptEvent::Data(streamer->ScriptResourceIdentifier(),
+                                      streamer->ScriptURLString()));
+  // Running the task can and will block: SourceStream::GetSomeData will get
+  // called and it will block and wait for data from the network.
+  task->Run();
+  streamer->StreamingCompleteOnBackgroundThread();
+}
+
 void ScriptStreamer::NotifyAppendData(ScriptResource* resource) {
   DCHECK(IsMainThread());
   if (streaming_suppressed_)
@@ -436,11 +452,12 @@
       }
     }
 
-    if (ScriptStreamerThread::Shared()->IsRunningTask()) {
-      // At the moment we only have one thread for running the tasks. A
-      // new task shouldn't be queued before the running task completes,
-      // because the running task can block and wait for data from the
-      // network.
+    if (!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled() &&
+        ScriptStreamerThread::Shared()->IsRunningTask()) {
+      // If scheduled script streaming is disabled, we only have one thread for
+      // running the tasks. A new task shouldn't be queued before the running
+      // task completes, because the running task can block and wait for data
+      // from the network.
       SuppressStreaming();
       RecordNotStreamingReasonHistogram(script_type_, kThreadBusy);
       RecordStartedStreamingHistogram(script_type_, 0);
@@ -476,10 +493,24 @@
       return;
     }
 
-    ScriptStreamerThread::Shared()->PostTask(
-        CrossThreadBind(&ScriptStreamerThread::RunScriptStreamingTask,
-                        WTF::Passed(std::move(script_streaming_task)),
-                        WrapCrossThreadPersistent(this)));
+    if (RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled()) {
+      // Script streaming tasks are high priority, as they can block the
+      // parser, and they can (and probably will) block during their own
+      // execution as they wait for more input.
+      //
+      // TODO(leszeks): Decrease the priority of these tasks where possible.
+      BackgroundScheduler::PostOnBackgroundThreadWithTraits(
+          FROM_HERE, {base::TaskPriority::USER_BLOCKING, base::MayBlock()},
+          CrossThreadBind(RunScriptStreamingTask,
+                          WTF::Passed(std::move(script_streaming_task)),
+                          WrapCrossThreadPersistent(this)));
+    } else {
+      ScriptStreamerThread::Shared()->PostTask(
+          CrossThreadBind(&ScriptStreamerThread::RunScriptStreamingTask,
+                          WTF::Passed(std::move(script_streaming_task)),
+                          WrapCrossThreadPersistent(this)));
+    }
+
     RecordStartedStreamingHistogram(script_type_, 1);
   }
   if (stream_)
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
index 0ea5e53..6111fec 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
@@ -108,8 +108,10 @@
   }
 
   void ProcessTasksUntilStreamingComplete() {
-    while (ScriptStreamerThread::Shared()->IsRunningTask()) {
-      test::RunPendingTasks();
+    if (!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled()) {
+      while (ScriptStreamerThread::Shared()->IsRunningTask()) {
+        test::RunPendingTasks();
+      }
     }
     // Once more, because the "streaming complete" notification might only
     // now be in the task queue.
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.cc
index a197c9d..9051edde 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
 #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/web_task_runner.h"
 
 namespace blink {
@@ -22,19 +23,24 @@
 static Mutex* g_mutex = nullptr;
 
 void ScriptStreamerThread::Init() {
-  DCHECK(!g_shared_thread);
-  DCHECK(IsMainThread());
-  // This is called in the main thread before any tasks are created, so no
-  // locking is needed.
-  g_mutex = new Mutex();
-  g_shared_thread = new ScriptStreamerThread();
+  // Only enabled when ScheduledScriptStreaming is disabled.
+  if (!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled()) {
+    DCHECK(!g_shared_thread);
+    DCHECK(IsMainThread());
+    // This is called in the main thread before any tasks are created, so no
+    // locking is needed.
+    g_mutex = new Mutex();
+    g_shared_thread = new ScriptStreamerThread();
+  }
 }
 
 ScriptStreamerThread* ScriptStreamerThread::Shared() {
+  DCHECK(!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled());
   return g_shared_thread;
 }
 
 void ScriptStreamerThread::PostTask(CrossThreadClosure task) {
+  DCHECK(!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled());
   DCHECK(IsMainThread());
   MutexLocker locker(mutex_);
   DCHECK(!running_task_);
@@ -60,6 +66,7 @@
 void ScriptStreamerThread::RunScriptStreamingTask(
     std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> task,
     ScriptStreamer* streamer) {
+  DCHECK(!RuntimeEnabledFeatures::ScheduledScriptStreamingEnabled());
   TRACE_EVENT1(
       "v8,devtools.timeline", "v8.parseOnBackground", "data",
       InspectorParseScriptEvent::Data(streamer->ScriptResourceIdentifier(),
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
index 292660ef..ec89538 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
@@ -581,8 +581,8 @@
                                                       size_t size,
                                                       size_t* actual_size) {
   *actual_size = WTF::Partitions::BufferActualSize(size);
-  return WTF::Partitions::BufferRealloc(old_buffer, *actual_size,
-                                        "SerializedScriptValue buffer");
+  return WTF::Partitions::BufferTryRealloc(old_buffer, *actual_size,
+                                           "SerializedScriptValue buffer");
 }
 
 void V8ScriptValueSerializer::FreeBufferMemory(void* buffer) {
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h
index 7d74e07..7d8031f 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h
@@ -93,6 +93,9 @@
   v8::Maybe<uint32_t> GetWasmModuleTransferId(
       v8::Isolate*,
       v8::Local<v8::WasmCompiledModule>) override;
+  // Reallocates memory at |ptr| to the new size and returns the new pointer or
+  // nullptr on failure. |actual_size| will hold the actual size of allocation
+  // requested.
   void* ReallocateBufferMemory(void* old_buffer,
                                size_t,
                                size_t* actual_size) override;
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
index 26154ed..fd56d312 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
@@ -20,6 +20,103 @@
 
 namespace {
 
+// The |FetchDataLoader| for streaming compilation of WebAssembly code. The
+// received bytes get forwarded to the V8 API class |WasmStreaming|.
+class FetchDataLoaderForWasmStreaming final : public FetchDataLoader,
+                                              public BytesConsumer::Client {
+  USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderForWasmStreaming);
+
+ public:
+  FetchDataLoaderForWasmStreaming(ScriptState* script_state,
+                                  std::shared_ptr<v8::WasmStreaming> streaming)
+      : streaming_(std::move(streaming)), script_state_(script_state) {}
+
+  void Start(BytesConsumer* consumer,
+             FetchDataLoader::Client* client) override {
+    DCHECK(!consumer_);
+    DCHECK(!client_);
+    client_ = client;
+    consumer_ = consumer;
+    consumer_->SetClient(this);
+    OnStateChange();
+  }
+
+  void OnStateChange() override {
+    while (true) {
+      // |buffer| is owned by |consumer_|.
+      const char* buffer = nullptr;
+      size_t available = 0;
+      BytesConsumer::Result result = consumer_->BeginRead(&buffer, &available);
+
+      if (result == BytesConsumer::Result::kShouldWait)
+        return;
+      if (result == BytesConsumer::Result::kOk) {
+        if (available > 0) {
+          DCHECK_NE(buffer, nullptr);
+          streaming_->OnBytesReceived(reinterpret_cast<const uint8_t*>(buffer),
+                                      available);
+        }
+        result = consumer_->EndRead(available);
+      }
+      switch (result) {
+        case BytesConsumer::Result::kShouldWait:
+          NOTREACHED();
+          return;
+        case BytesConsumer::Result::kOk: {
+          break;
+        }
+        case BytesConsumer::Result::kDone: {
+          streaming_->Finish();
+          client_->DidFetchDataLoadedCustomFormat();
+          return;
+        }
+        case BytesConsumer::Result::kError: {
+          return AbortCompilation();
+        }
+      }
+    }
+  }
+
+  String DebugName() const override { return "FetchDataLoaderForWasmModule"; }
+
+  void Cancel() override {
+    consumer_->Cancel();
+    return AbortCompilation();
+  }
+
+  void Trace(blink::Visitor* visitor) override {
+    visitor->Trace(consumer_);
+    visitor->Trace(client_);
+    visitor->Trace(script_state_);
+    FetchDataLoader::Trace(visitor);
+    BytesConsumer::Client::Trace(visitor);
+  }
+
+ private:
+  // TODO(ahaas): replace with spec-ed error types, once spec clarifies
+  // what they are.
+  void AbortCompilation() {
+    if (script_state_->ContextIsValid()) {
+      ScriptState::Scope scope(script_state_);
+      streaming_->Abort(V8ThrowException::CreateTypeError(
+          script_state_->GetIsolate(), "Could not download wasm module"));
+    } else {
+      // We are not allowed to execute a script, which indicates that we should
+      // not reject the promise of the streaming compilation. By passing no
+      // abort reason, we indicate the V8 side that the promise should not get
+      // rejected.
+      streaming_->Abort(v8::Local<v8::Value>());
+    }
+  }
+  Member<BytesConsumer> consumer_;
+  Member<FetchDataLoader::Client> client_;
+  std::shared_ptr<v8::WasmStreaming> streaming_;
+  const Member<ScriptState> script_state_;
+};
+
+// TODO(ahaas): Remove |FetchDataLoaderAsWasmModule| once the
+// |SetWasmCompileStreamingCallback| API is successfully replaced by the
+// |SetWasmStreamingCallback| API.
 class FetchDataLoaderAsWasmModule final : public FetchDataLoader,
                                           public BytesConsumer::Client {
   USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsWasmModule);
@@ -42,7 +139,7 @@
 
   void OnStateChange() override {
     while (true) {
-      // {buffer} is owned by {m_consumer}.
+      // |buffer| is owned by |consumer_|.
       const char* buffer = nullptr;
       size_t available = 0;
       BytesConsumer::Result result = consumer_->BeginRead(&buffer, &available);
@@ -96,8 +193,8 @@
   // TODO(mtrofin): replace with spec-ed error types, once spec clarifies
   // what they are.
   void AbortCompilation() {
-    ScriptState::Scope scope(script_state_);
-    if (!ExecutionContext::From(script_state_)->IsContextDestroyed()) {
+    if (script_state_->ContextIsValid()) {
+      ScriptState::Scope scope(script_state_);
       builder_.Abort(V8ThrowException::CreateTypeError(
           script_state_->GetIsolate(), "Could not download wasm module"));
     } else {
@@ -135,6 +232,97 @@
   }
 };
 
+// ExceptionToAbortStreamingScope converts a possible exception to an abort
+// message for WasmStreaming instead of throwing the exception.
+//
+// All exceptions which happen in the setup of WebAssembly streaming compilation
+// have to be passed as an abort message to V8 so that V8 can reject the promise
+// associated to the streaming compilation.
+class ExceptionToAbortStreamingScope {
+  STACK_ALLOCATED();
+  WTF_MAKE_NONCOPYABLE(ExceptionToAbortStreamingScope);
+
+ public:
+  ExceptionToAbortStreamingScope(std::shared_ptr<v8::WasmStreaming> streaming,
+                                 ExceptionState& exception_state)
+      : streaming_(streaming), exception_state_(exception_state) {}
+
+  ~ExceptionToAbortStreamingScope() {
+    if (!exception_state_.HadException())
+      return;
+
+    streaming_->Abort(exception_state_.GetException());
+    exception_state_.ClearException();
+  }
+
+ private:
+  std::shared_ptr<v8::WasmStreaming> streaming_;
+  ExceptionState& exception_state_;
+};
+
+void StreamFromResponseCallback(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  ExceptionState exception_state(args.GetIsolate(),
+                                 ExceptionState::kExecutionContext,
+                                 "WebAssembly", "compile");
+  std::shared_ptr<v8::WasmStreaming> streaming =
+      v8::WasmStreaming::Unpack(args.GetIsolate(), args.Data());
+  ExceptionToAbortStreamingScope exception_scope(streaming, exception_state);
+
+  ScriptState* script_state = ScriptState::ForCurrentRealm(args);
+  if (!script_state->ContextIsValid()) {
+    // We do not have an execution context, we just abort streaming compilation
+    // immediately without error.
+    streaming->Abort(v8::Local<v8::Value>());
+    return;
+  }
+
+  Response* response =
+      V8Response::ToImplWithTypeCheck(args.GetIsolate(), args[0]);
+  if (!response) {
+    exception_state.ThrowTypeError(
+        "An argument must be provided, which must be a "
+        "Response or Promise<Response> object");
+    return;
+  }
+
+  if (!response->ok()) {
+    exception_state.ThrowTypeError("HTTP status code is not ok");
+    return;
+  }
+
+  if (response->MimeType() != "application/wasm") {
+    exception_state.ThrowTypeError(
+        "Incorrect response MIME type. Expected 'application/wasm'.");
+    return;
+  }
+
+  Body::BodyLocked body_locked = response->IsBodyLocked(exception_state);
+  if (body_locked == Body::BodyLocked::kBroken)
+    return;
+
+  if (body_locked == Body::BodyLocked::kLocked ||
+      response->IsBodyUsed(exception_state) == Body::BodyUsed::kUsed) {
+    DCHECK(!exception_state.HadException());
+    exception_state.ThrowTypeError(
+        "Cannot compile WebAssembly.Module from an already read Response");
+    return;
+  }
+
+  if (exception_state.HadException())
+    return;
+
+  if (!response->BodyBuffer()) {
+    exception_state.ThrowTypeError("Response object has a null body.");
+    return;
+  }
+
+  FetchDataLoaderForWasmStreaming* loader =
+      new FetchDataLoaderForWasmStreaming(script_state, streaming);
+  response->BodyBuffer()->StartLoading(loader, new WasmDataLoaderClient(),
+                                       exception_state);
+}
+
 // This callback may be entered as a promise is resolved, or directly
 // from the overload callback.
 // See
@@ -147,7 +335,7 @@
   ExceptionToRejectPromiseScope reject_promise_scope(args, exception_state);
 
   ScriptState* script_state = ScriptState::ForCurrentRealm(args);
-  if (!ExecutionContext::From(script_state)) {
+  if (!script_state->ContextIsValid()) {
     V8SetReturnValue(args, ScriptPromise().V8Value());
     return;
   }
@@ -172,13 +360,18 @@
     return;
   }
 
-  if (response->IsBodyLocked(exception_state) == Body::BodyLocked::kLocked ||
+  Body::BodyLocked body_locked = response->IsBodyLocked(exception_state);
+  if (body_locked == Body::BodyLocked::kBroken)
+    return;
+
+  if (body_locked == Body::BodyLocked::kLocked ||
       response->IsBodyUsed(exception_state) == Body::BodyUsed::kUsed) {
     DCHECK(!exception_state.HadException());
     exception_state.ThrowTypeError(
         "Cannot compile WebAssembly.Module from an already read Response");
     return;
   }
+
   if (exception_state.HadException())
     return;
 
@@ -234,6 +427,7 @@
 void WasmResponseExtensions::Initialize(v8::Isolate* isolate) {
   if (RuntimeEnabledFeatures::WebAssemblyStreamingEnabled()) {
     isolate->SetWasmCompileStreamingCallback(WasmCompileStreamingImpl);
+    isolate->SetWasmStreamingCallback(StreamFromResponseCallback);
   }
 }
 
diff --git a/third_party/blink/renderer/bindings/modules/BUILD.gn b/third_party/blink/renderer/bindings/modules/BUILD.gn
index 1fe835b..01b6956d 100644
--- a/third_party/blink/renderer/bindings/modules/BUILD.gn
+++ b/third_party/blink/renderer/bindings/modules/BUILD.gn
@@ -22,7 +22,6 @@
     "//third_party/blink/renderer/modules/background_fetch/background_fetch_click_event.idl",
     "//third_party/blink/renderer/modules/background_fetch/background_fetch_event.idl",
     "//third_party/blink/renderer/modules/background_fetch/background_fetch_fail_event.idl",
-    "//third_party/blink/renderer/modules/background_fetch/background_fetched_event.idl",
     "//third_party/blink/renderer/modules/background_sync/sync_event.idl",
     "//third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl",
     "//third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl",
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 71b6440..4f46e9bf 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -415,9 +415,13 @@
 
     if (!LowLatencyEnabled())
       canvas2d_bridge_->FinalizeFrame();
+  }
 
-    if (LowLatencyEnabled() && !dirty_rect_.IsEmpty() &&
-        GetOrCreateCanvasResourceProvider(kPreferAcceleration)) {
+  if (LowLatencyEnabled() && !dirty_rect_.IsEmpty()) {
+    AccelerationHint hint =
+        Is2d() ? kPreferNoAcceleration : kPreferAcceleration;
+    if (GetOrCreateCanvasResourceProvider(hint)) {
+      ResourceProvider()->TryEnableSingleBuffering();
       // Push a frame
       base::TimeTicks start_time = WTF::CurrentTimeTicks();
       scoped_refptr<CanvasResource> canvas_resource =
@@ -1138,9 +1142,8 @@
 scoped_refptr<Image> HTMLCanvasElement::CopiedImage(
     SourceDrawingBuffer source_buffer,
     AccelerationHint hint) {
-  if (SurfaceLayerBridge()) {
+  if (PlaceholderFrame())
     return PlaceholderFrame()->Bitmap();
-  }
 
   if (!IsPaintable())
     return nullptr;
diff --git a/third_party/blink/renderer/core/paint/BUILD.gn b/third_party/blink/renderer/core/paint/BUILD.gn
index f4738106..b7663d0d 100644
--- a/third_party/blink/renderer/core/paint/BUILD.gn
+++ b/third_party/blink/renderer/core/paint/BUILD.gn
@@ -216,6 +216,8 @@
     "svg_inline_text_box_painter.h",
     "svg_mask_painter.cc",
     "svg_mask_painter.h",
+    "svg_model_object_painter.cc",
+    "svg_model_object_painter.h",
     "svg_paint_context.cc",
     "svg_paint_context.h",
     "svg_root_inline_box_painter.cc",
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.cc b/third_party/blink/renderer/core/paint/paint_layer_painter.cc
index 8760ba53..dcf00696 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_painter.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_painter.cc
@@ -817,9 +817,12 @@
     PaintLayerFlags paint_flags,
     const PaintLayerFragment& fragment,
     const LayoutSize& subpixel_accumulation) {
-  // Now do a paint with the root layer shifted to be us. The cull rect
-  // is infinite to simplify invalidation of clip property node changes across
-  // transform boundaries.
+  // Now do a paint with the root layer shifted to be us.
+
+  // We do not apply cull rect optimizations across transforms for two reasons:
+  //   1) Performance: We can optimize transform changes by not repainting.
+  //   2) Complexity: Difficulty updating clips when ancestor transforms change.
+  // For these reasons, we use an infinite dirty rect here.
   PaintLayerPaintingInfo new_paint_info(
       &paint_layer_, LayoutRect(LayoutRect::InfiniteIntRect()),
       painting_info.GetGlobalPaintFlags(), subpixel_accumulation);
diff --git a/third_party/blink/renderer/core/paint/svg_container_painter.cc b/third_party/blink/renderer/core/paint/svg_container_painter.cc
index 13e54af..58e7b810 100644
--- a/third_party/blink/renderer/core/paint/svg_container_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_container_painter.cc
@@ -13,6 +13,7 @@
 #include "third_party/blink/renderer/core/paint/object_painter.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/svg_foreign_object_painter.h"
+#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
 #include "third_party/blink/renderer/core/paint/svg_paint_context.h"
 #include "third_party/blink/renderer/core/svg/svg_svg_element.h"
 
@@ -24,11 +25,6 @@
       !layout_svg_container_.SelfWillPaint())
     return;
 
-  FloatRect bounding_box =
-      layout_svg_container_.VisualRectInLocalSVGCoordinates();
-  // LayoutSVGHiddenContainer's visual rect is always empty but we need to
-  // paint its descendants.
-
   // Spec: An empty viewBox on the <svg> element disables rendering.
   DCHECK(layout_svg_container_.GetElement());
   if (IsSVGSVGElement(*layout_svg_container_.GetElement()) &&
@@ -37,17 +33,19 @@
 
   PaintInfo paint_info_before_filtering(paint_info);
 
-  // Content underneath transforms applies an infinite cull rect. This is
-  // to simplify invalidation of clip property node changes across transform
-  // boundaries.
+  if (SVGModelObjectPainter(layout_svg_container_)
+          .CullRectSkipsPainting(paint_info_before_filtering)) {
+    return;
+  }
+
+  // We do not apply cull rect optimizations across transforms for two reasons:
+  //   1) Performance: We can optimize transform changes by not repainting.
+  //   2) Complexity: Difficulty updating clips when ancestor transforms change.
+  // This is why we use an infinite cull rect if there is a transform. Non-svg
+  // content, does this in PaintLayerPainter::PaintSingleFragment.
   if (layout_svg_container_.StyleRef().HasTransform()) {
     paint_info_before_filtering.ApplyInfiniteCullRect();
   } else {
-    if (!layout_svg_container_.IsSVGHiddenContainer() &&
-        !paint_info.GetCullRect().IntersectsCullRect(
-            layout_svg_container_.LocalToSVGParentTransform(), bounding_box))
-      return;
-
     paint_info_before_filtering.UpdateCullRect(
         layout_svg_container_.LocalToSVGParentTransform());
   }
@@ -94,20 +92,14 @@
     }
   }
 
-  if (paint_info_before_filtering.phase != PaintPhase::kForeground)
-    return;
+  SVGModelObjectPainter(layout_svg_container_)
+      .PaintOutline(paint_info_before_filtering);
 
-  if (layout_svg_container_.Style()->OutlineWidth() &&
-      layout_svg_container_.Style()->Visibility() == EVisibility::kVisible) {
-    PaintInfo outline_paint_info(paint_info_before_filtering);
-    outline_paint_info.phase = PaintPhase::kSelfOutlineOnly;
-    ObjectPainter(layout_svg_container_)
-        .PaintOutline(outline_paint_info, LayoutPoint(bounding_box.Location()));
-  }
-
-  if (paint_info_before_filtering.IsPrinting())
+  if (paint_info_before_filtering.IsPrinting() &&
+      paint_info_before_filtering.phase == PaintPhase::kForeground) {
     ObjectPainter(layout_svg_container_)
         .AddPDFURLRectIfNeeded(paint_info_before_filtering, LayoutPoint());
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/svg_image_painter.cc b/third_party/blink/renderer/core/paint/svg_image_painter.cc
index 977d09f..93d3611f 100644
--- a/third_party/blink/renderer/core/paint/svg_image_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_image_painter.cc
@@ -4,20 +4,15 @@
 
 #include "third_party/blink/renderer/core/paint/svg_image_painter.h"
 
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/layout/layout_image_resource.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
-#include "third_party/blink/renderer/core/page/chrome_client.h"
-#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/paint/object_painter.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
+#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
 #include "third_party/blink/renderer/core/paint/svg_paint_context.h"
 #include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
 #include "third_party/blink/renderer/core/svg/svg_image_element.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
 #include "third_party/blink/renderer/platform/graphics/scoped_interpolation_quality.h"
 
 namespace blink {
@@ -28,13 +23,14 @@
       !layout_svg_image_.ImageResource()->HasImage())
     return;
 
-  FloatRect bounding_box = layout_svg_image_.VisualRectInLocalSVGCoordinates();
-  if (!paint_info.GetCullRect().IntersectsCullRect(
-          layout_svg_image_.LocalToSVGParentTransform(), bounding_box))
-    return;
-
   PaintInfo paint_info_before_filtering(paint_info);
-  // Images cannot have children so do not call updateCullRect.
+
+  if (SVGModelObjectPainter(layout_svg_image_)
+          .CullRectSkipsPainting(paint_info_before_filtering)) {
+    return;
+  }
+  // Images cannot have children so do not call UpdateCullRect.
+
   SVGTransformContext transform_context(
       paint_info_before_filtering, layout_svg_image_,
       layout_svg_image_.LocalToSVGParentTransform());
@@ -52,12 +48,8 @@
     }
   }
 
-  if (layout_svg_image_.Style()->OutlineWidth()) {
-    PaintInfo outline_paint_info(paint_info_before_filtering);
-    outline_paint_info.phase = PaintPhase::kSelfOutlineOnly;
-    ObjectPainter(layout_svg_image_)
-        .PaintOutline(outline_paint_info, LayoutPoint(bounding_box.Location()));
-  }
+  SVGModelObjectPainter(layout_svg_image_)
+      .PaintOutline(paint_info_before_filtering);
 }
 
 void SVGImagePainter::PaintForeground(const PaintInfo& paint_info) {
diff --git a/third_party/blink/renderer/core/paint/svg_model_object_painter.cc b/third_party/blink/renderer/core/paint/svg_model_object_painter.cc
new file mode 100644
index 0000000..956f01c
--- /dev/null
+++ b/third_party/blink/renderer/core/paint/svg_model_object_painter.cc
@@ -0,0 +1,46 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
+
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h"
+#include "third_party/blink/renderer/core/paint/object_painter.h"
+#include "third_party/blink/renderer/core/paint/paint_info.h"
+
+namespace blink {
+
+bool SVGModelObjectPainter::CullRectSkipsPainting(const PaintInfo& paint_info) {
+  // We do not apply cull rect optimizations across transforms for two reasons:
+  //   1) Performance: We can optimize transform changes by not repainting.
+  //   2) Complexity: Difficulty updating clips when ancestor transforms change.
+  // For these reasons, we do not cull painting if there is a transform.
+  if (layout_svg_model_object_.StyleRef().HasTransform())
+    return false;
+
+  // LayoutSVGHiddenContainer's visual rect is always empty but we need to
+  // paint its descendants so we cannot skip painting.
+  if (layout_svg_model_object_.IsSVGHiddenContainer())
+    return false;
+
+  return !paint_info.GetCullRect().IntersectsCullRect(
+      layout_svg_model_object_.LocalToSVGParentTransform(),
+      layout_svg_model_object_.VisualRectInLocalSVGCoordinates());
+}
+
+void SVGModelObjectPainter::PaintOutline(const PaintInfo& paint_info) {
+  if (paint_info.phase != PaintPhase::kForeground)
+    return;
+  if (layout_svg_model_object_.Style()->Visibility() != EVisibility::kVisible)
+    return;
+  if (!layout_svg_model_object_.Style()->OutlineWidth())
+    return;
+
+  PaintInfo outline_paint_info(paint_info);
+  outline_paint_info.phase = PaintPhase::kSelfOutlineOnly;
+  auto visual_rect = layout_svg_model_object_.VisualRectInLocalSVGCoordinates();
+  ObjectPainter(layout_svg_model_object_)
+      .PaintOutline(outline_paint_info, LayoutPoint(visual_rect.Location()));
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/svg_model_object_painter.h b/third_party/blink/renderer/core/paint/svg_model_object_painter.h
new file mode 100644
index 0000000..6f3df6d
--- /dev/null
+++ b/third_party/blink/renderer/core/paint/svg_model_object_painter.h
@@ -0,0 +1,35 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SVG_MODEL_OBJECT_PAINTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SVG_MODEL_OBJECT_PAINTER_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+struct PaintInfo;
+class LayoutSVGModelObject;
+
+class SVGModelObjectPainter {
+  STACK_ALLOCATED();
+
+ public:
+  SVGModelObjectPainter(const LayoutSVGModelObject& layout_svg_model_object)
+      : layout_svg_model_object_(layout_svg_model_object) {}
+
+  // If the object is outside the cull rect, painting can be skipped in most
+  // cases. An important exception is when there is a transform style: see the
+  // comment in the implementation.
+  bool CullRectSkipsPainting(const PaintInfo&);
+
+  void PaintOutline(const PaintInfo&);
+
+ private:
+  const LayoutSVGModelObject& layout_svg_model_object_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SVG_MODEL_OBJECT_PAINTER_H_
diff --git a/third_party/blink/renderer/core/paint/svg_shape_painter.cc b/third_party/blink/renderer/core/paint/svg_shape_painter.cc
index ea42ac8b..2c8ed98 100644
--- a/third_party/blink/renderer/core/paint/svg_shape_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_shape_painter.cc
@@ -11,9 +11,9 @@
 #include "third_party/blink/renderer/core/layout/svg/svg_marker_data.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
-#include "third_party/blink/renderer/core/paint/object_painter.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/svg_container_painter.h"
+#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
 #include "third_party/blink/renderer/core/paint/svg_paint_context.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
@@ -46,13 +46,14 @@
       layout_svg_shape_.IsShapeEmpty())
     return;
 
-  FloatRect bounding_box = layout_svg_shape_.VisualRectInLocalSVGCoordinates();
-  if (!paint_info.GetCullRect().IntersectsCullRect(
-          layout_svg_shape_.LocalSVGTransform(), bounding_box))
-    return;
-
   PaintInfo paint_info_before_filtering(paint_info);
-  // Shapes cannot have children so do not call updateCullRect.
+
+  if (SVGModelObjectPainter(layout_svg_shape_)
+          .CullRectSkipsPainting(paint_info_before_filtering)) {
+    return;
+  }
+  // Shapes cannot have children so do not call UpdateCullRect.
+
   SVGTransformContext transform_context(paint_info_before_filtering,
                                         layout_svg_shape_,
                                         layout_svg_shape_.LocalSVGTransform());
@@ -124,7 +125,8 @@
             }
             break;
           case PT_MARKERS:
-            PaintMarkers(paint_context.GetPaintInfo(), bounding_box);
+            PaintMarkers(paint_context.GetPaintInfo(),
+                         layout_svg_shape_.VisualRectInLocalSVGCoordinates());
             break;
           default:
             NOTREACHED();
@@ -134,12 +136,8 @@
     }
   }
 
-  if (layout_svg_shape_.Style()->OutlineWidth()) {
-    PaintInfo outline_paint_info(paint_info_before_filtering);
-    outline_paint_info.phase = PaintPhase::kSelfOutlineOnly;
-    ObjectPainter(layout_svg_shape_)
-        .PaintOutline(outline_paint_info, LayoutPoint(bounding_box.Location()));
-  }
+  SVGModelObjectPainter(layout_svg_shape_)
+      .PaintOutline(paint_info_before_filtering);
 }
 
 class PathWithTemporaryWindingRule {
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js b/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
index 57bf5fb7..b020a21 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
+++ b/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
@@ -209,6 +209,9 @@
    */
   async linkifyObject(snapshotObjectId) {
     const heapProfilerModel = this._profile.heapProfilerModel();
+    // heapProfilerModel is null if snapshot was loaded from file
+    if (!heapProfilerModel)
+      return null;
     const remoteObject = await heapProfilerModel.objectForSnapshotObjectId(String(snapshotObjectId), 'link');
     if (!remoteObject || remoteObject.type !== 'function')
       return null;
diff --git a/third_party/blink/renderer/modules/background_fetch/BUILD.gn b/third_party/blink/renderer/modules/background_fetch/BUILD.gn
index 831d97f..0cd04774 100644
--- a/third_party/blink/renderer/modules/background_fetch/BUILD.gn
+++ b/third_party/blink/renderer/modules/background_fetch/BUILD.gn
@@ -32,8 +32,6 @@
     "background_fetch_type_converters.h",
     "background_fetch_update_event.cc",
     "background_fetch_update_event.h",
-    "background_fetched_event.cc",
-    "background_fetched_event.h",
     "service_worker_global_scope_background_fetch.h",
     "service_worker_registration_background_fetch.cc",
     "service_worker_registration_background_fetch.h",
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
index 2ed7682..ca9a66d 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
@@ -69,10 +69,17 @@
 void BackgroundFetchBridge::UpdateUI(const String& developer_id,
                                      const String& unique_id,
                                      const String& title,
+                                     const SkBitmap& icon,
                                      UpdateUICallback callback) {
+  if (title.IsNull() && icon.isNull()) {
+    std::move(callback).Run(
+        mojom::blink::BackgroundFetchError::INVALID_ARGUMENT);
+    return;
+  }
+
   GetService()->UpdateUI(
       GetSupplementable()->WebRegistration()->RegistrationId(), developer_id,
-      unique_id, title, std::move(callback));
+      unique_id, title, icon, std::move(callback));
 }
 
 void BackgroundFetchBridge::GetRegistration(const String& developer_id,
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h b/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h
index 652f8ff..8e48fa0 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h
@@ -60,11 +60,12 @@
   void GetIconDisplaySize(GetIconDisplaySizeCallback callback);
 
   // Updates the user interface for the Background Fetch identified by
-  // |unique_id| with the updated |title|. Will invoke the |callback| when the
-  // interface has been requested to update.
+  // |unique_id| with the updated |title| or |icon|. Will invoke the |callback|
+  // when the interface has been requested to update.
   void UpdateUI(const String& developer_id,
                 const String& unique_id,
                 const String& title,
+                const SkBitmap& icon,
                 UpdateUICallback callback);
 
   // Aborts the active Background Fetch for |unique_id|. Will invoke the
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.cc
index c1aeb79..8f57469d7 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.cc
@@ -7,11 +7,13 @@
 #include "third_party/blink/public/platform/modules/background_fetch/web_background_fetch_settled_fetch.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/fetch/request.h"
 #include "third_party/blink/renderer/core/fetch/response.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h"
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_settled_fetch.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetched_event_init.h"
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_options.h"
 #include "third_party/blink/renderer/modules/event_modules_names.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 
@@ -30,17 +32,20 @@
     WaitUntilObserver* observer,
     ServiceWorkerRegistration* registration)
     : BackgroundFetchSettledEvent(type, initializer, unique_id, observer),
-      registration_(registration) {}
+      registration_(registration),
+      loader_(new BackgroundFetchIconLoader) {}
 
 BackgroundFetchUpdateEvent::~BackgroundFetchUpdateEvent() = default;
 
 void BackgroundFetchUpdateEvent::Trace(blink::Visitor* visitor) {
   visitor->Trace(registration_);
+  visitor->Trace(loader_);
   BackgroundFetchSettledEvent::Trace(visitor);
 }
 
-ScriptPromise BackgroundFetchUpdateEvent::updateUI(ScriptState* script_state,
-                                                   const String& title) {
+ScriptPromise BackgroundFetchUpdateEvent::updateUI(
+    ScriptState* script_state,
+    const BackgroundFetchUpdateUIOptions& ui_options) {
   if (!registration_) {
     // Return a Promise that will never settle when a developer calls this
     // method on a BackgroundFetchedEvent instance they created themselves.
@@ -48,17 +53,36 @@
   }
   DCHECK(!unique_id_.IsEmpty());
 
+  if (!ui_options.hasTitle() && ui_options.icons().IsEmpty()) {
+    // Nothing to update, just return a resolved promise.
+    ScriptPromise::CastUndefined(script_state);
+  }
+
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   ScriptPromise promise = resolver->Promise();
 
-  BackgroundFetchBridge::From(registration_)
-      ->UpdateUI(id(), unique_id_, title,
-                 WTF::Bind(&BackgroundFetchUpdateEvent::DidUpdateUI,
-                           WrapPersistent(this), WrapPersistent(resolver)));
+  if (ui_options.icons().IsEmpty()) {
+    DidGetIcon(resolver, ui_options.title(), SkBitmap());
+  } else {
+    loader_->Start(
+        BackgroundFetchBridge::From(registration_),
+        ExecutionContext::From(script_state), ui_options.icons(),
+        WTF::Bind(&BackgroundFetchUpdateEvent::DidGetIcon, WrapPersistent(this),
+                  WrapPersistent(resolver), ui_options.title()));
+  }
 
   return promise;
 }
 
+void BackgroundFetchUpdateEvent::DidGetIcon(ScriptPromiseResolver* resolver,
+                                            const String& title,
+                                            const SkBitmap& icon) {
+  BackgroundFetchBridge::From(registration_)
+      ->UpdateUI(id(), unique_id_, title, icon,
+                 WTF::Bind(&BackgroundFetchUpdateEvent::DidUpdateUI,
+                           WrapPersistent(this), WrapPersistent(resolver)));
+}
+
 void BackgroundFetchUpdateEvent::DidUpdateUI(
     ScriptPromiseResolver* resolver,
     mojom::blink::BackgroundFetchError error) {
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h b/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h
index 5683234..c060dcff 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h
@@ -11,6 +11,9 @@
 
 namespace blink {
 
+class BackgroundFetchIconLoader;
+class BackgroundFetchUpdateUIOptions;
+
 // Event for interacting with fetch requests that have completed.
 class MODULES_EXPORT BackgroundFetchUpdateEvent final
     : public BackgroundFetchSettledEvent {
@@ -37,7 +40,8 @@
   ~BackgroundFetchUpdateEvent() override;
 
   // Web Exposed method defined in the IDL file.
-  ScriptPromise updateUI(ScriptState* script_state, const String& title);
+  ScriptPromise updateUI(ScriptState* script_state,
+                         const BackgroundFetchUpdateUIOptions& ui_options);
 
   void Trace(blink::Visitor* visitor) override;
 
@@ -53,10 +57,15 @@
                              WaitUntilObserver* observer,
                              ServiceWorkerRegistration* registration);
 
+  void DidGetIcon(ScriptPromiseResolver* resolver,
+                  const String& title,
+                  const SkBitmap& icon);
+
   void DidUpdateUI(ScriptPromiseResolver* resolver,
                    mojom::blink::BackgroundFetchError error);
 
   Member<ServiceWorkerRegistration> registration_;
+  Member<BackgroundFetchIconLoader> loader_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.idl b/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.idl
index c9c7948..f4faa5c 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.idl
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.idl
@@ -10,5 +10,5 @@
     RuntimeEnabled=BackgroundFetch
 ]
 interface BackgroundFetchUpdateEvent : BackgroundFetchSettledEvent {
-    [CallWith=ScriptState] Promise<void> updateUI(DOMString title);
+    [CallWith=ScriptState] Promise<void> updateUI(BackgroundFetchUpdateUIOptions title);
 };
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_options.idl b/third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_options.idl
new file mode 100644
index 0000000..549c1b70
--- /dev/null
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_update_ui_options.idl
@@ -0,0 +1,13 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://wicg.github.io/background-fetch/#backgroundfetchupdateevent
+
+// TODO(crbug.com/865063): Fix names after the standard is updated.
+// Spec Bug: https://github.com/WICG/background-fetch/issues/86
+
+dictionary BackgroundFetchUpdateUIOptions {
+    DOMString? title;
+    sequence<ImageResource> icons = [];
+};
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetched_event.cc b/third_party/blink/renderer/modules/background_fetch/background_fetched_event.cc
deleted file mode 100644
index 5416bd2..0000000
--- a/third_party/blink/renderer/modules/background_fetch/background_fetched_event.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/background_fetch/background_fetched_event.h"
-
-#include "third_party/blink/public/platform/modules/background_fetch/web_background_fetch_settled_fetch.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/fetch/request.h"
-#include "third_party/blink/renderer/core/fetch/response.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_settled_fetch.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetched_event_init.h"
-#include "third_party/blink/renderer/modules/event_modules_names.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-namespace blink {
-
-BackgroundFetchedEvent::BackgroundFetchedEvent(
-    const AtomicString& type,
-    const BackgroundFetchedEventInit& initializer)
-    : BackgroundFetchEvent(type, initializer, nullptr /* observer */),
-      fetches_(initializer.fetches()) {}
-
-BackgroundFetchedEvent::BackgroundFetchedEvent(
-    const AtomicString& type,
-    const BackgroundFetchedEventInit& initializer,
-    const String& unique_id,
-    const WebVector<WebBackgroundFetchSettledFetch>& fetches,
-    ScriptState* script_state,
-    WaitUntilObserver* observer,
-    ServiceWorkerRegistration* registration)
-    : BackgroundFetchEvent(type, initializer, observer),
-      unique_id_(unique_id),
-      registration_(registration) {
-  fetches_.ReserveInitialCapacity(fetches.size());
-  for (const WebBackgroundFetchSettledFetch& fetch : fetches) {
-    auto* settled_fetch = BackgroundFetchSettledFetch::Create(
-        Request::Create(script_state, fetch.request),
-        Response::Create(script_state, fetch.response));
-
-    fetches_.push_back(settled_fetch);
-  }
-}
-
-BackgroundFetchedEvent::~BackgroundFetchedEvent() = default;
-
-HeapVector<Member<BackgroundFetchSettledFetch>>
-BackgroundFetchedEvent::fetches() const {
-  return fetches_;
-}
-
-ScriptPromise BackgroundFetchedEvent::updateUI(ScriptState* script_state,
-                                               const String& title) {
-  if (!registration_) {
-    // Return a Promise that will never settle when a developer calls this
-    // method on a BackgroundFetchedEvent instance they created themselves.
-    return ScriptPromise();
-  }
-  DCHECK(!unique_id_.IsEmpty());
-
-  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
-  ScriptPromise promise = resolver->Promise();
-
-  BackgroundFetchBridge::From(registration_)
-      ->UpdateUI(id(), unique_id_, title,
-                 WTF::Bind(&BackgroundFetchedEvent::DidUpdateUI,
-                           WrapPersistent(this), WrapPersistent(resolver)));
-
-  return promise;
-}
-
-void BackgroundFetchedEvent::DidUpdateUI(
-    ScriptPromiseResolver* resolver,
-    mojom::blink::BackgroundFetchError error) {
-  switch (error) {
-    case mojom::blink::BackgroundFetchError::NONE:
-    case mojom::blink::BackgroundFetchError::INVALID_ID:
-      resolver->Resolve();
-      return;
-    case mojom::blink::BackgroundFetchError::STORAGE_ERROR:
-      resolver->Reject(
-          DOMException::Create(DOMExceptionCode::kAbortError,
-                               "Failed to update UI due to I/O error."));
-      return;
-    case mojom::blink::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE:
-    case mojom::blink::BackgroundFetchError::DUPLICATED_DEVELOPER_ID:
-    case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT:
-      // Not applicable for this callback.
-      break;
-  }
-
-  NOTREACHED();
-}
-
-const AtomicString& BackgroundFetchedEvent::InterfaceName() const {
-  return EventNames::BackgroundFetchedEvent;
-}
-
-void BackgroundFetchedEvent::Trace(blink::Visitor* visitor) {
-  visitor->Trace(fetches_);
-  visitor->Trace(registration_);
-  BackgroundFetchEvent::Trace(visitor);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetched_event.h b/third_party/blink/renderer/modules/background_fetch/background_fetched_event.h
deleted file mode 100644
index d86e7392..0000000
--- a/third_party/blink/renderer/modules/background_fetch/background_fetched_event.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_BACKGROUND_FETCHED_EVENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_BACKGROUND_FETCHED_EVENT_H_
-
-#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom-blink.h"
-#include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_event.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-
-namespace blink {
-
-class BackgroundFetchSettledFetch;
-class BackgroundFetchedEventInit;
-class ScriptPromiseResolver;
-class ScriptState;
-class ServiceWorkerRegistration;
-struct WebBackgroundFetchSettledFetch;
-
-class MODULES_EXPORT BackgroundFetchedEvent final
-    : public BackgroundFetchEvent {
-  DEFINE_WRAPPERTYPEINFO();
-
- public:
-  static BackgroundFetchedEvent* Create(
-      const AtomicString& type,
-      const BackgroundFetchedEventInit& initializer) {
-    return new BackgroundFetchedEvent(type, initializer);
-  }
-
-  static BackgroundFetchedEvent* Create(
-      const AtomicString& type,
-      const BackgroundFetchedEventInit& initializer,
-      const String& unique_id,
-      const WebVector<WebBackgroundFetchSettledFetch>& fetches,
-      ScriptState* script_state,
-      WaitUntilObserver* observer,
-      ServiceWorkerRegistration* registration) {
-    return new BackgroundFetchedEvent(type, initializer, unique_id, fetches,
-                                      script_state, observer, registration);
-  }
-
-  ~BackgroundFetchedEvent() override;
-
-  // Web Exposed attribute defined in the IDL file.
-  HeapVector<Member<BackgroundFetchSettledFetch>> fetches() const;
-
-  // Web Exposed method defined in the IDL file.
-  ScriptPromise updateUI(ScriptState* script_state, const String& title);
-
-  // ExtendableEvent interface.
-  const AtomicString& InterfaceName() const override;
-
-  void Trace(blink::Visitor* visitor) override;
-
- private:
-  BackgroundFetchedEvent(const AtomicString& type,
-                         const BackgroundFetchedEventInit& initializer);
-  BackgroundFetchedEvent(
-      const AtomicString& type,
-      const BackgroundFetchedEventInit& initializer,
-      const String& unique_id,
-      const WebVector<WebBackgroundFetchSettledFetch>& fetches,
-      ScriptState* script_state,
-      WaitUntilObserver* observer,
-      ServiceWorkerRegistration* registration);
-
-  void DidUpdateUI(ScriptPromiseResolver* resolver,
-                   mojom::blink::BackgroundFetchError error);
-
-  // Globally unique ID for the registration, generated in content/. Used to
-  // distinguish registrations in case a developer re-uses |developer_id_|s. Not
-  // exposed to JavaScript.
-  String unique_id_;
-
-  HeapVector<Member<BackgroundFetchSettledFetch>> fetches_;
-  Member<ServiceWorkerRegistration> registration_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_BACKGROUND_FETCHED_EVENT_H_
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetched_event.idl b/third_party/blink/renderer/modules/background_fetch/background_fetched_event.idl
deleted file mode 100644
index 2226821..0000000
--- a/third_party/blink/renderer/modules/background_fetch/background_fetched_event.idl
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://wicg.github.io/background-fetch/#background-fetch-end-event
-
-[
-    Constructor(DOMString type, BackgroundFetchedEventInit init),
-    Exposed=ServiceWorker,
-    RuntimeEnabled=BackgroundFetch
-] interface BackgroundFetchedEvent : BackgroundFetchEvent {
-    readonly attribute FrozenArray<BackgroundFetchSettledFetch> fetches;
-
-    [CallWith=ScriptState] Promise<void> updateUI(DOMString title);
-};
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetched_event_init.idl b/third_party/blink/renderer/modules/background_fetch/background_fetched_event_init.idl
deleted file mode 100644
index 68d6f684..0000000
--- a/third_party/blink/renderer/modules/background_fetch/background_fetched_event_init.idl
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://wicg.github.io/background-fetch/#background-fetch-end-event
-
-dictionary BackgroundFetchedEventInit : BackgroundFetchEventInit {
-    required sequence<BackgroundFetchSettledFetch> fetches;
-};
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
index 5c679f9..208ff8c 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
@@ -120,16 +120,15 @@
     return CanvasElement().GetGPUMemoryUsage();
   }
   void DrawSomething() {
-    Canvas2DLayerBridge* bridge = CanvasElement().GetCanvas2DLayerBridge();
-    bridge->DidDraw(FloatRect(0, 0, 1, 1));
-    bridge->FinalizeFrame();
+    CanvasElement().DidDraw();
+    CanvasElement().FinalizeFrame();
     // Grabbing an image forces a flush
-    bridge->NewImageSnapshot(kPreferAcceleration);
+    CanvasElement().CopiedImage(kBackBuffer, kPreferAcceleration);
   }
 
-  void CreateContext(OpacityMode,
-                     String color_space = String(),
-                     LinearPixelMathState = kLinearPixelMathDisabled);
+  enum LatencyMode { kNormalLatency, kLowLatency };
+
+  void CreateContext(OpacityMode, LatencyMode = kNormalLatency);
   ScriptState* GetScriptState() {
     return ToScriptStateForMainWorld(canvas_element_->GetFrame());
   }
@@ -185,19 +184,12 @@
       opaque_bitmap_(IntSize(10, 10), kOpaqueBitmap),
       alpha_bitmap_(IntSize(10, 10), kTransparentBitmap) {}
 
-void CanvasRenderingContext2DTest::CreateContext(
-    OpacityMode opacity_mode,
-    String color_space,
-    LinearPixelMathState LinearPixelMath_state) {
+void CanvasRenderingContext2DTest::CreateContext(OpacityMode opacity_mode,
+                                                 LatencyMode latency_mode) {
   String canvas_type("2d");
   CanvasContextCreationAttributesCore attributes;
   attributes.alpha = opacity_mode == kNonOpaque;
-  if (!color_space.IsEmpty()) {
-    attributes.color_space = color_space;
-    if (LinearPixelMath_state == kLinearPixelMathEnabled) {
-      attributes.pixel_format = "float16";
-    }
-  }
+  attributes.low_latency = latency_mode == kLowLatency;
   canvas_element_->GetCanvasRenderingContext(canvas_type, attributes);
 }
 
@@ -1209,4 +1201,22 @@
   EXPECT_FALSE(layer->NeedsCompositingInputsUpdate());
 }
 
+TEST_F(CanvasRenderingContext2DTest, LowLatencyIsSingleBuffered) {
+  CreateContext(kNonOpaque, kLowLatency);
+  // No need to set-up the layer bridge when testing low latency mode.
+  DrawSomething();
+  auto frame1_resource =
+      CanvasElement()
+          .GetOrCreateCanvasResourceProvider(kPreferNoAcceleration)
+          ->ProduceFrame();
+  EXPECT_TRUE(!!frame1_resource);
+  DrawSomething();
+  auto frame2_resource =
+      CanvasElement()
+          .GetOrCreateCanvasResourceProvider(kPreferNoAcceleration)
+          ->ProduceFrame();
+  EXPECT_TRUE(!!frame2_resource);
+  EXPECT_EQ(frame1_resource.get(), frame2_resource.get());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc
index 8a15c24..01f17d13 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc
@@ -88,10 +88,4 @@
   return last_device_orientation_data_.Get();
 }
 
-WebPlatformEventType DeviceOrientationDispatcher::GetWebPlatformEventType()
-    const {
-  return (absolute_) ? kWebPlatformEventTypeDeviceOrientationAbsolute
-                     : kWebPlatformEventTypeDeviceOrientation;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h b/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h
index 62a9453..b8e25cb0 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h
@@ -33,7 +33,6 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h"
-#include "third_party/blink/public/platform/web_platform_event_type.h"
 #include "third_party/blink/renderer/core/frame/platform_event_dispatcher.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
@@ -74,8 +73,6 @@
   void StartListening(LocalFrame* frame) override;
   void StopListening() override;
 
-  WebPlatformEventType GetWebPlatformEventType() const;
-
   const bool absolute_;
   Member<DeviceOrientationData> last_device_orientation_data_;
   std::unique_ptr<DeviceOrientationEventPump> event_pump_;
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index c5efe86..6ff80c5 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -74,7 +74,6 @@
           "background_fetch/background_fetch_settled_fetch.idl",
           "background_fetch/background_fetch_settled_fetches.idl",
           "background_fetch/background_fetch_update_event.idl",
-          "background_fetch/background_fetched_event.idl",
           "background_sync/sync_event.idl",
           "background_sync/sync_manager.idl",
           "battery/battery_manager.idl",
@@ -469,7 +468,7 @@
           "background_fetch/background_fetch_fail_event_init.idl",
           "background_fetch/background_fetch_options.idl",
           "background_fetch/background_fetch_settled_event_init.idl",
-          "background_fetch/background_fetched_event_init.idl",
+          "background_fetch/background_fetch_update_ui_options.idl",
           "background_sync/sync_event_init.idl",
           "bluetooth/bluetooth_le_scan_filter_init.idl",
           "bluetooth/request_device_options.idl",
diff --git a/third_party/blink/renderer/modules/vr/vr_display.cc b/third_party/blink/renderer/modules/vr/vr_display.cc
index a221211..d49ebfc 100644
--- a/third_party/blink/renderer/modules/vr/vr_display.cc
+++ b/third_party/blink/renderer/modules/vr/vr_display.cc
@@ -244,7 +244,7 @@
 
     pending_magic_window_vsync_ = false;
     pending_presenting_vsync_ = true;
-    vr_presentation_provider_->GetFrameData(
+    vr_presentation_data_provider_->GetFrameData(
         WTF::Bind(&VRDisplay::OnPresentingVSync, WrapWeakPersistent(this)));
 
     DVLOG(2) << __FUNCTION__ << " done: pending_presenting_vsync_="
@@ -502,17 +502,26 @@
 void VRDisplay::OnRequestSessionReturned(
     device::mojom::blink::XRSessionPtr session) {
   pending_present_request_ = false;
-  if (session && session->connection) {
-    vr_presentation_provider_.Bind(std::move(session->connection->provider));
+  if (session) {
+    DCHECK(session->submit_frame_sink);
+    vr_presentation_data_provider_.Bind(std::move(session->data_provider));
+    // The presentation provider error handler can trigger if a device is
+    // disconnected from the system. This can happen if, for example, an HMD is
+    // unplugged.
+    vr_presentation_data_provider_.set_connection_error_handler(
+        WTF::Bind(&VRDisplay::OnPresentationProviderConnectionError,
+                  WrapWeakPersistent(this)));
+    vr_presentation_provider_.Bind(
+        std::move(session->submit_frame_sink->provider));
     vr_presentation_provider_.set_connection_error_handler(
         WTF::Bind(&VRDisplay::OnPresentationProviderConnectionError,
                   WrapWeakPersistent(this)));
 
     frame_transport_ = new XRFrameTransport();
     frame_transport_->BindSubmitFrameClient(
-        std::move(session->connection->client_request));
+        std::move(session->submit_frame_sink->client_request));
     frame_transport_->SetTransportOptions(
-        std::move(session->connection->transport_options));
+        std::move(session->submit_frame_sink->transport_options));
 
     this->BeginPresent();
   } else {
@@ -529,11 +538,11 @@
 
 void VRDisplay::OnMagicWindowRequestReturned(
     device::mojom::blink::XRSessionPtr session) {
-  if (!session || !session->magic_window_provider) {
-    // System does not support any kind of magic window.
+  if (!session) {
+    // System does not support any kind of session.
     return;
   }
-  magic_window_provider_.Bind(std::move(session->magic_window_provider));
+  magic_window_provider_.Bind(std::move(session->data_provider));
   RequestVSync();
 }
 
@@ -611,7 +620,7 @@
   }
   is_presenting_ = true;
   // Call RequestVSync to switch from the (internal) document rAF to the
-  // VrPresentationProvider GetFrameData rate.
+  // XRPresentationProvider GetFrameData rate.
   RequestVSync();
   ReportPresentationResult(PresentationResult::kSuccess);
 
@@ -1038,6 +1047,7 @@
            << " pending_magic_window_vsync_=" << pending_magic_window_vsync_
            << " pending_presenting_vsync_=" << pending_presenting_vsync_;
   vr_presentation_provider_.reset();
+  vr_presentation_data_provider_.reset();
   if (is_presenting_) {
     ForceExitPresent();
   }
diff --git a/third_party/blink/renderer/modules/vr/vr_display.h b/third_party/blink/renderer/modules/vr/vr_display.h
index bfd14698..4c6da38 100644
--- a/third_party/blink/renderer/modules/vr/vr_display.h
+++ b/third_party/blink/renderer/modules/vr/vr_display.h
@@ -217,14 +217,15 @@
   bool did_log_getFrameData_ = false;
   bool did_log_requestPresent_ = false;
 
-  device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider_;
+  device::mojom::blink::XRFrameDataProviderPtr magic_window_provider_;
 
   device::mojom::blink::VRDisplayHostPtr display_;
 
   bool present_image_needs_copy_ = false;
 
   mojo::Binding<device::mojom::blink::VRDisplayClient> display_client_binding_;
-  device::mojom::blink::VRPresentationProviderPtr vr_presentation_provider_;
+  device::mojom::blink::XRFrameDataProviderPtr vr_presentation_data_provider_;
+  device::mojom::blink::XRPresentationProviderPtr vr_presentation_provider_;
 
   HeapDeque<Member<ScriptPromiseResolver>> pending_present_resolvers_;
 };
diff --git a/third_party/blink/renderer/modules/xr/xr_device.cc b/third_party/blink/renderer/modules/xr/xr_device.cc
index 7925e02..edd484b 100644
--- a/third_party/blink/renderer/modules/xr/xr_device.cc
+++ b/third_party/blink/renderer/modules/xr/xr_device.cc
@@ -199,9 +199,6 @@
     return;
   }
 
-  if (session_ptr->magic_window_provider)
-    magic_window_provider_.Bind(std::move(session_ptr->magic_window_provider));
-
   XRPresentationContext* output_context = nullptr;
   if (options.hasOutputContext()) {
     output_context = options.outputContext();
@@ -218,8 +215,10 @@
   sessions_.insert(session);
 
   if (options.immersive()) {
-    frameProvider()->BeginImmersiveSession(session,
-                                           std::move(session_ptr->connection));
+    frameProvider()->BeginImmersiveSession(session, std::move(session_ptr));
+  } else {
+    magic_window_provider_.Bind(std::move(session_ptr->data_provider));
+    enviroment_provider_.Bind(std::move(session_ptr->enviroment_provider));
   }
 
   resolver->Resolve(session);
diff --git a/third_party/blink/renderer/modules/xr/xr_device.h b/third_party/blink/renderer/modules/xr/xr_device.h
index f4db8e21..2e83621 100644
--- a/third_party/blink/renderer/modules/xr/xr_device.h
+++ b/third_party/blink/renderer/modules/xr/xr_device.h
@@ -54,10 +54,14 @@
   const device::mojom::blink::VRDisplayHostPtr& xrDisplayHostPtr() const {
     return display_;
   }
-  const device::mojom::blink::VRMagicWindowProviderPtr&
-  xrMagicWindowProviderPtr() const {
+  const device::mojom::blink::XRFrameDataProviderPtr& xrMagicWindowProviderPtr()
+      const {
     return magic_window_provider_;
   }
+  const device::mojom::blink::XREnviromentIntegrationProviderPtr&
+  xrEnviromentProviderPtr() const {
+    return enviroment_provider_;
+  }
   const device::mojom::blink::VRDisplayInfoPtr& xrDisplayInfoPtr() const {
     return display_info_;
   }
@@ -107,7 +111,8 @@
   // Indicates whether we've already logged a request for an immersive session.
   bool did_log_request_immersive_session_ = false;
 
-  device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider_;
+  device::mojom::blink::XRFrameDataProviderPtr magic_window_provider_;
+  device::mojom::blink::XREnviromentIntegrationProviderPtr enviroment_provider_;
   device::mojom::blink::VRDisplayHostPtr display_;
   device::mojom::blink::VRDisplayInfoPtr display_info_;
   unsigned int display_info_id_ = 0;
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_provider.cc b/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
index 8a5a4e9..79b42f7 100644
--- a/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
+++ b/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
@@ -92,25 +92,29 @@
 
 void XRFrameProvider::BeginImmersiveSession(
     XRSession* session,
-    device::mojom::blink::XRPresentationConnectionPtr connection) {
+    device::mojom::blink::XRSessionPtr session_ptr) {
   // Make sure the session is indeed an immersive one.
   DCHECK(session && session->immersive());
 
   // Ensure we can only have one immersive session at a time.
   DCHECK(!immersive_session_);
-  DCHECK(connection);
+  DCHECK(session_ptr->data_provider);
+  DCHECK(session_ptr->submit_frame_sink);
 
   immersive_session_ = session;
 
-  presentation_provider_.Bind(std::move(connection->provider));
+  immersive_data_provider_.Bind(std::move(session_ptr->data_provider));
+
+  presentation_provider_.Bind(
+      std::move(session_ptr->submit_frame_sink->provider));
   presentation_provider_.set_connection_error_handler(
       WTF::Bind(&XRFrameProvider::OnPresentationProviderConnectionError,
                 WrapWeakPersistent(this)));
 
   frame_transport_->BindSubmitFrameClient(
-      std::move(connection->client_request));
+      std::move(session_ptr->submit_frame_sink->client_request));
   frame_transport_->SetTransportOptions(
-      std::move(connection->transport_options));
+      std::move(session_ptr->submit_frame_sink->transport_options));
   frame_transport_->PresentChange();
 }
 
@@ -131,6 +135,7 @@
 
 void XRFrameProvider::OnPresentationProviderConnectionError() {
   presentation_provider_.reset();
+  immersive_data_provider_.reset();
   if (vsync_connection_failed_)
     return;
   immersive_session_->ForceEnd();
@@ -147,10 +152,8 @@
   immersive_session_ = nullptr;
   pending_immersive_vsync_ = false;
   frame_id_ = -1;
-
-  if (presentation_provider_.is_bound()) {
-    presentation_provider_.reset();
-  }
+  presentation_provider_.reset();
+  immersive_data_provider_.reset();
 
   frame_transport_ = new XRFrameTransport();
 
@@ -200,7 +203,7 @@
 
   pending_immersive_vsync_ = true;
 
-  presentation_provider_->GetFrameData(WTF::Bind(
+  immersive_data_provider_->GetFrameData(WTF::Bind(
       &XRFrameProvider::OnImmersiveFrameData, WrapWeakPersistent(this)));
 }
 
@@ -527,6 +530,7 @@
 
 void XRFrameProvider::Dispose() {
   presentation_provider_.reset();
+  immersive_data_provider_.reset();
   // TODO(bajones): Do something for outstanding frame requests?
 }
 
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_provider.h b/third_party/blink/renderer/modules/xr/xr_frame_provider.h
index 159a4d55..c483e03 100644
--- a/third_party/blink/renderer/modules/xr/xr_frame_provider.h
+++ b/third_party/blink/renderer/modules/xr/xr_frame_provider.h
@@ -27,11 +27,10 @@
   explicit XRFrameProvider(XRDevice*);
 
   XRSession* immersive_session() const { return immersive_session_; }
-  device::mojom::blink::VRSubmitFrameClientPtr GetSubmitFrameClient();
+  device::mojom::blink::XRPresentationClientPtr GetSubmitFrameClient();
 
-  void BeginImmersiveSession(
-      XRSession* session,
-      device::mojom::blink::XRPresentationConnectionPtr connection);
+  void BeginImmersiveSession(XRSession* session,
+                             device::mojom::blink::XRSessionPtr session_ptr);
   void OnImmersiveSessionEnded();
 
   void RequestFrame(XRSession*);
@@ -66,8 +65,8 @@
   // Non-immersive Sessions which have requested a frame update.
   HeapVector<Member<XRSession>> requesting_sessions_;
 
-  device::mojom::blink::VRPresentationProviderPtr presentation_provider_;
-  device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider_;
+  device::mojom::blink::XRPresentationProviderPtr presentation_provider_;
+  device::mojom::blink::XRFrameDataProviderPtr immersive_data_provider_;
   device::mojom::blink::VRPosePtr frame_pose_;
 
   // This frame ID is XR-specific and is used to track when frames arrive at the
diff --git a/third_party/blink/renderer/modules/xr/xr_session.cc b/third_party/blink/renderer/modules/xr/xr_session.cc
index d838ef8..b3ca9f0 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.cc
+++ b/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -312,7 +312,7 @@
 
   // TODO(https://crbug.com/845520): Promise should be rejected if session
   // is deleted.
-  device_->xrMagicWindowProviderPtr()->RequestHitTest(
+  device_->xrEnviromentProviderPtr()->RequestHitTest(
       std::move(ray),
       WTF::Bind(&XRSession::OnHitTestResults, WrapWeakPersistent(this),
                 WrapPersistent(resolver)));
@@ -550,8 +550,8 @@
     DVLOG(2) << __FUNCTION__ << ": got angle=" << output_angle;
   }
 
-  if (device_->xrMagicWindowProviderPtr()) {
-    device_->xrMagicWindowProviderPtr()->UpdateSessionGeometry(
+  if (device_->xrEnviromentProviderPtr()) {
+    device_->xrEnviromentProviderPtr()->UpdateSessionGeometry(
         IntSize(output_width_, output_height_),
         display::Display::DegreesToRotation(output_angle));
   }
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index e3383f4..a176ed33 100644
--- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -524,6 +524,10 @@
   RuntimeEnabledFeatures::SetWorkStealingInScriptRunnerEnabled(enable);
 }
 
+void WebRuntimeFeatures::EnableScheduledScriptStreaming(bool enable) {
+  RuntimeEnabledFeatures::SetScheduledScriptStreamingEnabled(enable);
+}
+
 void WebRuntimeFeatures::EnableStopInBackground(bool enable) {
   RuntimeEnabledFeatures::SetStopInBackgroundEnabled(enable);
 }
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index 4685fcd2..8d951cd 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -152,6 +152,7 @@
 
   ~CanvasResourceProviderTextureGpuMemoryBuffer() override = default;
   bool SupportsDirectCompositing() const override { return true; }
+  bool SupportsSingleBuffering() const override { return true; }
 
  private:
   scoped_refptr<CanvasResource> CreateResource() final {
@@ -263,6 +264,7 @@
 
   ~CanvasResourceProviderRamGpuMemoryBuffer() override = default;
   bool SupportsDirectCompositing() const override { return true; }
+  bool SupportsSingleBuffering() const override { return true; }
 
  private:
   scoped_refptr<CanvasResource> CreateResource() final {
@@ -318,6 +320,7 @@
   }
   ~CanvasResourceProviderSharedBitmap() override = default;
   bool SupportsDirectCompositing() const override { return true; }
+  bool SupportsSingleBuffering() const override { return true; }
 
  private:
   scoped_refptr<CanvasResource> CreateResource() final {
@@ -684,6 +687,7 @@
   canvas_image_provider_.reset();
   xform_canvas_ = nullptr;
   surface_ = nullptr;
+  single_buffer_ = nullptr;
 }
 
 uint32_t CanvasResourceProvider::ContentUniqueID() const {
@@ -721,6 +725,11 @@
 }
 
 scoped_refptr<CanvasResource> CanvasResourceProvider::NewOrRecycledResource() {
+  if (IsSingleBuffered()) {
+    if (!single_buffer_)
+      single_buffer_ = CreateResource();
+    return single_buffer_;
+  }
   if (recycled_resources_.size()) {
     scoped_refptr<CanvasResource> resource =
         std::move(recycled_resources_.back());
@@ -730,4 +739,11 @@
   return CreateResource();
 }
 
+void CanvasResourceProvider::TryEnableSingleBuffering() {
+  if (IsSingleBuffered() || !SupportsSingleBuffering())
+    return;
+  SetResourceRecyclingEnabled(false);
+  is_single_buffered_ = true;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
index 661aa5d..12866715 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
@@ -100,11 +100,26 @@
   virtual bool IsValid() const = 0;
   virtual bool IsAccelerated() const = 0;
   virtual bool SupportsDirectCompositing() const = 0;
+  virtual bool SupportsSingleBuffering() const { return false; }
   uint32_t ContentUniqueID() const;
   CanvasResourceDispatcher* ResourceDispatcher() {
     return resource_dispatcher_.get();
   }
 
+  // Indicates that the compositing path is single buffered, meaning that
+  // ProduceFrame() return a reference to the same resource each time, which
+  // implies that Producing an animation frame may overwrite the resource used
+  // by the previous frame. This results in graphics updates skipping the
+  // queue, thus reducing latency, but with the possible side effects of
+  // tearring (in cases where the resource is scanned out directly) and
+  // irregular frame rate.
+  bool IsSingleBuffered() { return is_single_buffered_; }
+
+  // Attempt to enable single buffering mode on this resource provider.  May
+  // fail if the CanvasResourcePRovider subclass does not support this mode of
+  // operation.
+  void TryEnableSingleBuffering();
+
   void RecycleResource(scoped_refptr<CanvasResource>);
   void SetResourceRecyclingEnabled(bool);
   void ClearRecycledResources();
@@ -189,6 +204,9 @@
   WTF::Vector<scoped_refptr<CanvasResource>> recycled_resources_;
   bool resource_recycling_enabled_ = true;
 
+  bool is_single_buffered_ = false;
+  scoped_refptr<CanvasResource> single_buffer_;
+
   base::WeakPtrFactory<CanvasResourceProvider> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(CanvasResourceProvider);
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
index 2db3ef5..a0ace7b 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
@@ -30,24 +30,24 @@
 }
 
 void XRFrameTransport::SetTransportOptions(
-    device::mojom::blink::VRDisplayFrameTransportOptionsPtr transport_options) {
+    device::mojom::blink::XRPresentationTransportOptionsPtr transport_options) {
   transport_options_ = std::move(transport_options);
 }
 
 void XRFrameTransport::BindSubmitFrameClient(
-    device::mojom::blink::VRSubmitFrameClientRequest request) {
+    device::mojom::blink::XRPresentationClientRequest request) {
   submit_frame_client_binding_.Close();
   submit_frame_client_binding_.Bind(std::move(request));
 }
 
 bool XRFrameTransport::DrawingIntoSharedBuffer() {
   switch (transport_options_->transport_method) {
-    case device::mojom::blink::VRDisplayFrameTransportMethod::
+    case device::mojom::blink::XRPresentationTransportMethod::
         SUBMIT_AS_TEXTURE_HANDLE:
-    case device::mojom::blink::VRDisplayFrameTransportMethod::
+    case device::mojom::blink::XRPresentationTransportMethod::
         SUBMIT_AS_MAILBOX_HOLDER:
       return false;
-    case device::mojom::blink::VRDisplayFrameTransportMethod::
+    case device::mojom::blink::XRPresentationTransportMethod::
         DRAW_INTO_TEXTURE_MAILBOX:
       return true;
     default:
@@ -85,7 +85,7 @@
 }
 
 void XRFrameTransport::FrameSubmitMissing(
-    device::mojom::blink::VRPresentationProvider* vr_presentation_provider,
+    device::mojom::blink::XRPresentationProvider* vr_presentation_provider,
     gpu::gles2::GLES2Interface* gl,
     int16_t vr_frame_id) {
   TRACE_EVENT0("gpu", __FUNCTION__);
@@ -95,7 +95,7 @@
 }
 
 void XRFrameTransport::FrameSubmit(
-    device::mojom::blink::VRPresentationProvider* vr_presentation_provider,
+    device::mojom::blink::XRPresentationProvider* vr_presentation_provider,
     gpu::gles2::GLES2Interface* gl,
     DrawingBuffer::Client* drawing_buffer_client,
     scoped_refptr<Image> image_ref,
@@ -105,7 +105,7 @@
   DCHECK(transport_options_);
 
   if (transport_options_->transport_method ==
-      device::mojom::blink::VRDisplayFrameTransportMethod::
+      device::mojom::blink::XRPresentationTransportMethod::
           SUBMIT_AS_TEXTURE_HANDLE) {
 #if defined(OS_WIN)
     // Currently, we assume that this transport needs a copy.
@@ -143,7 +143,7 @@
     NOTIMPLEMENTED();
 #endif
   } else if (transport_options_->transport_method ==
-             device::mojom::blink::VRDisplayFrameTransportMethod::
+             device::mojom::blink::XRPresentationTransportMethod::
                  SUBMIT_AS_MAILBOX_HOLDER) {
     // Currently, this transport assumes we don't need to make a separate copy
     // of the canvas content.
@@ -188,7 +188,7 @@
         frame_wait_time_);
     TRACE_EVENT_END0("gpu", "XRFrameTransport::SubmitFrame");
   } else if (transport_options_->transport_method ==
-             device::mojom::blink::VRDisplayFrameTransportMethod::
+             device::mojom::blink::XRPresentationTransportMethod::
                  DRAW_INTO_TEXTURE_MAILBOX) {
     TRACE_EVENT0("gpu", "XRFrameTransport::SubmitFrameDrawnIntoTexture");
     gpu::SyncToken sync_token;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
index 1af00bce..57dc839 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
@@ -30,25 +30,25 @@
 
 class PLATFORM_EXPORT XRFrameTransport final
     : public GarbageCollectedFinalized<XRFrameTransport>,
-      public device::mojom::blink::VRSubmitFrameClient {
+      public device::mojom::blink::XRPresentationClient {
  public:
   explicit XRFrameTransport();
   ~XRFrameTransport() override;
 
   void BindSubmitFrameClient(
-      device::mojom::blink::VRSubmitFrameClientRequest request);
+      device::mojom::blink::XRPresentationClientRequest request);
 
   void PresentChange();
 
   void SetTransportOptions(
-      device::mojom::blink::VRDisplayFrameTransportOptionsPtr);
+      device::mojom::blink::XRPresentationTransportOptionsPtr);
 
   bool DrawingIntoSharedBuffer();
 
   // Call before finalizing the frame's image snapshot.
   void FramePreImage(gpu::gles2::GLES2Interface*);
 
-  void FrameSubmit(device::mojom::blink::VRPresentationProvider*,
+  void FrameSubmit(device::mojom::blink::XRPresentationProvider*,
                    gpu::gles2::GLES2Interface*,
                    DrawingBuffer::Client*,
                    scoped_refptr<Image> image_ref,
@@ -56,7 +56,7 @@
                    int16_t vr_frame_id,
                    bool needs_copy);
 
-  void FrameSubmitMissing(device::mojom::blink::VRPresentationProvider*,
+  void FrameSubmitMissing(device::mojom::blink::XRPresentationProvider*,
                           gpu::gles2::GLES2Interface*,
                           int16_t vr_frame_id);
 
@@ -68,12 +68,12 @@
   WTF::TimeDelta WaitForGpuFenceReceived();
   void CallPreviousFrameCallback();
 
-  // VRSubmitFrameClient
+  // XRPresentationClient
   void OnSubmitFrameTransferred(bool success) override;
   void OnSubmitFrameRendered() override;
   void OnSubmitFrameGpuFence(const gfx::GpuFenceHandle&) override;
 
-  mojo::Binding<device::mojom::blink::VRSubmitFrameClient>
+  mojo::Binding<device::mojom::blink::XRPresentationClient>
       submit_frame_client_binding_;
 
   // Used to keep the image alive until the next frame if using
@@ -91,7 +91,7 @@
   bool waiting_for_previous_frame_fence_ = false;
   std::unique_ptr<gfx::GpuFence> previous_frame_fence_;
 
-  device::mojom::blink::VRDisplayFrameTransportOptionsPtr transport_options_;
+  device::mojom::blink::XRPresentationTransportOptionsPtr transport_options_;
 
   std::unique_ptr<GpuMemoryBufferImageCopy> frame_copier_;
 };
diff --git a/third_party/blink/renderer/platform/heap/gc_info.cc b/third_party/blink/renderer/platform/heap/gc_info.cc
index 1033c65..6c515bc 100644
--- a/third_party/blink/renderer/platform/heap/gc_info.cc
+++ b/third_party/blink/renderer/platform/heap/gc_info.cc
@@ -49,7 +49,7 @@
 }
 
 void GCInfoTable::EnsureGCInfoIndex(const GCInfo* gc_info,
-                                    size_t* gc_info_index_slot) {
+                                    uint32_t* gc_info_index_slot) {
   DCHECK(gc_info);
   DCHECK(gc_info_index_slot);
 
@@ -64,14 +64,13 @@
   if (*gc_info_index_slot)
     return;
 
-  int index = ++current_index_;
-  size_t gc_info_index = static_cast<size_t>(index);
+  uint32_t gc_info_index = ++current_index_;
   CHECK(gc_info_index < GCInfoTable::kMaxIndex);
   if (current_index_ >= limit_)
     Resize();
 
   table_[gc_info_index] = gc_info;
-  ReleaseStore(reinterpret_cast<int*>(gc_info_index_slot), index);
+  ReleaseStore(gc_info_index_slot, gc_info_index);
 }
 
 void GCInfoTable::Resize() {
diff --git a/third_party/blink/renderer/platform/heap/gc_info.h b/third_party/blink/renderer/platform/heap/gc_info.h
index b6e7e42..a5c138e 100644
--- a/third_party/blink/renderer/platform/heap/gc_info.h
+++ b/third_party/blink/renderer/platform/heap/gc_info.h
@@ -44,7 +44,7 @@
 };
 
 #if DCHECK_IS_ON()
-PLATFORM_EXPORT void AssertObjectHasGCInfo(const void*, size_t gc_info_index);
+PLATFORM_EXPORT void AssertObjectHasGCInfo(const void*, uint32_t gc_info_index);
 #endif
 
 class PLATFORM_EXPORT GCInfoTable {
@@ -56,14 +56,14 @@
   // of the Oilpan GC Clang plugin, there appear to be at most about 6,000
   // types. Thus 14 bits should be more than twice as many bits as we will ever
   // need.
-  static constexpr size_t kMaxIndex = 1 << 14;
+  static constexpr uint32_t kMaxIndex = 1 << 14;
 
   // Sets up a singleton table that can be acquired using Get().
   static void CreateGlobalTable();
 
   static GCInfoTable& Get() { return *global_table_; }
 
-  inline const GCInfo* GCInfoFromIndex(size_t index) {
+  inline const GCInfo* GCInfoFromIndex(uint32_t index) {
     DCHECK_GE(index, 1u);
     DCHECK(index < kMaxIndex);
     DCHECK(table_);
@@ -72,9 +72,9 @@
     return info;
   }
 
-  void EnsureGCInfoIndex(const GCInfo*, size_t*);
+  void EnsureGCInfoIndex(const GCInfo*, uint32_t*);
 
-  size_t GcInfoIndex() { return current_index_; }
+  uint32_t GcInfoIndex() { return current_index_; }
 
  private:
   FRIEND_TEST_ALL_PREFIXES(GCInfoTest, InitialEmpty);
@@ -95,10 +95,10 @@
 
   // GCInfo indices start from 1 for heap objects, with 0 being treated
   // specially as the index for freelist entries and large heap objects.
-  size_t current_index_ = 0;
+  uint32_t current_index_ = 0;
 
   // The limit (exclusive) of the currently allocated table.
-  size_t limit_ = 0;
+  uint32_t limit_ = 0;
 
   Mutex table_mutex_;
 };
@@ -108,14 +108,14 @@
 template <typename T>
 struct GCInfoAtBaseType {
   STATIC_ONLY(GCInfoAtBaseType);
-  static size_t Index() {
+  static uint32_t Index() {
     static_assert(sizeof(T), "T must be fully defined");
     static const GCInfo kGcInfo = {
         TraceTrait<T>::Trace,          FinalizerTrait<T>::Finalize,
         NameTrait<T>::GetName,         FinalizerTrait<T>::kNonTrivialFinalizer,
         std::is_polymorphic<T>::value,
     };
-    static size_t gc_info_index = 0;
+    static uint32_t gc_info_index = 0;
     if (!AcquireLoad(&gc_info_index))
       GCInfoTable::Get().EnsureGCInfoIndex(&kGcInfo, &gc_info_index);
     DCHECK_GE(gc_info_index, 1u);
@@ -144,7 +144,7 @@
 template <typename T>
 struct GCInfoTrait {
   STATIC_ONLY(GCInfoTrait);
-  static size_t Index() {
+  static uint32_t Index() {
     return GCInfoAtBaseType<typename GetGarbageCollectedType<T>::type>::Index();
   }
 };
diff --git a/third_party/blink/renderer/platform/heap/gc_info_test.cc b/third_party/blink/renderer/platform/heap/gc_info_test.cc
index d651be0..6447fc31 100644
--- a/third_party/blink/renderer/platform/heap/gc_info_test.cc
+++ b/third_party/blink/renderer/platform/heap/gc_info_test.cc
@@ -16,8 +16,8 @@
 TEST(GCInfoTest, ResizeToMaxIndex) {
   GCInfoTable table;
   GCInfo info = {nullptr, nullptr, nullptr, false, false};
-  size_t slot = 0;
-  for (size_t i = 0; i < (GCInfoTable::kMaxIndex - 1); i++) {
+  uint32_t slot = 0;
+  for (uint32_t i = 0; i < (GCInfoTable::kMaxIndex - 1); i++) {
     slot = 0;
     table.EnsureGCInfoIndex(&info, &slot);
     EXPECT_LT(0u, slot);
diff --git a/third_party/blink/renderer/platform/heap/heap.cc b/third_party/blink/renderer/platform/heap/heap.cc
index 7688dfb5..cd4d676 100644
--- a/third_party/blink/renderer/platform/heap/heap.cc
+++ b/third_party/blink/renderer/platform/heap/heap.cc
@@ -430,8 +430,8 @@
   return arena_index_with_min_arena_age;
 }
 
-BaseArena* ThreadHeap::ExpandedVectorBackingArena(size_t gc_info_index) {
-  size_t entry_index = gc_info_index & kLikelyToBePromptlyFreedArrayMask;
+BaseArena* ThreadHeap::ExpandedVectorBackingArena(uint32_t gc_info_index) {
+  uint32_t entry_index = gc_info_index & kLikelyToBePromptlyFreedArrayMask;
   --likely_to_be_promptly_freed_[entry_index];
   int arena_index = vector_backing_arena_index_;
   arena_ages_[arena_index] = ++current_arena_ages_;
@@ -448,9 +448,9 @@
   }
 }
 
-void ThreadHeap::PromptlyFreed(size_t gc_info_index) {
+void ThreadHeap::PromptlyFreed(uint32_t gc_info_index) {
   DCHECK(thread_state_->CheckThread());
-  size_t entry_index = gc_info_index & kLikelyToBePromptlyFreedArrayMask;
+  uint32_t entry_index = gc_info_index & kLikelyToBePromptlyFreedArrayMask;
   // See the comment in vectorBackingArena() for why this is +3.
   likely_to_be_promptly_freed_[entry_index] += 3;
 }
@@ -550,7 +550,7 @@
   size_t total_dead_count = 0;
   size_t total_live_size = 0;
   size_t total_dead_size = 0;
-  for (size_t gc_info_index = 1;
+  for (uint32_t gc_info_index = 1;
        gc_info_index <= GCInfoTable::Get().GcInfoIndex(); ++gc_info_index) {
     total_live_count += info.live_count[gc_info_index];
     total_dead_count += info.dead_count[gc_info_index];
diff --git a/third_party/blink/renderer/platform/heap/heap.h b/third_party/blink/renderer/platform/heap/heap.h
index 1623c418..8f55a62a 100644
--- a/third_party/blink/renderer/platform/heap/heap.h
+++ b/third_party/blink/renderer/platform/heap/heap.h
@@ -280,7 +280,7 @@
   Address AllocateOnArenaIndex(ThreadState*,
                                size_t,
                                int arena_index,
-                               size_t gc_info_index,
+                               uint32_t gc_info_index,
                                const char* type_name);
   template <typename T>
   static Address Allocate(size_t, bool eagerly_sweep = false);
@@ -350,9 +350,9 @@
   //   (*) More than 33% of the same type of vectors have been promptly
   //       freed since the last GC.
   //
-  BaseArena* VectorBackingArena(size_t gc_info_index) {
+  BaseArena* VectorBackingArena(uint32_t gc_info_index) {
     DCHECK(thread_state_->CheckThread());
-    size_t entry_index = gc_info_index & kLikelyToBePromptlyFreedArrayMask;
+    uint32_t entry_index = gc_info_index & kLikelyToBePromptlyFreedArrayMask;
     --likely_to_be_promptly_freed_[entry_index];
     int arena_index = vector_backing_arena_index_;
     // If likely_to_be_promptly_freed_[entryIndex] > 0, that means that
@@ -367,14 +367,14 @@
     DCHECK(IsVectorArenaIndex(arena_index));
     return arenas_[arena_index];
   }
-  BaseArena* ExpandedVectorBackingArena(size_t gc_info_index);
+  BaseArena* ExpandedVectorBackingArena(uint32_t gc_info_index);
   static bool IsVectorArenaIndex(int arena_index) {
     return BlinkGC::kVector1ArenaIndex <= arena_index &&
            arena_index <= BlinkGC::kVector4ArenaIndex;
   }
   static bool IsNormalArenaIndex(int);
   void AllocationPointAdjusted(int arena_index);
-  void PromptlyFreed(size_t gc_info_index);
+  void PromptlyFreed(uint32_t gc_info_index);
   void ClearArenaAges();
   int ArenaIndexOfVectorArenaLeastRecentlyExpanded(int begin_arena_index,
                                                    int end_arena_index);
@@ -602,7 +602,7 @@
 inline Address ThreadHeap::AllocateOnArenaIndex(ThreadState* state,
                                                 size_t size,
                                                 int arena_index,
-                                                size_t gc_info_index,
+                                                uint32_t gc_info_index,
                                                 const char* type_name) {
   DCHECK(state->IsAllocationAllowed());
   DCHECK_NE(arena_index, BlinkGC::kLargeObjectArenaIndex);
@@ -651,7 +651,7 @@
       arena_index = ArenaIndexForObjectSize(size);
   }
 
-  size_t gc_info_index = GCInfoTrait<T>::Index();
+  uint32_t gc_info_index = GCInfoTrait<T>::Index();
   // TODO(haraken): We don't support reallocate() for finalizable objects.
   DCHECK(!GCInfoTable::Get()
               .GCInfoFromIndex(previous_header->GcInfoIndex())
diff --git a/third_party/blink/renderer/platform/heap/heap_allocator.h b/third_party/blink/renderer/platform/heap/heap_allocator.h
index ab841704..e69c0df 100644
--- a/third_party/blink/renderer/platform/heap/heap_allocator.h
+++ b/third_party/blink/renderer/platform/heap/heap_allocator.h
@@ -72,7 +72,7 @@
     ThreadState* state =
         ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
     DCHECK(state->IsAllocationAllowed());
-    size_t gc_info_index = GCInfoTrait<HeapVectorBacking<T>>::Index();
+    uint32_t gc_info_index = GCInfoTrait<HeapVectorBacking<T>>::Index();
     NormalPageArena* arena = static_cast<NormalPageArena*>(
         state->Heap().VectorBackingArena(gc_info_index));
     return reinterpret_cast<T*>(arena->AllocateObject(
@@ -83,7 +83,7 @@
     ThreadState* state =
         ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
     DCHECK(state->IsAllocationAllowed());
-    size_t gc_info_index = GCInfoTrait<HeapVectorBacking<T>>::Index();
+    uint32_t gc_info_index = GCInfoTrait<HeapVectorBacking<T>>::Index();
     NormalPageArena* arena = static_cast<NormalPageArena*>(
         state->Heap().ExpandedVectorBackingArena(gc_info_index));
     return reinterpret_cast<T*>(arena->AllocateObject(
@@ -96,7 +96,7 @@
                                   size_t quantized_shrunk_size);
   template <typename T>
   static T* AllocateInlineVectorBacking(size_t size) {
-    size_t gc_info_index = GCInfoTrait<HeapVectorBacking<T>>::Index();
+    uint32_t gc_info_index = GCInfoTrait<HeapVectorBacking<T>>::Index();
     ThreadState* state =
         ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
     const char* type_name = WTF_HEAP_PROFILER_TYPE_NAME(HeapVectorBacking<T>);
@@ -112,7 +112,7 @@
 
   template <typename T, typename HashTable>
   static T* AllocateHashTableBacking(size_t size) {
-    size_t gc_info_index =
+    uint32_t gc_info_index =
         GCInfoTrait<HeapHashTableBacking<HashTable>>::Index();
     ThreadState* state =
         ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
diff --git a/third_party/blink/renderer/platform/heap/heap_page.cc b/third_party/blink/renderer/platform/heap/heap_page.cc
index 47b4c3d..07ae942 100644
--- a/third_party/blink/renderer/platform/heap/heap_page.cc
+++ b/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -1646,14 +1646,14 @@
       live_count++;
       live_size += header->size();
 
-      size_t gc_info_index = header->GcInfoIndex();
+      uint32_t gc_info_index = header->GcInfoIndex();
       info.live_count[gc_info_index]++;
       info.live_size[gc_info_index] += header->size();
     } else {
       dead_count++;
       dead_size += header->size();
 
-      size_t gc_info_index = header->GcInfoIndex();
+      uint32_t gc_info_index = header->GcInfoIndex();
       info.dead_count[gc_info_index]++;
       info.dead_size[gc_info_index] += header->size();
     }
@@ -1730,7 +1730,7 @@
   size_t live_count = 0;
   size_t dead_count = 0;
   HeapObjectHeader* header = ObjectHeader();
-  size_t gc_info_index = header->GcInfoIndex();
+  uint32_t gc_info_index = header->GcInfoIndex();
   size_t payload_size = header->PayloadSize();
   if (header->IsMarked()) {
     live_count = 1;
diff --git a/third_party/blink/renderer/platform/heap/heap_page.h b/third_party/blink/renderer/platform/heap/heap_page.h
index b6977736..2bc6d7c 100644
--- a/third_party/blink/renderer/platform/heap/heap_page.h
+++ b/third_party/blink/renderer/platform/heap/heap_page.h
@@ -194,7 +194,7 @@
 
   size_t size() const;
 
-  NO_SANITIZE_ADDRESS size_t GcInfoIndex() const {
+  NO_SANITIZE_ADDRESS uint32_t GcInfoIndex() const {
     return (encoded_ & kHeaderGCInfoIndexMask) >> kHeaderGCInfoIndexShift;
   }
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 5da92de..5a7e167 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1118,6 +1118,9 @@
       name: "RTCUnifiedPlanByDefault",
     },
     {
+      name: "ScheduledScriptStreaming",
+    },
+    {
       name: "ScriptedSpeech",
       status: "stable",
     },
diff --git a/third_party/blink/renderer/platform/scheduler/DEPS b/third_party/blink/renderer/platform/scheduler/DEPS
index c8e9a1cd..749a0a1 100644
--- a/third_party/blink/renderer/platform/scheduler/DEPS
+++ b/third_party/blink/renderer/platform/scheduler/DEPS
@@ -39,6 +39,7 @@
   "+base/task/sequence_manager/sequence_manager.h",
   "+base/task/sequence_manager/task_queue.h",
   "+base/task/sequence_manager/time_domain.h",
+  "+base/task_scheduler/task_traits.h",
   "+base/threading/platform_thread.h",
   "+base/threading/sequenced_task_runner_handle.h",
   "+base/threading/thread.h",
diff --git a/third_party/blink/renderer/platform/scheduler/common/background_scheduler.cc b/third_party/blink/renderer/platform/scheduler/common/background_scheduler.cc
index 18d898e3..5337518 100644
--- a/third_party/blink/renderer/platform/scheduler/common/background_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/background_scheduler.cc
@@ -11,8 +11,16 @@
 
 void BackgroundScheduler::PostOnBackgroundThread(const base::Location& location,
                                                  CrossThreadClosure closure) {
-  base::PostTaskWithTraits(location,
-                           {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+  PostOnBackgroundThreadWithTraits(
+      location, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+      std::move(closure));
+}
+
+void BackgroundScheduler::PostOnBackgroundThreadWithTraits(
+    const base::Location& location,
+    const base::TaskTraits& traits,
+    CrossThreadClosure closure) {
+  base::PostTaskWithTraits(location, traits,
                            ConvertToBaseCallback(std::move(closure)));
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/public/background_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/background_scheduler.h
index ef80a0a..57bffd3 100644
--- a/third_party/blink/renderer/platform/scheduler/public/background_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/public/background_scheduler.h
@@ -6,6 +6,8 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_BACKGROUND_SCHEDULER_H_
 
 #include "base/location.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task_scheduler/task_traits.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 
@@ -13,14 +15,22 @@
 
 namespace BackgroundScheduler {
 
-// This is a thin wrapper around base::TaskScheduler to accomodate
-// Blink's CrossThreadClosure, which only allows background tasks.
+// These are a thin wrapper around base::TaskScheduler to accomodate
+// Blink's CrossThreadClosure, which only allows background tasks
+// (i.e. tasks which are run off the main thread).
 //
 // Non-background tasks should be posted using another scheduler, e.g.
 // FrameShceduler.
 PLATFORM_EXPORT void PostOnBackgroundThread(const base::Location&,
                                             CrossThreadClosure);
 
+PLATFORM_EXPORT void PostOnBackgroundThreadWithTraits(const base::Location&,
+                                                      const base::TaskTraits&,
+                                                      CrossThreadClosure);
+
+// TODO(altimin): Expose CreateBackgroundTaskRunnerWithTraits when the
+// need arises.
+
 }  // namespace BackgroundScheduler
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/allocator/partitions.h b/third_party/blink/renderer/platform/wtf/allocator/partitions.h
index 079afd0..8ee8698e 100644
--- a/third_party/blink/renderer/platform/wtf/allocator/partitions.h
+++ b/third_party/blink/renderer/platform/wtf/allocator/partitions.h
@@ -101,6 +101,11 @@
                                            const char* type_name) {
     return BufferPartition()->Realloc(p, n, type_name);
   }
+  ALWAYS_INLINE static void* BufferTryRealloc(void* p,
+                                              size_t n,
+                                              const char* type_name) {
+    return BufferPartition()->TryRealloc(p, n, type_name);
+  }
   ALWAYS_INLINE static void BufferFree(void* p) { BufferPartition()->Free(p); }
   ALWAYS_INLINE static size_t BufferActualSize(size_t n) {
     return BufferPartition()->ActualSize(n);
diff --git a/third_party/blink/tools/audit_non_blink_usage.py b/third_party/blink/tools/audit_non_blink_usage.py
index 0b33cd7..aa4e0c1 100755
--- a/third_party/blink/tools/audit_non_blink_usage.py
+++ b/third_party/blink/tools/audit_non_blink_usage.py
@@ -118,6 +118,13 @@
             # Base atomic utilities
             'base::AtomicSequenceNumber',
 
+            # Task traits
+            'base::TaskTraits',
+            'base::MayBlock',
+            'base::TaskPriority',
+            'base::TaskShutdownBehavior',
+            'base::WithBaseSyncPrimitives',
+
             # Byte order
             'base::ByteSwap',
             'base::NetToHost(16|32|64)',
diff --git a/tools/binary_size/libsupersize/gsutil.py b/tools/binary_size/libsupersize/gsutil.py
new file mode 100644
index 0000000..855517b
--- /dev/null
+++ b/tools/binary_size/libsupersize/gsutil.py
@@ -0,0 +1,67 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Update the Google Cloud Storage bucket hosting the Super Size UI."""
+
+import argparse
+import os
+import subprocess
+import uuid
+
+
+GS_BUCKET = 'gs://chrome-supersize'
+
+
+def _SyncStatic():
+  """Upload static files from the static directory."""
+  static_files = os.path.join(os.path.dirname(__file__), 'static')
+  subprocess.check_call([
+    'gsutil.py', '-m', 'rsync', '-r', static_files, GS_BUCKET
+  ])
+
+
+def _SyncTemplates():
+  """Generate and upload the templates/sw.js file."""
+  template_file = os.path.join(os.path.dirname(__file__), 'templates', 'sw.js')
+  cache_hash = uuid.uuid4().hex
+
+  p = subprocess.Popen([
+    'gsutil.py', 'cp', '-p', '-', '%s/sw.js' % GS_BUCKET
+  ], stdin=subprocess.PIPE)
+  with open(template_file, 'r') as in_file:
+    p.communicate(in_file.read().replace('{{cache_hash}}', cache_hash))
+
+
+def _SetMetaAndPermissions():
+  # sw.js has the wrong type due to being created from a stream
+  subprocess.check_call([
+    'gsutil.py', 'setmeta', '-h', 'Content-Type:application/javascript',
+    '%s/sw.js' % GS_BUCKET
+  ])
+  subprocess.check_call([
+    'gsutil.py', '-m', 'setmeta', '-h', 'Content-Type:application/x-ndjson',
+    '%s/milestones/*.ndjson' % GS_BUCKET
+  ])
+
+  # All files in the root of the bucket are user readable
+  subprocess.check_call([
+    'gsutil.py', '-m', 'acl', 'ch', '-u', 'AllUsers:R', '%s/*' % GS_BUCKET
+  ])
+
+
+def main():
+  parser = argparse.ArgumentParser(description=__doc__)
+  parser.add_argument('--sync', action='store_true', required=True,
+                      help='Sync static and template files to GCS.')
+
+  args = parser.parse_args()
+
+  if args.sync:
+    _SyncStatic()
+    _SyncTemplates()
+    _SetMetaAndPermissions()
+
+
+if __name__ == '__main__':
+  main()
diff --git a/tools/binary_size/libsupersize/static/index.html b/tools/binary_size/libsupersize/static/index.html
index eb6187e..9e176e1 100644
--- a/tools/binary_size/libsupersize/static/index.html
+++ b/tools/binary_size/libsupersize/static/index.html
@@ -7,9 +7,10 @@
 -->
 
 <head>
-    <title>Binary Size Analysis</title>
+    <title>Super Size Tiger View</title>
     <script src="start-worker.js"></script>
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="theme-color" content="#4285f4">
     <link href="https://fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,500" rel="stylesheet">
     <style>
         body {
@@ -205,17 +206,23 @@
     </style>
     <link rel="stylesheet" href="options.css">
     <link rel="icon" href="favicon.ico" sizes="16x16 32x32 256x256" type="image/x-icon">
+    <link rel="manifest" href="manifest.json">
     <script defer src="shared.js"></script>
     <script defer src="state.js"></script>
     <script defer src="infocard-ui.js"></script>
     <script defer src="tree-ui.js"></script>
+    <script defer async>
+        if ('serviceWorker' in navigator) {
+            navigator.serviceWorker.register('sw.js');
+        }
+    </script>
 </head>
 
 <body>
     <div class="scrim toggle-options" hidden></div>
     <header class="appbar">
         <div class="appbar-inner">
-            <h1 class="headline">Binary Size Analysis</h1>
+            <h1 class="headline">Super Size Tiger View</h1>
             <input type="file" name="upload" id="upload" accept=".ndjson" >
             <label for="upload" class="text-button filled-button with-icon">
                 <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="#fff">
diff --git a/tools/binary_size/libsupersize/static/manifest.json b/tools/binary_size/libsupersize/static/manifest.json
new file mode 100644
index 0000000..355e862
--- /dev/null
+++ b/tools/binary_size/libsupersize/static/manifest.json
@@ -0,0 +1,22 @@
+{
+  "short_name": "Super Size",
+  "name": "Super Size Tiger View",
+  "description": "View interactive size breakdowns from Chrome",
+  "icons": [
+    {
+      "src": "favicon.ico",
+      "sizes": "16x16 32x32 256x256"
+    },
+    {
+      "src": "splash.png",
+      "type": "image/png",
+      "sizes": "512x512"
+    }
+  ],
+  "lang": "en",
+  "start_url": "index.html",
+  "background_color": "#fff",
+  "display": "standalone",
+  "scope": "./",
+  "theme_color": "#4285f4"
+}
diff --git a/tools/binary_size/libsupersize/static/options.css b/tools/binary_size/libsupersize/static/options.css
index f627327..2fa0185b 100644
--- a/tools/binary_size/libsupersize/static/options.css
+++ b/tools/binary_size/libsupersize/static/options.css
@@ -34,7 +34,7 @@
   position: fixed;
   right: 0;
   top: 0;
-  height: 100vh;
+  bottom: 0;
   width: 224px;
   background: #fffffff5;
   box-shadow: 0 1px 2px #3c40434d, 0 2px 6px 2px #3c404326;
@@ -306,15 +306,11 @@
   .symbols {
     padding: 0 16px;
   }
-  .appbar-progress {
-    margin: 0 -16px;
-    width: calc(100% + 32px);
-  }
 
-  .filled-button {
+  .text-button.with-icon {
     padding-right: 6px;
   }
-  .filled-button .label-text {
+  .text-button.with-icon .label-text {
     display: none;
   }
 }
diff --git a/tools/binary_size/libsupersize/static/splash.png b/tools/binary_size/libsupersize/static/splash.png
new file mode 100644
index 0000000..db8d5f8
--- /dev/null
+++ b/tools/binary_size/libsupersize/static/splash.png
Binary files differ
diff --git a/tools/binary_size/libsupersize/templates/sw.js b/tools/binary_size/libsupersize/templates/sw.js
new file mode 100644
index 0000000..6807eed
--- /dev/null
+++ b/tools/binary_size/libsupersize/templates/sw.js
@@ -0,0 +1,51 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @ts-check
+'use strict';
+
+const cacheName = '{{cache_hash}}';
+const filesToCache = [
+  'favicon.ico',
+  'index.html',
+  'infocard-ui.js',
+  'infocard.css',
+  'manifest.json',
+  'options.css',
+  'shared.js',
+  'start-worker.js',
+  'state.js',
+  'tree-ui.js',
+  'tree-worker.js',
+];
+
+// On install, cache the items in the `filesToCache` list
+self.addEventListener('install', event => {
+  event.waitUntil(
+    caches.open(cacheName).then(cache => cache.addAll(filesToCache))
+  );
+});
+
+// On activate, remove any old caches
+self.addEventListener('activate', event => {
+  async function deleteOldCache(key) {
+    if (key !== cacheName) {
+      return caches.delete(key);
+    }
+  }
+
+  event.waitUntil(
+    caches.keys().then(keyList => Promise.all(keyList.map(deleteOldCache)))
+  );
+  return self.clients.claim();
+});
+
+// On fetch, return entries from the cache if possible
+self.addEventListener('fetch', event => {
+  event.respondWith(
+    caches
+      .match(event.request, {ignoreSearch: true})
+      .then(response => response || fetch(event.request))
+  );
+});
diff --git a/tools/cygprofile/phased_orderfile.py b/tools/cygprofile/phased_orderfile.py
index 73bb234..ac0d27fb 100755
--- a/tools/cygprofile/phased_orderfile.py
+++ b/tools/cygprofile/phased_orderfile.py
@@ -13,6 +13,13 @@
 orderfile with three parts: the code touched only in startup, the code
 touched only during interaction, and code common to the two phases. We refer to
 these parts as the orderfile phases.
+
+Example invocation, with PROFILE_DIR the location of the profile data pulled
+from a device and LIBTYPE either monochrome or chrome as appropriate.
+./tools/cygprofile/phased_orderfile.py \
+    --profile-directory=PROFILE_DIR \
+    --instrumented-build-dir=out-android/Orderfile/ \
+    --library-name=libLIBTYPE.so --offset-output-base=PROFILE_DIR/offset
 """
 
 import argparse
@@ -26,7 +33,7 @@
 
 
 # Files matched when using this script to analyze directly (see main()).
-PROFILE_GLOB = 'cygprofile-*.txt_*'
+PROFILE_GLOB = 'profile-hitmap-*.txt_*'
 
 
 OrderfilePhaseOffsets = collections.namedtuple(
@@ -45,6 +52,9 @@
   COMMON_STABILITY_THRESHOLD = 1.75
   INTERACTION_STABILITY_THRESHOLD = 2.5
 
+  # The process name of the browser as used in the profile dumps.
+  BROWSER = 'browser'
+
   def __init__(self, profiles, processor):
     """Intialize.
 
@@ -54,7 +64,11 @@
     """
     self._profiles = profiles
     self._processor = processor
+
+    # These members cache various computed values.
     self._phase_offsets = None
+    self._annotated_offsets = None
+    self._process_list = None
 
   def IsStableProfile(self):
     """Verify that the profiling has been stable.
@@ -65,7 +79,7 @@
       True if the profile was stable as described above.
     """
     (startup_stability, common_stability,
-     interaction_stability) = self.ComputeStability()
+     interaction_stability) = [s[0] for s in self.ComputeStability()]
 
     stable = True
     if startup_stability > self.STARTUP_STABILITY_THRESHOLD:
@@ -89,11 +103,46 @@
     they cover.
 
     Returns:
-      (float, float, float) A heuristic stability metric for startup, common and
-          interaction orderfile phases, respectively.
+      ((float, int), (float, int), (float, int)) A heuristic stability metric
+          for startup, common and interaction orderfile phases,
+          respectively. Each metric is a pair of the ratio of symbol sizes as
+          described above, and the size of the intersection.
+    """
+    (startup_intersection, startup_union,
+     common_intersection, common_union,
+     interaction_intersection, interaction_union,
+     _, _) = self.GetCombinedOffsets()
+    startup_intersection_size = self._processor.OffsetsPrimarySize(
+        startup_intersection)
+    common_intersection_size = self._processor.OffsetsPrimarySize(
+        common_intersection)
+    interaction_intersection_size = self._processor.OffsetsPrimarySize(
+        interaction_intersection)
+    startup_stability = self._SafeDiv(
+        self._processor.OffsetsPrimarySize(startup_union),
+        startup_intersection_size)
+    common_stability = self._SafeDiv(
+        self._processor.OffsetsPrimarySize(common_union),
+        common_intersection_size)
+    interaction_stability = self._SafeDiv(
+        self._processor.OffsetsPrimarySize(interaction_union),
+        interaction_intersection_size)
+    return ((startup_stability, startup_intersection_size),
+            (common_stability, common_intersection_size),
+            (interaction_stability, interaction_intersection_size))
+
+  def GetCombinedOffsets(self):
+    """Get offsets for the union and intersection of orderfile phases.
+
+    Returns:
+      ([int] * 8) For each of startup, common, interaction and all, respectively
+          the intersection and union offsets, in that order.
     """
     phase_offsets = self._GetOrderfilePhaseOffsets()
-    assert len(phase_offsets) > 1  # Otherwise the analysis is silly.
+    assert phase_offsets
+    if len(phase_offsets) == 1:
+      logging.error('Only one run set, the combined offset files will all be '
+                    'identical')
 
     startup_union = set(phase_offsets[0].startup)
     startup_intersection = set(phase_offsets[0].startup)
@@ -108,16 +157,172 @@
       common_intersection &= set(offsets.common)
       interaction_union |= set(offsets.interaction)
       interaction_intersection &= set(offsets.interaction)
-    startup_stability = self._SafeDiv(
-        self._processor.OffsetsPrimarySize(startup_union),
-        self._processor.OffsetsPrimarySize(startup_intersection))
-    common_stability = self._SafeDiv(
-        self._processor.OffsetsPrimarySize(common_union),
-        self._processor.OffsetsPrimarySize(common_intersection))
-    interaction_stability = self._SafeDiv(
-        self._processor.OffsetsPrimarySize(interaction_union),
-        self._processor.OffsetsPrimarySize(interaction_intersection))
-    return (startup_stability, common_stability, interaction_stability)
+    return (startup_intersection, startup_union,
+            common_intersection, common_union,
+            interaction_intersection, interaction_union,
+            (startup_union & common_union & interaction_union),
+            (startup_union | common_union | interaction_union))
+
+  def GetOffsetsForMemoryFootprint(self):
+    """Get offsets organized to minimize the memory footprint.
+
+    The startup, common and interaction offsets are computed for each
+    process. Any symbols used by one process in startup or interaction that are
+    used in a different phase by another process are moved to the common
+    section. This should minimize the memory footprint by keeping startup- or
+    interaction-only pages clean, at the possibly expense of startup time, as
+    more of the common section will need to be loaded. To mitigate that effect,
+    symbols moved from startup are placed at the beginning of the common
+    section, and those moved from interaction are placed at the end.
+
+    Browser startup symbols are placed at the beginning of the startup section
+    in the hope of working out with native library prefetching to minimize
+    startup time.
+
+    Returns:
+      OrdrerfilePhaseOffsets as described above.
+    """
+    startup = []
+    common_head = []
+    common = []
+    common_tail = []
+    interaction = []
+
+    process_offsets = {p: self._GetCombinedProcessOffsets(p)
+                       for p in self._GetProcessList()}
+    assert self.BROWSER in process_offsets.keys()
+
+    any_startup = set()
+    any_interaction = set()
+    any_common = set()
+    for offsets in process_offsets.itervalues():
+      any_startup |= set(offsets.startup)
+      any_interaction |= set(offsets.interaction)
+      any_common |= set(offsets.common)
+
+    already_added = set()
+    # This helper function splits |offsets|, adding to |alternate| all offsets
+    # that are in |interfering| or are already known to be common, and otherwise
+    # adding to |target|.
+    def add_process_offsets(offsets, interfering, target, alternate):
+      for o in offsets:
+        if o in already_added:
+          continue
+        if o in interfering or o in any_common:
+          alternate.append(o)
+        else:
+          target.append(o)
+        already_added.add(o)
+
+    # This helper updates |common| with new members of |offsets|.
+    def add_common_offsets(offsets):
+      for o in offsets:
+        if o not in already_added:
+          common.append(o)
+          already_added.add(o)
+
+    add_process_offsets(process_offsets[self.BROWSER].startup,
+                        any_interaction, startup, common_head)
+    add_process_offsets(process_offsets[self.BROWSER].interaction,
+                        any_startup, interaction, common_tail)
+    add_common_offsets(process_offsets[self.BROWSER].common)
+
+    for p in process_offsets:
+      if p == self.BROWSER:
+        continue
+      add_process_offsets(process_offsets[p].startup,
+                          any_interaction, startup, common_head)
+      add_process_offsets(process_offsets[p].interaction,
+                          any_startup, interaction, common_tail)
+      add_common_offsets(process_offsets[p].common)
+
+    return OrderfilePhaseOffsets(
+        startup=startup,
+        common=(common_head + common + common_tail),
+        interaction=interaction)
+
+  def GetOffsetsForStartup(self):
+    """Get offsets organized to minimize startup time.
+
+    The startup, common and interaction offsets are computed for each
+    process. Any symbol used by one process in interaction that appears in a
+    different phase in another process is moved to common, but any symbol that
+    appears in startup for *any* process stays in startup.
+
+    This should maximize startup performance at the expense of increasing the
+    memory footprint, as some startup symbols will not be able to page out.
+
+    The startup symbols in the browser process appear first in the hope of
+    working out with native library prefetching to minimize startup time.
+    """
+    startup = []
+    common = []
+    interaction = []
+    already_added = set()
+
+    process_offsets = {p: self._GetCombinedProcessOffsets(p)
+                       for p in self._GetProcessList()}
+    startup.extend(process_offsets[self.BROWSER].startup)
+    already_added |= set(process_offsets[self.BROWSER].startup)
+    common.extend(process_offsets[self.BROWSER].common)
+    already_added |= set(process_offsets[self.BROWSER].common)
+    interaction.extend(process_offsets[self.BROWSER].interaction)
+    already_added |= set(process_offsets[self.BROWSER].interaction)
+
+    for process, offsets in process_offsets.iteritems():
+      if process == self.BROWSER:
+        continue
+      startup.extend(o for o in offsets.startup
+                     if o not in already_added)
+      already_added |= set(offsets.startup)
+      common.extend(o for o in offsets.common
+                     if o not in already_added)
+      already_added |= set(offsets.common)
+      interaction.extend(o for o in offsets.interaction
+                     if o not in already_added)
+      already_added |= set(offsets.interaction)
+
+    return OrderfilePhaseOffsets(
+        startup=startup, common=common, interaction=interaction)
+
+  def _GetCombinedProcessOffsets(self, process):
+    """Combine offsets across runs for a particular process.
+
+    Args:
+      process (str) The process to combine.
+
+    Returns:
+      OrderfilePhaseOffsets, the startup, common and interaction offsets for the
+      process in question. The offsets are sorted arbitrarily.
+    """
+    (startup, common, interaction) = ([], [], [])
+    assert self._profiles.GetPhases() == set([0,1]), 'Unexpected phases'
+    for o in self._GetAnnotatedOffsets():
+      startup_count = o.Count(0, process)
+      interaction_count = o.Count(1, process)
+      if not startup_count and not interaction_count:
+        continue
+      if startup_count and interaction_count:
+        common.append(o.Offset())
+      elif startup_count:
+        startup.append(o.Offset())
+      else:
+        interaction.append(o.Offset())
+    return OrderfilePhaseOffsets(
+        startup=startup, common=common, interaction=interaction)
+
+  def _GetAnnotatedOffsets(self):
+    if self._annotated_offsets is None:
+      self._annotated_offsets = self._profiles.GetAnnotatedOffsets()
+      self._processor.TranslateAnnotatedSymbolOffsets(self._annotated_offsets)
+    return self._annotated_offsets
+
+  def _GetProcessList(self):
+    if self._process_list is None:
+      self._process_list = set()
+      for o in self._GetAnnotatedOffsets():
+        self._process_list.update(o.Processes())
+    return self._process_list
 
   def _GetOrderfilePhaseOffsets(self):
     """Compute the phase offsets for each run.
@@ -129,7 +334,8 @@
     if self._phase_offsets is not None:
       return self._phase_offsets
 
-    assert self._profiles.GetPhases() == set([0, 1]), 'Unexpected phases'
+    assert self._profiles.GetPhases() == set([0, 1]), (
+        'Unexpected phases {}'.format(self._profiles.GetPhases()))
     self._phase_offsets = []
     for first, second in zip(self._profiles.GetRunGroupOffsets(phase=0),
                              self._profiles.GetRunGroupOffsets(phase=1)):
@@ -175,10 +381,17 @@
                       help=('Directory containing profile runs. Files '
                             'matching {} are used.'.format(PROFILE_GLOB)))
   parser.add_argument('--instrumented-build-dir', type=str,
-                      help='Path to the instrumented build', required=True)
+                      help='Path to the instrumented build (eg, out/Orderfile)',
+                      required=True)
   parser.add_argument('--library-name', default='libchrome.so',
                       help=('Chrome shared library name (usually libchrome.so '
                             'or libmonochrome.so'))
+  parser.add_argument('--offset-output-base', default=None, type=str,
+                      help=('If present, a base name to output offsets to. '
+                            'No offsets are output if this is missing. The '
+                            'base name is suffixed with _for_memory and '
+                            '_for_startup, corresponding to the two sets of '
+                            'offsets produced.'))
   return parser
 
 
@@ -186,12 +399,25 @@
   logging.basicConfig(level=logging.INFO)
   parser = _CreateArgumentParser()
   args = parser.parse_args()
-  profiles = process_profiles.ProfileManager(
-      glob.glob(os.path.join(args.profile_directory, PROFILE_GLOB)))
+  profiles = process_profiles.ProfileManager(itertools.chain.from_iterable(
+      glob.glob(os.path.join(d, PROFILE_GLOB))
+      for d in args.profile_directory.split(',')))
   processor = process_profiles.SymbolOffsetProcessor(os.path.join(
       args.instrumented_build_dir, 'lib.unstripped', args.library_name))
   phaser = PhasedAnalyzer(profiles, processor)
-  print 'Stability: {:.2f} {:.2f} {:.2f}'.format(*phaser.ComputeStability())
+  stability = phaser.ComputeStability()
+  print 'Stability: {:.2} {:.2} {:.2}'.format(*[s[0] for s in stability])
+  print 'Sizes: {} {} {}'.format(*[s[1] for s in stability])
+  if args.offset_output_base is not None:
+    for name, offsets in zip(
+        ['_for_memory', '_for_startup'],
+        [phaser.GetOffsetsForMemoryFootprint(),
+         phaser.GetOffsetsForStartup()]):
+      with file(args.offset_output_base + name, 'w') as output:
+        output.write('\n'.join(
+            str(i) for i in (offsets.startup + offsets.common +
+                             offsets.interaction)))
+        output.write('\n')
 
 
 if __name__ == '__main__':
diff --git a/tools/cygprofile/phased_orderfile_unittest.py b/tools/cygprofile/phased_orderfile_unittest.py
index f2209bf..6941f7f 100755
--- a/tools/cygprofile/phased_orderfile_unittest.py
+++ b/tools/cygprofile/phased_orderfile_unittest.py
@@ -11,20 +11,47 @@
 import phased_orderfile
 import process_profiles
 
-from test_utils import (SimpleTestSymbol,
+from test_utils import (ProfileFile,
+                        SimpleTestSymbol,
                         TestSymbolOffsetProcessor,
                         TestProfileManager)
 
 
-class Mod10Processor(object):
+class Mod10Processor(process_profiles.SymbolOffsetProcessor):
   """A restricted mock for a SymbolOffsetProcessor.
 
-  This only implements GetReachedOffsetsFromDump, and works by mapping a dump
-  offset to offset - (offset % 10). If the dump offset is negative, it is marked
-  as not found.
+  This only implements {Translate,Get}ReacheOffsetsFromDump, and works by
+  mapping a dump offset to offset - (offset % 10). If the dump offset is
+  negative, it is marked as not found.
   """
-  def GetReachedOffsetsFromDump(self, dump):
-    return [x - (x % 10) for x in dump if x >= 0]
+  def __init__(self):
+    super(Mod10Processor, self).__init__(None)
+
+  def _TranslateReachedOffsetsFromDump(self, items, get, update):
+    for i in items:
+      x = get(i)
+      if x >= 0:
+        update(i, x - (x % 10))
+      else:
+        update(i, None)
+
+
+class IdentityProcessor(process_profiles.SymbolOffsetProcessor):
+  """A restricted mock for a SymbolOffsetProcessor.
+
+  This only implements {Translate,Get}ReachedOffsetsFromDump, and maps the dump
+  offset to itself. If the dump offset is negative, it is marked as not found.
+  """
+  def __init__(self):
+    super(IdentityProcessor, self).__init__(None)
+
+  def _TranslateReachedOffsetsFromDump(self, items, get, update):
+    for i in items:
+      x = get(i)
+      if x >= 0:
+        update(i, x)
+      else:
+        update(i, None)
 
 
 class PhasedOrderfileTestCase(unittest.TestCase):
@@ -32,11 +59,6 @@
   def setUp(self):
     self._file_counter = 0
 
-  def File(self, timestamp_sec, phase):
-    self._file_counter += 1
-    return 'file-{}-{}.txt_{}'.format(
-        self._file_counter, timestamp_sec * 1000 * 1000 * 1000, phase)
-
   def testProfileStability(self):
     symbols = [SimpleTestSymbol(str(i), i, 10)
                for i in xrange(20)]
@@ -46,7 +68,8 @@
         startup=s, common=c, interaction=i)
     phaser._phase_offsets = [opo(range(5), range(6, 10), range(11,15)),
                              opo(range(4), range(6, 10), range(18, 20))]
-    self.assertEquals((1.25, 1, None), phaser.ComputeStability())
+    self.assertEquals((1.25, 1, None),
+                      tuple(s[0] for s in phaser.ComputeStability()))
 
   def testIsStable(self):
     symbols = [SimpleTestSymbol(str(i), i, 10)
@@ -64,12 +87,12 @@
 
   def testGetOrderfilePhaseOffsets(self):
     mgr = TestProfileManager({
-        self.File(0, 0): [12, 21, -1, 33],
-        self.File(0, 1): [31, 49, 52],
-        self.File(100, 0): [113, 128],
-        self.File(200, 1): [132, 146],
-        self.File(300, 0): [19, 20, 32],
-        self.File(300, 1): [24, 39]})
+        ProfileFile(0, 0): [12, 21, -1, 33],
+        ProfileFile(0, 1): [31, 49, 52],
+        ProfileFile(100, 0): [113, 128],
+        ProfileFile(200, 1): [132, 146],
+        ProfileFile(300, 0): [19, 20, 32],
+        ProfileFile(300, 1): [24, 39]})
     phaser = phased_orderfile.PhasedAnalyzer(mgr, Mod10Processor())
     opo = lambda s, c, i: phased_orderfile.OrderfilePhaseOffsets(
         startup=s, common=c, interaction=i)
@@ -79,6 +102,47 @@
                           opo([10], [20, 30], [])],
                          phaser._GetOrderfilePhaseOffsets())
 
+  def testGetCombinedProcessOffsets(self):
+    mgr = TestProfileManager({
+        ProfileFile(40, 0, ''): [1, 2, 3],
+        ProfileFile(50, 1, ''): [3, 4, 5],
+        ProfileFile(51, 0, 'renderer'): [2, 3, 6],
+        ProfileFile(51, 1, 'gpu-process'): [6, 7],
+        ProfileFile(70, 0, ''): [2, 8, 9],
+        ProfileFile(70, 1, ''): [9]})
+    phaser = phased_orderfile.PhasedAnalyzer(mgr, IdentityProcessor())
+    offsets = phaser._GetCombinedProcessOffsets('browser')
+    self.assertListEqual([1, 2, 8], sorted(offsets.startup))
+    self.assertListEqual([4, 5], sorted(offsets.interaction))
+    self.assertListEqual([3, 9], sorted(offsets.common))
+
+    offsets = phaser._GetCombinedProcessOffsets('gpu-process')
+    self.assertListEqual([], sorted(offsets.startup))
+    self.assertListEqual([6, 7], sorted(offsets.interaction))
+    self.assertListEqual([], sorted(offsets.common))
+
+    self.assertListEqual(['browser', 'gpu-process', 'renderer'],
+                         sorted(phaser._GetProcessList()))
+
+  def testGetOffsetVariations(self):
+    mgr = TestProfileManager({
+        ProfileFile(40, 0, ''): [1, 2, 3],
+        ProfileFile(50, 1, ''): [3, 4, 5],
+        ProfileFile(51, 0, 'renderer'): [2, 3, 6],
+        ProfileFile(51, 1, 'gpu-process'): [6, 7],
+        ProfileFile(70, 0, ''): [2, 6, 8, 9],
+        ProfileFile(70, 1, ''): [9]})
+    phaser = phased_orderfile.PhasedAnalyzer(mgr, IdentityProcessor())
+    offsets = phaser.GetOffsetsForMemoryFootprint()
+    self.assertListEqual([1, 2, 8], offsets.startup)
+    self.assertListEqual([6, 3, 9], offsets.common)
+    self.assertListEqual([4, 5, 7], offsets.interaction)
+
+    offsets = phaser.GetOffsetsForStartup()
+    self.assertListEqual([1, 2, 6, 8], offsets.startup)
+    self.assertListEqual([3, 9], offsets.common)
+    self.assertListEqual([4, 5, 7], offsets.interaction)
+
 
 if __name__ == "__main__":
   unittest.main()
diff --git a/tools/cygprofile/process_profiles.py b/tools/cygprofile/process_profiles.py
index a436ead..916750f6 100755
--- a/tools/cygprofile/process_profiles.py
+++ b/tools/cygprofile/process_profiles.py
@@ -56,6 +56,7 @@
     self._name_to_symbol = None
     self._offset_to_primary = None
     self._offset_to_symbols = None
+    self._offset_to_symbol_info = None
 
   def SymbolInfos(self):
     """The symbols associated with this processor's binary.
@@ -152,24 +153,14 @@
     Returns:
       [int] Reached symbol offsets.
     """
-    dump_offset_to_symbol_info = self._GetDumpOffsetToSymbolInfo()
-    logging.info('Offset to Symbol size = %d', len(dump_offset_to_symbol_info))
-    assert max(dump) / 4 <= len(dump_offset_to_symbol_info)
-    already_seen = set()
     reached_offsets = []
-    reached_return_addresses_not_found = 0
-    for dump_offset in dump:
-      symbol_info = dump_offset_to_symbol_info[dump_offset / 4]
-      if symbol_info is None:
-        reached_return_addresses_not_found += 1
-        continue
-      if symbol_info.offset in already_seen:
-        continue
-      reached_offsets.append(symbol_info.offset)
-      already_seen.add(symbol_info.offset)
-    if reached_return_addresses_not_found:
-      logging.warning('%d return addresses don\'t map to any symbol',
-                      reached_return_addresses_not_found)
+    already_seen = set()
+    def update(_, symbol_offset):
+      if symbol_offset is None or symbol_offset in already_seen:
+        return
+      reached_offsets.append(symbol_offset)
+      already_seen.add(symbol_offset)
+    self._TranslateReachedOffsetsFromDump(dump, lambda x: x, update)
     return reached_offsets
 
   def MatchSymbolNames(self, symbol_names):
@@ -185,6 +176,52 @@
     matched_names = our_symbol_names.intersection(set(symbol_names))
     return [self.NameToSymbolMap()[n] for n in matched_names]
 
+  def TranslateAnnotatedSymbolOffsets(self, annotated_offsets):
+    """Merges offsets across run groups and translates to symbol offsets.
+
+    Like GetReachedOffsetsFromDump, but works with AnnotatedOffsets.
+
+    Args:
+      annotated_offsets (AnnotatedOffset iterable) List of annotated offsets,
+        eg from ProfileManager.GetAnnotatedOffsets(). This will be mutated to
+        translate raw offsets to symbol offsets.
+    """
+    self._TranslateReachedOffsetsFromDump(
+        annotated_offsets,
+        lambda o: o.Offset(),
+        lambda o, symbol_offset: o.SetOffset(symbol_offset))
+
+  def _TranslateReachedOffsetsFromDump(self, items, get, update):
+    """Translate raw binary offsets to symbol offsets.
+
+    See GetReachedOffsetsFromDump for details. This version calls
+    |get(i)| on each element |i| of |items|, then calls
+    |update(i, symbol_offset)| with the updated offset. If the offset is not
+    found, update will be called with None.
+
+    Args:
+      items: (iterable) Items containing offsets.
+      get: (lambda item) As described above.
+      update: (lambda item, int) As described above.
+    """
+    dump_offset_to_symbol_info = self._GetDumpOffsetToSymbolInfo()
+    logging.info('Offset to Symbol size = %d', len(dump_offset_to_symbol_info))
+    reached_return_addresses_not_found = 0
+    for i in items:
+      dump_offset = get(i)
+      idx = dump_offset / 4
+      assert idx < len(dump_offset_to_symbol_info), (
+          'Dump offset out of binary range')
+      symbol_info = dump_offset_to_symbol_info[idx]
+      if symbol_info is None:
+        reached_return_addresses_not_found += 1
+        update(i, None)
+      else:
+        update(i, symbol_info.offset)
+    if reached_return_addresses_not_found:
+      logging.warning('%d return addresses don\'t map to any symbol',
+                      reached_return_addresses_not_found)
+
   def _GetDumpOffsetToSymbolInfo(self):
     """Computes an array mapping each word in .text to a symbol.
 
@@ -192,15 +229,16 @@
       [symbol_extractor.SymbolInfo or None] For every 4 bytes of the .text
         section, maps it to a symbol, or None.
     """
-    min_offset = min(s.offset for s in self.SymbolInfos())
-    max_offset = max(s.offset + s.size for s in self.SymbolInfos())
-    text_length_words = (max_offset - min_offset) / 4
-    offset_to_symbol_info = [None for _ in xrange(text_length_words)]
-    for s in self.SymbolInfos():
-      offset = s.offset - min_offset
-      for i in range(offset / 4, (offset + s.size) / 4):
-        offset_to_symbol_info[i] = s
-    return offset_to_symbol_info
+    if self._offset_to_symbol_info is None:
+      min_offset = min(s.offset for s in self.SymbolInfos())
+      max_offset = max(s.offset + s.size for s in self.SymbolInfos())
+      text_length_words = (max_offset - min_offset) / 4
+      self._offset_to_symbol_info = [None for _ in xrange(text_length_words)]
+      for s in self.SymbolInfos():
+        offset = s.offset - min_offset
+        for i in range(offset / 4, (offset + s.size) / 4):
+          self._offset_to_symbol_info[i] = s
+    return self._offset_to_symbol_info
 
 
 class ProfileManager(object):
@@ -222,11 +260,11 @@
   example the dump for the startup could be phase 0 and then the steady-state
   would be labeled phase 1.
 
-  We assume the files are named like *-TIMESTAMP.SUFFIX_PHASE, where TIMESTAMP
-  is in nanoseconds, SUFFIX is string without dashes, PHASE is an integer
-  numbering the phases as 0, 1, 2..., and the only dot is the one between
-  TIMESTAMP and SUFFIX. Note that the current dump filename also includes a
-  process id which is currently unused.
+  We assume the files are named like
+  profile-hitmap-PROCESS-PID-TIMESTAMP.SUFFIX_PHASE, where PROCESS is a possibly
+  empty string, PID is the process id, TIMESTAMP is in nanoseconds, SUFFIX is
+  string without dashes, PHASE is an integer numbering the phases as 0, 1, 2...,
+  and the only dot is the one between TIMESTAMP and SUFFIX.
 
   This manager supports several configurations of dumps.
 
@@ -242,6 +280,44 @@
     time. This files can be grouped into run sets that are within 30 seconds of
     each other. Each run set is then grouped into phases as before.
   """
+  class AnnotatedOffset(object):
+    """Describes an offset with how it appeared in a profile set.
+
+    Each offset is annotated with the phase and process that it appeared in, and
+    can report how often it occurred in a specific phase and process.
+    """
+    def __init__(self, offset):
+      self._offset = offset
+      self._count = {}
+
+    def __str__(self):
+      return '{}: {}'.format(self._offset, self._count)
+
+    def __eq__(self, other):
+      if other is None:
+        return False
+      return (self._offset == other._offset and
+              self._count == other._count)
+
+    def Increment(self, phase, process):
+      key = (phase, process)
+      self._count[key] = self._count.setdefault(key, 0) + 1
+
+    def Count(self, phase, process):
+      return self._count.get((phase, process), 0)
+
+    def Processes(self):
+      return set(k[1] for k in self._count.iterkeys())
+
+    def Phases(self):
+      return set(k[0] for k in self._count.iterkeys())
+
+    def Offset(self):
+      return self._offset
+
+    def SetOffset(self, o):
+      self._offset = o
+
   class _RunGroup(object):
     RUN_GROUP_THRESHOLD_NS = 30e9
 
@@ -295,6 +371,22 @@
     return self._GetOffsetsForGroup(f for f in self._filenames
                                     if self._Phase(f) == phase)
 
+  def GetAnnotatedOffsets(self):
+    """Merges offsets across run groups and annotates each one.
+
+    Returns:
+      [AnnotatedOffset]
+    """
+    offset_map = {}  # offset int -> AnnotatedOffset
+    for g in self._GetRunGroups():
+      for f in g:
+        phase = self._Phase(f)
+        process = self._ProcessName(f)
+        for offset in self._ReadOffsets(f):
+          offset_map.setdefault(offset, self.AnnotatedOffset(offset)).Increment(
+              phase, process)
+    return offset_map.values()
+
   def GetRunGroupOffsets(self, phase=None):
     """Merges files from each run group and returns offset list for each.
 
@@ -323,10 +415,20 @@
     return [g.Filenames(phase) for g in self._run_groups]
 
   @classmethod
+  def _ProcessName(cls, filename):
+    # The filename starts with 'profile-hitmap-' and ends with
+    # '-PID-TIMESTAMP.text_X'. Anything in between is the process name. The
+    # browser has an empty process name, which is insterted here.
+    process_name_parts = os.path.basename(filename).split('-')[2:-2]
+    if not process_name_parts:
+      return 'browser'
+    return '-'.join(process_name_parts)
+
+  @classmethod
   def _Timestamp(cls, filename):
-      dash_index = filename.rindex('-')
-      dot_index = filename.rindex('.')
-      return int(filename[dash_index+1:dot_index])
+    dash_index = filename.rindex('-')
+    dot_index = filename.rindex('.')
+    return int(filename[dash_index+1:dot_index])
 
   @classmethod
   def _Phase(cls, filename):
@@ -347,6 +449,19 @@
         g.Add(f)
         self._run_groups.append(g)
 
+    # Some sanity checks on the run groups.
+    assert self._run_groups
+    if len(self._run_groups) < 5:
+      return  # Small runs have too much variance for testing.
+    sizes = map(lambda g: len(g.Filenames()), self._run_groups)
+    avg_size = sum(sizes) / len(self._run_groups)
+    num_outliers = len([s for s in sizes
+                        if s > 1.5 * avg_size or s < 0.75 * avg_size])
+    expected_outliers = 0.1 * len(self._run_groups)
+    assert num_outliers < expected_outliers, (
+        'Saw {} outliers instead of at most {} for average of {}'.format(
+            num_outliers, expected_outliers, avg_size))
+
 
 def GetReachedOffsetsFromDumpFiles(dump_filenames, library_filename):
   """Produces a list of symbol offsets reached by the dumps.
diff --git a/tools/cygprofile/process_profiles_unittest.py b/tools/cygprofile/process_profiles_unittest.py
index 77fc31c..c896a49 100755
--- a/tools/cygprofile/process_profiles_unittest.py
+++ b/tools/cygprofile/process_profiles_unittest.py
@@ -10,7 +10,8 @@
 
 import process_profiles
 
-from test_utils import (SimpleTestSymbol,
+from test_utils import (ProfileFile,
+                        SimpleTestSymbol,
                         TestSymbolOffsetProcessor,
                         TestProfileManager)
 
@@ -28,10 +29,10 @@
                          self.symbol_2, self.symbol_3]
     self._file_counter = 0
 
-  def File(self, timestamp_sec, phase):
-    self._file_counter += 1
-    return 'file-{}-{}.txt_{}'.format(
-        self._file_counter, timestamp_sec * 1000 * 1000 * 1000, phase)
+  def MakeAnnotatedOffset(self, offset, counts):
+    ao = process_profiles.ProfileManager.AnnotatedOffset(offset)
+    ao._count = counts
+    return ao
 
   def testGetOffsetToSymbolInfo(self):
     processor = TestSymbolOffsetProcessor(self.symbol_infos)
@@ -103,8 +104,9 @@
     self.assertEquals(5, process_profiles._Median([1, 4, 5, 6, 100]))
 
   def testRunGroups(self):
-    files = [self.File(40, 0), self.File(100, 0), self.File(200, 1),
-             self.File(35, 1), self.File(42, 0), self.File(95, 0)]
+    files = [ProfileFile(40, 0), ProfileFile(100, 0),
+             ProfileFile(200, 1), ProfileFile(35, 1),
+             ProfileFile(42, 0), ProfileFile(95, 0)]
     mgr = process_profiles.ProfileManager(files)
     mgr._ComputeRunGroups()
     self.assertEquals(3, len(mgr._run_groups))
@@ -118,11 +120,34 @@
     self.assertTrue(files[5] in mgr._run_groups[1].Filenames())
     self.assertTrue(files[2] in mgr._run_groups[2].Filenames())
 
+  def testRunGroupSanity(self):
+    files = []
+    # Generate 20 sets of files in groups separated by 60s.
+    for ts_base in xrange(0, 20):
+      ts = ts_base * 60
+      files.extend([ProfileFile(ts, 0, 'browser'),
+                    ProfileFile(ts + 1, 0, 'renderer'),
+                    ProfileFile(ts + 2, 1, 'browser'),
+                    ProfileFile(ts + 3, 0, 'gpu'),
+                    ProfileFile(ts + 2, 1, 'renderer'),
+                    ProfileFile(ts + 5, 1, 'gpu')])
+    # The following call should not assert.
+    process_profiles.ProfileManager(files)._ComputeRunGroups()
+
+    files.extend([ProfileFile(20 * 60, 0, 'browser'),
+                  ProfileFile(20 * 60 + 2, 1, 'renderer'),
+                  ProfileFile(21 * 60, 0, 'browser')] +
+                 [ProfileFile(22 * 60, 0, 'renderer')
+                  for _ in xrange(0, 10)])
+
+    self.assertRaises(AssertionError,
+                      process_profiles.ProfileManager(files)._ComputeRunGroups)
+
   def testReadOffsets(self):
     mgr = TestProfileManager({
-        self.File(30, 0): [1, 3, 5, 7],
-        self.File(40, 1): [8, 10],
-        self.File(50, 0): [13, 15]})
+        ProfileFile(30, 0): [1, 3, 5, 7],
+        ProfileFile(40, 1): [8, 10],
+        ProfileFile(50, 0): [13, 15]})
     self.assertListEqual([1, 3, 5, 7, 8, 10, 13, 15],
                          mgr.GetMergedOffsets())
     self.assertListEqual([8, 10], mgr.GetMergedOffsets(1))
@@ -130,9 +155,9 @@
 
   def testRunGroupOffsets(self):
     mgr = TestProfileManager({
-        self.File(30, 0): [1, 2, 3, 4],
-        self.File(150, 0): [9, 11, 13],
-        self.File(40, 1): [5, 6, 7]})
+        ProfileFile(30, 0): [1, 2, 3, 4],
+        ProfileFile(150, 0): [9, 11, 13],
+        ProfileFile(40, 1): [5, 6, 7]})
     offsets_list = mgr.GetRunGroupOffsets()
     self.assertEquals(2, len(offsets_list))
     self.assertListEqual([1, 2, 3, 4, 5, 6, 7], offsets_list[0])
@@ -150,22 +175,54 @@
     # The fact that the ProfileManager sorts by filename is implicit in the
     # other tests. It is tested explicitly here.
     mgr = TestProfileManager({
-        self.File(40, 0): [1, 2, 3, 4],
-        self.File(150, 0): [9, 11, 13],
-        self.File(30, 1): [5, 6, 7]})
+        ProfileFile(40, 0): [1, 2, 3, 4],
+        ProfileFile(150, 0): [9, 11, 13],
+        ProfileFile(30, 1): [5, 6, 7]})
     offsets_list = mgr.GetRunGroupOffsets()
     self.assertEquals(2, len(offsets_list))
     self.assertListEqual([5, 6, 7, 1, 2, 3, 4], offsets_list[0])
 
   def testPhases(self):
     mgr = TestProfileManager({
-        self.File(40, 0): [],
-        self.File(150, 0): [],
-        self.File(30, 1): [],
-        self.File(30, 2): [],
-        self.File(30, 0): []})
+        ProfileFile(40, 0): [],
+        ProfileFile(150, 0): [],
+        ProfileFile(30, 1): [],
+        ProfileFile(30, 2): [],
+        ProfileFile(30, 0): []})
     self.assertEquals(set([0,1,2]), mgr.GetPhases())
 
+  def testGetAnnotatedOffsets(self):
+    mgr = TestProfileManager({
+        ProfileFile(40, 0, ''): [1, 2, 3],
+        ProfileFile(50, 1, ''): [3, 4, 5],
+        ProfileFile(51, 0, 'renderer'): [2, 3, 6],
+        ProfileFile(51, 1, 'gpu-process'): [6, 7],
+        ProfileFile(70, 0, ''): [2, 8, 9],
+        ProfileFile(70, 1, ''): [9]})
+    offsets = mgr.GetAnnotatedOffsets()
+    self.assertListEqual([
+        self.MakeAnnotatedOffset(1, {(0, 'browser'): 1}),
+        self.MakeAnnotatedOffset(2, {(0, 'browser'): 2,
+                                     (0, 'renderer'): 1}),
+        self.MakeAnnotatedOffset(3, {(0, 'browser'): 1,
+                                     (1, 'browser'): 1,
+                                     (0, 'renderer'): 1}),
+        self.MakeAnnotatedOffset(4, {(1, 'browser'): 1}),
+        self.MakeAnnotatedOffset(5, {(1, 'browser'): 1}),
+        self.MakeAnnotatedOffset(6, {(0, 'renderer'): 1,
+                                     (1, 'gpu-process'): 1}),
+        self.MakeAnnotatedOffset(7, {(1, 'gpu-process'): 1}),
+        self.MakeAnnotatedOffset(8, {(0, 'browser'): 1}),
+        self.MakeAnnotatedOffset(9, {(0, 'browser'): 1,
+                                     (1, 'browser'): 1})],
+                         offsets)
+    self.assertListEqual(['browser', 'renderer'],
+                         sorted(offsets[1].Processes()))
+    self.assertListEqual(['browser'], list(offsets[0].Processes()))
+    self.assertListEqual([0], list(offsets[1].Phases()))
+    self.assertListEqual([0, 1], sorted(offsets[2].Phases()))
+    self.assertListEqual([0, 1], sorted(mgr.GetPhases()))
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/tools/cygprofile/test_utils.py b/tools/cygprofile/test_utils.py
index 47043b15..6aacbc9 100644
--- a/tools/cygprofile/test_utils.py
+++ b/tools/cygprofile/test_utils.py
@@ -8,6 +8,9 @@
 
 import process_profiles
 
+# Used by ProfileFile to generate unique file names.
+_FILE_COUNTER = 0
+
 SimpleTestSymbol = collections.namedtuple(
     'SimpleTestSymbol', ['name', 'offset', 'size'])
 
@@ -25,3 +28,14 @@
 
   def _ReadOffsets(self, filename):
     return self._filecontents_mapping[filename]
+
+
+def ProfileFile(timestamp_sec, phase, process_name=None):
+  global _FILE_COUNTER
+  _FILE_COUNTER += 1
+  if process_name:
+    name_str = process_name + '-'
+  else:
+    name_str = ''
+  return 'test-directory/profile-hitmap-{}{}-{}.txt_{}'.format(
+      name_str, _FILE_COUNTER, timestamp_sec * 1000 * 1000 * 1000, phase)
diff --git a/tools/grit/grit.py b/tools/grit/grit.py
index b17ceb9..2813b93 100755
--- a/tools/grit/grit.py
+++ b/tools/grit/grit.py
@@ -13,4 +13,3 @@
 
 if __name__ == '__main__':
   grit.grit_runner.Main(sys.argv[1:])
-
diff --git a/tools/grit/grit/__init__.py b/tools/grit/grit/__init__.py
index 57e6709..a1eeaca 100755
--- a/tools/grit/grit/__init__.py
+++ b/tools/grit/grit/__init__.py
@@ -7,4 +7,3 @@
 '''
 
 pass
-
diff --git a/tools/grit/grit/clique.py b/tools/grit/grit/clique.py
index 7d920a8..7607e5d 100755
--- a/tools/grit/grit/clique.py
+++ b/tools/grit/grit/clique.py
@@ -483,4 +483,3 @@
         language, transl_msg.GetId())
 
     self.clique[language] = transl_msg
-
diff --git a/tools/grit/grit/extern/tclib.py b/tools/grit/grit/extern/tclib.py
index e84f177e..a9b1a39f 100755
--- a/tools/grit/grit/extern/tclib.py
+++ b/tools/grit/grit/extern/tclib.py
@@ -500,4 +500,3 @@
     Returns a copy of this Translation.
     """
     return Translation(None, clone_from=self)
-
diff --git a/tools/grit/grit/format/__init__.py b/tools/grit/grit/format/__init__.py
index 2a3c59ca..28a4dc7 100755
--- a/tools/grit/grit/format/__init__.py
+++ b/tools/grit/grit/format/__init__.py
@@ -7,4 +7,3 @@
 '''
 
 pass
-
diff --git a/tools/grit/grit/gather/regexp.py b/tools/grit/grit/gather/regexp.py
index 30488a6..16bc323a 100755
--- a/tools/grit/grit/gather/regexp.py
+++ b/tools/grit/grit/gather/regexp.py
@@ -82,4 +82,3 @@
 
     if self.single_message_:
       self.skeleton_.append(self.uberclique.MakeClique(self.single_message_))
-
diff --git a/tools/grit/grit/gather/tr_html.py b/tools/grit/grit/gather/tr_html.py
index 3487251..d5122f6e 100755
--- a/tools/grit/grit/gather/tr_html.py
+++ b/tools/grit/grit/gather/tr_html.py
@@ -742,4 +742,3 @@
           continue
       new_skel.append(chunk)
     self.skeleton_ = new_skel
-
diff --git a/tools/grit/grit/gather/txt_unittest.py b/tools/grit/grit/gather/txt_unittest.py
index e2ff8a5..80586526 100755
--- a/tools/grit/grit/gather/txt_unittest.py
+++ b/tools/grit/grit/gather/txt_unittest.py
@@ -31,4 +31,3 @@
 
 if __name__ == '__main__':
   unittest.main()
-
diff --git a/tools/grit/grit/node/base.py b/tools/grit/grit/node/base.py
index e40bad88..76fbb31e 100755
--- a/tools/grit/grit/node/base.py
+++ b/tools/grit/grit/node/base.py
@@ -621,4 +621,3 @@
   '''Convenience baseclass for nodes that can have content.'''
   def _ContentType(self):
     return self._CONTENT_TYPE_MIXED
-
diff --git a/tools/grit/grit/node/base_unittest.py b/tools/grit/grit/node/base_unittest.py
index f7e7b75..58acdfb 100755
--- a/tools/grit/grit/node/base_unittest.py
+++ b/tools/grit/grit/node/base_unittest.py
@@ -255,4 +255,3 @@
 
 if __name__ == '__main__':
   unittest.main()
-
diff --git a/tools/grit/grit/node/custom/filename_unittest.py b/tools/grit/grit/node/custom/filename_unittest.py
index 9099086..9ea8eb9 100755
--- a/tools/grit/grit/node/custom/filename_unittest.py
+++ b/tools/grit/grit/node/custom/filename_unittest.py
@@ -31,4 +31,3 @@
 
 if __name__ == '__main__':
   unittest.main()
-
diff --git a/tools/grit/grit/node/io.py b/tools/grit/grit/node/io.py
index 69146199..83e14b1f 100755
--- a/tools/grit/grit/node/io.py
+++ b/tools/grit/grit/node/io.py
@@ -116,4 +116,3 @@
   def GetEmitType(self):
     '''Returns the emit_type for this node. Default is 'append'.'''
     return self.attrs['emit_type']
-
diff --git a/tools/grit/grit/node/mapping.py b/tools/grit/grit/node/mapping.py
index 259be97..71b250b2 100755
--- a/tools/grit/grit/node/mapping.py
+++ b/tools/grit/grit/node/mapping.py
@@ -58,4 +58,3 @@
   if name not in _ELEMENT_TO_CLASS:
     raise exception.UnknownElement()
   return _ELEMENT_TO_CLASS[name]
-
diff --git a/tools/grit/grit/node/structure.py b/tools/grit/grit/node/structure.py
index 7b6f7bf..3d2012a 100755
--- a/tools/grit/grit/node/structure.py
+++ b/tools/grit/grit/node/structure.py
@@ -356,4 +356,3 @@
     assert hasattr(self, 'gatherer')
     if self.ExpandVariables():
       self.gatherer.SubstituteMessages(substituter)
-
diff --git a/tools/grit/grit/node/variant.py b/tools/grit/grit/node/variant.py
index 4206712b..487f7f9 100755
--- a/tools/grit/grit/node/variant.py
+++ b/tools/grit/grit/node/variant.py
@@ -39,4 +39,3 @@
 
   def GetInputPath(self):
     return self.attrs['file']
-
diff --git a/tools/grit/grit/pseudo.py b/tools/grit/grit/pseudo.py
index 17a6ec6a..cb57daab 100755
--- a/tools/grit/grit/pseudo.py
+++ b/tools/grit/grit/pseudo.py
@@ -125,4 +125,3 @@
       transl.AppendText(PseudoString(part))
 
   return transl
-
diff --git a/tools/grit/grit/shortcuts.py b/tools/grit/grit/shortcuts.py
index 69a4386d..30bdbf7 100755
--- a/tools/grit/grit/shortcuts.py
+++ b/tools/grit/grit/shortcuts.py
@@ -90,4 +90,3 @@
   for group in groups.values():
     warnings += group.GenerateWarnings(tc_project)
   return warnings
-
diff --git a/tools/grit/grit/shortcuts_unittests.py b/tools/grit/grit/shortcuts_unittests.py
index 421cfb2..b7c37b5 100755
--- a/tools/grit/grit/shortcuts_unittests.py
+++ b/tools/grit/grit/shortcuts_unittests.py
@@ -77,4 +77,3 @@
 
 if __name__ == '__main__':
   unittest.main()
-
diff --git a/tools/grit/grit/tool/__init__.py b/tools/grit/grit/tool/__init__.py
index c8565d5..4f769f2a 100755
--- a/tools/grit/grit/tool/__init__.py
+++ b/tools/grit/grit/tool/__init__.py
@@ -7,4 +7,3 @@
 '''
 
 pass
-
diff --git a/tools/grit/grit/tool/android2grd.py b/tools/grit/grit/tool/android2grd.py
index c0538ed..e9e0ed1 100755
--- a/tools/grit/grit/tool/android2grd.py
+++ b/tools/grit/grit/tool/android2grd.py
@@ -476,4 +476,3 @@
       return value == 'true'
     else:
       return True
-
diff --git a/tools/grit/grit/tool/count.py b/tools/grit/grit/tool/count.py
index e87c4900..1517b16 100755
--- a/tools/grit/grit/tool/count.py
+++ b/tools/grit/grit/tool/count.py
@@ -32,4 +32,3 @@
         count += 1
 
     print "There are %d occurrences of message %s." % (count, id)
-
diff --git a/tools/grit/grit/tool/menu_from_parts.py b/tools/grit/grit/tool/menu_from_parts.py
index 36d2d40..c7be7bd9 100755
--- a/tools/grit/grit/tool/menu_from_parts.py
+++ b/tools/grit/grit/tool/menu_from_parts.py
@@ -76,4 +76,3 @@
 
     with util.WrapOutputStream(open(output_file, 'w')) as f:
       transl2tc.TranslationToTc.WriteTranslations(f, translations)
-
diff --git a/tools/grit/grit/tool/postprocess_interface.py b/tools/grit/grit/tool/postprocess_interface.py
index 4a43254..c870b932 100755
--- a/tools/grit/grit/tool/postprocess_interface.py
+++ b/tools/grit/grit/tool/postprocess_interface.py
@@ -27,6 +27,3 @@
       The root node of the processed GRD tree.
     '''
     raise NotImplementedError()
-
-
-
diff --git a/tools/grit/grit/tool/postprocess_unittest.py b/tools/grit/grit/tool/postprocess_unittest.py
index 330db490..91f02d69 100755
--- a/tools/grit/grit/tool/postprocess_unittest.py
+++ b/tools/grit/grit/tool/postprocess_unittest.py
@@ -60,4 +60,3 @@
 
 if __name__ == '__main__':
   unittest.main()
-
diff --git a/tools/grit/grit/tool/preprocess_interface.py b/tools/grit/grit/tool/preprocess_interface.py
index 4c5456c6..eea10b2 100755
--- a/tools/grit/grit/tool/preprocess_interface.py
+++ b/tools/grit/grit/tool/preprocess_interface.py
@@ -23,6 +23,3 @@
       The processed text.
     '''
     raise NotImplementedError()
-
-
-
diff --git a/tools/grit/grit/tool/preprocess_unittest.py b/tools/grit/grit/tool/preprocess_unittest.py
index 1fc7192..da4242b 100755
--- a/tools/grit/grit/tool/preprocess_unittest.py
+++ b/tools/grit/grit/tool/preprocess_unittest.py
@@ -46,4 +46,3 @@
 
 if __name__ == '__main__':
   unittest.main()
-
diff --git a/tools/grit/grit/tool/rc2grd.py b/tools/grit/grit/tool/rc2grd.py
index 10d36f60..a0ef77fc 100755
--- a/tools/grit/grit/tool/rc2grd.py
+++ b/tools/grit/grit/tool/rc2grd.py
@@ -406,4 +406,3 @@
     except:
       print 'Exception processing message with text "%s"' % text
       raise
-
diff --git a/tools/grit/grit/tool/rc2grd_unittest.py b/tools/grit/grit/tool/rc2grd_unittest.py
index b41f5e43..0e48f07f 100755
--- a/tools/grit/grit/tool/rc2grd_unittest.py
+++ b/tools/grit/grit/tool/rc2grd_unittest.py
@@ -134,4 +134,3 @@
 
 if __name__ == '__main__':
   unittest.main()
-
diff --git a/tools/grit/grit/tool/test.py b/tools/grit/grit/tool/test.py
index 246b3ded..8f4cdd9 100755
--- a/tools/grit/grit/tool/test.py
+++ b/tools/grit/grit/tool/test.py
@@ -21,4 +21,3 @@
     print 'Options: %s' % repr(global_options)
     print 'Arguments: %s' % repr(my_arguments)
     return 0
-
diff --git a/tools/grit/grit/tool/transl2tc.py b/tools/grit/grit/tool/transl2tc.py
index f3f06a9..a8af6ed16 100755
--- a/tools/grit/grit/tool/transl2tc.py
+++ b/tools/grit/grit/tool/transl2tc.py
@@ -249,4 +249,3 @@
       output_file.write(' ')
       output_file.write(text)
       output_file.write('\n')
-
diff --git a/tools/grit/grit/util_unittest.py b/tools/grit/grit/util_unittest.py
index 03f8cfe..ecadfa3c 100755
--- a/tools/grit/grit/util_unittest.py
+++ b/tools/grit/grit/util_unittest.py
@@ -116,4 +116,3 @@
 
 if __name__ == '__main__':
   unittest.main()
-
diff --git a/tools/grit/grit/xtb_reader.py b/tools/grit/grit/xtb_reader.py
index b92da39e..df6d9f8 100755
--- a/tools/grit/grit/xtb_reader.py
+++ b/tools/grit/grit/xtb_reader.py
@@ -138,4 +138,3 @@
   xml.sax.parse(xtb_file, handler)
   assert handler.language != ''
   return handler.language
-
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 4d1aa96..0da6452 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -28641,6 +28641,7 @@
   <int value="341152650" label="SoundContentSetting:enabled"/>
   <int value="345664265" label="BlinkHeapIncrementalMarking:disabled"/>
   <int value="346711293" label="enable-save-password-bubble"/>
+  <int value="348115702" label="new-password-form-parsing-for-saving:enabled"/>
   <int value="348854923" label="v8-cache-strategies-for-cache-storage"/>
   <int value="350399958" label="ModuleScriptsImportMetaUrl:disabled"/>
   <int value="352191859" label="disabled-new-style-notification"/>
@@ -29065,6 +29066,8 @@
   <int value="1194496204" label="NewWallpaperPicker:enabled"/>
   <int value="1196644408" label="performance-monitor-gathering"/>
   <int value="1196834473" label="disable-smart-virtual-keyboard"/>
+  <int value="1201441984"
+      label="new-password-form-parsing-for-saving:disabled"/>
   <int value="1205849612" label="enable-sync-synced-notifications"/>
   <int value="1209221384" label="enable-experimental-accessibility-features"/>
   <int value="1210343926" label="enable-drop-sync-credential"/>
@@ -45702,6 +45705,18 @@
   <int value="2" label="EMPTY_FIELD"/>
 </enum>
 
+<enum name="SyncEntityChange">
+  <summary>
+    Type of change of a sync entity. Recorded once for every sync entity
+    whenever it is commited to the server or updated from the server.
+  </summary>
+  <int value="0" label="Local deletion (commited upstream)"/>
+  <int value="1" label="Local creation (commited upstream)"/>
+  <int value="2" label="Local update (commited upstream)"/>
+  <int value="3" label="Remote deletion (updated downstream)"/>
+  <int value="4" label="Remote update (updated downstream)"/>
+</enum>
+
 <enum name="SyncErrorInfobarTypes">
   <summary>Possible errors that can trigger a sync error infobar.</summary>
   <int value="1" label="Sign in needs update"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b1d326c..9013798e 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -45186,6 +45186,9 @@
 </histogram>
 
 <histogram name="MessageLoop.DelayedTaskQueue.PendingTasksCountOnIdle">
+  <obsolete>
+    Deprecated as of 07/2018.
+  </obsolete>
   <owner>gab@chromium.org</owner>
   <summary>
     The size of the delayed task queue when the loop becomes idle. Diagnosis
@@ -45194,6 +45197,9 @@
 </histogram>
 
 <histogram name="MessageLoop.DelayedTaskQueue.PostedDelay" units="ms">
+  <obsolete>
+    Deprecated as of 07/2018.
+  </obsolete>
   <owner>gab@chromium.org</owner>
   <summary>
     Reports the delay of a delayed task posted to a MessageLoop. Reported once
@@ -45201,7 +45207,20 @@
   </summary>
 </histogram>
 
+<histogram name="MessageLoop.DelayedTaskQueueForUI.PendingTasksCountOnIdle">
+  <owner>gab@chromium.org</owner>
+  <summary>
+    The size of the delayed task queue when the loop becomes idle on a UI
+    thread. Diagnosis metric for https://crbug.com/850450#c4. Note: this metric
+    is a bit broken on Mac OSX as CFRunLoop doesn't deterministically invoke
+    MessageLoop::DoIdleWork().
+  </summary>
+</histogram>
+
 <histogram name="MessageLoop.ScheduledSleep.Completed" units="ms">
+  <obsolete>
+    Deprecated as of 07/2018.
+  </obsolete>
   <owner>gab@chromium.org</owner>
   <summary>
     Reports the delay for which the MessageLoop successfully slept until an
@@ -45211,6 +45230,9 @@
 </histogram>
 
 <histogram name="MessageLoop.ScheduledSleep.Interrupted" units="ms">
+  <obsolete>
+    Deprecated as of 07/2018.
+  </obsolete>
   <owner>gab@chromium.org</owner>
   <summary>
     Reports the delay for which the MessageLoop had planned to sleep (next
@@ -100122,6 +100144,17 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="Sync.ModelTypeEntityChange"
+    enum="SyncEntityChange" expires_after="2020-02-01">
+  <owner>jkrcal@chromium.org</owner>
+  <summary>
+    Recorded once for every sync entity change (whenever it is commited to the
+    server or updated from the server). This metric is used for monitoring
+    general health of sync client-side code. Note: This is only recorded with a
+    data type suffix. The base version is never recorded.
+  </summary>
+</histogram>
+
 <histogram name="Sync.ModelTypeMemoryKB" units="KB">
   <owner>pavely@chromium.org</owner>
   <summary>
@@ -126488,6 +126521,7 @@
   <suffix name="USER_EVENT" label="USER_EVENT"/>
   <suffix name="WIFI_CREDENTIAL" label="WIFI_CREDENTIAL"/>
   <affected-histogram name="Sync.ModelTypeCount"/>
+  <affected-histogram name="Sync.ModelTypeEntityChange"/>
   <affected-histogram name="Sync.ModelTypeMemoryKB"/>
 </histogram_suffixes>
 
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 6407a9f..b3374da 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -255,8 +255,6 @@
 crbug.com/738854 [ Nexus_5X ] system_health.common_mobile/load:tools:drive [ Skip ]
 crbug.com/738854 [ Android_Webview ] system_health.common_mobile/load:tools:drive [ Skip ]
 crbug.com/797261 [ Android_Webview ] system_health.common_mobile/load:games:spychase [ Skip ]
-crbug.com/798536 [ Android ] system_health.common_mobile/background:news:nytimes [ Skip ]
-crbug.com/798536 [ Android ] system_health.common_mobile/load:games:spychase [ Skip ]
 crbug.com/736147 [ Android_One ] system_health.common_mobile/browse:social:tumblr_infinite_scroll [ Skip ]
 crbug.com/803461 [ Nexus_5 ] system_health.common_mobile/browse:chrome:newtab [ Skip ]
 
diff --git a/ui/accelerated_widget_mac/ca_layer_tree_coordinator.mm b/ui/accelerated_widget_mac/ca_layer_tree_coordinator.mm
index 9bc48ec..fb4e271 100644
--- a/ui/accelerated_widget_mac/ca_layer_tree_coordinator.mm
+++ b/ui/accelerated_widget_mac/ca_layer_tree_coordinator.mm
@@ -48,7 +48,7 @@
   if (pending_ca_renderer_layer_tree_) {
     pending_ca_renderer_layer_tree_->CommitScheduledCALayers(
         root_ca_layer_.get(), std::move(current_ca_renderer_layer_tree_),
-        scale_factor_);
+        pixel_size_, scale_factor_);
     current_ca_renderer_layer_tree_.swap(pending_ca_renderer_layer_tree_);
   } else {
     TRACE_EVENT0("gpu", "Blank frame: No overlays or CALayers");
diff --git a/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm b/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm
index 93c7fe4c..ba08f5f6 100644
--- a/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm
+++ b/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm
@@ -80,7 +80,8 @@
   bool result = ScheduleCALayer(new_ca_layer_tree.get(), properties);
   EXPECT_TRUE(result);
   new_ca_layer_tree->CommitScheduledCALayers(
-      superlayer, std::move(ca_layer_tree), properties->scale_factor);
+      superlayer, std::move(ca_layer_tree), properties->rect.size(),
+      properties->scale_factor);
   std::swap(new_ca_layer_tree, ca_layer_tree);
 }
 
@@ -508,8 +509,8 @@
     bool result = ScheduleCALayer(ca_layer_tree.get(), &properties);
     EXPECT_TRUE(result);
   }
-  ca_layer_tree->CommitScheduledCALayers(superlayer_, nullptr,
-                                         properties.scale_factor);
+  ca_layer_tree->CommitScheduledCALayers(
+      superlayer_, nullptr, properties.rect.size(), properties.scale_factor);
 
   // Validate the root layer.
   EXPECT_EQ(1u, [[superlayer_ sublayers] count]);
@@ -588,8 +589,8 @@
     bool result = ScheduleCALayer(ca_layer_tree.get(), &properties);
     EXPECT_TRUE(result);
   }
-  ca_layer_tree->CommitScheduledCALayers(superlayer_, nullptr,
-                                         properties.scale_factor);
+  ca_layer_tree->CommitScheduledCALayers(
+      superlayer_, nullptr, properties.rect.size(), properties.scale_factor);
 
   // Validate the root layer.
   EXPECT_EQ(1u, [[superlayer_ sublayers] count]);
@@ -882,7 +883,8 @@
     bool result = ScheduleCALayer(new_ca_layer_tree.get(), &properties);
     EXPECT_TRUE(result);
     new_ca_layer_tree->CommitScheduledCALayers(
-        superlayer_, std::move(ca_layer_tree), properties.scale_factor);
+        superlayer_, std::move(ca_layer_tree), properties.rect.size(),
+        properties.scale_factor);
     std::swap(new_ca_layer_tree, ca_layer_tree);
 
     // Validate the tree structure.
@@ -896,7 +898,7 @@
     EXPECT_EQ(1u, [[transform_layer sublayers] count]);
 
     // Validate the content layer and fullscreen low power mode.
-    EXPECT_TRUE(CGRectEqualToRect([root_layer frame], CGRectZero));
+    EXPECT_FALSE(CGRectEqualToRect([root_layer frame], CGRectZero));
     EXPECT_NE([root_layer backgroundColor], nil);
   }
 
@@ -909,7 +911,8 @@
     result = ScheduleCALayer(new_ca_layer_tree.get(), &properties);
     EXPECT_TRUE(result);
     new_ca_layer_tree->CommitScheduledCALayers(
-        superlayer_, std::move(ca_layer_tree), properties.scale_factor);
+        superlayer_, std::move(ca_layer_tree), properties.rect.size(),
+        properties.scale_factor);
     std::swap(new_ca_layer_tree, ca_layer_tree);
 
     // Validate the tree structure.
@@ -936,7 +939,8 @@
     result = ScheduleCALayer(new_ca_layer_tree.get(), &properties);
     EXPECT_TRUE(result);
     new_ca_layer_tree->CommitScheduledCALayers(
-        superlayer_, std::move(ca_layer_tree), properties.scale_factor);
+        superlayer_, std::move(ca_layer_tree), properties.rect.size(),
+        properties.scale_factor);
     std::swap(new_ca_layer_tree, ca_layer_tree);
 
     // Validate the tree structure.
@@ -963,7 +967,8 @@
     result = ScheduleCALayer(new_ca_layer_tree.get(), &properties_black);
     EXPECT_TRUE(result);
     new_ca_layer_tree->CommitScheduledCALayers(
-        superlayer_, std::move(ca_layer_tree), properties.scale_factor);
+        superlayer_, std::move(ca_layer_tree), properties.rect.size(),
+        properties.scale_factor);
     std::swap(new_ca_layer_tree, ca_layer_tree);
 
     // Validate the tree structure.
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
index 7c90bae6..a4e7fe3 100644
--- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
+++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
@@ -51,6 +51,7 @@
   // not re-used by |this| will be removed from the CALayer hierarchy.
   void CommitScheduledCALayers(CALayer* superlayer,
                                std::unique_ptr<CARendererLayerTree> old_tree,
+                               const gfx::Size& pixel_size,
                                float scale_factor);
 
   // Returns the contents used for a given solid color.
@@ -86,15 +87,12 @@
     // to nil, so that its destructor will not remove an active CALayer.
     void CommitToCA(CALayer* superlayer,
                     RootLayer* old_layer,
+                    const gfx::Size& pixel_size,
                     float scale_factor);
 
-    // Check to see if the CALayer tree is just a video layer on a black
-    // background. If so, return true and set background_rect to the
-    // background's bounding rect, otherwise return false. CommitToCA() calls
-    // this function and, based on its return value, either gives the root
-    // layer this frame and a black background color or clears them.
-    bool WantsFullcreenLowPowerBackdrop(float scale_factor,
-                                        gfx::RectF* background_rect);
+    // Return true if the CALayer tree is just a video layer on a black or
+    // transparent background, false otherwise.
+    bool WantsFullcreenLowPowerBackdrop();
 
     std::vector<ClipAndSortingLayer> clip_and_sorting_layers;
     base::scoped_nsobject<CALayer> ca_layer;
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
index 9b64866..1c5988fe 100644
--- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
+++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
@@ -220,6 +220,7 @@
 void CARendererLayerTree::CommitScheduledCALayers(
     CALayer* superlayer,
     std::unique_ptr<CARendererLayerTree> old_tree,
+    const gfx::Size& pixel_size,
     float scale_factor) {
   TRACE_EVENT0("gpu", "CARendererLayerTree::CommitScheduledCALayers");
   RootLayer* old_root_layer = nullptr;
@@ -229,7 +230,7 @@
       old_root_layer = &old_tree->root_layer_;
   }
 
-  root_layer_.CommitToCA(superlayer, old_root_layer, scale_factor);
+  root_layer_.CommitToCA(superlayer, old_root_layer, pixel_size, scale_factor);
   // If there are any extra CALayers in |old_tree| that were not stolen by this
   // tree, they will be removed from the CALayer tree in this deallocation.
   old_tree.reset();
@@ -237,9 +238,7 @@
   scale_factor_ = scale_factor;
 }
 
-bool CARendererLayerTree::RootLayer::WantsFullcreenLowPowerBackdrop(
-    float scale_factor,
-    gfx::RectF* background_rect) {
+bool CARendererLayerTree::RootLayer::WantsFullcreenLowPowerBackdrop() {
   bool found_video_layer = false;
   for (auto& clip_layer : clip_and_sorting_layers) {
     for (auto& transform_layer : clip_layer.transform_layers) {
@@ -250,7 +249,6 @@
 
         // See if this is the video layer.
         if (content_layer.use_av_layer) {
-          background_rect->Union(gfx::RectF(content_layer.rect));
           found_video_layer = true;
           if (!transform_layer.transform.IsPositiveScaleOrTranslation())
             return false;
@@ -263,15 +261,13 @@
         // solid black or transparent
         if (content_layer.io_surface)
           return false;
-        if (content_layer.background_color == SK_ColorBLACK) {
-          background_rect->Union(gfx::RectF(content_layer.rect));
-        } else if (content_layer.background_color != SK_ColorTRANSPARENT) {
+        if (content_layer.background_color != SK_ColorBLACK &&
+            content_layer.background_color != SK_ColorTRANSPARENT) {
           return false;
         }
       }
     }
   }
-  background_rect->Scale(1 / scale_factor);
   return found_video_layer;
 }
 
@@ -554,6 +550,7 @@
 
 void CARendererLayerTree::RootLayer::CommitToCA(CALayer* superlayer,
                                                 RootLayer* old_layer,
+                                                const gfx::Size& pixel_size,
                                                 float scale_factor) {
   if (old_layer) {
     DCHECK(old_layer->ca_layer);
@@ -569,8 +566,9 @@
     DLOG(ERROR) << "CARendererLayerTree root layer not attached to tree.";
   }
 
-  gfx::RectF bg_rect;
-  if (WantsFullcreenLowPowerBackdrop(scale_factor, &bg_rect)) {
+  if (WantsFullcreenLowPowerBackdrop()) {
+    const gfx::RectF bg_rect(
+        ScaleSize(gfx::SizeF(pixel_size), 1 / scale_factor));
     if (gfx::RectF([ca_layer frame]) != bg_rect)
       [ca_layer setFrame:bg_rect.ToCGRect()];
     if (![ca_layer backgroundColor])
diff --git a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
index df8c615..c5d5f32 100644
--- a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
+++ b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
@@ -390,17 +390,18 @@
 
                 if (photos.length == 1) {
                     GetDisplayNameTask task =
-                            new GetDisplayNameTask(ContextUtils.getApplicationContext(), false);
-                    task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Uri.parse(photos[0]));
+                            new GetDisplayNameTask(ContextUtils.getApplicationContext(), false,
+                                    new Uri[] {Uri.parse(photos[0])});
+                    task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                     return;
                 } else {
                     Uri[] filePathArray = new Uri[photos.length];
                     for (int i = 0; i < photos.length; ++i) {
                         filePathArray[i] = Uri.parse(photos[i]);
                     }
-                    GetDisplayNameTask task =
-                            new GetDisplayNameTask(ContextUtils.getApplicationContext(), true);
-                    task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, filePathArray);
+                    GetDisplayNameTask task = new GetDisplayNameTask(
+                            ContextUtils.getApplicationContext(), true, filePathArray);
+                    task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                 }
                 break;
 
@@ -565,9 +566,9 @@
             for (int i = 0; i < itemCount; ++i) {
                 filePathArray[i] = clipData.getItemAt(i).getUri();
             }
-            GetDisplayNameTask task =
-                    new GetDisplayNameTask(ContextUtils.getApplicationContext(), true);
-            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, filePathArray);
+            GetDisplayNameTask task = new GetDisplayNameTask(
+                    ContextUtils.getApplicationContext(), true, filePathArray);
+            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
             return;
         }
 
@@ -577,9 +578,9 @@
         }
 
         if (ContentResolver.SCHEME_CONTENT.equals(results.getScheme())) {
-            GetDisplayNameTask task =
-                    new GetDisplayNameTask(ContextUtils.getApplicationContext(), false);
-            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, results.getData());
+            GetDisplayNameTask task = new GetDisplayNameTask(
+                    ContextUtils.getApplicationContext(), false, new Uri[] {results.getData()});
+            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
             return;
         }
 
@@ -699,32 +700,34 @@
         return count;
     }
 
-    class GetDisplayNameTask extends AsyncTask<Uri, Void, String[]> {
+    class GetDisplayNameTask extends AsyncTask<Void, Void, String[]> {
         String[] mFilePaths;
         final Context mContext;
         final boolean mIsMultiple;
+        final Uri[] mUris;
 
-        public GetDisplayNameTask(Context context, boolean isMultiple) {
+        public GetDisplayNameTask(Context context, boolean isMultiple, Uri[] uris) {
             mContext = context;
             mIsMultiple = isMultiple;
+            mUris = uris;
         }
 
         @Override
-        public String[] doInBackground(Uri...uris) {
-            mFilePaths = new String[uris.length];
-            String[] displayNames = new String[uris.length];
+        public String[] doInBackground(Void... params) {
+            mFilePaths = new String[mUris.length];
+            String[] displayNames = new String[mUris.length];
             try {
-                for (int i = 0; i < uris.length; i++) {
+                for (int i = 0; i < mUris.length; i++) {
                     // The selected files must be returned as a list of absolute paths. A MIUI 8.5
                     // device was observed to return a file:// URI instead, so convert if necessary.
                     // See https://crbug.com/752834 for context.
-                    if (ContentResolver.SCHEME_FILE.equals(uris[i].getScheme())) {
-                        mFilePaths[i] = uris[i].getSchemeSpecificPart();
+                    if (ContentResolver.SCHEME_FILE.equals(mUris[i].getScheme())) {
+                        mFilePaths[i] = mUris[i].getSchemeSpecificPart();
                     } else {
-                        mFilePaths[i] = uris[i].toString();
+                        mFilePaths[i] = mUris[i].toString();
                     }
                     displayNames[i] = ContentUriUtils.getDisplayName(
-                            uris[i], mContext, MediaStore.MediaColumns.DISPLAY_NAME);
+                            mUris[i], mContext, MediaStore.MediaColumns.DISPLAY_NAME);
                 }
             }  catch (SecurityException e) {
                 // Some third party apps will present themselves as being able
diff --git a/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java b/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
index 101215af..ebcc7d3 100644
--- a/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
+++ b/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
@@ -133,12 +133,12 @@
     @Test
     public void testMultipleFileSelectorWithFileUris() throws Throwable {
         SelectFileDialog selectFileDialog = new SelectFileDialog(0);
-        SelectFileDialog.GetDisplayNameTask task =
-                selectFileDialog.new GetDisplayNameTask(ContextUtils.getApplicationContext(), true);
         Uri[] filePathArray = new Uri[] {
                 Uri.parse("file:///storage/emulated/0/DCIM/Camera/IMG_0.jpg"),
                 Uri.parse("file:///storage/emulated/0/DCIM/Camera/IMG_1.jpg")};
-        task.doInBackground(filePathArray);
+        SelectFileDialog.GetDisplayNameTask task = selectFileDialog.new GetDisplayNameTask(
+                ContextUtils.getApplicationContext(), true, filePathArray);
+        task.doInBackground();
         assertEquals(task.mFilePaths[0].toString(),
                 "///storage/emulated/0/DCIM/Camera/IMG_0.jpg");
         assertEquals(task.mFilePaths[1].toString(),
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index beae9238..3e0f7dc 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -258,29 +258,6 @@
     "//third_party/zlib",
   ]
 
-  # Text rendering conditions (complicated so separated out).
-  if (use_aura || is_mac || is_android || is_fuchsia) {
-    # Mac doesn't use RenderTextHarfBuzz by default yet.
-    sources += [
-      "harfbuzz_font_skia.cc",
-      "harfbuzz_font_skia.h",
-      "render_text_harfbuzz.cc",
-      "render_text_harfbuzz.h",
-      "render_text_mac.h",
-      "render_text_mac.mm",
-      "text_utils_skia.cc",
-    ]
-
-    if (!is_ios) {
-      sources += [
-        "render_text.cc",
-        "render_text.h",
-      ]
-    }
-  } else {
-    # We don't support RenderText on these platforms.
-  }
-
   if (is_android) {
     set_sources_assignment_filter([])
     sources += [
@@ -316,8 +293,17 @@
 
   if (!is_ios) {
     sources += [
+      "harfbuzz_font_skia.cc",
+      "harfbuzz_font_skia.h",
       "paint_vector_icon.cc",
       "paint_vector_icon.h",
+      "render_text.cc",
+      "render_text.h",
+      "render_text_harfbuzz.cc",
+      "render_text_harfbuzz.h",
+      "render_text_mac.h",
+      "render_text_mac.mm",
+      "text_utils_skia.cc",
       "vector_icon_types.h",
     ]
   }