diff --git a/DEPS b/DEPS
index bc63e37..4464bb9 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # 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': '03707bbe71e93513636b7887590823abbe66f221',
+  'v8_revision': 'b7ac09574e4274c8e7a923e59a6cfbdb153e4ed6',
   # 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.
@@ -96,7 +96,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': 'c50cbdedf9a36a08ef7f2bb584625332f1a9592f',
+  'catapult_revision': 'df42e552c40e046862a87aee40aac52565bb3425',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index 47ee97d..7bafd482 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -7,7 +7,6 @@
 #include "ash/common/accelerators/accelerator_controller.h"
 #include "ash/common/accelerators/accelerator_table.h"
 #include "ash/common/focus_cycler.h"
-#include "ash/common/material_design/material_design_controller.h"
 #include "ash/common/session/session_controller.h"
 #include "ash/common/shelf/shelf_constants.h"
 #include "ash/common/shelf/shelf_layout_manager_observer.h"
@@ -170,15 +169,6 @@
       EXPECT_EQ(shelf_widget_bounds_.x(), shelf_bounds.x());
     }
 
-    // Auto hidden shelf has a visible height of 0 in MD (where this inequality
-    // does not apply); whereas auto hidden shelf has a visible height of 3 in
-    // non-MD.
-    if (!ash::MaterialDesignController::IsImmersiveModeMaterial() ||
-        shelf->GetAutoHideState() != ash::SHELF_AUTO_HIDE_HIDDEN) {
-      EXPECT_GE(shelf_bounds.height(),
-                auto_hidden_shelf_widget_bounds_.height());
-    }
-
     float scroll_delta =
         GetShelfLayoutManager()->PrimaryAxisValue(scroll_.y(), scroll_.x());
     bool increasing_drag =
@@ -510,12 +500,7 @@
   gfx::Rect bounds_fullscreen = window->bounds();
   EXPECT_TRUE(widget->IsFullscreen());
 
-  // Shelf hints are removed in immersive full screen mode in MD; and some shelf
-  // hints are shown in non-MD mode.
-  if (ash::MaterialDesignController::IsImmersiveModeMaterial())
-    EXPECT_EQ(bounds_noshelf.ToString(), bounds_fullscreen.ToString());
-  else
-    EXPECT_NE(bounds_noshelf.ToString(), bounds_fullscreen.ToString());
+  EXPECT_EQ(bounds_noshelf.ToString(), bounds_fullscreen.ToString());
 
   // Swipe up. This should show the shelf.
   end = below_start - delta;
diff --git a/base/allocator/allocator_check.cc b/base/allocator/allocator_check.cc
index 5a0564d..87d0e7e 100644
--- a/base/allocator/allocator_check.cc
+++ b/base/allocator/allocator_check.cc
@@ -14,6 +14,10 @@
 #include <malloc.h>
 #endif
 
+#if defined(OS_MACOSX)
+#include "base/allocator/allocator_interception_mac.h"
+#endif
+
 namespace base {
 namespace allocator {
 
@@ -28,6 +32,9 @@
 #define TC_MALLOPT_IS_OVERRIDDEN_BY_TCMALLOC 0xbeef42
   return (mallopt(TC_MALLOPT_IS_OVERRIDDEN_BY_TCMALLOC, 0) ==
           TC_MALLOPT_IS_OVERRIDDEN_BY_TCMALLOC);
+#elif defined(OS_MACOSX) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+  // From allocator_interception_mac.mm.
+  return base::allocator::g_replaced_default_zone;
 #else
   return true;
 #endif
diff --git a/base/allocator/allocator_interception_mac.h b/base/allocator/allocator_interception_mac.h
index 694d66b3..ff9b0b1 100644
--- a/base/allocator/allocator_interception_mac.h
+++ b/base/allocator/allocator_interception_mac.h
@@ -8,6 +8,7 @@
 #include <malloc/malloc.h>
 #include <stddef.h>
 
+#include "base/base_export.h"
 #include "third_party/apple_apsl/malloc.h"
 
 namespace base {
@@ -58,6 +59,8 @@
 // |functions|.
 void ReplaceFunctionsForDefaultZone(const MallocZoneFunctions* functions);
 
+extern bool g_replaced_default_zone;
+
 // Calls the original implementation of malloc/calloc prior to interception.
 bool UncheckedMallocMac(size_t size, void** result);
 bool UncheckedCallocMac(size_t num_items, size_t size, void** result);
@@ -66,7 +69,7 @@
 // Foundation and Objective-C allocations.
 // Has no effect on the default malloc zone if the allocator shim already
 // performs that interception.
-void InterceptAllocationsMac();
+BASE_EXPORT void InterceptAllocationsMac();
 }  // namespace allocator
 }  // namespace base
 
diff --git a/base/allocator/allocator_interception_mac.mm b/base/allocator/allocator_interception_mac.mm
index be6c0fa..e945a29 100644
--- a/base/allocator/allocator_interception_mac.mm
+++ b/base/allocator/allocator_interception_mac.mm
@@ -27,6 +27,8 @@
 
 #include <new>
 
+#include "base/allocator/allocator_shim.h"
+#include "base/allocator/features.h"
 #include "base/logging.h"
 #include "base/mac/mac_util.h"
 #include "base/mac/mach_logging.h"
@@ -38,12 +40,13 @@
 namespace base {
 namespace allocator {
 
+bool g_replaced_default_zone = false;
+
 MallocZoneFunctions::MallocZoneFunctions() {}
 
 namespace {
 
 bool g_oom_killer_enabled;
-bool g_replaced_default_zone = false;
 
 // Starting with Mac OS X 10.7, the zone allocators set up by the system are
 // read-only, to prevent them from being overwritten in an attack. However,
@@ -203,12 +206,6 @@
 
 #endif  // !defined(ADDRESS_SANITIZER)
 
-// === C++ operator new ===
-
-void oom_killer_new() {
-  TerminateBecauseOutOfMemory(0);
-}
-
 #if !defined(ADDRESS_SANITIZER)
 
 // === Core Foundation CFAllocators ===
@@ -441,13 +438,6 @@
   // system's malloc implementation. It's unlikely that anyone's even heard of
   // it.
 
-  // === C++ operator new ===
-
-  // Yes, operator new does call through to malloc, but this will catch failures
-  // that our imperfect handling of malloc cannot.
-
-  std::set_new_handler(oom_killer_new);
-
 #ifndef ADDRESS_SANITIZER
   // === Core Foundation CFAllocators ===
 
diff --git a/base/process/memory_mac.mm b/base/process/memory_mac.mm
index 155004dc..4b5a3ce 100644
--- a/base/process/memory_mac.mm
+++ b/base/process/memory_mac.mm
@@ -5,10 +5,18 @@
 #include "base/process/memory.h"
 
 #include "base/allocator/allocator_interception_mac.h"
+#include "base/allocator/allocator_shim.h"
+#include "base/allocator/features.h"
 #include "build/build_config.h"
 
 namespace base {
 
+namespace {
+void oom_killer_new() {
+  TerminateBecauseOutOfMemory(0);
+}
+}  // namespace
+
 void EnableTerminationOnHeapCorruption() {
 #if !ARCH_CPU_64_BITS
   DLOG(WARNING) << "EnableTerminationOnHeapCorruption only works on 64-bit";
@@ -24,6 +32,17 @@
 }
 
 void EnableTerminationOnOutOfMemory() {
+  // Step 1: Enable OOM killer on C++ failures.
+  std::set_new_handler(oom_killer_new);
+
+// Step 2: Enable OOM killer on C-malloc failures for the default zone (if we
+// have a shim).
+#if BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM)
+  allocator::SetCallNewHandlerOnMallocFailure(true);
+#endif
+
+  // Step 3: Enable OOM killer on all other malloc zones (or just "all" without
+  // "other" if shim is disabled).
   allocator::InterceptAllocationsMac();
 }
 
diff --git a/base/process/memory_unittest.cc b/base/process/memory_unittest.cc
index ce28225..ecf0b87 100644
--- a/base/process/memory_unittest.cc
+++ b/base/process/memory_unittest.cc
@@ -27,6 +27,8 @@
 #endif
 #if defined(OS_MACOSX)
 #include <malloc/malloc.h>
+#include "base/allocator/allocator_interception_mac.h"
+#include "base/allocator/allocator_shim.h"
 #include "base/process/memory_unittest_mac.h"
 #endif
 #if defined(OS_LINUX)
@@ -59,6 +61,9 @@
 // will fail.
 
 TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) {
+#if BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM)
+  base::allocator::InitializeAllocatorShim();
+#endif
   // Assert that freeing an unallocated pointer will crash the process.
   char buf[9];
   asm("" : "=r" (buf));  // Prevent clang from being too smart.
@@ -79,6 +84,12 @@
 #endif  // defined(OS_MACOSX)
 
 TEST(MemoryTest, AllocatorShimWorking) {
+#if defined(OS_MACOSX)
+#if BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM)
+  base::allocator::InitializeAllocatorShim();
+#endif
+  base::allocator::InterceptAllocationsMac();
+#endif
   ASSERT_TRUE(base::allocator::IsAllocatorInitialized());
 }
 
@@ -124,6 +135,10 @@
 class OutOfMemoryDeathTest : public OutOfMemoryTest {
  public:
   void SetUpInDeathAssert() {
+#if defined(OS_MACOSX) && BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM)
+    base::allocator::InitializeAllocatorShim();
+#endif
+
     // Must call EnableTerminationOnOutOfMemory() because that is called from
     // chrome's main function and therefore hasn't been called yet.
     // Since this call may result in another thread being created and death
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni
index f2118103c..2bcd6caa 100644
--- a/build/config/sysroot.gni
+++ b/build/config/sysroot.gni
@@ -16,6 +16,10 @@
   target_sysroot_dir = ""
 
   use_sysroot = true
+
+  # TODO(tonikitoo): Remove this arg when wheezy is finally dropped and we
+  # can just use debian/jessie everywhere by default. crbug.com/564904.
+  use_jessie_sysroot = false
 }
 
 if (is_linux && target_sysroot_dir != "") {
@@ -58,15 +62,8 @@
     if (current_cpu == "x64") {
       sysroot = "//build/linux/debian_wheezy_amd64-sysroot"
 
-      # TODO(tonikitoo): Remove the whole if clause below when debian/wheezy
-      # sysroots are switched to debian/jessie, crbug.com/564904.
-      import("//build_overrides/build.gni")
-      if (build_with_chromium) {
-        import("//ui/ozone/ozone.gni")
-        import("//ui/base/ui_features.gni")
-        if (use_ozone && use_xkbcommon) {
-          sysroot = "//build/linux/debian_jessie_amd64-sysroot"
-        }
+      if (use_jessie_sysroot) {
+        sysroot = "//build/linux/debian_jessie_amd64-sysroot"
       }
     } else if (current_cpu == "x86") {
       sysroot = "//build/linux/debian_wheezy_i386-sysroot"
diff --git a/cc/surfaces/compositor_frame_sink_support.cc b/cc/surfaces/compositor_frame_sink_support.cc
index e7848f80..f79f22c 100644
--- a/cc/surfaces/compositor_frame_sink_support.cc
+++ b/cc/surfaces/compositor_frame_sink_support.cc
@@ -76,25 +76,34 @@
   ++ack_pending_count_;
   float device_scale_factor = frame.metadata.device_scale_factor;
 
+  surface_factory_.SubmitCompositorFrame(
+      local_surface_id, std::move(frame),
+      base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck,
+                 weak_factory_.GetWeakPtr()));
+
   if (surface_manager_->using_surface_references()) {
     SurfaceId last_surface_id = reference_tracker_.current_surface_id();
 
     // Populate list of surface references to add and remove based on reference
-    // surfaces in current frame compared with the last frame.
-    reference_tracker_.UpdateReferences(local_surface_id,
-                                        frame.metadata.referenced_surfaces);
+    // surfaces in current frame compared with the last frame. The list of
+    // surface references includes references from both the pending and active
+    // frame if any.
+    SurfaceId current_surface_id(frame_sink_id_, local_surface_id);
+    Surface* surface = surface_manager_->GetSurfaceForId(current_surface_id);
+    // TODO(fsamuel): This is pretty inefficent. We copy over referenced
+    // surfaces. Then we pass them into the ReferencedSurfaceTracker to copy
+    // them again into a set. ReferencedSurfaceTracker should just take in two
+    // vectors, one for pending referenced surfaces and one for active
+    // referenced surfaces.
+    std::vector<SurfaceId> referenced_surfaces =
+        surface->active_referenced_surfaces();
 
-    surface_factory_.SubmitCompositorFrame(
-        local_surface_id, std::move(frame),
-        base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck,
-                   weak_factory_.GetWeakPtr()));
+    referenced_surfaces.insert(referenced_surfaces.end(),
+                               surface->pending_referenced_surfaces().begin(),
+                               surface->pending_referenced_surfaces().end());
+    reference_tracker_.UpdateReferences(local_surface_id, referenced_surfaces);
 
     UpdateSurfaceReferences(last_surface_id, local_surface_id);
-  } else {
-    surface_factory_.SubmitCompositorFrame(
-        local_surface_id, std::move(frame),
-        base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck,
-                   weak_factory_.GetWeakPtr()));
   }
 
   if (display_)
diff --git a/cc/surfaces/compositor_frame_sink_support.h b/cc/surfaces/compositor_frame_sink_support.h
index cfdd0a2..6bf64d14 100644
--- a/cc/surfaces/compositor_frame_sink_support.h
+++ b/cc/surfaces/compositor_frame_sink_support.h
@@ -46,6 +46,10 @@
     return surface_factory_.current_surface_for_testing();
   }
 
+  const ReferencedSurfaceTracker& ReferenceTrackerForTesting() const {
+    return reference_tracker_;
+  }
+
   void EvictFrame();
   void SetNeedsBeginFrame(bool needs_begin_frame);
   void SubmitCompositorFrame(const LocalSurfaceId& local_surface_id,
diff --git a/cc/surfaces/compositor_frame_sink_support_unittest.cc b/cc/surfaces/compositor_frame_sink_support_unittest.cc
index 6a49fce..67d08fa3 100644
--- a/cc/surfaces/compositor_frame_sink_support_unittest.cc
+++ b/cc/surfaces/compositor_frame_sink_support_unittest.cc
@@ -50,13 +50,17 @@
 class CompositorFrameSinkSupportTest : public testing::Test,
                                        public CompositorFrameSinkSupportClient {
  public:
-  CompositorFrameSinkSupportTest() {}
+  CompositorFrameSinkSupportTest()
+      : surface_manager_(SurfaceManager::LifetimeType::REFERENCES) {}
   ~CompositorFrameSinkSupportTest() override {}
 
   CompositorFrameSinkSupport& parent_support() { return *supports_[0]; }
   Surface* parent_surface() {
     return parent_support().current_surface_for_testing();
   }
+  const ReferencedSurfaceTracker& parent_reference_tracker() {
+    return parent_support().ReferenceTrackerForTesting();
+  }
 
   CompositorFrameSinkSupport& child_support1() { return *supports_[1]; }
   Surface* child_surface1() {
@@ -105,7 +109,11 @@
 
   void TearDown() override {
     surface_manager_.SetDependencyTracker(nullptr);
+
+    // SurfaceDependencyTracker depends on this BeginFrameSource and so it must
+    // be destroyed AFTER the dependency tracker is destroyed.
     begin_frame_source_.reset();
+
     supports_.clear();
   }
 
@@ -387,5 +395,53 @@
   EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty());
 }
 
+// This test verifies that the set of references from a Surface includes both
+// the pending and active CompositorFrames.
+TEST_F(CompositorFrameSinkSupportTest,
+       DisplayCompositorLockingReferencesFromPendingAndActiveFrames) {
+  const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
+  const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
+  const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1);
+  const SurfaceReference parent_child_reference(parent_id, child_id);
+  const SurfaceReference parent_arbitrary_reference(parent_id, arbitrary_id);
+
+  // child_support1 submits a CompositorFrame without any dependencies.
+  child_support1().SubmitCompositorFrame(
+      child_id.local_surface_id(), MakeCompositorFrame(empty_surface_ids()));
+
+  // Verify that the child surface is not blocked.
+  EXPECT_TRUE(child_surface1()->HasActiveFrame());
+  EXPECT_FALSE(child_surface1()->HasPendingFrame());
+  EXPECT_THAT(child_surface1()->blocking_surfaces_for_testing(), IsEmpty());
+
+  // parent_support submits a CompositorFrame that depends on |child_id1|
+  // which is already active. Thus, this CompositorFrame should activate
+  // immediately.
+  parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
+                                         MakeCompositorFrame({child_id}));
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_FALSE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(), IsEmpty());
+  // Verify that the parent will add a reference to the |child_id|.
+  EXPECT_THAT(parent_reference_tracker().references_to_add(),
+              UnorderedElementsAre(parent_child_reference));
+  EXPECT_THAT(parent_reference_tracker().references_to_remove(), IsEmpty());
+
+  // parent_support now submits another CompositorFrame to the same surface
+  // but depends on arbitrary_id. The parent surface should now have both
+  // a pending and active CompositorFrame.
+  parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
+                                         MakeCompositorFrame({arbitrary_id}));
+  EXPECT_TRUE(parent_surface()->HasActiveFrame());
+  EXPECT_TRUE(parent_surface()->HasPendingFrame());
+  EXPECT_THAT(parent_surface()->blocking_surfaces_for_testing(),
+              UnorderedElementsAre(arbitrary_id));
+  // Verify that the parent will add a reference to |arbitrary_id| and will not
+  // remove a reference to |child_id|.
+  EXPECT_THAT(parent_reference_tracker().references_to_add(),
+              UnorderedElementsAre(parent_arbitrary_reference));
+  EXPECT_THAT(parent_reference_tracker().references_to_remove(), IsEmpty());
+}
+
 }  // namespace test
 }  // namespace cc
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc
index 57e3a3c9..c2ab354 100644
--- a/cc/surfaces/surface.cc
+++ b/cc/surfaces/surface.cc
@@ -63,6 +63,8 @@
     pending_frame_ = std::move(frame);
     if (pending_frame_) {
       factory_->ReceiveFromChild(pending_frame_->resource_list);
+      pending_referenced_surfaces_ =
+          pending_frame_->metadata.referenced_surfaces;
       // Ask the surface manager to inform |this| when its dependencies are
       // resolved.
       factory_->manager()->RequestSurfaceResolution(this);
@@ -149,6 +151,7 @@
   DCHECK(pending_frame_);
   ActivateFrame(std::move(pending_frame_.value()));
   pending_frame_.reset();
+  pending_referenced_surfaces_.clear();
   // ActiveFrame resources are now double ref-ed. Unref.
   UnrefFrameResources(*active_frame_);
 }
@@ -177,7 +180,7 @@
   if (previous_frame)
     UnrefFrameResources(*previous_frame);
 
-  referenced_surfaces_ = active_frame_->metadata.referenced_surfaces;
+  active_referenced_surfaces_ = active_frame_->metadata.referenced_surfaces;
 
   for (auto& observer : observers_)
     observer.OnSurfaceActivated(this);
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h
index a427a822..e8fbccf 100644
--- a/cc/surfaces/surface.h
+++ b/cc/surfaces/surface.h
@@ -101,8 +101,12 @@
     return destruction_dependencies_.size();
   }
 
-  const std::vector<SurfaceId>& referenced_surfaces() const {
-    return referenced_surfaces_;
+  const std::vector<SurfaceId>& active_referenced_surfaces() const {
+    return active_referenced_surfaces_;
+  }
+
+  const std::vector<SurfaceId>& pending_referenced_surfaces() const {
+    return pending_referenced_surfaces_;
   }
 
   const SurfaceDependencies& blocking_surfaces_for_testing() const {
@@ -140,8 +144,19 @@
   // on multiple Displays.
   std::set<BeginFrameSource*> begin_frame_sources_;
 
-  // The total set of CompositorFrames referenced by the active CompositorFrame.
-  std::vector<SurfaceId> referenced_surfaces_;
+  // The set of SurfaceIds referenced by the active CompositorFrame.
+  // TODO(fsamuel): It seems unnecessary to copy this vector over
+  // from CompostiorFrameMetadata to store locally here. We can simply
+  // provide an accessor to the referenced surfaces directly from
+  // CompositorFrameMetadata.
+  std::vector<SurfaceId> active_referenced_surfaces_;
+
+  // The set of SurfaceIds referenced by the pending CompositorFrame.
+  // TODO(fsamuel): It seems unnecessary to copy this vector over
+  // from CompostiorFrameMetadata to store locally here. We can simply
+  // provide an accessor to the referenced surfaces directly from
+  // CompositorFrameMetadata.
+  std::vector<SurfaceId> pending_referenced_surfaces_;
 
   SurfaceDependencies blocking_surfaces_;
   base::ObserverList<PendingFrameObserver, true> observers_;
diff --git a/cc/surfaces/surface_dependency_tracker.cc b/cc/surfaces/surface_dependency_tracker.cc
index 934586b..df20152 100644
--- a/cc/surfaces/surface_dependency_tracker.cc
+++ b/cc/surfaces/surface_dependency_tracker.cc
@@ -26,6 +26,9 @@
 SurfaceDependencyTracker::~SurfaceDependencyTracker() {
   surface_manager_->RemoveObserver(this);
   begin_frame_source_->RemoveObserver(this);
+  for (Surface* pending_surface : pending_surfaces_)
+    pending_surface->RemoveObserver(this);
+  pending_surfaces_.clear();
 }
 
 void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) {
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc
index c91bf2c..f7e3119 100644
--- a/cc/surfaces/surface_manager.cc
+++ b/cc/surfaces/surface_manager.cc
@@ -327,7 +327,9 @@
     Surface* surf = surface_map_[live_surfaces[i]];
     DCHECK(surf);
 
-    for (const SurfaceId& id : surf->referenced_surfaces()) {
+    // TODO(fsamuel): We should probably keep alive pending referenced surfaces
+    // too.
+    for (const SurfaceId& id : surf->active_referenced_surfaces()) {
       if (live_surfaces_set.count(id))
         continue;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
index 6c986de..e09cf97 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
@@ -200,7 +200,7 @@
 
         // Check if we should launch an Instant App to handle the intent.
         if (InstantAppsHandler.getInstance().handleIncomingIntent(
-                this, intent, mIsCustomTabIntent && !mIsHerbIntent)) {
+                this, intent, mIsCustomTabIntent && !mIsHerbIntent, false)) {
             finish();
             return;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
index c33e7ac..5c50882 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -642,15 +642,15 @@
                 return;
             }
         } else if (ACTION_DOWNLOAD_RESUME.equals(intent.getAction())) {
-            boolean metered = DownloadManagerService.isActiveNetworkMetered(mContext);
-            if (!entry.canDownloadWhileMetered) {
-                // If user manually resumes a download, update the network type if it
-                // is not metered previously.
-                entry.canDownloadWhileMetered = metered;
-            }
-            entry.isAutoResumable = true;
+            // If user manually resumes a download, update the network type if it
+            // is not metered previously.
+            boolean canDownloadWhileMetered = entry.canDownloadWhileMetered
+                    || DownloadManagerService.isActiveNetworkMetered(mContext);
             // Update the SharedPreference entry.
-            mDownloadSharedPreferenceHelper.addOrReplaceSharedPreferenceEntry(entry);
+            mDownloadSharedPreferenceHelper.addOrReplaceSharedPreferenceEntry(
+                    new DownloadSharedPreferenceEntry(entry.notificationId, entry.isOffTheRecord,
+                            canDownloadWhileMetered, entry.downloadGuid, entry.fileName,
+                            entry.itemType, true));
         } else if (ACTION_DOWNLOAD_RESUME_ALL.equals(intent.getAction())
                 && (mDownloadSharedPreferenceHelper.getEntries().isEmpty()
                         || DownloadManagerService.hasDownloadManagerService())) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java
index ac75223..4ae33fa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceEntry.java
@@ -27,13 +27,13 @@
 
     public final int notificationId;
     public final boolean isOffTheRecord;  // Whether the download is public (non incognito).
-    public boolean canDownloadWhileMetered;
+    public final boolean canDownloadWhileMetered;
     public final String fileName;
     public final String downloadGuid;
     public final int itemType;
     // This can only be false for paused downloads. For downloads that are pending or in progress,
     // isAutoResumable should always be true.
-    public boolean isAutoResumable;
+    public final boolean isAutoResumable;
 
     static final DownloadSharedPreferenceEntry INVALID_ENTRY =
             new DownloadSharedPreferenceEntry(-1, false, false, null, "", ITEM_TYPE_DOWNLOAD,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
index fa9c7a6..c954ec50 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -586,7 +586,7 @@
             Intent resolvedIntent = new Intent(intent);
             resolvedIntent.setData(Uri.parse(url));
             return handler.handleIncomingIntent(getAvailableContext(), resolvedIntent,
-                    ChromeLauncherActivity.isCustomTabIntent(resolvedIntent));
+                    ChromeLauncherActivity.isCustomTabIntent(resolvedIntent), true);
         } else if (!isIncomingRedirect) {
             // Check if the navigation is coming from SERP and skip instant app handling.
             if (isSerpReferrer(tab)) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java
index 8470bfd..4b7beb7b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsHandler.java
@@ -11,6 +11,7 @@
 import android.os.SystemClock;
 import android.provider.Browser;
 
+import org.chromium.base.BuildInfo;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.metrics.CachedMetrics.EnumeratedHistogramSample;
@@ -159,18 +160,32 @@
         }
     }
 
-    /** Handle incoming intent. */
+    /**
+     * Handle incoming intent.
+     * @param context Context.
+     * @param intent The incoming intent being handled.
+     * @param isCustomTabsIntent Whether we are in custom tabs.
+     * @param isRedirect Whether this is the redirect resolve case where incoming intent was
+     *        resolved to another URL.
+     * @return Whether Instant Apps is handling the URL request.
+     */
     public boolean handleIncomingIntent(Context context, Intent intent,
-            boolean isCustomTabsIntent) {
+            boolean isCustomTabsIntent, boolean isRedirect) {
         long startTimeStamp = SystemClock.elapsedRealtime();
         boolean result = handleIncomingIntentInternal(context, intent, isCustomTabsIntent,
-                startTimeStamp);
+                startTimeStamp, isRedirect);
         recordHandleIntentDuration(startTimeStamp);
         return result;
     }
 
     private boolean handleIncomingIntentInternal(
-            Context context, Intent intent, boolean isCustomTabsIntent, long startTime) {
+            Context context, Intent intent, boolean isCustomTabsIntent, long startTime,
+            boolean isRedirect) {
+        if (!isRedirect && !isCustomTabsIntent && BuildInfo.isAtLeastO()) {
+            Log.i(TAG, "Disabled for Android O+");
+            return false;
+        }
+
         if (isCustomTabsIntent && !IntentUtils.safeGetBooleanExtra(
                 intent, CUSTOM_APPS_INSTANT_APP_EXTRA, false)) {
             Log.i(TAG, "Not handling with Instant Apps (missing CUSTOM_APPS_INSTANT_APP_EXTRA)");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/media/router/OWNERS
index dc2593f..7816a76 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/OWNERS
@@ -1,2 +1,4 @@
 avayvod@chromium.org
 mlamouri@chromium.org
+
+# COMPONENT: Blink>PresentationAPI
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/OWNERS
index dc2593f..68dc47e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/OWNERS
@@ -1,2 +1,4 @@
 avayvod@chromium.org
 mlamouri@chromium.org
+
+# COMPONENT: Internals>Media>UI
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java
index fed38043..6757ff15 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTask.java
@@ -11,7 +11,6 @@
 import org.chromium.base.Callback;
 import org.chromium.base.Log;
 import org.chromium.base.SysUtils;
-import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.ChromeBackgroundServiceWaiter;
 import org.chromium.chrome.browser.offlinepages.interfaces.BackgroundSchedulerProcessor;
 
@@ -37,8 +36,26 @@
      *
      * @returns true for success
      */
-    public boolean startBackgroundRequests(Context context, Bundle bundle,
-                                           ChromeBackgroundServiceWaiter waiter) {
+    public void startBackgroundRequests(
+            Context context, Bundle bundle, final ChromeBackgroundServiceWaiter waiter) {
+        // Complete the wait if background request processing was not started.
+        // If background processing was started, completion is going to be handled by callback.
+        if (!startBackgroundRequestsImpl(context, bundle, waiter)) {
+            waiter.onWaitDone();
+        }
+    }
+
+    /**
+     * Triggers processing of background offlining requests.  This is called when
+     * system conditions are appropriate for background offlining, typically from the
+     * GcmTaskService onRunTask() method.  In response, we will start the
+     * task processing by passing the call along to the C++ RequestCoordinator.
+     * Also starts UMA collection.
+     *
+     * @returns true for success
+     */
+    private boolean startBackgroundRequestsImpl(
+            Context context, Bundle bundle, final ChromeBackgroundServiceWaiter waiter) {
         // Set up backup scheduled task in case processing is killed before RequestCoordinator
         // has a chance to reschedule base on remaining work.
         TriggerConditions previousTriggerConditions =
@@ -58,51 +75,23 @@
             return false;
         }
 
-        // Now initiate processing.
-        processBackgroundRequests(bundle, currentConditions, waiter);
-
         // Gather UMA data to measure how often the user's machine is amenable to background
         // loading when we wake to do a task.
         long taskScheduledTimeMillis = TaskExtrasPacker.unpackTimeFromBundle(bundle);
         OfflinePageUtils.recordWakeupUMA(context, taskScheduledTimeMillis);
 
-        return true;
+        return mBridge.startScheduledProcessing(currentConditions, createCallback(waiter));
     }
 
-    /**
-     * Triggers processing of background offlining requests.
-     */
-    // TODO(petewil): Change back to private when UMA works in the test, and test
-    // startBackgroundRequests instead of this method.
-    @VisibleForTesting
-    public void processBackgroundRequests(
-            Bundle bundle, DeviceConditions deviceConditions,
-            final ChromeBackgroundServiceWaiter waiter) {
-        // TODO(petewil): Nothing is holding the Wake Lock.  We need some solution to
-        // keep hold of it.  Options discussed so far are having a fresh set of functions
-        // to grab and release a countdown latch, or holding onto the wake lock ourselves,
-        // or grabbing the wake lock and then starting chrome and running
-        // startScheduledProcessing on the UI thread.
-
-        // TODO(petewil): Decode the TriggerConditions from the bundle.
-
-        Callback<Boolean> callback = new Callback<Boolean>() {
-            /**
-             * Callback function which indicates completion of background work.
-             * @param result - true if work was actually done (used for UMA).
-             */
+    private Callback<Boolean> createCallback(final ChromeBackgroundServiceWaiter waiter) {
+        return new Callback<Boolean>() {
+            /** Callback releasing the wakelock once background work concludes. */
             @Override
             public void onResult(Boolean result) {
-                // Release the wake lock.
                 Log.d(TAG, "onProcessingDone");
+                // Release the wake lock.
                 waiter.onWaitDone();
             }
         };
-
-        // Pass the activation on to the bridge to the C++ RequestCoordinator.
-        if (!mBridge.startScheduledProcessing(deviceConditions, callback)) {
-            // Processing not started currently. Let callback know.
-            callback.onResult(false);
-        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
index 2ee557cd..fe55c0f2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -2,3 +2,5 @@
 dominickn@chromium.org
 mlamouri@chromium.org
 changwan@chromium.org
+
+# COMPONENT: Content>WebApps
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
index a140742..756b9d73 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/instantapps/InstantAppsHandlerTest.java
@@ -66,7 +66,7 @@
         Intent i = createViewIntent();
         i.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true);
 
-        assertFalse(mHandler.handleIncomingIntent(mContext, i, false));
+        assertFalse(mHandler.handleIncomingIntent(mContext, i, false, true));
     }
 
 
@@ -75,13 +75,13 @@
         Intent i = createViewIntent();
         i.putExtra("com.google.android.gms.instantapps.DO_NOT_LAUNCH_INSTANT_APP", true);
 
-        assertFalse(mHandler.handleIncomingIntent(mContext, i, false));
+        assertFalse(mHandler.handleIncomingIntent(mContext, i, false, true));
     }
 
     @SmallTest
     public void testInstantAppsDisabled_mainIntent() {
         Intent i = new Intent(Intent.ACTION_MAIN);
-        assertFalse(mHandler.handleIncomingIntent(mContext, i, false));
+        assertFalse(mHandler.handleIncomingIntent(mContext, i, false, true));
     }
 
     @SmallTest
@@ -89,20 +89,20 @@
         Intent i = createViewIntent();
         i.putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName());
 
-        assertFalse(mHandler.handleIncomingIntent(mContext, i, false));
+        assertFalse(mHandler.handleIncomingIntent(mContext, i, false, true));
 
         Intent signedIntent = createViewIntent();
         signedIntent.setPackage(mContext.getPackageName());
         IntentHandler.addTrustedIntentExtras(signedIntent);
 
-        assertFalse(mHandler.handleIncomingIntent(mContext, signedIntent, false));
+        assertFalse(mHandler.handleIncomingIntent(mContext, signedIntent, false, true));
     }
 
     @SmallTest
     public void testInstantAppsDisabled_launchFromShortcut() {
         Intent i = createViewIntent();
         i.putExtra(ShortcutHelper.EXTRA_SOURCE, 1);
-        assertFalse(mHandler.handleIncomingIntent(mContext, i, false));
+        assertFalse(mHandler.handleIncomingIntent(mContext, i, false, true));
     }
 
     @SmallTest
@@ -112,33 +112,37 @@
         editor.putBoolean("applink.chrome_default_browser", false);
         editor.apply();
 
-        assertFalse(mHandler.handleIncomingIntent(mContext, createViewIntent(), false));
+        assertFalse(mHandler.handleIncomingIntent(mContext, createViewIntent(), false, true));
 
         // Even if Chrome is not default, launch Instant Apps for CustomTabs since those never
         // show disambiguation dialogs.
         Intent cti = createViewIntent()
                 .putExtra("android.support.customtabs.extra.EXTRA_ENABLE_INSTANT_APPS", true);
-        assertTrue(mHandler.handleIncomingIntent(mContext, cti, true));
+        assertTrue(mHandler.handleIncomingIntent(mContext, cti, true, true));
     }
 
     @SmallTest
     public void testInstantAppsEnabled() {
         Intent i = createViewIntent();
-        assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, false));
+        assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, false,
+                true));
 
         // Check that identical intent wouldn't be enabled for CustomTab flow.
-        assertFalse(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, true));
+        assertFalse(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, true,
+                true));
 
         // Add CustomTab specific extra and check it's now enabled.
         i.putExtra("android.support.customtabs.extra.EXTRA_ENABLE_INSTANT_APPS", true);
-        assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, true));
+        assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, true,
+                true));
     }
 
     @SmallTest
     public void testNfcIntent() {
         Intent i = new Intent(NfcAdapter.ACTION_NDEF_DISCOVERED);
         i.setData(Uri.parse("http://instantapp.com/"));
-        assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, false));
+        assertTrue(mHandler.handleIncomingIntent(getInstrumentation().getContext(), i, false,
+                true));
     }
 
     @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/media/OWNERS
index f4a9d9c..c8e9dde 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/OWNERS
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/OWNERS
@@ -1,3 +1,5 @@
 aberent@chromium.org
 avayvod@chromium.org
 mlamouri@chromium.org
+
+# COMPONENT: Internals>Media>UI
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS
index 73145cc..bd7774a8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/OWNERS
@@ -2,3 +2,5 @@
 dominickn@chromium.org
 changwan@chromium.org
 mlamouri@chromium.org
+
+# COMPONENT: Content>WebApps
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/router/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/media/router/OWNERS
index dc2593f..7816a76 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/media/router/OWNERS
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/router/OWNERS
@@ -1,2 +1,4 @@
 avayvod@chromium.org
 mlamouri@chromium.org
+
+# COMPONENT: Blink>PresentationAPI
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/OWNERS
index f1deab2..a276f281 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/OWNERS
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/OWNERS
@@ -1,3 +1,5 @@
 avayvod@chromium.org
 mlamouri@chromium.org
 zqzhang@chromium.org
+
+# COMPONENT: Internals>Media>UI
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java
index f589465..21e214a 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/BackgroundOfflinerTaskTest.java
@@ -113,44 +113,12 @@
 
     @Test
     @Feature({"OfflinePages"})
-    public void testIncomingTask() {
-        BackgroundOfflinerTask task =
-                new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor);
-        ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1000);
-        task.processBackgroundRequests(mTaskExtras, mDeviceConditions, waiter);
-
-        // Check with BackgroundSchedulerProcessor that it started processing.
-        assertTrue(mStubBackgroundSchedulerProcessor.getDidStartProcessing());
-        assertSame(mDeviceConditions, mStubBackgroundSchedulerProcessor.getDeviceConditions());
-
-        // Call the callback and then waiter should not block.
-        mStubBackgroundSchedulerProcessor.callback();
-        waiter.startWaiting();
-    }
-
-    @Test
-    @Feature({"OfflinePages"})
-    public void testIncomingTaskNotStarted() {
-        mStubBackgroundSchedulerProcessor.setFailToStart(true);
-        BackgroundOfflinerTask task = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor);
-        ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1000);
-        task.processBackgroundRequests(mTaskExtras, mDeviceConditions, waiter);
-
-        // Check with BackgroundSchedulerProcessor that it did not start.
-        assertFalse(mStubBackgroundSchedulerProcessor.getDidStartProcessing());
-
-        // The waiter should not block if startScheduledProcessing returned false.
-        waiter.startWaiting();
-    }
-
-    @Test
-    @Feature({"OfflinePages"})
     public void testStartBackgroundRequests() {
         BackgroundOfflinerTask task = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor);
         ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1);
         assertNull("Nothing scheduled", mGcmNetworkManager.getScheduledTask());
-        assertTrue(task.startBackgroundRequests(
-                RuntimeEnvironment.application, mTaskExtras, waiter));
+
+        task.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter);
 
         // Check that the backup task was scheduled.
         Task gcmTask = mGcmNetworkManager.getScheduledTask();
@@ -158,23 +126,50 @@
         assertEquals(mTriggerConditions,
                 TaskExtrasPacker.unpackTriggerConditionsFromBundle(gcmTask.getExtras()));
 
-        // Check with BackgroundSchedulerProcessor that startScheduledProcessing got called.
+        // Check with BackgroundSchedulerProcessor that processing stated.
         assertTrue(mStubBackgroundSchedulerProcessor.getDidStartProcessing());
         assertSame(mDeviceConditions, mStubBackgroundSchedulerProcessor.getDeviceConditions());
+
+        // Waiter is only released at the end of the test, when the processing concludes.
+        mStubBackgroundSchedulerProcessor.callback();
+        waiter.startWaiting();
+    }
+
+    @Test
+    @Feature({"OfflinePages"})
+    public void testStartBackgroundRequestsNotStarted() {
+        mStubBackgroundSchedulerProcessor.setFailToStart(true);
+        BackgroundOfflinerTask task = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor);
+        ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1);
+        assertNull("Nothing scheduled", mGcmNetworkManager.getScheduledTask());
+
+        task.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter);
+        waiter.startWaiting();
+
+        // Check that the backup task was scheduled.
+        Task gcmTask = mGcmNetworkManager.getScheduledTask();
+        assertNotNull("Backup task scheduled", gcmTask);
+        assertEquals(mTriggerConditions,
+                TaskExtrasPacker.unpackTriggerConditionsFromBundle(gcmTask.getExtras()));
+
+        // Check with BackgroundSchedulerProcessor that it did not start.
+        assertFalse(mStubBackgroundSchedulerProcessor.getDidStartProcessing());
     }
 
     @Test
     @Feature({"OfflinePages"})
     public void testStartBackgroundRequestsForLowBatteryLevel() {
+        // Setup low battery conditions.
         DeviceConditions deviceConditionsLowBattery = new DeviceConditions(
                 !POWER_CONNECTED, MINIMUM_BATTERY_LEVEL - 1, ConnectionType.CONNECTION_WIFI);
         when(mOfflinePageUtils.getDeviceConditionsImpl(any(Context.class)))
                 .thenReturn(deviceConditionsLowBattery);
+
         BackgroundOfflinerTask task = new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor);
         ChromeBackgroundServiceWaiter waiter = new ChromeBackgroundServiceWaiter(1);
         assertNull("Nothing scheduled", mGcmNetworkManager.getScheduledTask());
-        assertFalse(task.startBackgroundRequests(
-                RuntimeEnvironment.application, mTaskExtras, waiter));
+        task.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter);
+        waiter.startWaiting();
 
         // Check that the backup task was scheduled.
         Task gcmTask = mGcmNetworkManager.getScheduledTask();
@@ -190,11 +185,16 @@
                 POWER_CONNECTED, MINIMUM_BATTERY_LEVEL - 1, ConnectionType.CONNECTION_WIFI);
         when(mOfflinePageUtils.getDeviceConditionsImpl(any(Context.class)))
                 .thenReturn(deviceConditionsPowerConnected);
+
         BackgroundOfflinerTask task2 =
                 new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor);
         ChromeBackgroundServiceWaiter waiter2 = new ChromeBackgroundServiceWaiter(1);
-        assertTrue(task2.startBackgroundRequests(
-                RuntimeEnvironment.application, mTaskExtras, waiter2));
+        task2.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter2);
+
+        assertTrue(mStubBackgroundSchedulerProcessor.getDidStartProcessing());
+
+        mStubBackgroundSchedulerProcessor.callback();
+        waiter2.startWaiting();
     }
 
     @Test
@@ -207,8 +207,8 @@
         // Transition the test Activity to a running state.
         ApplicationStatus.onStateChangeForTesting(mTestActivity, ActivityState.STARTED);
 
-        assertFalse(task.startBackgroundRequests(
-                RuntimeEnvironment.application, mTaskExtras, waiter));
+        task.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter);
+        waiter.startWaiting();
 
         // Check that the backup task was scheduled.
         Task gcmTask = mGcmNetworkManager.getScheduledTask();
@@ -224,7 +224,11 @@
         BackgroundOfflinerTask task2 =
                 new BackgroundOfflinerTask(mStubBackgroundSchedulerProcessor);
         ChromeBackgroundServiceWaiter waiter2 = new ChromeBackgroundServiceWaiter(1);
-        assertTrue(task2.startBackgroundRequests(
-                RuntimeEnvironment.application, mTaskExtras, waiter2));
+        task2.startBackgroundRequests(RuntimeEnvironment.application, mTaskExtras, waiter2);
+
+        assertTrue(mStubBackgroundSchedulerProcessor.getDidStartProcessing());
+
+        mStubBackgroundSchedulerProcessor.callback();
+        waiter2.startWaiting();
     }
 }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 2bdd423..77a1be94 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -6352,9 +6352,6 @@
       <message name="IDS_FLAGS_DATASAVER_PROMPT_DEMO_MODE" desc="The value of the Data Saver prompt flag which always shows prompt on network properties change.">
         Demo mode
       </message>
-      <message name="IDS_FLAGS_DISABLE_UNIFIED_MEDIA_PIPELINE_NAME" desc="Title for the flag to disable the unified media pipeline on Android.">
-        Disables the unified media pipeline on Android.
-      </message>
       <message name="IDS_FLAGS_DISABLE_UNIFIED_MEDIA_PIPELINE_DESCRIPTION" desc="Description for the flag to disable the unified media pipeline on Android.">
         Disables the unified (Android and desktop) media pipeline on Android.
       </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 6c414b5..ea494c1 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2432,6 +2432,8 @@
       "captive_portal/captive_portal_tab_helper.h",
       "captive_portal/captive_portal_tab_reloader.cc",
       "captive_portal/captive_portal_tab_reloader.h",
+      "component_updater/ssl_error_assistant_component_installer.cc",
+      "component_updater/ssl_error_assistant_component_installer.h",
       "ssl/captive_portal_blocking_page.cc",
       "ssl/captive_portal_blocking_page.h",
       "ssl/captive_portal_metrics_recorder.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 63fac04..1679909 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1766,12 +1766,6 @@
      IDS_FLAGS_ENABLE_WEB_USB_DESCRIPTION, kOsAll,
      FEATURE_VALUE_TYPE(features::kWebUsb)},
 #if defined(OS_ANDROID)
-    {"disable-unified-media-pipeline",
-     IDS_FLAGS_DISABLE_UNIFIED_MEDIA_PIPELINE_NAME,
-     IDS_FLAGS_DISABLE_UNIFIED_MEDIA_PIPELINE_DESCRIPTION, kOsAndroid,
-     SINGLE_VALUE_TYPE(switches::kDisableUnifiedMediaPipeline)},
-#endif  // OS_ANDROID
-#if defined(OS_ANDROID)
     {"force-show-update-menu-item", IDS_FLAGS_UPDATE_MENU_ITEM_NAME,
      IDS_FLAGS_UPDATE_MENU_ITEM_DESCRIPTION, kOsAndroid,
      SINGLE_VALUE_TYPE(switches::kForceShowUpdateMenuItem)},
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 98690ba..0cbbdd0 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -239,6 +239,10 @@
 #include "chrome/browser/background/background_mode_manager.h"
 #endif  // BUILDFLAG(ENABLE_BACKGROUND)
 
+#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
+#include "chrome/browser/component_updater/ssl_error_assistant_component_installer.h"
+#endif  // BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
+
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "chrome/browser/extensions/startup_helper.h"
 #include "extensions/browser/extension_protocols.h"
@@ -468,14 +472,19 @@
 #endif  // defined(OS_MACOSX)
 
 void RegisterComponentsForUpdate() {
-  const auto cus = g_browser_process->component_updater();
+  component_updater::ComponentUpdateService* cus =
+      g_browser_process->component_updater();
 
+  // Registration can be before or after cus->Start() so it is ok to post
+  // a task to the UI thread to do registration once you done the necessary
+  // file IO to know you existing component version.
+#if !defined(OS_ANDROID)
+#if !defined(OS_CHROMEOS)
   if (base::FeatureList::IsEnabled(features::kImprovedRecoveryComponent))
     RegisterRecoveryImprovedComponent(cus, g_browser_process->local_state());
   else
     RegisterRecoveryComponent(cus, g_browser_process->local_state());
-
-#if !defined(OS_ANDROID)
+#endif  // !defined(OS_CHROMEOS)
   RegisterPepperFlashComponent(cus);
 #if !defined(OS_CHROMEOS)
   RegisterSwiftShaderComponent(cus);
@@ -523,6 +532,10 @@
     RegisterOriginTrialsComponent(cus, path);
 
     RegisterFileTypePoliciesComponent(cus, path);
+
+#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
+    RegisterSSLErrorAssistantComponent(cus, path);
+#endif
   }
 
 #if defined(OS_WIN)
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index c9242bc1..cba43cd 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1146,8 +1146,6 @@
     "policy/user_network_configuration_updater.h",
     "policy/user_network_configuration_updater_factory.cc",
     "policy/user_network_configuration_updater_factory.h",
-    "policy/user_policy_disk_cache.cc",
-    "policy/user_policy_disk_cache.h",
     "policy/user_policy_manager_factory_chromeos.cc",
     "policy/user_policy_manager_factory_chromeos.h",
     "policy/user_policy_token_loader.cc",
diff --git a/chrome/browser/chromeos/options/network_config_view.cc b/chrome/browser/chromeos/options/network_config_view.cc
index 4cdb6ec..a5fd09d 100644
--- a/chrome/browser/chromeos/options/network_config_view.cc
+++ b/chrome/browser/chromeos/options/network_config_view.cc
@@ -200,10 +200,6 @@
   return child_config_view_->GetInitiallyFocusedView();
 }
 
-int NetworkConfigView::GetDefaultDialogButton() const {
-  return ui::DIALOG_BUTTON_CANCEL;
-}
-
 base::string16 NetworkConfigView::GetWindowTitle() const {
   DCHECK(!child_config_view_->GetTitle().empty());
   return child_config_view_->GetTitle();
diff --git a/chrome/browser/chromeos/options/network_config_view.h b/chrome/browser/chromeos/options/network_config_view.h
index 250e3d1..d1f6cb0c 100644
--- a/chrome/browser/chromeos/options/network_config_view.h
+++ b/chrome/browser/chromeos/options/network_config_view.h
@@ -62,7 +62,6 @@
   bool Accept() override;
   views::View* CreateExtraView() override;
   views::View* GetInitiallyFocusedView() override;
-  int GetDefaultDialogButton() const override;
 
   // views::WidgetDelegate methods.
   base::string16 GetWindowTitle() const override;
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
index 0f4b4911..f73ec0c 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos.cc
@@ -18,7 +18,6 @@
 #include "base/sequenced_task_runner.h"
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/browser/chromeos/policy/user_policy_disk_cache.h"
 #include "chrome/browser/chromeos/policy/user_policy_token_loader.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/dbus/cryptohome_client.h"
diff --git a/chrome/browser/chromeos/policy/user_policy_disk_cache.cc b/chrome/browser/chromeos/policy/user_policy_disk_cache.cc
deleted file mode 100644
index 5a97941..0000000
--- a/chrome/browser/chromeos/policy/user_policy_disk_cache.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-// 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.
-
-#include "chrome/browser/chromeos/policy/user_policy_disk_cache.h"
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "components/policy/core/common/cloud/enterprise_metrics.h"
-#include "components/policy/proto/device_management_local.pb.h"
-
-namespace em = enterprise_management;
-
-namespace policy {
-
-UserPolicyDiskCache::Delegate::~Delegate() {}
-
-UserPolicyDiskCache::UserPolicyDiskCache(
-    const base::WeakPtr<Delegate>& delegate,
-    const base::FilePath& backing_file_path,
-    scoped_refptr<base::SequencedTaskRunner> background_task_runner)
-    : delegate_(delegate),
-      backing_file_path_(backing_file_path),
-      origin_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      background_task_runner_(background_task_runner) {
-}
-
-void UserPolicyDiskCache::Load() {
-  DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
-  bool ret = background_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&UserPolicyDiskCache::LoadOnFileThread, this));
-  DCHECK(ret);
-}
-
-void UserPolicyDiskCache::Store(
-    const em::CachedCloudPolicyResponse& policy) {
-  DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
-  background_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&UserPolicyDiskCache::StoreOnFileThread, this, policy));
-}
-
-UserPolicyDiskCache::~UserPolicyDiskCache() {}
-
-void UserPolicyDiskCache::LoadOnFileThread() {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
-
-  em::CachedCloudPolicyResponse cached_response;
-  if (!base::PathExists(backing_file_path_)) {
-    LoadDone(LOAD_RESULT_NOT_FOUND, cached_response);
-    return;
-  }
-
-  // Read the protobuf from the file.
-  std::string data;
-  if (!base::ReadFileToString(backing_file_path_, &data)) {
-    LOG(WARNING) << "Failed to read policy data from "
-                 << backing_file_path_.value();
-    LoadDone(LOAD_RESULT_READ_ERROR, cached_response);
-    return;
-  }
-
-  // Decode it.
-  if (!cached_response.ParseFromArray(data.c_str(), data.size())) {
-    LOG(WARNING) << "Failed to parse policy data read from "
-                 << backing_file_path_.value();
-    LoadDone(LOAD_RESULT_PARSE_ERROR, cached_response);
-    return;
-  }
-
-  LoadDone(LOAD_RESULT_SUCCESS, cached_response);
-}
-
-void UserPolicyDiskCache::LoadDone(
-    LoadResult result,
-    const em::CachedCloudPolicyResponse& policy) {
-  origin_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(
-          &UserPolicyDiskCache::ReportResultOnUIThread, this, result, policy));
-}
-
-void UserPolicyDiskCache::ReportResultOnUIThread(
-    LoadResult result,
-    const em::CachedCloudPolicyResponse& policy) {
-  DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
-
-  switch (result) {
-    case LOAD_RESULT_NOT_FOUND:
-      break;
-    case LOAD_RESULT_READ_ERROR:
-    case LOAD_RESULT_PARSE_ERROR:
-      UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
-                                kMetricPolicyLoadFailed,
-                                policy::kMetricPolicySize);
-      break;
-    case LOAD_RESULT_SUCCESS:
-      UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
-                                kMetricPolicyLoadSucceeded,
-                                policy::kMetricPolicySize);
-      break;
-  }
-
-  if (delegate_.get())
-    delegate_->OnDiskCacheLoaded(result, policy);
-}
-
-void UserPolicyDiskCache::StoreOnFileThread(
-    const em::CachedCloudPolicyResponse& policy) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
-  std::string data;
-  if (!policy.SerializeToString(&data)) {
-    LOG(WARNING) << "Failed to serialize policy data";
-    UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
-                              kMetricPolicyStoreFailed,
-                              policy::kMetricPolicySize);
-    return;
-  }
-
-  if (!base::CreateDirectory(backing_file_path_.DirName())) {
-    LOG(WARNING) << "Failed to create directory "
-                 << backing_file_path_.DirName().value();
-    UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
-                              kMetricPolicyStoreFailed,
-                              policy::kMetricPolicySize);
-    return;
-  }
-
-  int size = data.size();
-  if (base::WriteFile(backing_file_path_, data.c_str(), size) != size) {
-    LOG(WARNING) << "Failed to write " << backing_file_path_.value();
-    UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
-                              kMetricPolicyStoreFailed,
-                              policy::kMetricPolicySize);
-    return;
-  }
-  UMA_HISTOGRAM_ENUMERATION(policy::kMetricPolicy,
-                            kMetricPolicyStoreSucceeded,
-                            policy::kMetricPolicySize);
-}
-
-}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/user_policy_disk_cache.h b/chrome/browser/chromeos/policy/user_policy_disk_cache.h
deleted file mode 100644
index 6588ea5..0000000
--- a/chrome/browser/chromeos/policy/user_policy_disk_cache.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// 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.
-
-#ifndef CHROME_BROWSER_CHROMEOS_POLICY_USER_POLICY_DISK_CACHE_H_
-#define CHROME_BROWSER_CHROMEOS_POLICY_USER_POLICY_DISK_CACHE_H_
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-
-namespace base {
-class SequencedTaskRunner;
-}
-
-namespace enterprise_management {
-class CachedCloudPolicyResponse;
-}
-
-namespace policy {
-
-// Handles the on-disk cache file used by UserPolicyCache. This class handles
-// the necessary thread switching and may outlive the associated UserPolicyCache
-// instance.
-class UserPolicyDiskCache
-    : public base::RefCountedThreadSafe<UserPolicyDiskCache> {
- public:
-  // Indicates the status of a completed load operation.
-  enum LoadResult {
-    // Policy was loaded successfully.
-    LOAD_RESULT_SUCCESS,
-    // Cache file missing.
-    LOAD_RESULT_NOT_FOUND,
-    // Failed to read cache file.
-    LOAD_RESULT_READ_ERROR,
-    // Failed to parse cache file.
-    LOAD_RESULT_PARSE_ERROR,
-  };
-
-  // Delegate interface for observing loads operations.
-  class Delegate {
-   public:
-    virtual ~Delegate();
-    virtual void OnDiskCacheLoaded(
-        LoadResult result,
-        const enterprise_management::CachedCloudPolicyResponse& policy) = 0;
-  };
-
-  UserPolicyDiskCache(
-      const base::WeakPtr<Delegate>& delegate,
-      const base::FilePath& backing_file_path,
-      scoped_refptr<base::SequencedTaskRunner> background_task_runner);
-
-  // Starts reading the policy cache from disk. Passes the read policy
-  // information back to the hosting UserPolicyCache after a successful cache
-  // load through UserPolicyCache::OnDiskCacheLoaded().
-  void Load();
-
-  // Triggers a write operation to the disk cache on the FILE thread.
-  void Store(const enterprise_management::CachedCloudPolicyResponse& policy);
-
- private:
-  friend class base::RefCountedThreadSafe<UserPolicyDiskCache>;
-  ~UserPolicyDiskCache();
-
-  // Tries to load the cache file on the FILE thread.
-  void LoadOnFileThread();
-
-  // Forwards the result to the UI thread.
-  void LoadDone(LoadResult result,
-                const enterprise_management::CachedCloudPolicyResponse& policy);
-
-  // Passes back the successfully read policy to the cache on the UI thread.
-  void ReportResultOnUIThread(
-      LoadResult result,
-      const enterprise_management::CachedCloudPolicyResponse& policy);
-
-  // Saves a policy blob on the FILE thread.
-  void StoreOnFileThread(
-      const enterprise_management::CachedCloudPolicyResponse& policy);
-
-  base::WeakPtr<Delegate> delegate_;
-  const base::FilePath backing_file_path_;
-  scoped_refptr<base::SequencedTaskRunner> origin_task_runner_;
-  scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(UserPolicyDiskCache);
-};
-
-}  // namespace policy
-
-#endif  // CHROME_BROWSER_CHROMEOS_POLICY_USER_POLICY_DISK_CACHE_H_
diff --git a/chrome/browser/component_updater/recovery_component_installer.cc b/chrome/browser/component_updater/recovery_component_installer.cc
index 9f4e58d..868e5c7e 100644
--- a/chrome/browser/component_updater/recovery_component_installer.cc
+++ b/chrome/browser/component_updater/recovery_component_installer.cc
@@ -493,8 +493,7 @@
 
 void RegisterRecoveryComponent(ComponentUpdateService* cus,
                                PrefService* prefs) {
-#if defined(GOOGLE_CHROME_BUILD)
-#if defined(OS_WIN) || defined(OS_MACOSX)
+#if !defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
   if (SimulatingElevatedRecovery()) {
     BrowserThread::PostTask(
         BrowserThread::UI,
@@ -509,8 +508,7 @@
       FROM_HERE,
       base::Bind(&RecoveryRegisterHelper, cus, prefs),
       base::TimeDelta::FromSeconds(6));
-#endif
-#endif
+#endif  // !defined(OS_CHROMEOS) && defined(GOOGLE_CHROME_BUILD)
 }
 
 void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) {
diff --git a/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc b/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc
new file mode 100644
index 0000000..a2451440
--- /dev/null
+++ b/chrome/browser/component_updater/ssl_error_assistant_component_installer.cc
@@ -0,0 +1,138 @@
+// 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 "chrome/browser/component_updater/ssl_error_assistant_component_installer.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "chrome/browser/ssl/ssl_error_handler.h"
+#include "content/public/browser/browser_thread.h"
+
+using component_updater::ComponentUpdateService;
+
+namespace {
+
+const base::FilePath::CharType kConfigBinaryPbFileName[] =
+    FILE_PATH_LITERAL("ssl_error_assistant.pb");
+
+// The SHA256 of the SubjectPublicKeyInfo used to sign the extension.
+// The extension id is: giekcmmlnklenlaomppkphknjmnnpneh
+const uint8_t kPublicKeySHA256[32] = {
+    0x68, 0x4a, 0x2c, 0xcb, 0xda, 0xb4, 0xdb, 0x0e, 0xcf, 0xfa, 0xf7,
+    0xad, 0x9c, 0xdd, 0xfd, 0x47, 0x97, 0xe4, 0x73, 0x24, 0x67, 0x93,
+    0x9c, 0xb1, 0x14, 0xcd, 0x3f, 0x54, 0x66, 0x25, 0x99, 0x3f};
+
+void LoadProtoFromDisk(const base::FilePath& pb_path) {
+  if (pb_path.empty())
+    return;
+
+  std::string binary_pb;
+  if (!base::ReadFileToString(pb_path, &binary_pb)) {
+    // The file won't exist on new installations, so this is not always an
+    // error.
+    DVLOG(1) << "Failed reading from " << pb_path.value();
+    return;
+  }
+  auto proto = base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
+  if (!proto->ParseFromString(binary_pb)) {
+    DVLOG(1) << "Failed parsing proto " << pb_path.value();
+    return;
+  }
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI, FROM_HERE,
+      base::Bind(&SSLErrorHandler::SetErrorAssistantProto,
+                 base::Passed(std::move(proto))));
+}
+
+}  // namespace
+
+namespace component_updater {
+
+bool SSLErrorAssistantComponentInstallerTraits::
+    SupportsGroupPolicyEnabledComponentUpdates() const {
+  return false;
+}
+
+bool SSLErrorAssistantComponentInstallerTraits::RequiresNetworkEncryption()
+    const {
+  return false;
+}
+
+update_client::CrxInstaller::Result
+SSLErrorAssistantComponentInstallerTraits::OnCustomInstall(
+    const base::DictionaryValue& manifest,
+    const base::FilePath& install_dir) {
+  return update_client::CrxInstaller::Result(0);  // Nothing custom here.
+}
+
+base::FilePath SSLErrorAssistantComponentInstallerTraits::GetInstalledPath(
+    const base::FilePath& base) {
+  return base.Append(kConfigBinaryPbFileName);
+}
+
+void SSLErrorAssistantComponentInstallerTraits::ComponentReady(
+    const base::Version& version,
+    const base::FilePath& install_dir,
+    std::unique_ptr<base::DictionaryValue> manifest) {
+  DVLOG(1) << "Component ready, version " << version.GetString() << " in "
+           << install_dir.value();
+
+  if (!content::BrowserThread::PostBlockingPoolTask(
+          FROM_HERE,
+          base::Bind(&LoadProtoFromDisk, GetInstalledPath(install_dir)))) {
+    NOTREACHED();
+  }
+}
+
+// Called during startup and installation before ComponentReady().
+bool SSLErrorAssistantComponentInstallerTraits::VerifyInstallation(
+    const base::DictionaryValue& manifest,
+    const base::FilePath& install_dir) const {
+  // No need to actually validate the proto here, since we'll do the checking
+  // in PopulateFromDynamicUpdate().
+  return base::PathExists(GetInstalledPath(install_dir));
+}
+
+base::FilePath
+SSLErrorAssistantComponentInstallerTraits::GetRelativeInstallDir() const {
+  return base::FilePath(FILE_PATH_LITERAL("SSLErrorAssistant"));
+}
+
+void SSLErrorAssistantComponentInstallerTraits::GetHash(
+    std::vector<uint8_t>* hash) const {
+  hash->assign(kPublicKeySHA256,
+               kPublicKeySHA256 + arraysize(kPublicKeySHA256));
+}
+
+std::string SSLErrorAssistantComponentInstallerTraits::GetName() const {
+  return "SSL Error Assistant";
+}
+
+update_client::InstallerAttributes
+SSLErrorAssistantComponentInstallerTraits::GetInstallerAttributes() const {
+  return update_client::InstallerAttributes();
+}
+
+std::vector<std::string>
+SSLErrorAssistantComponentInstallerTraits::GetMimeTypes() const {
+  return std::vector<std::string>();
+}
+
+void RegisterSSLErrorAssistantComponent(ComponentUpdateService* cus,
+                                        const base::FilePath& user_data_dir) {
+  DVLOG(1) << "Registering SSL Error Assistant component.";
+
+  std::unique_ptr<ComponentInstallerTraits> traits(
+      new SSLErrorAssistantComponentInstallerTraits());
+  // |cus| takes ownership of |installer|.
+  DefaultComponentInstaller* installer =
+      new DefaultComponentInstaller(std::move(traits));
+  installer->Register(cus, base::Closure());
+}
+
+}  // namespace component_updater
diff --git a/chrome/browser/component_updater/ssl_error_assistant_component_installer.h b/chrome/browser/component_updater/ssl_error_assistant_component_installer.h
new file mode 100644
index 0000000..88cfd07f
--- /dev/null
+++ b/chrome/browser/component_updater/ssl_error_assistant_component_installer.h
@@ -0,0 +1,54 @@
+// 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 CHROME_BROWSER_COMPONENT_UPDATER_SSL_ERROR_ASSISTANT_COMPONENT_INSTALLER_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_SSL_ERROR_ASSISTANT_COMPONENT_INSTALLER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/values.h"
+#include "components/component_updater/default_component_installer.h"
+
+namespace base {
+class FilePath;
+}  // namespace base
+
+namespace component_updater {
+class SSLErrorAssistantComponentInstallerTraits
+    : public ComponentInstallerTraits {
+ public:
+  SSLErrorAssistantComponentInstallerTraits() {}
+  ~SSLErrorAssistantComponentInstallerTraits() override {}
+
+ private:
+  // ComponentInstallerTraits methods:
+  bool SupportsGroupPolicyEnabledComponentUpdates() const override;
+  bool RequiresNetworkEncryption() const override;
+  update_client::CrxInstaller::Result OnCustomInstall(
+      const base::DictionaryValue& manifest,
+      const base::FilePath& install_dir) override;
+  bool VerifyInstallation(const base::DictionaryValue& manifest,
+                          const base::FilePath& install_dir) const override;
+  void ComponentReady(const base::Version& version,
+                      const base::FilePath& install_dir,
+                      std::unique_ptr<base::DictionaryValue> manifest) override;
+  base::FilePath GetRelativeInstallDir() const override;
+  void GetHash(std::vector<uint8_t>* hash) const override;
+  std::string GetName() const override;
+  update_client::InstallerAttributes GetInstallerAttributes() const override;
+  std::vector<std::string> GetMimeTypes() const override;
+
+  static base::FilePath GetInstalledPath(const base::FilePath& base);
+
+  DISALLOW_COPY_AND_ASSIGN(SSLErrorAssistantComponentInstallerTraits);
+};
+
+void RegisterSSLErrorAssistantComponent(ComponentUpdateService* cus,
+                                        const base::FilePath& user_data_dir);
+
+}  // namespace component_updater
+
+#endif  // CHROME_BROWSER_COMPONENT_UPDATER_SSL_ERROR_ASSISTANT_COMPONENT_INSTALLER_H_
diff --git a/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc b/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
index 2f082c3..f3307b4 100644
--- a/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
+++ b/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
@@ -259,7 +259,8 @@
   EXPECT_TRUE(error().empty());
 }
 
-IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, WriteCancel) {
+// TODO(crbug.com/690717): test is flaky.
+IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, DISABLED_WriteCancel) {
   FillImageFileWithPattern('a');
   FillDeviceFileWithPattern(0);
 
@@ -305,7 +306,8 @@
   EXPECT_TRUE(error().empty());
 }
 
-IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, VerifyCancel) {
+// TODO(crbug.com/690717): test is flaky.
+IN_PROC_BROWSER_TEST_F(ImageWriterUtilityClientTest, DISABLED_VerifyCancel) {
   FillImageFileWithPattern('s');
   FillDeviceFileWithPattern('s');
 
diff --git a/chrome/browser/manifest/OWNERS b/chrome/browser/manifest/OWNERS
index da7cb5a..24b83f5d 100644
--- a/chrome/browser/manifest/OWNERS
+++ b/chrome/browser/manifest/OWNERS
@@ -1,2 +1,4 @@
 mlamouri@chromium.org
 dfalcantara@chromium.org
+
+# COMPONENT: Manifest
diff --git a/chrome/browser/media/android/router/OWNERS b/chrome/browser/media/android/router/OWNERS
index 9dcb9a6..a1a8cd5 100644
--- a/chrome/browser/media/android/router/OWNERS
+++ b/chrome/browser/media/android/router/OWNERS
@@ -1,3 +1,5 @@
 avayvod@chromium.org
 mfoltz@chromium.org
-mlamouri@chromium.org
\ No newline at end of file
+mlamouri@chromium.org
+
+# COMPONENT: Blink>PresentationAPI
diff --git a/chrome/browser/permissions/OWNERS b/chrome/browser/permissions/OWNERS
index a1538844..0011758 100644
--- a/chrome/browser/permissions/OWNERS
+++ b/chrome/browser/permissions/OWNERS
@@ -3,3 +3,5 @@
 miguelg@chromium.org
 mlamouri@chromium.org
 raymes@chromium.org
+
+# COMPONENT: Internals>Permissions
diff --git a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
index dc71dce..e9aef46 100644
--- a/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
+++ b/chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc
@@ -271,6 +271,33 @@
   DISALLOW_COPY_AND_ASSIGN(ViewTextSelectionObserver);
 };
 
+// This class observes all the text selection updates within a WebContents.
+class TextSelectionObserver : public TextInputManagerObserverBase {
+ public:
+  explicit TextSelectionObserver(content::WebContents* web_contents)
+      : TextInputManagerObserverBase(web_contents) {
+    tester()->SetOnTextSelectionChangedCallback(base::Bind(
+        &TextSelectionObserver::VerifyChange, base::Unretained(this)));
+  }
+
+  void WaitForSelectedText(const std::string& text) {
+    selected_text_ = text;
+    Wait();
+  }
+
+ private:
+  void VerifyChange() {
+    if (base::UTF16ToUTF8(tester()->GetUpdatedView()->GetSelectedText()) ==
+        selected_text_) {
+      OnSuccess();
+    }
+  }
+
+  std::string selected_text_;
+
+  DISALLOW_COPY_AND_ASSIGN(TextSelectionObserver);
+};
+
 // This class is used to verify the result of form field data requests.
 class FormFieldDataVerifier {
  public:
@@ -792,6 +819,51 @@
   }
 }
 
+// This test verifies that committing text works as expected for all the frames
+// on the page. Specifically, the test sends an IPC to the RenderWidget
+// corresponding to a focused frame with a focused <input> to commit some text.
+// Then, it verifies that the <input>'s value matches the committed text
+// (https://crbug.com/688842).
+IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
+                       ImeCommitTextForAllFrames) {
+  CreateIframePage("a(b,c(a))");
+  std::vector<content::RenderFrameHost*> frames{
+      GetFrame(IndexVector{}), GetFrame(IndexVector{0}),
+      GetFrame(IndexVector{1}), GetFrame(IndexVector{1, 0})};
+  for (size_t i = 0; i < frames.size(); ++i)
+    AddInputFieldToFrame(frames[i], "text", "", true);
+
+  std::vector<std::string> sample_text{"main", "child_b", "child_c", "child_a"};
+  ASSERT_EQ(frames.size(), sample_text.size());
+
+  // An observer of all text selection updates within a WebContents.
+  TextSelectionObserver observer(active_contents());
+  for (size_t index = 0; index < frames.size(); ++index) {
+    // Focus the input and listen to 'input' event inside the frame. When the
+    // event fires, select all the text inside the input. This will trigger a
+    // selection update on the browser side.
+    ASSERT_TRUE(ExecuteScript(frames[index],
+                              "window.focus();"
+                              "var input = document.querySelector('input');"
+                              "input.focus();"
+                              "window.addEventListener('input', function(e) {"
+                              "  input.select();"
+                              "});"))
+        << "Could not run script in frame with index:" << index;
+
+    // Commit some text for this frame.
+    content::SendImeCommitTextToWidget(
+        frames[index]->GetView()->GetRenderWidgetHost(),
+        base::UTF8ToUTF16(sample_text[index]),
+        std::vector<ui::CompositionUnderline>(), gfx::Range(), 0);
+
+    // Verify that the text we committed is now selected by listening to a
+    // selection update from a RenderWidgetHostView which has the expected
+    // selected text.
+    observer.WaitForSelectedText(sample_text[index]);
+  }
+}
+
 // TODO(ekaramad): Some of the following tests should be active on Android as
 // well. Enable them when the corresponding feature is implemented for Android
 // (https://crbug.com/602723).
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_page.html b/chrome/browser/resources/settings/date_time_page/date_time_page.html
index a85f2b62..345c0ed9 100644
--- a/chrome/browser/resources/settings/date_time_page/date_time_page.html
+++ b/chrome/browser/resources/settings/date_time_page/date_time_page.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
 <link rel="import" href="../controls/settings_dropdown_menu.html">
@@ -17,6 +18,7 @@
         --md-select-width: 400px;
       }
 
+      paper-toggle-button,
       cr-policy-pref-indicator {
         -webkit-margin-start: var(--checkbox-spacing);
       }
@@ -29,8 +31,8 @@
     </div>
     <div class="settings-box continuation">
       <div class="start">$i18n{timeZoneGeolocation}</div>
-      <template is="dom-if" if="[[hasTimeZoneAutoDetectPolicy_]]">
-        <cr-policy-pref-indicator pref="[[timeZonePolicyPref_]]">
+      <template is="dom-if" if="[[hasTimeZoneAutoDetectPolicy_]]" restamp>
+        <cr-policy-pref-indicator pref="[[fakeTimeZonePolicyPref_]]">
         </cr-policy-pref-indicator>
       </template>
       <paper-toggle-button
diff --git a/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py b/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py
index 0b546657..2c69d28 100755
--- a/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py
+++ b/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py
@@ -7,6 +7,7 @@
  Convert the ASCII ssl_error_assistant.asciipb proto into a binary resource.
 """
 
+import base64
 import os
 import sys
 
@@ -29,6 +30,10 @@
   def ValidatePb(self, opts, pb):
     assert pb.version_id > 0
     assert len(pb.captive_portal_cert) > 0
+    for cert in pb.captive_portal_cert:
+      assert(cert.sha256_hash.startswith("sha256/"))
+      decoded_hash = base64.b64decode(cert.sha256_hash[len("sha256/"):])
+      assert(len(decoded_hash) == 32)
 
   def ProcessPb(self, opts, pb):
     binary_pb_str = pb.SerializeToString()
diff --git a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
index 39f0dcd..5b30648 100644
--- a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
+++ b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
@@ -63,16 +63,20 @@
 const base::FilePath::CharType kDocRoot[] =
     FILE_PATH_LITERAL("chrome/test/data");
 
-// Inject a script into the page. Used by tests that check for visible
-// password fields to wait for notifications about these
-// fields. Notifications about visible password fields are queued at the
-// end of the event loop, so waiting for a dummy script to run ensures
-// that these notifcations have been sent.
+// Inject a script into every frame in the page. Used by tests that check for
+// visible password fields to wait for notifications about these
+// fields. Notifications about visible password fields are queued at the end of
+// the event loop, so waiting for a dummy script to run ensures that these
+// notifications have been sent.
 void InjectScript(content::WebContents* contents) {
-  bool js_result = false;
-  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
-      contents, "window.domAutomationController.send(true);", &js_result));
-  EXPECT_TRUE(js_result);
+  // Any frame in the page might have a password field, so inject scripts into
+  // all of them to ensure that notifications from all of them have been sent.
+  for (const auto& frame : contents->GetAllFrames()) {
+    bool js_result = false;
+    EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+        frame, "window.domAutomationController.send(true);", &js_result));
+    EXPECT_TRUE(js_result);
+  }
 }
 
 // A WebContentsObserver useful for testing the DidChangeVisibleSecurityState()
@@ -1152,16 +1156,8 @@
 // on an HTTP page load, and when the command-line flag is set, the
 // security level is downgraded to HTTP_SHOW_WARNING, even if the iframe
 // itself was loaded over HTTPS.
-#if defined(OS_LINUX)
-// Flaky on Linux. See https://crbug.com/662485.
-#define MAYBE_PasswordSecurityLevelDowngradedFromHttpsIframe \
-  DISABLED_PasswordSecurityLevelDowngradedFromHttpsIframe
-#else
-#define MAYBE_PasswordSecurityLevelDowngradedFromHttpsIframe \
-  PasswordSecurityLevelDowngradedFromHttpsIframe
-#endif
 IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTestWithPasswordCcSwitch,
-                       MAYBE_PasswordSecurityLevelDowngradedFromHttpsIframe) {
+                       PasswordSecurityLevelDowngradedFromHttpsIframe) {
   content::WebContents* contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   ASSERT_TRUE(contents);
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index 20fc6186..47899dd 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -3937,8 +3937,7 @@
 
 // Tests that the captive portal certificate list is not used when the feature
 // is disabled via Finch. The list is passed to SSLErrorHandler via a proto.
-IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest,
-                       CaptivePortalCertificateList_Disabled) {
+IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest, Disabled) {
   base::test::ScopedFeatureList scoped_feature_list;
   // Use InitFromCommandLine instead of InitAndDisableFeature to avoid making
   // the feature public in SSLErrorHandler header.
@@ -3952,10 +3951,11 @@
   // Mark the server's cert as a captive portal cert.
   const net::HashValue server_spki_hash =
       GetSPKIHash(https_server_mismatched_.GetCertificate().get());
-  chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  auto config_proto =
+      base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       server_spki_hash.ToString());
-  SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
+  SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
 
   // Navigate to an unsafe page on the server. A normal SSL interstitial should
   // be displayed since CaptivePortalCertificateList feature is disabled.
@@ -3983,8 +3983,7 @@
 
 // Tests that the captive portal certificate list is used when the feature
 // is enabled via Finch. The list is passed to SSLErrorHandler via a proto.
-IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest,
-                       CaptivePortalCertificateList_Enabled_FromProto) {
+IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListTest, Enabled_FromProto) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitFromCommandLine(
       "CaptivePortalCertificateList" /* enabled */,
@@ -3996,10 +3995,11 @@
   // Mark the server's cert as a captive portal cert.
   const net::HashValue server_spki_hash =
       GetSPKIHash(https_server_mismatched_.GetCertificate().get());
-  chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  auto config_proto =
+      base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       server_spki_hash.ToString());
-  SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
+  SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
 
   // Navigate to an unsafe page on the server. The captive portal interstitial
   // should be displayed since CaptivePortalCertificateList feature is enabled.
@@ -4027,6 +4027,11 @@
 
 namespace {
 
+// SPKI hash to captive-portal.badssl.com leaf certificate. This
+// doesn't match the actual cert (ok_cert.pem) but is good enough for testing.
+const char kCaptivePortalSPKI[] =
+    "sha256/fjZPHewEHTrMDX3I1ecEIeoy3WFxHyGplOLv28kIbtI=";
+
 // Test class that mimics a URL request with a certificate whose SPKI hash is in
 // ssl_error_assistant.asciipb resource. A better way of testing the SPKI hashes
 // inside the resource bundle would be to serve the actual certificate from the
@@ -4049,7 +4054,7 @@
   void SetUp() override {
     CertVerifierBrowserTest::SetUp();
     SSLErrorHandler::ResetConfigForTesting();
-    SetUpCertVerifier(0, net::OK);
+    SetUpCertVerifier(0, net::OK, std::string());
   }
 
   void TearDown() override {
@@ -4058,7 +4063,9 @@
   }
 
  protected:
-  void SetUpCertVerifier(net::CertStatus cert_status, int net_result) {
+  void SetUpCertVerifier(net::CertStatus cert_status,
+                         int net_result,
+                         const std::string& spki_hash) {
     scoped_refptr<net::X509Certificate> cert(https_server_.GetCertificate());
     net::CertVerifyResult verify_result;
     verify_result.is_issued_by_known_root =
@@ -4066,13 +4073,12 @@
     verify_result.verified_cert = cert;
     verify_result.cert_status = cert_status;
 
-    // Set the SPKI hash to captive-portal.badssl.com leaf certificate. This
-    // doesn't match the actual cert (ok_cert.pem) but is good enough for
-    // testing.
-    net::HashValue hash;
-    ASSERT_TRUE(
-        hash.FromString("sha256/fjZPHewEHTrMDX3I1ecEIeoy3WFxHyGplOLv28kIbtI="));
-    verify_result.public_key_hashes.push_back(hash);
+    // Set the SPKI hash to captive-portal.badssl.com leaf certificate.
+    if (!spki_hash.empty()) {
+      net::HashValue hash;
+      ASSERT_TRUE(hash.FromString(spki_hash));
+      verify_result.public_key_hashes.push_back(hash);
+    }
     mock_cert_verifier()->AddResultForCert(cert, verify_result, net_result);
   }
 
@@ -4090,8 +4096,7 @@
 
 // Same as CaptivePortalCertificateList_Enabled_FromProto, but this time the
 // cert's SPKI hash is listed in ssl_error_assistant.asciipb.
-IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest,
-                       Enabled_FromResource) {
+IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest, Enabled) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitFromCommandLine(
       "CaptivePortalCertificateList" /* enabled */,
@@ -4101,7 +4106,7 @@
 
   // Mark the server's cert as a captive portal cert.
   SetUpCertVerifier(net::CERT_STATUS_COMMON_NAME_INVALID,
-                    net::ERR_CERT_COMMON_NAME_INVALID);
+                    net::ERR_CERT_COMMON_NAME_INVALID, kCaptivePortalSPKI);
 
   // Navigate to an unsafe page on the server. The captive portal interstitial
   // should be displayed since CaptivePortalCertificateList feature is enabled.
@@ -4126,10 +4131,131 @@
                                SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1);
 }
 
+// Same as SSLUICaptivePortalListResourceBundleTest.Enabled, but this time the
+// proto is dynamically updated (e.g. by the component updater). The dynamic
+// update should always override the proto loaded from the resource bundle.
+IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest,
+                       Enabled_DynamicUpdate) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitFromCommandLine(
+      "CaptivePortalCertificateList" /* enabled */,
+      std::string() /* disabled */);
+  ASSERT_TRUE(https_server()->Start());
+
+  // Mark the server's cert as a captive portal cert.
+  SetUpCertVerifier(net::CERT_STATUS_COMMON_NAME_INVALID,
+                    net::ERR_CERT_COMMON_NAME_INVALID, kCaptivePortalSPKI);
+
+  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
+
+  {
+    // Dynamically update the SSL error assistant config, do not include the
+    // captive portal SPKI hash.
+    auto config_proto =
+        base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
+    config_proto->add_captive_portal_cert()->set_sha256_hash(
+        "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+    config_proto->add_captive_portal_cert()->set_sha256_hash(
+        "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
+    SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
+
+    // Navigate to an unsafe page on the server. A generic SSL interstitial
+    // should be displayed because the dynamic update doesn't contain the hash
+    // of the captive portal certificate.
+    base::HistogramTester histograms;
+    SSLInterstitialTimerObserver interstitial_timer_observer(tab);
+    ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
+    content::WaitForInterstitialAttach(tab);
+
+    InterstitialPage* interstitial_page = tab->GetInterstitialPage();
+    ASSERT_EQ(SSLBlockingPage::kTypeForTesting,
+              interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
+    EXPECT_TRUE(interstitial_timer_observer.timer_started());
+
+    // Check that the histogram was recorded for an SSL interstitial.
+    histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                                2);
+    histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                                 SSLErrorHandler::HANDLE_ALL, 1);
+    histograms.ExpectBucketCount(
+        SSLErrorHandler::GetHistogramNameForTesting(),
+        SSLErrorHandler::SHOW_SSL_INTERSTITIAL_OVERRIDABLE, 1);
+  }
+  {
+    // Dynamically update the error assistant config and add the captive portal
+    // SPKI hash.
+    auto config_proto =
+        base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
+    config_proto->set_version_id(1);
+    config_proto->add_captive_portal_cert()->set_sha256_hash(
+        "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+    config_proto->add_captive_portal_cert()->set_sha256_hash(
+        "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
+    config_proto->add_captive_portal_cert()->set_sha256_hash(
+        kCaptivePortalSPKI);
+    SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
+
+    // Navigate to the unsafe page again. This time, a captive portal
+    // interstitial should be displayed.
+    base::HistogramTester histograms;
+    SSLInterstitialTimerObserver interstitial_timer_observer(tab);
+    ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
+    content::WaitForInterstitialAttach(tab);
+
+    InterstitialPage* interstitial_page = tab->GetInterstitialPage();
+    ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting,
+              interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
+    EXPECT_FALSE(interstitial_timer_observer.timer_started());
+
+    // Check that the histogram was recorded for a captive portal interstitial.
+    histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                                3);
+    histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                                 SSLErrorHandler::HANDLE_ALL, 1);
+    histograms.ExpectBucketCount(
+        SSLErrorHandler::GetHistogramNameForTesting(),
+        SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
+    histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                                 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1);
+  }
+  {
+    // Try dynamically updating the error assistant config with an empty config
+    // with the same version number. The update should be ignored, and a captive
+    // portal interstitial should still be displayed.
+    auto empty_config =
+        base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
+    empty_config->set_version_id(1);
+    SSLErrorHandler::SetErrorAssistantProto(std::move(empty_config));
+
+    // Navigate to the unsafe page again. This time, a captive portal
+    // interstitial should be displayed.
+    base::HistogramTester histograms;
+    SSLInterstitialTimerObserver interstitial_timer_observer(tab);
+    ui_test_utils::NavigateToURL(browser(), https_server()->GetURL("/"));
+    content::WaitForInterstitialAttach(tab);
+
+    InterstitialPage* interstitial_page = tab->GetInterstitialPage();
+    ASSERT_EQ(CaptivePortalBlockingPage::kTypeForTesting,
+              interstitial_page->GetDelegateForTesting()->GetTypeForTesting());
+    EXPECT_FALSE(interstitial_timer_observer.timer_started());
+
+    // Check that the histogram was recorded for a captive portal interstitial.
+    histograms.ExpectTotalCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                                3);
+    histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                                 SSLErrorHandler::HANDLE_ALL, 1);
+    histograms.ExpectBucketCount(
+        SSLErrorHandler::GetHistogramNameForTesting(),
+        SSLErrorHandler::SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE, 1);
+    histograms.ExpectBucketCount(SSLErrorHandler::GetHistogramNameForTesting(),
+                                 SSLErrorHandler::CAPTIVE_PORTAL_CERT_FOUND, 1);
+  }
+}
+
 // Same as SSLUICaptivePortalNameMismatchTest, but this time the error is
 // authority-invalid. Captive portal interstitial should not be shown.
 IN_PROC_BROWSER_TEST_F(SSLUICaptivePortalListResourceBundleTest,
-                       Enabled_FromResource_AuthorityInvalid) {
+                       Enabled_AuthorityInvalid) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitFromCommandLine(
       "CaptivePortalCertificateList" /* enabled */,
@@ -4137,12 +4263,10 @@
   ASSERT_TRUE(https_server()->Start());
   base::HistogramTester histograms;
 
-  // Set interstitial delay to zero.
-  SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta());
   // Mark the server's cert as a captive portal cert, but with an
   // authority-invalid error.
   SetUpCertVerifier(net::CERT_STATUS_AUTHORITY_INVALID,
-                    net::ERR_CERT_AUTHORITY_INVALID);
+                    net::ERR_CERT_AUTHORITY_INVALID, kCaptivePortalSPKI);
 
   // Navigate to an unsafe page on the server. CaptivePortalCertificateList
   // feature is enabled but the error is not a name mismatch, so a generic SSL
@@ -4184,10 +4308,11 @@
   // Mark the server's cert as a captive portal cert.
   const net::HashValue server_spki_hash =
       GetSPKIHash(https_server_mismatched_.GetCertificate().get());
-  chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  auto config_proto =
+      base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       server_spki_hash.ToString());
-  SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
+  SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
 
   // Navigate to an unsafe page on the server. The captive portal interstitial
   // should be displayed since CaptivePortalCertificateList feature is enabled.
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc
index 5cbf4bec..0b852f40 100644
--- a/chrome/browser/ssl/ssl_error_handler.cc
+++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -139,15 +139,16 @@
 }
 
 // Reads the SSL error assistant configuration from the resource bundle.
-bool ReadErrorAssistantProtoFromResourceBundle(
-    chrome_browser_ssl::SSLErrorAssistantConfig* proto) {
+std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
+ReadErrorAssistantProtoFromResourceBundle() {
+  auto proto = base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(proto);
   ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
   base::StringPiece data =
       bundle.GetRawDataResource(IDR_SSL_ERROR_ASSISTANT_PB);
   google::protobuf::io::ArrayInputStream stream(data.data(), data.size());
-  return proto->ParseFromZeroCopyStream(&stream);
+  return proto->ParseFromZeroCopyStream(&stream) ? std::move(proto) : nullptr;
 }
 
 std::unique_ptr<std::unordered_set<std::string>> LoadCaptivePortalCertHashes(
@@ -192,8 +193,9 @@
       network_time::NetworkTimeTracker* tracker);
 
 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
-  void SetErrorAssistantProtoForTesting(
-      const chrome_browser_ssl::SSLErrorAssistantConfig& error_assistant_proto);
+  void SetErrorAssistantProto(
+      std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
+          error_assistant_proto);
 #endif
 
  private:
@@ -210,8 +212,12 @@
   network_time::NetworkTimeTracker* network_time_tracker_ = nullptr;
 
 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
+  // Error assistant configuration.
+  std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
+      error_assistant_proto_;
+
   // SPKI hashes belonging to certs treated as captive portals. Null until the
-  // first time IsKnownCaptivePortalCert() or SetErrorAssistantProtoForTesting()
+  // first time IsKnownCaptivePortalCert() or SetErrorAssistantProto()
   // is called.
   std::unique_ptr<std::unordered_set<std::string>> captive_portal_spki_hashes_;
 #endif
@@ -248,6 +254,7 @@
   network_time_tracker_ = nullptr;
   testing_clock_ = nullptr;
 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
+  error_assistant_proto_.reset();
   captive_portal_spki_hashes_.reset();
 #endif
 }
@@ -273,20 +280,27 @@
 }
 
 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
-void ConfigSingleton::SetErrorAssistantProtoForTesting(
-    const chrome_browser_ssl::SSLErrorAssistantConfig& error_assistant_proto) {
+void ConfigSingleton::SetErrorAssistantProto(
+    std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> proto) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  DCHECK(!captive_portal_spki_hashes_);
+  CHECK(proto);
+  // Ignore versions that are not new.
+  if (error_assistant_proto_ &&
+      proto->version_id() <= error_assistant_proto_->version_id()) {
+    return;
+  }
+  error_assistant_proto_ = std::move(proto);
   captive_portal_spki_hashes_ =
-      LoadCaptivePortalCertHashes(error_assistant_proto);
+      LoadCaptivePortalCertHashes(*error_assistant_proto_);
 }
 
 bool ConfigSingleton::IsKnownCaptivePortalCert(const net::SSLInfo& ssl_info) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!captive_portal_spki_hashes_) {
-    chrome_browser_ssl::SSLErrorAssistantConfig proto;
-    CHECK(ReadErrorAssistantProtoFromResourceBundle(&proto));
-    captive_portal_spki_hashes_ = LoadCaptivePortalCertHashes(proto);
+    error_assistant_proto_ = ReadErrorAssistantProtoFromResourceBundle();
+    CHECK(error_assistant_proto_);
+    captive_portal_spki_hashes_ =
+        LoadCaptivePortalCertHashes(*error_assistant_proto_);
   }
 
   for (const net::HashValue& hash_value : ssl_info.public_key_hashes) {
@@ -496,10 +510,10 @@
   return timer_.IsRunning();
 }
 
-void SSLErrorHandler::SetErrorAssistantProtoForTesting(
-    const chrome_browser_ssl::SSLErrorAssistantConfig& config_proto) {
+void SSLErrorHandler::SetErrorAssistantProto(
+    std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> config_proto) {
 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
-  g_config.Pointer()->SetErrorAssistantProtoForTesting(config_proto);
+  g_config.Pointer()->SetErrorAssistantProto(std::move(config_proto));
 #endif
 }
 
diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h
index 80089d737..f0dc06b 100644
--- a/chrome/browser/ssl/ssl_error_handler.h
+++ b/chrome/browser/ssl/ssl_error_handler.h
@@ -110,6 +110,12 @@
       const base::Callback<void(content::CertificateRequestResultType)>&
           callback);
 
+  // Sets the binary proto for SSL error assistant. The binary proto
+  // can be downloaded by the component updater, or set by tests.
+  static void SetErrorAssistantProto(
+      std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
+          config_proto);
+
   // Testing methods.
   static void ResetConfigForTesting();
   static void SetInterstitialDelayForTesting(const base::TimeDelta& delay);
@@ -119,8 +125,6 @@
   static void SetClockForTesting(base::Clock* testing_clock);
   static void SetNetworkTimeTrackerForTesting(
       network_time::NetworkTimeTracker* tracker);
-  static void SetErrorAssistantProtoForTesting(
-      const chrome_browser_ssl::SSLErrorAssistantConfig& config_proto);
   static std::string GetHistogramNameForTesting();
   static void SetErrorAssistantConfig(
       std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
diff --git a/chrome/browser/ssl/ssl_error_handler_unittest.cc b/chrome/browser/ssl/ssl_error_handler_unittest.cc
index 97e3793b..0beff0a 100644
--- a/chrome/browser/ssl/ssl_error_handler_unittest.cc
+++ b/chrome/browser/ssl/ssl_error_handler_unittest.cc
@@ -706,22 +706,23 @@
 TEST_F(SSLErrorHandlerNameMismatchTest, CaptivePortalCertificateList_Enabled) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitFromCommandLine(
-      "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
-
-  base::HistogramTester histograms;
+      "CaptivePortalCertificateList" /* enabled */,
+      std::string() /* disabled */);
 
   EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
   EXPECT_EQ(1u, ssl_info().public_key_hashes.size());
 
-  chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  auto config_proto =
+      base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       ssl_info().public_key_hashes[0].ToString());
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
-  SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
+  SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
 
+  base::HistogramTester histograms;
   error_handler()->StartHandlingError();
 
   // Timer shouldn't start for a known captive portal certificate.
@@ -731,8 +732,8 @@
   EXPECT_TRUE(delegate()->captive_portal_interstitial_shown());
   EXPECT_FALSE(delegate()->suggested_url_checked());
 
-  // A buggy SSL error handler might have incorrectly started the timer. Run to
-  // completion to ensure the timer is expired.
+  // A buggy SSL error handler might have incorrectly started the timer. Run
+  // to completion to ensure the timer is expired.
   base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
@@ -758,25 +759,28 @@
 TEST_F(SSLErrorHandlerNameMismatchTest, CaptivePortalCertificateList_Disabled) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitFromCommandLine(
-      "" /* enabled */, "CaptivePortalCertificateList" /* disabled */);
+      std::string() /* enabled */,
+      "CaptivePortalCertificateList" /* disabled */);
 
   base::HistogramTester histograms;
 
   EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
   EXPECT_EQ(1u, ssl_info().public_key_hashes.size());
 
-  chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  auto config_proto =
+      base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       ssl_info().public_key_hashes[0].ToString());
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
-  SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
+  SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
 
   error_handler()->StartHandlingError();
 
-  // Timer shouldn't start for a known captive portal certificate.
+  // Timer should start since captive portal certificate list feature is
+  // disabled.
   EXPECT_TRUE(error_handler()->IsTimerRunningForTesting());
   EXPECT_TRUE(delegate()->captive_portal_checked());
   EXPECT_FALSE(delegate()->ssl_interstitial_shown());
@@ -809,21 +813,23 @@
        CaptivePortalCertificateList_ShouldShowGenericInterstitial) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitFromCommandLine(
-      "CaptivePortalCertificateList" /* enabled */, "" /* disabled */);
+      "CaptivePortalCertificateList" /* enabled */,
+      std::string() /* disabled */);
 
   base::HistogramTester histograms;
 
   EXPECT_FALSE(error_handler()->IsTimerRunningForTesting());
   EXPECT_EQ(1u, ssl_info().public_key_hashes.size());
 
-  chrome_browser_ssl::SSLErrorAssistantConfig config_proto;
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  auto config_proto =
+      base::MakeUnique<chrome_browser_ssl::SSLErrorAssistantConfig>();
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       "sha256/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       ssl_info().public_key_hashes[0].ToString());
-  config_proto.add_captive_portal_cert()->set_sha256_hash(
+  config_proto->add_captive_portal_cert()->set_sha256_hash(
       "sha256/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
-  SSLErrorHandler::SetErrorAssistantProtoForTesting(config_proto);
+  SSLErrorHandler::SetErrorAssistantProto(std::move(config_proto));
 
   error_handler()->StartHandlingError();
 
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos_browsertest_chromeos.cc b/chrome/browser/ui/ash/system_tray_delegate_chromeos_browsertest_chromeos.cc
index b061e67..a64eb66 100644
--- a/chrome/browser/ui/ash/system_tray_delegate_chromeos_browsertest_chromeos.cc
+++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos_browsertest_chromeos.cc
@@ -6,7 +6,6 @@
 
 #include <string>
 
-#include "ash/common/material_design/material_design_controller.h"
 #include "ash/common/system/date/date_default_view.h"
 #include "ash/common/system/date/date_view.h"
 #include "ash/common/system/date/system_info_default_view.h"
@@ -38,39 +37,22 @@
 const char kUser2[] = "user2@gmail.com";
 
 base::HourClockType GetHourType() {
-  if (ash::MaterialDesignController::IsSystemTrayMenuMaterial()) {
-    const ash::TraySystemInfo* tray_system_info =
-        ash::Shell::GetInstance()
-            ->GetPrimarySystemTray()
-            ->GetTraySystemInfoForTesting();
-    const ash::SystemInfoDefaultView* system_info_default_view =
-        tray_system_info->GetDefaultViewForTesting();
+  const ash::TraySystemInfo* tray_system_info =
+      ash::Shell::GetInstance()
+          ->GetPrimarySystemTray()
+          ->GetTraySystemInfoForTesting();
+  const ash::SystemInfoDefaultView* system_info_default_view =
+      tray_system_info->GetDefaultViewForTesting();
 
-    return system_info_default_view->GetDateView()->GetHourTypeForTesting();
-  }
-
-  const ash::TrayDate* tray_date = ash::Shell::GetInstance()
-                                       ->GetPrimarySystemTray()
-                                       ->GetTrayDateForTesting();
-  const ash::DateDefaultView* date_default_view =
-      tray_date->GetDefaultViewForTesting();
-
-  return date_default_view->GetDateView()->GetHourTypeForTesting();
+  return system_info_default_view->GetDateView()->GetHourTypeForTesting();
 }
 
 void CreateDefaultView() {
-  if (ash::MaterialDesignController::IsSystemTrayMenuMaterial()) {
-    ash::TraySystemInfo* tray_system_info = ash::Shell::GetInstance()
-                                                ->GetPrimarySystemTray()
-                                                ->GetTraySystemInfoForTesting();
-    tray_system_info->CreateDefaultViewForTesting(
-        ash::LoginStatus::NOT_LOGGED_IN);
-  } else {
-    ash::TrayDate* tray_date = ash::Shell::GetInstance()
-                                   ->GetPrimarySystemTray()
-                                   ->GetTrayDateForTesting();
-    tray_date->CreateDefaultViewForTesting(ash::LoginStatus::NOT_LOGGED_IN);
-  }
+  ash::TraySystemInfo* tray_system_info = ash::Shell::GetInstance()
+                                              ->GetPrimarySystemTray()
+                                              ->GetTraySystemInfoForTesting();
+  tray_system_info->CreateDefaultViewForTesting(
+      ash::LoginStatus::NOT_LOGGED_IN);
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 0eb187b7..9af374e 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -319,8 +319,8 @@
     toolbarController_.reset([[ToolbarController alloc]
         initWithCommands:browser->command_controller()->command_updater()
                  profile:browser->profile()
-                 browser:browser
-          resizeDelegate:self]);
+                 browser:browser]);
+    [[toolbarController_ toolbarView] setResizeDelegate:self];
     [toolbarController_ setHasToolbar:[self hasToolbar]
                        hasLocationBar:[self hasLocationBar]];
 
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
index 62b049a..0cfae25 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.h
@@ -28,6 +28,7 @@
 class Profile;
 @class ReloadButton;
 @class ToolbarButton;
+@class ToolbarView;
 @class AppMenuController;
 
 namespace content {
@@ -99,12 +100,13 @@
 
 // Initialize the toolbar and register for command updates. The profile is
 // needed for initializing the location bar. The browser is needed for
-// the toolbar model and back/forward menus. The resizeDelegate is used
-// to smoothly animate height changes for the toolbar.
+// the toolbar model and back/forward menus.
 - (id)initWithCommands:(CommandUpdater*)commands
                profile:(Profile*)profile
-               browser:(Browser*)browser
-        resizeDelegate:(id<ViewResizer>)resizeDelegate;
+               browser:(Browser*)browser;
+
+// Strongly typed controlled view.
+- (ToolbarView*)toolbarView;
 
 // Get the C++ bridge object representing the location bar for this tab.
 - (LocationBarViewMac*)locationBarBridge;
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
index 4b3458fa..2ab43137 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
@@ -117,7 +117,6 @@
 - (void)addAccessibilityDescriptions;
 - (void)initCommandStatus:(CommandUpdater*)commands;
 - (void)prefChanged:(const std::string&)prefName;
-- (ToolbarView*)toolbarView;
 // Height of the toolbar in pixels when the bookmark bar is closed.
 - (CGFloat)baseToolbarHeight;
 - (void)toolbarFrameChanged;
@@ -212,8 +211,7 @@
 
 - (id)initWithCommands:(CommandUpdater*)commands
                profile:(Profile*)profile
-               browser:(Browser*)browser
-        resizeDelegate:(id<ViewResizer>)resizeDelegate {
+               browser:(Browser*)browser {
   DCHECK(commands && profile);
   if ((self = [super initWithNibName:@"Toolbar"
                               bundle:base::mac::FrameworkBundle()])) {
@@ -236,8 +234,6 @@
     // autoreleased at about the same time as the CommandUpdater (owned by the
     // Browser), so |commands_| may not be valid any more.
 
-    [[self toolbarView] setResizeDelegate:resizeDelegate];
-
     // Start global error services now so we badge the menu correctly.
     SyncGlobalErrorFactory::GetForProfile(profile);
     RecoveryInstallGlobalErrorFactory::GetForProfile(profile);
@@ -566,6 +562,10 @@
   [self mouseMoved:event];
 }
 
+- (ToolbarView*)toolbarView {
+  return base::mac::ObjCCastStrict<ToolbarView>([self view]);
+}
+
 - (LocationBarViewMac*)locationBarBridge {
   return locationBarView_.get();
 }
@@ -665,11 +665,6 @@
     [self showLocationBarOnly];
 }
 
-// (Private) Returns the backdrop to the toolbar as a ToolbarView.
-- (ToolbarView*)toolbarView{
-  return base::mac::ObjCCastStrict<ToolbarView>([self view]);
-}
-
 - (id)customFieldEditorForObject:(id)obj {
   if (obj == locationBar_) {
     // Lazily construct Field editor, Cocoa UI code always runs on the
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
index 01b22da..ffa76aa 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
@@ -25,6 +25,7 @@
 #include "chrome/browser/ui/cocoa/test/cocoa_profile_test.h"
 #include "chrome/browser/ui/cocoa/test/scoped_force_rtl_mac.h"
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
+#import "chrome/browser/ui/cocoa/toolbar/toolbar_view_cocoa.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
 #import "chrome/browser/ui/cocoa/view_resizer_pong.h"
@@ -125,8 +126,8 @@
     bar_.reset([[TestToolbarController alloc]
         initWithCommands:browser()->command_controller()->command_updater()
                  profile:profile()
-                 browser:browser()
-          resizeDelegate:resizeDelegate_.get()]);
+                 browser:browser()]);
+    [[bar_ toolbarView] setResizeDelegate:resizeDelegate_.get()];
     EXPECT_TRUE([bar_ view]);
     NSView* parent = [test_window() contentView];
     [parent addSubview:[bar_ view]];
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index 351229a..778e5e8 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -7,7 +7,6 @@
 #include "ash/common/ash_constants.h"
 #include "ash/common/frame/caption_buttons/frame_caption_button_container_view.h"
 #include "ash/common/frame/header_painter.h"
-#include "ash/common/material_design/material_design_controller.h"
 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
 #include "ash/common/wm_shell.h"
 #include "ash/shell.h"
@@ -196,21 +195,12 @@
   EXPECT_LT(Tab::GetImmersiveHeight(),
             frame_view->header_painter_->GetHeaderHeightForPainting());
 
-  // Ending the reveal. In MD, immersive browser should have the same behavior
-  // as full screen, i.e., no light bar and having an origin of (0,0). In
-  // non-MD, immersive browser will show a 3 dp light bar on the top.
+  // Ending the reveal. Immersive browser should have the same behavior as full
+  // screen, i.e., no light bar and having an origin of (0,0).
   revealed_lock.reset();
-  if (ash::MaterialDesignController::IsImmersiveModeMaterial()) {
-    EXPECT_FALSE(frame_view->ShouldPaint());
-    EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle());
-    EXPECT_EQ(0, frame_view->header_painter_->GetHeaderHeightForPainting());
-  } else {
-    EXPECT_TRUE(frame_view->ShouldPaint());
-    EXPECT_FALSE(frame_view->caption_button_container_->visible());
-    EXPECT_TRUE(frame_view->UseImmersiveLightbarHeaderStyle());
-    EXPECT_EQ(Tab::GetImmersiveHeight(),
-              frame_view->header_painter_->GetHeaderHeightForPainting());
-  }
+  EXPECT_FALSE(frame_view->ShouldPaint());
+  EXPECT_FALSE(frame_view->UseImmersiveLightbarHeaderStyle());
+  EXPECT_EQ(0, frame_view->header_painter_->GetHeaderHeightForPainting());
 
   // Exiting immersive fullscreen should make the caption buttons and the frame
   // visible again.
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
index 9fb9c7a..bbd3db8 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h"
 
-#include "ash/common/material_design/material_design_controller.h"
 #include "ash/common/shelf/shelf_layout_manager.h"
 #include "ash/public/cpp/shelf_types.h"
 #include "ash/root_window_controller.h"
@@ -131,26 +130,15 @@
   EXPECT_TRUE(controller()->IsEnabled());
   EXPECT_FALSE(controller()->IsRevealed());
   EXPECT_FALSE(toolbar->visible());
-  // For MD, the browser's top chrome is completely offscreen with tapstrip
-  // visible.
+  // The browser's top chrome is completely offscreen with tapstrip visible.
   EXPECT_TRUE(tabstrip->visible());
-  bool is_using_material_design =
-      ash::MaterialDesignController::IsImmersiveModeMaterial();
-  if (!is_using_material_design)
-    EXPECT_TRUE(tabstrip->IsImmersiveStyle());
 
   // The tab indicators should be flush with the top of the widget.
   EXPECT_EQ(0, GetBoundsInWidget(tabstrip).y());
 
-  // In MD, since the tab strip and tool bar are both hidden in immersive
-  // fullscreen mode, the web contents should extend to the edge of screen. In
-  // non-MD, the web contents should be immediately below the tab indicators.
-  if (is_using_material_design) {
-    EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y());
-  } else {
-    EXPECT_EQ(Tab::GetImmersiveHeight(),
-              GetBoundsInWidget(contents_web_view).y());
-  }
+  // Since the tab strip and tool bar are both hidden in immersive fullscreen
+  // mode, the web contents should extend to the edge of screen.
+  EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y());
 
   // Revealing the top-of-window views should set the tab strip back to the
   // normal style and show the toolbar.
@@ -167,12 +155,7 @@
 
   // The web contents should be at the same y position as they were when the
   // top-of-window views were hidden.
-  if (is_using_material_design) {
-    EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y());
-  } else {
-    EXPECT_EQ(Tab::GetImmersiveHeight(),
-              GetBoundsInWidget(contents_web_view).y());
-  }
+  EXPECT_EQ(0, GetBoundsInWidget(contents_web_view).y());
 
   // Repeat the test for when in both immersive fullscreen and tab fullscreen.
   SetTabFullscreen(true);
@@ -257,32 +240,24 @@
   ToggleFullscreen();
   ASSERT_TRUE(controller()->IsEnabled());
   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
-  if (!ash::MaterialDesignController::IsImmersiveModeMaterial())
-    EXPECT_FALSE(controller()->ShouldHideTabIndicators());
 
   SetTabFullscreen(true);
   ASSERT_TRUE(controller()->IsEnabled());
   EXPECT_EQ(ash::SHELF_HIDDEN, shelf->visibility_state());
-  if (!ash::MaterialDesignController::IsImmersiveModeMaterial())
-    EXPECT_TRUE(controller()->ShouldHideTabIndicators());
 
   // 2) Test that exiting tab fullscreen shows the tab indicators and autohides
   // the shelf.
   SetTabFullscreen(false);
   ASSERT_TRUE(controller()->IsEnabled());
   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
-  if (!ash::MaterialDesignController::IsImmersiveModeMaterial())
-    EXPECT_FALSE(controller()->ShouldHideTabIndicators());
 
-  // 3) Test that exiting tab fullscreen and immersive fullscreen
-  // simultaneously correctly updates the shelf visibility and whether the tab
-  // indicators should be hidden.
+  // 3) Test that exiting tab fullscreen and immersive fullscreen simultaneously
+  // correctly updates the shelf visibility and whether the tab indicators
+  // should be hidden.
   SetTabFullscreen(true);
   ToggleFullscreen();
   ASSERT_FALSE(controller()->IsEnabled());
   EXPECT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state());
-  if (!ash::MaterialDesignController::IsImmersiveModeMaterial())
-    EXPECT_TRUE(controller()->ShouldHideTabIndicators());
 }
 
 // Ensure the circular tab-loading throbbers are not painted as layers in
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui_browsertest.cc b/chrome/browser/ui/webui/settings/md_settings_ui_browsertest.cc
index 9a19676..a6da5edc 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui_browsertest.cc
@@ -24,9 +24,9 @@
 using content::WaitForLoadStop;
 
 IN_PROC_BROWSER_TEST_F(MdSettingsUITest, ViewSourceDoesntCrash) {
-  NavigateToURL(browser(),
-      GURL(content::kViewSourceScheme + std::string(":") +
-           chrome::kChromeUIMdSettingsURL));
+  NavigateToURL(browser(), GURL(content::kViewSourceScheme + std::string(":") +
+                                chrome::kChromeUIMdSettingsURL +
+                                std::string("strings.js")));
 }
 
 // May not complete on memory and Windows debug bots. TODO(dbeam): investigate
diff --git a/chrome/test/data/webui/settings/date_time_page_tests.js b/chrome/test/data/webui/settings/date_time_page_tests.js
index 7cf96a7..b5889bf5 100644
--- a/chrome/test/data/webui/settings/date_time_page_tests.js
+++ b/chrome/test/data/webui/settings/date_time_page_tests.js
@@ -121,11 +121,10 @@
 
       if (policy) {
         assertTrue(!!indicator);
-        assertGT(indicator.clientHeight, 0);
+        assertTrue(indicator.isActive());
       } else {
-        // Indicator should be missing or hidden.
-        if (indicator)
-          assertEquals(0, indicator.clientHeight);
+        // Indicator should be missing dom-ifed out.
+        assertFalse(!!indicator);
       }
 
       assertEquals(policy, dateTime.$.timeZoneAutoDetect.disabled);
@@ -165,6 +164,7 @@
       var prefs = getFakePrefs();
       prefs.settings.resolve_timezone_by_geolocation.value = false;
       dateTime = initializeDateTime(prefs, false);
+      cr.webUIListenerCallback('time-zone-auto-detect-policy', false);
 
       assertTrue(dateTimePageReadyCalled);
       assertTrue(getTimeZonesCalled);
@@ -186,6 +186,7 @@
       var prefs = getFakePrefs();
       prefs.settings.resolve_timezone_by_geolocation.value = false;
       dateTime = initializeDateTime(prefs, true, true);
+      cr.webUIListenerCallback('time-zone-auto-detect-policy', true, true);
 
       assertTrue(dateTimePageReadyCalled);
       assertFalse(getTimeZonesCalled);
@@ -214,6 +215,7 @@
     test('auto-detect forced off', function(done) {
       var prefs = getFakePrefs();
       dateTime = initializeDateTime(prefs, true, false);
+      cr.webUIListenerCallback('time-zone-auto-detect-policy', true, false);
 
       assertTrue(dateTimePageReadyCalled);
       assertTrue(getTimeZonesCalled);
@@ -238,6 +240,7 @@
 
     test('set date and time button', function() {
       dateTime = initializeDateTime(getFakePrefs(), false);
+      cr.webUIListenerCallback('time-zone-auto-detect-policy', false);
 
       var showSetDateTimeUICalled = false;
       registerMessageCallback('showSetDateTimeUI', null, function() {
diff --git a/chromecast/media/base/supported_codec_profile_levels_memo.cc b/chromecast/media/base/supported_codec_profile_levels_memo.cc
index 8af25951..be1e9a7 100644
--- a/chromecast/media/base/supported_codec_profile_levels_memo.cc
+++ b/chromecast/media/base/supported_codec_profile_levels_memo.cc
@@ -10,7 +10,8 @@
 namespace chromecast {
 namespace media {
 
-SupportedCodecProfileLevelsMemo::SupportedCodecProfileLevelsMemo() {}
+SupportedCodecProfileLevelsMemo::SupportedCodecProfileLevelsMemo()
+    : codec_profile_levels_(), thread_checker_() {}
 
 SupportedCodecProfileLevelsMemo::~SupportedCodecProfileLevelsMemo() {}
 
diff --git a/chromecast/media/cdm/BUILD.gn b/chromecast/media/cdm/BUILD.gn
index b2dd9da..2cf3f96f 100644
--- a/chromecast/media/cdm/BUILD.gn
+++ b/chromecast/media/cdm/BUILD.gn
@@ -6,29 +6,37 @@
 
 source_set("cdm") {
   sources = [
-    "cast_cdm.cc",
-    "cast_cdm.h",
-    "cast_cdm_context.cc",
-    "cast_cdm_context.h",
-    "cast_cdm_factory.cc",
-    "cast_cdm_factory.h",
     "chromecast_init_data.cc",
     "chromecast_init_data.h",
   ]
 
   deps = [
     "//base",
-    "//chromecast/media/base",
     "//media",
-    "//url:url",
   ]
 
-  if (is_android && use_playready) {
+  if (!is_android) {
     sources += [
-      "playready_drm_delegate_android.cc",
-      "playready_drm_delegate_android.h",
+      "cast_cdm.cc",
+      "cast_cdm.h",
+      "cast_cdm_context.cc",
+      "cast_cdm_context.h",
+      "cast_cdm_factory.cc",
+      "cast_cdm_factory.h",
     ]
 
-    deps += [ "//media/base/android" ]
+    deps += [
+      "//chromecast/media/base",
+      "//url:url",
+    ]
+  } else {
+    if (use_playready) {
+      sources += [
+        "playready_drm_delegate_android.cc",
+        "playready_drm_delegate_android.h",
+      ]
+
+      deps += [ "//media/base/android" ]
+    }
   }
 }
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index 0cedd5ff..c3d11d5 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -15,6 +15,7 @@
 
 #include "base/allocator/allocator_check.h"
 #include "base/allocator/allocator_extension.h"
+#include "base/allocator/features.h"
 #include "base/at_exit.h"
 #include "base/base_switches.h"
 #include "base/command_line.h"
@@ -86,6 +87,7 @@
 #include "ui/base/win/atl_module.h"
 #include "ui/display/win/dpi.h"
 #elif defined(OS_MACOSX)
+#include "base/allocator/allocator_shim.h"
 #include "base/mac/scoped_nsautorelease_pool.h"
 #include "base/power_monitor/power_monitor_device_source.h"
 #include "content/app/mac/mac_init.h"
@@ -515,6 +517,9 @@
     env_mode_ = params.env_mode;
 #endif
 
+#if defined(OS_MACOSX) && BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM)
+    base::allocator::InitializeAllocatorShim();
+#endif
     base::EnableTerminationOnOutOfMemory();
 #if defined(OS_WIN)
     base::win::RegisterInvalidParamHandler();
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index c4efd39..ca778a4 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -13,6 +13,7 @@
 #include "base/strings/string_util.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/common/accessibility_messages.h"
+#include "ui/accessibility/ax_role_properties.h"
 #include "ui/accessibility/ax_text_utils.h"
 #include "ui/accessibility/platform/ax_platform_node.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -348,7 +349,7 @@
   return GetData().location;
 }
 
-int32_t BrowserAccessibility::GetRole() const {
+ui::AXRole BrowserAccessibility::GetRole() const {
   return GetData().role;
 }
 
@@ -1026,29 +1027,7 @@
 }
 
 bool BrowserAccessibility::IsClickable() const {
-  switch (GetRole()) {
-    case ui::AX_ROLE_BUTTON:
-    case ui::AX_ROLE_CHECK_BOX:
-    case ui::AX_ROLE_COLOR_WELL:
-    case ui::AX_ROLE_DISCLOSURE_TRIANGLE:
-    case ui::AX_ROLE_IMAGE_MAP_LINK:
-    case ui::AX_ROLE_LINK:
-    case ui::AX_ROLE_LIST_BOX_OPTION:
-    case ui::AX_ROLE_MENU_BUTTON:
-    case ui::AX_ROLE_MENU_ITEM:
-    case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
-    case ui::AX_ROLE_MENU_ITEM_RADIO:
-    case ui::AX_ROLE_MENU_LIST_OPTION:
-    case ui::AX_ROLE_MENU_LIST_POPUP:
-    case ui::AX_ROLE_POP_UP_BUTTON:
-    case ui::AX_ROLE_RADIO_BUTTON:
-    case ui::AX_ROLE_SWITCH:
-    case ui::AX_ROLE_TAB:
-    case ui::AX_ROLE_TOGGLE_BUTTON:
-      return true;
-    default:
-      return false;
-  }
+  return ui::IsRoleClickable(GetRole());
 }
 
 bool BrowserAccessibility::IsControl() const {
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index 78047df..4a785e5 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -235,7 +235,7 @@
   int32_t GetId() const;
   const ui::AXNodeData& GetData() const;
   gfx::RectF GetLocation() const;
-  int32_t GetRole() const;
+  ui::AXRole GetRole() const;
   int32_t GetState() const;
 
   typedef base::StringPairs HtmlAttributes;
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc
index 934cdc6..78fc0709 100644
--- a/content/browser/accessibility/browser_accessibility_android.cc
+++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -432,6 +432,8 @@
       case ui::AX_ROLE_POP_UP_BUTTON:
       case ui::AX_ROLE_TEXT_FIELD:
         return value;
+      default:
+        break;
     }
   }
 
@@ -534,6 +536,9 @@
     case ui::AX_ROLE_ARTICLE:
       message_id = IDS_AX_ROLE_ARTICLE;
       break;
+    case ui::AX_ROLE_AUDIO:
+      message_id = IDS_AX_MEDIA_AUDIO_ELEMENT;
+      break;
     case ui::AX_ROLE_BANNER:
       message_id = IDS_AX_ROLE_BANNER;
       break;
@@ -624,6 +629,9 @@
     case ui::AX_ROLE_EMBEDDED_OBJECT:
       message_id = IDS_AX_ROLE_EMBEDDED_OBJECT;
       break;
+    case ui::AX_ROLE_FEED:
+      // TODO(patricialor): Add a string for this role.
+      break;
     case ui::AX_ROLE_FIGCAPTION:
       // No role description.
       break;
@@ -716,6 +724,9 @@
     case ui::AX_ROLE_MATH:
       message_id = IDS_AX_ROLE_MATH;
       break;
+    case ui::AX_ROLE_MENU:
+      message_id = IDS_AX_ROLE_MENU;
+      break;
     case ui::AX_ROLE_MENU_BAR:
       message_id = IDS_AX_ROLE_MENU_BAR;
       break;
@@ -737,9 +748,6 @@
     case ui::AX_ROLE_MENU_LIST_POPUP:
       // No role description.
       break;
-    case ui::AX_ROLE_MENU:
-      message_id = IDS_AX_ROLE_MENU;
-      break;
     case ui::AX_ROLE_METER:
       message_id = IDS_AX_ROLE_METER;
       break;
@@ -854,6 +862,9 @@
     case ui::AX_ROLE_TABLE:
       message_id = IDS_AX_ROLE_TABLE;
       break;
+    case ui::AX_ROLE_TERM:
+      message_id = IDS_AX_ROLE_DESCRIPTION_TERM;
+      break;
     case ui::AX_ROLE_TEXT_FIELD:
       // No role description.
       break;
@@ -887,6 +898,9 @@
     case ui::AX_ROLE_TOOLTIP:
       message_id = IDS_AX_ROLE_TOOLTIP;
       break;
+    case ui::AX_ROLE_VIDEO:
+      message_id = IDS_AX_MEDIA_VIDEO_ELEMENT;
+      break;
     case ui::AX_ROLE_WEB_AREA:
       // No role description.
       break;
@@ -896,6 +910,9 @@
     case ui::AX_ROLE_WINDOW:
       // No role description.
       break;
+    case ui::AX_ROLE_NONE:
+      // No role description.
+      break;
   }
 
   if (message_id != -1)
@@ -923,6 +940,8 @@
         index = static_cast<int>(((value - min)) * 100 / (max - min));
       break;
     }
+    default:
+      break;
   }
   return index;
 }
@@ -942,6 +961,8 @@
       // in RangeMin and RangeMax.
       count = 100;
       break;
+    default:
+      break;
   }
   return count;
 }
diff --git a/content/browser/manifest/OWNERS b/content/browser/manifest/OWNERS
index 2d28246..edb36297 100644
--- a/content/browser/manifest/OWNERS
+++ b/content/browser/manifest/OWNERS
@@ -1 +1,3 @@
 mlamouri@chromium.org
+
+# COMPONENT: Manifest
diff --git a/content/browser/media/session/OWNERS b/content/browser/media/session/OWNERS
index dc2593f..3fdb002 100644
--- a/content/browser/media/session/OWNERS
+++ b/content/browser/media/session/OWNERS
@@ -1,2 +1,4 @@
 avayvod@chromium.org
 mlamouri@chromium.org
+
+# COMPONENT: Internals>Media>Session
diff --git a/content/browser/media/session/media_session_impl_visibility_browsertest.cc b/content/browser/media/session/media_session_impl_visibility_browsertest.cc
index a6840e57..77032875 100644
--- a/content/browser/media/session/media_session_impl_visibility_browsertest.cc
+++ b/content/browser/media/session/media_session_impl_visibility_browsertest.cc
@@ -33,11 +33,6 @@
   DISABLED,
 };
 
-enum class Pipeline {
-  WMPI,
-  WMPA,
-};
-
 enum class BackgroundResuming {
   ENABLED,
   DISABLED,
@@ -65,8 +60,7 @@
 // media_session_visibility_browsertest_instances.cc for examples.
 class MediaSessionImplVisibilityBrowserTest
     : public ContentBrowserTest,
-      public ::testing::WithParamInterface<
-          std::tr1::tuple<VisibilityTestData, Pipeline>> {
+      public ::testing::WithParamInterface<VisibilityTestData> {
  public:
   MediaSessionImplVisibilityBrowserTest() = default;
   ~MediaSessionImplVisibilityBrowserTest() override = default;
@@ -116,12 +110,6 @@
     else
       command_line->AppendSwitch(switches::kDisableMediaSuspend);
 
-#if defined(OS_ANDROID)
-    Pipeline pipeline = std::tr1::get<1>(GetParam());
-    if (pipeline == Pipeline::WMPA)
-      command_line->AppendSwitch(switches::kDisableUnifiedMediaPipeline);
-#endif  // defined(OS_ANDROID)
-
     if (params.background_resuming == BackgroundResuming::ENABLED) {
       command_line->AppendSwitchASCII(switches::kEnableFeatures,
                                       media::kResumeBackgroundVideo.name);
@@ -132,7 +120,7 @@
   }
 
   const VisibilityTestData& GetVisibilityTestData() {
-    return std::tr1::get<0>(GetParam());
+    return GetParam();
   }
 
   void StartPlayer() {
@@ -276,14 +264,6 @@
      SessionState::SUSPENDED, SessionState::SUSPENDED},
 };
 
-Pipeline kPipelines[] = {
-    Pipeline::WMPI,
-#if defined(OS_ANDROID)
-// Disabling WMPA tests because of https://crbug.com/646312
-// Pipeline::WMPA,
-#endif  // defined(OS_ANDROID)
-};
-
 }  // anonymous namespace
 
 IN_PROC_BROWSER_TEST_P(MediaSessionImplVisibilityBrowserTest, TestEntryPoint) {
@@ -295,7 +275,6 @@
 
 INSTANTIATE_TEST_CASE_P(MediaSessionImplVisibilityBrowserTestInstances,
                         MediaSessionImplVisibilityBrowserTest,
-                        ::testing::Combine(::testing::ValuesIn(kTestParams),
-                                           ::testing::ValuesIn(kPipelines)));
+                        ::testing::ValuesIn(kTestParams));
 
 }  // namespace content
diff --git a/content/browser/permissions/OWNERS b/content/browser/permissions/OWNERS
index fee7a6d..8338bc51 100644
--- a/content/browser/permissions/OWNERS
+++ b/content/browser/permissions/OWNERS
@@ -1,2 +1,4 @@
 mlamouri@chromium.org
-timvolodine@chromium.org
\ No newline at end of file
+timvolodine@chromium.org
+
+# COMPONENT: Internals>Permissions
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 8e4112c0..17896da 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1872,7 +1872,6 @@
     switches::kDisableLowEndDeviceMode,
 #if defined(OS_ANDROID)
     switches::kDisableMediaSessionAPI,
-    switches::kDisableUnifiedMediaPipeline,
     switches::kEnableContentIntentDetection,
     switches::kRendererWaitForJavaDebugger,
 #endif
diff --git a/content/common/feature_policy/OWNERS b/content/common/feature_policy/OWNERS
index ffdb022..ab9c820 100644
--- a/content/common/feature_policy/OWNERS
+++ b/content/common/feature_policy/OWNERS
@@ -3,3 +3,5 @@
 
 iclelland@chromium.org
 raymes@chromium.org
+
+# COMPONENT: Blink>FeaturePolicy
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index bdf2af3..648b0c86 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -1171,9 +1171,9 @@
                        RenderWidgetHostViewChildFrame* target_view) {
   if (!container_surface_id.is_valid())
     return false;
-  for (cc::SurfaceId id :
-       GetSurfaceManager()->GetSurfaceForId(container_surface_id)
-           ->referenced_surfaces()) {
+  for (cc::SurfaceId id : GetSurfaceManager()
+                              ->GetSurfaceForId(container_surface_id)
+                              ->active_referenced_surfaces()) {
     if (id == target_view->SurfaceIdForTesting() ||
         ContainsSurfaceId(id, target_view))
       return true;
diff --git a/content/public/test/text_input_test_utils.cc b/content/public/test/text_input_test_utils.cc
index e37b5dc..5405d908 100644
--- a/content/public/test/text_input_test_utils.cc
+++ b/content/public/test/text_input_test_utils.cc
@@ -71,7 +71,7 @@
     on_text_selection_changed_callback_ = callback;
   }
 
-  const RenderWidgetHostView* GetUpdatedView() const { return updated_view_; }
+  RenderWidgetHostView* GetUpdatedView() const { return updated_view_; }
 
   bool text_input_state_changed() const { return text_input_state_changed_; }
 
@@ -262,6 +262,23 @@
       ->has_focused_editable_element();
 }
 
+void SendImeCommitTextToWidget(
+    RenderWidgetHost* rwh,
+    const base::string16& text,
+    const std::vector<ui::CompositionUnderline>& underlines,
+    const gfx::Range& replacement_range,
+    int relative_cursor_pos) {
+  std::vector<blink::WebCompositionUnderline> web_composition_underlines;
+  for (auto underline : underlines) {
+    web_composition_underlines.emplace_back(
+        static_cast<int>(underline.start_offset),
+        static_cast<int>(underline.end_offset), underline.color,
+        underline.thick, underline.background_color);
+  }
+  RenderWidgetHostImpl::From(rwh)->ImeCommitText(
+      text, web_composition_underlines, replacement_range, relative_cursor_pos);
+}
+
 size_t GetRegisteredViewsCountFromTextInputManager(WebContents* web_contents) {
   std::unordered_set<RenderWidgetHostView*> views;
   TextInputManager* manager =
@@ -325,7 +342,7 @@
   return observer_->text_input_manager()->active_view_for_testing();
 }
 
-const RenderWidgetHostView* TextInputManagerTester::GetUpdatedView() {
+RenderWidgetHostView* TextInputManagerTester::GetUpdatedView() {
   return observer_->GetUpdatedView();
 }
 
diff --git a/content/public/test/text_input_test_utils.h b/content/public/test/text_input_test_utils.h
index 6c0c2bc..f377320 100644
--- a/content/public/test/text_input_test_utils.h
+++ b/content/public/test/text_input_test_utils.h
@@ -25,6 +25,10 @@
 class Range;
 }
 
+namespace ui {
+struct CompositionUnderline;
+}
+
 namespace content {
 
 class MessageLoopRunner;
@@ -65,6 +69,15 @@
 // Returns true if |frame| has a focused editable element.
 bool DoesFrameHaveFocusedEditableElement(RenderFrameHost* frame);
 
+// Sends a request to the RenderWidget corresponding to |rwh| to commit the
+// given |text|.
+void SendImeCommitTextToWidget(
+    RenderWidgetHost* rwh,
+    const base::string16& text,
+    const std::vector<ui::CompositionUnderline>& underlines,
+    const gfx::Range& replacement_range,
+    int relative_cursor_pos);
+
 // This class provides the necessary API for accessing the state of and also
 // observing the TextInputManager for WebContents.
 class TextInputManagerTester {
@@ -106,7 +119,7 @@
 
   // Returns the RenderWidgetHostView which has most recently updated any of its
   // state (e.g., TextInputState or otherwise).
-  const RenderWidgetHostView* GetUpdatedView();
+  RenderWidgetHostView* GetUpdatedView();
 
   // Returns true if a call to TextInputManager::UpdateTextInputState has led
   // to a change in TextInputState (since the time the observer has been
diff --git a/content/renderer/manifest/OWNERS b/content/renderer/manifest/OWNERS
index 2d28246..edb36297 100644
--- a/content/renderer/manifest/OWNERS
+++ b/content/renderer/manifest/OWNERS
@@ -1 +1,3 @@
 mlamouri@chromium.org
+
+# COMPONENT: Manifest
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index effe56d..7143f42 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -822,55 +822,38 @@
 }
 
 #if defined(OS_ANDROID)
-// Returns true if WMPI should be used for playback, false otherwise.
+// Returns true if the MediaPlayerRenderer should be used for playback, false
+// if the default renderer should be used instead.
 //
 // Note that HLS and MP4 detection are pre-redirect and path-based. It is
 // possible to load such a URL and find different content.
-bool UseWebMediaPlayerImpl(const GURL& url) {
-  // Always use WMPI for playing blob URLs since WMPA could never play them very
-  // well and no longer has support for MSE based playbacks.
+bool UseMediaPlayerRenderer(const GURL& url) {
+  // Always use the default renderer for playing blob URLs.
   if (url.SchemeIsBlob())
-    return true;
-
-  // WMPI does not support HLS.
-  if (media::MediaCodecUtil::IsHLSURL(url))
     return false;
 
-  // Don't use WMPI if the container likely contains a codec we can't decode in
-  // software and platform decoders are not available.
+  // The default renderer does not support HLS.
+  if (media::MediaCodecUtil::IsHLSURL(url))
+    return true;
+
+  // Don't use the default renderer if the container likely contains a codec we
+  // can't decode in software and platform decoders are not available.
   if (!media::HasPlatformDecoderSupport()) {
     // Assume that "mp4" means H264. Without platform decoder support we cannot
     // play it with Spitzer, thus fall back to AVDA. http://crbug.com/642988.
     if (base::ToLowerASCII(url.spec()).find("mp4") != std::string::npos)
-      return false;
+      return true;
   }
 
   // Indicates if the Android MediaPlayer should be used instead of WMPI.
   if (GetContentClient()->renderer()->ShouldUseMediaPlayerForURL(url))
-    return false;
+    return true;
 
-  // Otherwise enable WMPI if indicated via experiment or command line.
-  return media::IsUnifiedMediaPipelineEnabled();
+  // Otherwise, use the default renderer.
+  return false;
 }
 #endif  // defined(OS_ANDROID)
 
-#if defined(ENABLE_MOJO_CDM)
-// Returns whether mojo CDM should be used at runtime. Note that even when mojo
-// CDM is enabled at compile time (ENABLE_MOJO_CDM is defined), there are cases
-// where we want to choose other CDM types. For example, in the future, when we
-// experiment mojo CDM on desktop, we will choose between mojo CDM and pepper
-// CDM at runtime.
-// TODO(xhwang): Remove this when we use mojo CDM for all remote CDM cases by
-// default.
-bool UseMojoCdm() {
-#if defined(OS_ANDROID)
-  return media::IsUnifiedMediaPipelineEnabled();
-#else
-  return true;
-#endif
-}
-#endif  // defined(ENABLE_MOJO_CDM)
-
 double ConvertToBlinkTime(const base::TimeTicks& time_ticks) {
   return (time_ticks - base::TimeTicks()).InSecondsF();
 }
@@ -2821,7 +2804,7 @@
       new RenderMediaLog(url::Origin(frame_->getSecurityOrigin()).GetURL()));
 
 #if defined(OS_ANDROID)
-  if (UseWebMediaPlayerImpl(url) && !media_surface_manager_)
+  if (!UseMediaPlayerRenderer(url) && !media_surface_manager_)
     media_surface_manager_ = new RendererSurfaceViewManager(this);
 #endif  // defined(OS_ANDROID)
 
@@ -2860,7 +2843,7 @@
 
   bool use_fallback_path = false;
 #if defined(OS_ANDROID)
-  use_fallback_path = !UseWebMediaPlayerImpl(url);
+  use_fallback_path = UseMediaPlayerRenderer(url);
 #endif  // defined(OS_ANDROID)
 
   std::unique_ptr<media::RendererFactory> media_renderer_factory;
@@ -6562,10 +6545,8 @@
     return cdm_factory_.get();
 
 #if defined(ENABLE_MOJO_CDM)
-  if (UseMojoCdm()) {
-    cdm_factory_.reset(new media::MojoCdmFactory(GetMediaInterfaceProvider()));
-    return cdm_factory_.get();
-  }
+  cdm_factory_.reset(new media::MojoCdmFactory(GetMediaInterfaceProvider()));
+  return cdm_factory_.get();
 #endif  //  defined(ENABLE_MOJO_CDM)
 
 #if BUILDFLAG(ENABLE_PEPPER_CDMS)
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 5b60ffc..36baa7d 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -670,7 +670,13 @@
 }
 
 bool RenderWidget::ShouldHandleImeEvents() const {
-  return GetWebWidget() && GetWebWidget()->isWebFrameWidget() && has_focus_;
+  // TODO(ekaramad): We track page focus in all RenderViews on the page but the
+  // RenderWidgets corresponding to OOPIFs do not get the update. For now, this
+  // method returns true when the RenderWidget is for an OOPIF, i.e., IME events
+  // will be processed regardless of page focus. We should revisit this after
+  // page focus for OOPIFs has been fully resolved (https://crbug.com/689777).
+  return GetWebWidget() && GetWebWidget()->isWebFrameWidget() &&
+         (has_focus_ || for_oopif_);
 }
 
 void RenderWidget::SetWindowRectSynchronously(
@@ -1605,7 +1611,7 @@
 #endif
   ImeEventGuard guard(this);
   input_handler_->set_handling_input_event(true);
-  if (auto* controller = GetInputMethodController())
+  if (auto* controller = GetInputMethodController()) {
     controller->commitText(
         WebString::fromUTF16(text),
         WebVector<WebCompositionUnderline>(underlines),
@@ -1613,6 +1619,7 @@
             ? WebRange(replacement_range.start(), replacement_range.length())
             : WebRange(),
         relative_cursor_pos);
+  }
   input_handler_->set_handling_input_event(false);
   UpdateCompositionInfo(false /* not an immediate request */);
 }
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
index 5343b92..819a198 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
@@ -18,7 +18,7 @@
 namespace content {
 
 // Implements fake adapters with named mock data set for use in tests as a
-// result of layout tests calling testRunner.setBluetoothMockDataSet.
+// result of layout tests calling testRunner.setBluetoothFakeAdapter.
 
 // An adapter named 'FooAdapter' in
 // https://webbluetoothcg.github.io/web-bluetooth/tests/ is provided by a
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc
index 1f0ac7bb..3fe409fdd 100644
--- a/content/test/content_browser_test_utils_internal.cc
+++ b/content/test/content_browser_test_utils_internal.cc
@@ -324,7 +324,7 @@
     return false;
   for (cc::SurfaceId id :
        surface_manager_->GetSurfaceForId(container_surface_id)
-           ->referenced_surfaces()) {
+           ->active_referenced_surfaces()) {
     if (id == target_view_->SurfaceIdForTesting() || ContainsSurfaceId(id))
       return true;
   }
diff --git a/extensions/browser/api/cast_channel/logger.h b/extensions/browser/api/cast_channel/logger.h
index 3453f541..905ba8b8 100644
--- a/extensions/browser/api/cast_channel/logger.h
+++ b/extensions/browser/api/cast_channel/logger.h
@@ -35,7 +35,7 @@
 
 // Logs information of each channel and sockets and exports the log as
 // a blob. Logger is done on the IO thread.
-class Logger : public base::RefCounted<Logger> {
+class Logger : public base::RefCountedThreadSafe<Logger> {
  public:
   // |clock|: Clock used for generating timestamps for the events. Owned by
   // this class.
@@ -92,7 +92,7 @@
   LastErrors GetLastErrors(int channel_id) const;
 
  private:
-  friend class base::RefCounted<Logger>;
+  friend class base::RefCountedThreadSafe<Logger>;
   ~Logger();
 
   struct AggregatedSocketEventLog {
diff --git a/extensions/renderer/argument_spec.cc b/extensions/renderer/argument_spec.cc
index c1e2132..b72e3c0 100644
--- a/extensions/renderer/argument_spec.cc
+++ b/extensions/renderer/argument_spec.cc
@@ -75,6 +75,8 @@
     type_ = ArgumentType::BOOLEAN;
   else if (type_string == "string")
     type_ = ArgumentType::STRING;
+  else if (type_string == "binary")
+    type_ = ArgumentType::BINARY;
   else if (type_string == "any")
     type_ = ArgumentType::ANY;
   else if (type_string == "function")
@@ -172,6 +174,13 @@
     v8::Local<v8::Array> array = value.As<v8::Array>();
     return ParseArgumentToArray(context, array, refs, out_value, error);
   }
+  if (type_ == ArgumentType::BINARY) {
+    if (!value->IsArrayBuffer() && !value->IsArrayBufferView()) {
+      *error = "Wrong type";
+      return false;
+    }
+    return ParseArgumentToAny(context, value, out_value, error);
+  }
   if (type_ == ArgumentType::ANY)
     return ParseArgumentToAny(context, value, out_value, error);
   NOTREACHED();
@@ -317,7 +326,7 @@
                                       v8::Local<v8::Value> value,
                                       std::unique_ptr<base::Value>* out_value,
                                       std::string* error) const {
-  DCHECK_EQ(ArgumentType::ANY, type_);
+  DCHECK(type_ == ArgumentType::ANY || type_ == ArgumentType::BINARY);
   if (out_value) {
     std::unique_ptr<content::V8ValueConverter> converter(
         content::V8ValueConverter::create());
@@ -327,6 +336,8 @@
       *error = "Could not convert to 'any'.";
       return false;
     }
+    if (type_ == ArgumentType::BINARY)
+      DCHECK_EQ(base::Value::Type::BINARY, converted->GetType());
     *out_value = std::move(converted);
   }
   return true;
diff --git a/extensions/renderer/argument_spec.h b/extensions/renderer/argument_spec.h
index 2f9c7ac..8145d01 100644
--- a/extensions/renderer/argument_spec.h
+++ b/extensions/renderer/argument_spec.h
@@ -29,6 +29,7 @@
   STRING,
   OBJECT,
   LIST,
+  BINARY,
   FUNCTION,
   ANY,
   REF,
diff --git a/extensions/renderer/argument_spec_unittest.cc b/extensions/renderer/argument_spec_unittest.cc
index 12a8c61..da2ac4e4 100644
--- a/extensions/renderer/argument_spec_unittest.cc
+++ b/extensions/renderer/argument_spec_unittest.cc
@@ -22,32 +22,40 @@
                      const std::string& script_source,
                      const std::string& expected_json_single_quotes) {
     RunTest(spec, script_source, true, TestResult::PASS,
-            ReplaceSingleQuotes(expected_json_single_quotes), std::string());
+            ReplaceSingleQuotes(expected_json_single_quotes), nullptr,
+            std::string());
+  }
+
+  void ExpectSuccess(const ArgumentSpec& spec,
+                     const std::string& script_source,
+                     const base::Value& expected_value) {
+    RunTest(spec, script_source, true, TestResult::PASS, std::string(),
+            &expected_value, std::string());
   }
 
   void ExpectSuccessWithNoConversion(const ArgumentSpec& spec,
                                      const std::string& script_source) {
-    RunTest(spec, script_source, false, TestResult::PASS,
-            std::string(), std::string());
+    RunTest(spec, script_source, false, TestResult::PASS, std::string(),
+            nullptr, std::string());
   }
 
   void ExpectFailure(const ArgumentSpec& spec,
                      const std::string& script_source) {
-    RunTest(spec, script_source, true, TestResult::FAIL, std::string(),
+    RunTest(spec, script_source, true, TestResult::FAIL, std::string(), nullptr,
             std::string());
   }
 
   void ExpectFailureWithNoConversion(const ArgumentSpec& spec,
                                      const std::string& script_source) {
     RunTest(spec, script_source, false, TestResult::FAIL, std::string(),
-            std::string());
+            nullptr, std::string());
   }
 
   void ExpectThrow(const ArgumentSpec& spec,
                    const std::string& script_source,
                    const std::string& expected_thrown_message) {
     RunTest(spec, script_source, true, TestResult::THROW, std::string(),
-            expected_thrown_message);
+            nullptr, expected_thrown_message);
   }
 
   void AddTypeRef(const std::string& id, std::unique_ptr<ArgumentSpec> spec) {
@@ -62,6 +70,7 @@
                bool should_convert,
                TestResult expected_result,
                const std::string& expected_json,
+               const base::Value* expected_value,
                const std::string& expected_thrown_message);
 
   ArgumentSpec::RefMap type_refs_;
@@ -74,6 +83,7 @@
                                    bool should_convert,
                                    TestResult expected_result,
                                    const std::string& expected_json,
+                                   const base::Value* expected_value,
                                    const std::string& expected_thrown_message) {
   v8::Isolate* isolate = instance_->isolate();
   v8::HandleScope handle_scope(instance_->isolate());
@@ -96,7 +106,10 @@
   ASSERT_EQ(should_throw, try_catch.HasCaught()) << script_source;
   if (should_succeed && should_convert) {
     ASSERT_TRUE(out_value);
-    EXPECT_EQ(expected_json, ValueToString(*out_value));
+    if (expected_value)
+      EXPECT_TRUE(expected_value->Equals(out_value.get())) << script_source;
+    else
+      EXPECT_EQ(expected_json, ValueToString(*out_value));
   } else if (should_throw) {
     EXPECT_EQ(expected_thrown_message,
               gin::V8ToString(try_catch.Message()->Get()));
@@ -242,6 +255,39 @@
     ExpectFailureWithNoConversion(spec, "([function() {}])");
     ExpectFailureWithNoConversion(spec, "1");
   }
+
+  {
+    const char kBinarySpec[] = "{ 'type': 'binary' }";
+    ArgumentSpec spec(*ValueFromString(kBinarySpec));
+    // Simple case: empty ArrayBuffer -> empty BinaryValue.
+    ExpectSuccess(spec, "(new ArrayBuffer())", base::BinaryValue());
+    {
+      // A non-empty (but zero-filled) ArrayBufferView.
+      const char kBuffer[] = {0, 0, 0, 0};
+      std::unique_ptr<base::BinaryValue> expected_value =
+          base::BinaryValue::CreateWithCopiedBuffer(kBuffer,
+                                                    arraysize(kBuffer));
+      ASSERT_TRUE(expected_value);
+      ExpectSuccessWithNoConversion(spec, "(new Int32Array(2))");
+    }
+    {
+      // Actual data.
+      const char kBuffer[] = {'p', 'i', 'n', 'g'};
+      std::unique_ptr<base::BinaryValue> expected_value =
+          base::BinaryValue::CreateWithCopiedBuffer(kBuffer,
+                                                    arraysize(kBuffer));
+      ASSERT_TRUE(expected_value);
+      ExpectSuccess(spec,
+                    "var b = new ArrayBuffer(4);\n"
+                    "var v = new Uint8Array(b);\n"
+                    "var s = 'ping';\n"
+                    "for (var i = 0; i < s.length; ++i)\n"
+                    "  v[i] = s.charCodeAt(i);\n"
+                    "b;",
+                    *expected_value);
+    }
+    ExpectFailure(spec, "1");
+  }
 }
 
 TEST_F(ArgumentSpecUnitTest, TypeRefsTest) {
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm
index 18cfa16..47f246b 100644
--- a/ios/chrome/browser/tabs/tab.mm
+++ b/ios/chrome/browser/tabs/tab.mm
@@ -339,10 +339,6 @@
 // Sets the favicon on the current NavigationItem.
 - (void)setFavicon:(const gfx::Image*)image;
 
-// Updates the title field of the current session entry. Also updates the
-// history database.
-- (void)updateTitle:(NSString*)title;
-
 // Saves the current title to the history database.
 - (void)saveTitleToHistoryDB;
 
@@ -998,20 +994,6 @@
       overscrollActionsControllerDelegate);
 }
 
-- (void)updateTitle:(NSString*)title {
-  web::NavigationItem* item = [self navigationManager]->GetVisibleItem();
-  if (!item)
-    return;
-  item->SetTitle(base::SysNSStringToUTF16(title));
-  // TODO(crbug.com/546218): See if this can be removed; it's not clear that
-  // other platforms send this (tab sync triggers need to be compared against
-  // upstream).
-  if (webStateImpl_)
-    webStateImpl_->GetNavigationManagerImpl().OnNavigationItemChanged();
-
-  [self saveTitleToHistoryDB];
-}
-
 - (void)saveTitleToHistoryDB {
   // If incognito, don't update history.
   if (browserState_->IsOffTheRecord())
@@ -1840,13 +1822,8 @@
 
 - (void)webController:(CRWWebController*)webController
        titleDidChange:(NSString*)title {
-  NSString* oldTitle = [self title];
-  BOOL isTitleChanged = (!oldTitle && title) || (oldTitle && !title) ||
-                        (![oldTitle isEqualToString:title]);
-  if (isTitleChanged) {
-    [self updateTitle:title];
-    [parentTabModel_ notifyTabChanged:self];
-  }
+  [self saveTitleToHistoryDB];
+  [parentTabModel_ notifyTabChanged:self];
 }
 
 - (BOOL)urlTriggersNativeAppLaunch:(const GURL&)url
diff --git a/ios/chrome/browser/tabs/tab_unittest.mm b/ios/chrome/browser/tabs/tab_unittest.mm
index c611f47d..d863fa3 100644
--- a/ios/chrome/browser/tabs/tab_unittest.mm
+++ b/ios/chrome/browser/tabs/tab_unittest.mm
@@ -242,6 +242,8 @@
     [[tab_ navigationManager]->GetSessionController() commitPendingItem];
     [[tab_ webController] webStateImpl]->OnNavigationCommitted(redirectUrl);
     [tab_ webDidStartLoadingURL:redirectUrl shouldUpdateHistory:YES];
+    base::string16 new_title = base::SysNSStringToUTF16(title);
+    [tab_ navigationManager]->GetLastCommittedItem()->SetTitle(new_title);
     [tab_ webController:mock_web_controller_ titleDidChange:title];
     [[[(id)mock_web_controller_ expect]
         andReturnValue:OCMOCK_VALUE(kPageLoaded)] loadPhase];
diff --git a/ios/web/net/cookie_notification_bridge.h b/ios/web/net/cookie_notification_bridge.h
index 0e4c1304..8e6273e 100644
--- a/ios/web/net/cookie_notification_bridge.h
+++ b/ios/web/net/cookie_notification_bridge.h
@@ -7,7 +7,6 @@
 
 #import "base/mac/scoped_nsobject.h"
 #include "base/macros.h"
-#include "base/threading/thread_checker.h"
 
 @class NSNotification;
 
@@ -22,9 +21,8 @@
   ~CookieNotificationBridge();
 
  private:
-  void OnNotificationReceived(NSNotification* notification);
+  static void OnNotificationReceived(NSNotification* notification);
   base::scoped_nsprotocol<id> observer_;
-  base::ThreadChecker thread_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(CookieNotificationBridge);
 };
diff --git a/ios/web/net/cookie_notification_bridge.mm b/ios/web/net/cookie_notification_bridge.mm
index 3c2d538..4ab27e0e 100644
--- a/ios/web/net/cookie_notification_bridge.mm
+++ b/ios/web/net/cookie_notification_bridge.mm
@@ -34,7 +34,6 @@
 
 void CookieNotificationBridge::OnNotificationReceived(
     NSNotification* notification) {
-  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK([[notification name]
       isEqualToString:NSHTTPCookieManagerCookiesChangedNotification]);
   web::WebThread::PostTask(
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 8eacd96..3132253f 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -702,6 +702,8 @@
                     stateObject:(NSString*)stateObject;
 // Sets _documentURL to newURL, and updates any relevant state information.
 - (void)setDocumentURL:(const GURL&)newURL;
+// Sets WKWebView's title to the last committed navigation item.
+- (void)updateNavigationItemTitle;
 // Returns YES if the current navigation item corresponds to a web page
 // loaded by a POST request.
 - (BOOL)isCurrentNavigationItemPOST;
@@ -1368,6 +1370,29 @@
   }
 }
 
+- (void)updateNavigationItemTitle {
+  NSString* webViewTitle = [_webView title];
+  DCHECK(webViewTitle);
+  auto& navigationManager = _webStateImpl->GetNavigationManagerImpl();
+  web::NavigationItem* item = navigationManager.GetLastCommittedItem();
+  if (!item)
+    return;
+
+  base::string16 newTitle = base::SysNSStringToUTF16(webViewTitle);
+  if (item->GetTitle() == newTitle)
+    return;
+
+  item->SetTitle(newTitle);
+  // TODO(crbug.com/546218): See if this can be removed; it's not clear that
+  // other platforms send this (tab sync triggers need to be compared against
+  // upstream).
+  navigationManager.OnNavigationItemChanged();
+
+  if ([_delegate respondsToSelector:@selector(webController:titleDidChange:)]) {
+    [_delegate webController:self titleDidChange:webViewTitle];
+  }
+}
+
 - (BOOL)isCurrentNavigationItemPOST {
   // |_pendingNavigationInfo| will be nil if the decidePolicy* delegate methods
   // were not called.
@@ -4729,9 +4754,10 @@
   DCHECK_EQ(_webView, webView);
   _certVerificationErrors->Clear();
 
-  // This is the point where the document's URL has actually changed, and
-  // pending navigation information should be applied to state information.
+  // This is the point where the document's URL and title have actually changed,
+  // and pending navigation information should be applied to state information.
   [self setDocumentURL:net::GURLWithNSURL([_webView URL])];
+  [self updateNavigationItemTitle];
 
   if (!_lastRegisteredRequestURL.is_valid() &&
       _documentURL != _lastRegisteredRequestURL) {
@@ -4969,10 +4995,12 @@
     return;
   }
 
-  if ([self.delegate
-          respondsToSelector:@selector(webController:titleDidChange:)]) {
-    DCHECK([_webView title]);
-    [self.delegate webController:self titleDidChange:[_webView title]];
+  bool hasPendingNavigation = web::WKNavigationState::COMMITTED <=
+                              [_navigationStates lastAddedNavigationState];
+  if (hasPendingNavigation) {
+    // Do not update the title if there is a navigation in progress because
+    // there is no way to tell if KVO change fired for new or previous page.
+    [self updateNavigationItemTitle];
   }
 }
 
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index 02623a57..749b5b6c 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -778,6 +778,7 @@
 TEST_F(CRWWebControllerTest, WebUrlWithTrustLevel) {
   [[[mockWebView_ stub] andReturn:[NSURL URLWithString:@(kTestURLString)]] URL];
   [[[mockWebView_ stub] andReturnBool:NO] hasOnlySecureContent];
+  [[[mockWebView_ stub] andReturn:@""] title];
 
   // Stub out the injection process.
   [[mockWebView_ stub] evaluateJavaScript:OCMOCK_ANY
diff --git a/ios/web/web_state/ui/crw_wk_navigation_states.h b/ios/web/web_state/ui/crw_wk_navigation_states.h
index 5005e40..c16fc5b 100644
--- a/ios/web/web_state/ui/crw_wk_navigation_states.h
+++ b/ios/web/web_state/ui/crw_wk_navigation_states.h
@@ -54,6 +54,10 @@
 // last added navigation. Returns nil if there are no stored navigations.
 - (WKNavigation*)lastAddedNavigation;
 
+// State of WKNavigation which was added the most recently via
+// |setState:forNavigation:|.
+- (web::WKNavigationState)lastAddedNavigationState;
+
 @end
 
 #endif  // IOS_WEB_WEB_STATE_UI_CRW_WK_NAVIGATION_STATES_H_
diff --git a/ios/web/web_state/ui/crw_wk_navigation_states.mm b/ios/web/web_state/ui/crw_wk_navigation_states.mm
index f15ebc09..59f1c6d 100644
--- a/ios/web/web_state/ui/crw_wk_navigation_states.mm
+++ b/ios/web/web_state/ui/crw_wk_navigation_states.mm
@@ -105,4 +105,13 @@
   return result;
 }
 
+- (web::WKNavigationState)lastAddedNavigationState {
+  CRWWKNavigationsStateRecord* lastAddedRecord = nil;
+  WKNavigation* lastAddedNavigation = [self lastAddedNavigation];
+  if (lastAddedNavigation)
+    lastAddedRecord = [_records objectForKey:lastAddedNavigation];
+
+  return lastAddedRecord.state;
+}
+
 @end
diff --git a/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm b/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm
index 61c4409..5b3eb4f3 100644
--- a/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm
+++ b/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm
@@ -31,14 +31,22 @@
   // navigation_1 is the only navigation and it is the latest.
   [states_ setState:WKNavigationState::REQUESTED forNavigation:navigation1_];
   EXPECT_EQ(navigation1_, [states_ lastAddedNavigation]);
+  EXPECT_EQ(WKNavigationState::REQUESTED, [states_ lastAddedNavigationState]);
 
   // navigation_2 is added later and hence the latest.
   [states_ setState:WKNavigationState::REQUESTED forNavigation:navigation2_];
   EXPECT_EQ(navigation2_, [states_ lastAddedNavigation]);
+  EXPECT_EQ(WKNavigationState::REQUESTED, [states_ lastAddedNavigationState]);
 
   // Updating state for existing navigation does not make it the latest.
   [states_ setState:WKNavigationState::STARTED forNavigation:navigation1_];
   EXPECT_EQ(navigation2_, [states_ lastAddedNavigation]);
+  EXPECT_EQ(WKNavigationState::REQUESTED, [states_ lastAddedNavigationState]);
+
+  // navigation_2 is still the latest.
+  [states_ setState:WKNavigationState::STARTED forNavigation:navigation2_];
+  EXPECT_EQ(navigation2_, [states_ lastAddedNavigation]);
+  EXPECT_EQ(WKNavigationState::STARTED, [states_ lastAddedNavigationState]);
 }
 
 }  // namespace web
diff --git a/media/base/key_systems.cc b/media/base/key_systems.cc
index ef16ad6..6e3d4072 100644
--- a/media/base/key_systems.cc
+++ b/media/base/key_systems.cc
@@ -443,7 +443,7 @@
 #if defined(OS_ANDROID)
     // Ensure that the renderer can access the decoders necessary to use the
     // key system.
-    if (!properties->UseAesDecryptor() && !ArePlatformDecodersAvailable()) {
+    if (!properties->UseAesDecryptor() && !HasPlatformDecoderSupport()) {
       DLOG(WARNING) << properties->GetKeySystemName() << " not registered";
       continue;
     }
diff --git a/media/base/media.cc b/media/base/media.cc
index 38daf05b..8e9e719 100644
--- a/media/base/media.cc
+++ b/media/base/media.cc
@@ -86,17 +86,6 @@
 bool PlatformHasOpusSupport() {
   return base::android::BuildInfo::GetInstance()->sdk_int() >= 21;
 }
-
-bool IsUnifiedMediaPipelineEnabled() {
-  return !base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kDisableUnifiedMediaPipeline);
-}
-
-bool ArePlatformDecodersAvailable() {
-  return IsUnifiedMediaPipelineEnabled()
-             ? HasPlatformDecoderSupport()
-             : MediaCodecUtil::IsMediaCodecAvailable();
-}
 #endif
 
 }  // namespace media
diff --git a/media/base/media.h b/media/base/media.h
index 7dd8765..f6a53f4 100644
--- a/media/base/media.h
+++ b/media/base/media.h
@@ -27,20 +27,6 @@
 // Indicates if the platform supports Opus. Determined *ONLY* by the platform
 // version, so does not guarantee that either can actually be played.
 MEDIA_EXPORT bool PlatformHasOpusSupport();
-
-// Returns true if the unified media pipeline is enabled; the pipeline may still
-// not work for all codecs if HasPlatformDecoderSupport() is false. Please see
-// MimeUtil for an exhaustive listing of supported codecs.
-//
-// TODO(dalecurtis): These methods are temporary and should be removed once the
-// unified media pipeline is supported everywhere.  http://crbug.com/580626.
-MEDIA_EXPORT bool IsUnifiedMediaPipelineEnabled();
-
-// Returns whether the platform decoders are available for use.
-// This includes decoders being available on the platform and accessible, such
-// as via the GPU process. Should only be used for actual decoders
-// (e.g. MediaCodec) and not full-featured players (e.g. MediaPlayer).
-MEDIA_EXPORT bool ArePlatformDecodersAvailable();
 #endif
 
 }  // namespace media
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 49dc7289..b94cfcf 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -22,12 +22,6 @@
 const char kReportVp9AsAnUnsupportedMimeType[] =
     "report-vp9-as-an-unsupported-mime-type";
 
-#if defined(OS_ANDROID)
-// Use WebMediaPlayerAndroid instead of WebMediaPlayerImpl. This is a temporary
-// switch for holding back the new unified media pipeline.
-const char kDisableUnifiedMediaPipeline[] = "disable-unified-media-pipeline";
-#endif
-
 #if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_SOLARIS)
 // The Alsa device to use when opening an audio input stream.
 const char kAlsaInputDevice[] = "alsa-input-device";
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index c3e184b9..0f1d43aa 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -24,10 +24,6 @@
 
 MEDIA_EXPORT extern const char kReportVp9AsAnUnsupportedMimeType[];
 
-#if defined(OS_ANDROID)
-MEDIA_EXPORT extern const char kDisableUnifiedMediaPipeline[];
-#endif
-
 #if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_SOLARIS)
 MEDIA_EXPORT extern const char kAlsaInputDevice[];
 MEDIA_EXPORT extern const char kAlsaOutputDevice[];
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc
index cb5dfd55..f4cf92f 100644
--- a/media/base/mime_util_internal.cc
+++ b/media/base/mime_util_internal.cc
@@ -122,12 +122,10 @@
 
 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) {
 #if defined(OS_ANDROID)
-  platform_info_.is_unified_media_pipeline_enabled =
-      IsUnifiedMediaPipelineEnabled();
   // When the unified media pipeline is enabled, we need support for both GPU
   // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport().
   // When the Android pipeline is used, we only need access to MediaCodec.
-  platform_info_.has_platform_decoders = ArePlatformDecodersAvailable();
+  platform_info_.has_platform_decoders = HasPlatformDecoderSupport();
   platform_info_.has_platform_vp8_decoder =
       MediaCodecUtil::IsVp8DecoderAvailable();
   platform_info_.has_platform_vp9_decoder =
@@ -464,11 +462,11 @@
                          base::CompareCase::SENSITIVE)) {
         return false;
       }
-      return !is_encrypted && platform_info.is_unified_media_pipeline_enabled;
+      return !is_encrypted;
 
     case OPUS:
       // If clear, the unified pipeline can always decode Opus in software.
-      if (!is_encrypted && platform_info.is_unified_media_pipeline_enabled)
+      if (!is_encrypted)
         return true;
 
       // Otherwise, platform support is required.
@@ -491,10 +489,8 @@
 
     case HEVC:
 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
-      if (platform_info.is_unified_media_pipeline_enabled &&
-          !platform_info.has_platform_decoders) {
+      if (!platform_info.has_platform_decoders)
         return false;
-      }
 
 #if defined(OS_ANDROID)
       // HEVC/H.265 is supported in Lollipop+ (API Level 21), according to
@@ -509,7 +505,7 @@
 
     case VP8:
       // If clear, the unified pipeline can always decode VP8 in software.
-      if (!is_encrypted && platform_info.is_unified_media_pipeline_enabled)
+      if (!is_encrypted)
         return true;
 
       if (is_encrypted)
@@ -526,7 +522,7 @@
       }
 
       // If clear, the unified pipeline can always decode VP9 in software.
-      if (!is_encrypted && platform_info.is_unified_media_pipeline_enabled)
+      if (!is_encrypted)
         return true;
 
       if (!platform_info.has_platform_vp9_decoder)
diff --git a/media/base/mime_util_internal.h b/media/base/mime_util_internal.h
index b6d98f44..e853b89 100644
--- a/media/base/mime_util_internal.h
+++ b/media/base/mime_util_internal.h
@@ -52,8 +52,6 @@
     bool has_platform_vp8_decoder = false;
     bool has_platform_vp9_decoder = false;
     bool supports_opus = false;
-
-    bool is_unified_media_pipeline_enabled = false;
   };
 
   // See mime_util.h for more information on these methods.
diff --git a/media/base/mime_util_unittest.cc b/media/base/mime_util_unittest.cc
index 8d630dc..99be40b5 100644
--- a/media/base/mime_util_unittest.cc
+++ b/media/base/mime_util_unittest.cc
@@ -57,7 +57,6 @@
   MAKE_TEST_VECTOR(has_platform_vp8_decoder);
   MAKE_TEST_VECTOR(has_platform_vp9_decoder);
   MAKE_TEST_VECTOR(supports_opus);
-  MAKE_TEST_VECTOR(is_unified_media_pipeline_enabled);
 #undef MAKE_TEST_VECTOR
 
   MimeUtil::PlatformInfo info;
@@ -71,20 +70,16 @@
     RUN_TEST_VECTOR(has_platform_vp8_decoder) {
       RUN_TEST_VECTOR(has_platform_vp9_decoder) {
         RUN_TEST_VECTOR(supports_opus) {
-          RUN_TEST_VECTOR(is_unified_media_pipeline_enabled) {
-            for (int codec = MimeUtil::INVALID_CODEC;
-                 codec <= MimeUtil::LAST_CODEC; ++codec) {
-              SCOPED_TRACE(base::StringPrintf(
-                  "has_platform_decoders=%d, has_platform_vp8_decoder=%d, "
-                  "supports_opus=%d, "
-                  "has_platform_vp9_decoder=%d, "
-                  "is_unified_media_pipeline_enabled=%d, "
-                  "codec=%d",
-                  info.has_platform_decoders, info.has_platform_vp8_decoder,
-                  info.supports_opus, info.has_platform_vp9_decoder,
-                  info.is_unified_media_pipeline_enabled, codec));
-              test_func(info, static_cast<MimeUtil::Codec>(codec));
-            }
+          for (int codec = MimeUtil::INVALID_CODEC;
+               codec <= MimeUtil::LAST_CODEC; ++codec) {
+            SCOPED_TRACE(base::StringPrintf(
+                "has_platform_decoders=%d, has_platform_vp8_decoder=%d, "
+                "supports_opus=%d, "
+                "has_platform_vp9_decoder=%d, "
+                "codec=%d",
+                info.has_platform_decoders, info.has_platform_vp8_decoder,
+                info.supports_opus, info.has_platform_vp9_decoder, codec));
+            test_func(info, static_cast<MimeUtil::Codec>(codec));
           }
         }
       }
@@ -100,7 +95,6 @@
   states_to_vary.has_platform_vp8_decoder = true;
   states_to_vary.has_platform_vp9_decoder = true;
   states_to_vary.supports_opus = true;
-  states_to_vary.is_unified_media_pipeline_enabled = true;
   states_to_vary.has_platform_decoders = true;
   return states_to_vary;
 }
@@ -294,76 +288,10 @@
       });
 }
 
-TEST(IsCodecSupportedOnPlatformTest, ClearCodecBehaviorWithAndroidPipeline) {
-  // Vary all parameters except |is_unified_media_pipeline_enabled|.
+TEST(IsCodecSupportedOnPlatformTest, ClearCodecBehavior) {
   MimeUtil::PlatformInfo states_to_vary = VaryAllFields();
-  states_to_vary.is_unified_media_pipeline_enabled = false;
 
-  // Disable the unified pipeline.
   MimeUtil::PlatformInfo test_states;
-  test_states.is_unified_media_pipeline_enabled = false;
-
-  RunCodecSupportTest(
-      states_to_vary, test_states,
-      [](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) {
-        const bool result = MimeUtil::IsCodecSupportedOnPlatform(
-            codec, kTestMimeType, false, info);
-        switch (codec) {
-          // These codecs are never supported by the Android platform.
-          case MimeUtil::INVALID_CODEC:
-          case MimeUtil::AC3:
-          case MimeUtil::EAC3:
-          case MimeUtil::MPEG2_AAC:
-          case MimeUtil::THEORA:
-            EXPECT_FALSE(result);
-            break;
-
-          // These codecs are always available via MediaPlayer.
-          case MimeUtil::FLAC:
-          case MimeUtil::PCM:
-          case MimeUtil::MP3:
-          case MimeUtil::MPEG4_AAC:
-          case MimeUtil::VORBIS:
-          case MimeUtil::H264:
-          case MimeUtil::VP8:
-            EXPECT_TRUE(result);
-            break;
-
-          // The remaining codecs depend on the platform version.
-          case MimeUtil::OPUS:
-            EXPECT_EQ(info.supports_opus, result);
-            break;
-
-          case MimeUtil::VP9:
-            // MediaPlayer only supports VP9 in WebM.
-            EXPECT_FALSE(result);
-            break;
-
-          case MimeUtil::HEVC:
-            EXPECT_EQ(HasHevcSupport(), result);
-            break;
-        }
-      });
-
-  // Verify vp9 support in WebM.
-  RunCodecSupportTest(
-      states_to_vary, test_states,
-      [](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) {
-        const bool result = MimeUtil::IsCodecSupportedOnPlatform(
-            codec, "video/webm", true, info);
-        if (codec == MimeUtil::VP9)
-          EXPECT_EQ(info.has_platform_vp9_decoder, result);
-      });
-}
-
-TEST(IsCodecSupportedOnPlatformTest, ClearCodecBehaviorWithUnifiedPipeline) {
-  // Vary all parameters except |is_unified_media_pipeline_enabled|.
-  MimeUtil::PlatformInfo states_to_vary = VaryAllFields();
-  states_to_vary.is_unified_media_pipeline_enabled = false;
-
-  // Enable the unified pipeline.
-  MimeUtil::PlatformInfo test_states;
-  test_states.is_unified_media_pipeline_enabled = true;
 
   RunCodecSupportTest(
       states_to_vary, test_states,
@@ -412,9 +340,8 @@
   RunCodecSupportTest(
       states_to_vary, test_states,
       [](const MimeUtil::PlatformInfo& info, MimeUtil::Codec codec) {
-        EXPECT_EQ(info.is_unified_media_pipeline_enabled,
-                  MimeUtil::IsCodecSupportedOnPlatform(
-                      MimeUtil::OPUS, "audio/ogg", false, info));
+        EXPECT_TRUE(MimeUtil::IsCodecSupportedOnPlatform(
+            MimeUtil::OPUS, "audio/ogg", false, info));
       });
 }
 
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index c34175f..abab8e86 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -810,6 +810,8 @@
 crbug.com/526463 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Failure Timeout ]
 crbug.com/526463 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Failure Timeout ]
 
+crbug.com/526463 virtual/wheelscrolllatching/fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Timeout Pass ]
+
 crbug.com/410974 virtual/threaded/fast/scroll-behavior/scroll-customization/scrollstate-basic.html [ Pass Failure ]
 crbug.com/410974 virtual/threaded/fast/scroll-behavior/scroll-customization/scrollstate-consume-deltas.html [ Pass Failure ]
 crbug.com/410974 virtual/threaded/fast/scroll-behavior/scroll-customization/scrollstate-consume-deltas-throw.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/add-listener-after-promise.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/add-listener-after-promise.html
index a1e7c69..9fae0051 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/add-listener-after-promise.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/add-listener-after-promise.html
@@ -14,7 +14,7 @@
     .then(characteristic => {
       return characteristic.startNotifications()
         .then(() => new Promise(resolve => {
-          let event_listener = e => {
+          let event_listener = () => {
             characteristic.removeEventListener(
               'characteristicvaluechanged', event_listener);
             resolve();
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/notification-after-disconnection.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/notification-after-disconnection.html
index 591596a..c2671353 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/notification-after-disconnection.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/notification-after-disconnection.html
@@ -8,7 +8,7 @@
   // The iframe we create will subscribe to notifications and will ensure
   // that the browser keeps receiving notifications even after this frame's
   // device disconnects.
-  let iframe_connected = new Promise(resolve => {
+  let iframe_connected = new Promise((resolve, reject) => {
     window.onmessage = messageEvent => {
       if (messageEvent.data === 'Ready') {
         let iframe = document.querySelector('iframe');
@@ -41,7 +41,7 @@
         .then(characteristic => characteristic.startNotifications())
         .then(characteristic => new Promise(resolve => {
           // Make sure we are receiving events.
-          let event_listener = e => {
+          let event_listener = () => {
             characteristic.removeEventListener(
               'characteristicvaluechanged', event_listener);
             resolve(characteristic);
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners-expected.txt
new file mode 100644
index 0000000..f9c92dc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners-expected.txt
@@ -0,0 +1,147 @@
+A
+B
+C
+
+Fetching listeners for depth = undefined and pierce = undefined
+{
+  "listeners": [
+    {
+      "type": "documentListener",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    }
+  ]
+}
+Fetching listeners for depth = 1 and pierce = undefined
+{
+  "listeners": [
+    {
+      "type": "documentListener",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    }
+  ]
+}
+Fetching listeners for depth = 4 and pierce = undefined
+{
+  "listeners": [
+    {
+      "type": "documentListener",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    },
+    {
+      "type": "listenerA",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    }
+  ]
+}
+Fetching listeners for depth = -1 and pierce = undefined
+{
+  "listeners": [
+    {
+      "type": "documentListener",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    },
+    {
+      "type": "listenerA",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    },
+    {
+      "type": "listenerB",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    },
+    {
+      "type": "listenerC",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    }
+  ]
+}
+Fetching listeners for depth = -1 and pierce = true
+{
+  "listeners": [
+    {
+      "type": "documentListener",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    },
+    {
+      "type": "listenerA",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    },
+    {
+      "type": "listenerB",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    },
+    {
+      "type": "listenerC",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    },
+    {
+      "type": "iframeListener",
+      "useCapture": false,
+      "passive": false,
+      "once": false,
+      "scriptId": "<string>",
+      "lineNumber": "<number>",
+      "columnNumber": "<number>"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners.html b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners.html
new file mode 100644
index 0000000..42d704d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom/dom-getEventListeners.html
@@ -0,0 +1,74 @@
+<html>
+<head>
+<script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script>
+<script>
+
+function test()
+{
+    var objectId;
+    InspectorTest.sendCommand("DOM.enable", {});
+    InspectorTest.sendCommand("Runtime.enable", {});
+    InspectorTest.sendCommand("DOMDebugger.enable", {});
+    InspectorTest.sendCommandPromise("Runtime.evaluate", { expression: "document" })
+        .then((result) => { objectId = result.result.result.objectId })
+        .then(() => dumpListeners(objectId))
+        .then(() => dumpListeners(objectId, 1))
+        .then(() => dumpListeners(objectId, 4))
+        .then(() => dumpListeners(objectId, -1))
+        .then(() => dumpListeners(objectId, -1, true))
+        .then(() => InspectorTest.completeTest());
+
+    function dumpListeners(objectId, depth, pierce) {
+        var params = {objectId : objectId};
+        if (depth)
+          params.depth = depth;
+        if (pierce !== undefined)
+          params.pierce = pierce;
+        InspectorTest.log(`Fetching listeners for depth = ${depth} and pierce = ${pierce}`);
+        return InspectorTest.sendCommandPromise("DOMDebugger.getEventListeners", params).then((result) => logResponse(result.result));
+    }
+
+    function stabilize(key, value) {
+        var unstableKeys = ["scriptId", "lineNumber", "columnNumber"];
+        if (unstableKeys.indexOf(key) !== -1)
+            return "<" + typeof(value) + ">";
+        return value;
+    }
+
+    function logResponse(response) {
+        InspectorTest.log(JSON.stringify(response, stabilize, 2));
+    }
+}
+
+</script>
+<template id="shadow-template" onclick="clickTemplate">
+<style>
+:host {
+    color: red;
+}
+</style>
+<div></div><h1>Hi from a template!</h1></div>
+</template>
+</head>
+<body class="body-class" onload="runTest()">
+    <div id="A"> A
+      <div id="B"> B
+        <div id="C"> C
+        </div>
+      </div>
+    </div>
+  
+    <iframe src="../dom/resources/iframe-with-listener.html" width="400" height="200"></iframe>
+    <div id="shadow-host"></div>
+    <script type="text/javascript">
+        var host = document.querySelector("#shadow-host").createShadowRoot();
+        var template = document.querySelector("#shadow-template");
+        host.appendChild(template.content);
+        template.remove();
+        document.getElementById("A").addEventListener("listenerA", () => {});
+        document.getElementById("B").addEventListener("listenerB", () => {});
+        document.getElementById("C").addEventListener("listenerC", () => {});
+        document.addEventListener("documentListener", () => {});
+    </script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom/resources/iframe-with-listener.html b/third_party/WebKit/LayoutTests/inspector-protocol/dom/resources/iframe-with-listener.html
new file mode 100644
index 0000000..37ae1cb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom/resources/iframe-with-listener.html
@@ -0,0 +1,10 @@
+<html>
+<body>
+<div id="iframenode">
+Hello from the iframe.
+</div>
+<script>
+document.getElementById("iframenode").addEventListener("iframeListener", () => { });
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html
index 1073b34..99ee444b 100644
--- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html
+++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html
@@ -54,7 +54,6 @@
     var view = new Timeline.EventsTimelineTreeView(UI.panels.timeline._filters, null);
     view.setModel(model);
     view.updateContents(Timeline.TimelineSelection.fromRange(model.timelineModel().minimumRecordTime(), model.timelineModel().maximumRecordTime()));
-    var filtersControl = view._filtersControl;
     function printEventMessage(event, level)
     {
         InspectorTest.addResult(" ".repeat(level) + event.args["data"].message);
@@ -70,12 +69,11 @@
     dumpRecords();
 
     InspectorTest.addResult("Filtered by 'bar':");
-    var textFilterUI = filtersControl._textFilterUI;
-    textFilterUI._internalSetValue("bar", true);
+    view._textFilterUI._internalSetValue("bar", true);
     dumpRecords();
 
     InspectorTest.addResult("Filtered by 'foo':");
-    textFilterUI._internalSetValue("foo", true);
+    view._textFilterUI._internalSetValue("foo", true);
     dumpRecords();
 
     InspectorTest.completeTest();
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
index 89392da9..0f56560 100644
--- a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
+++ b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
@@ -325,7 +325,7 @@
 class EventCatcher {
   constructor(object, event) {
     this.eventFired = false;
-    let event_listener = e => {
+    let event_listener = () => {
       object.removeEventListener(event, event_listener);
       this.eventFired = true;
     }
diff --git a/third_party/WebKit/Source/bindings/bindings.gni b/third_party/WebKit/Source/bindings/bindings.gni
index ad3994a0..a4ba8791 100644
--- a/third_party/WebKit/Source/bindings/bindings.gni
+++ b/third_party/WebKit/Source/bindings/bindings.gni
@@ -114,8 +114,6 @@
                     "core/v8/ScriptString.h",
                     "core/v8/ScriptValue.cpp",
                     "core/v8/ScriptValue.h",
-                    "core/v8/ScriptValueSerializer.cpp",
-                    "core/v8/ScriptValueSerializer.h",
                     "core/v8/ScriptWrappable.cpp",
                     "core/v8/ScriptWrappable.h",
                     "core/v8/ScriptWrappableVisitor.cpp",
@@ -231,7 +229,6 @@
                     "core/v8/ScriptPromiseResolverTest.cpp",
                     "core/v8/ScriptPromiseTest.cpp",
                     "core/v8/ScriptStreamerTest.cpp",
-                    "core/v8/ScriptValueSerializerTest.cpp",
                     "core/v8/ScriptWrappableVisitorTest.cpp",
                     "core/v8/SerializedScriptValueTest.cpp",
                     "core/v8/ToV8Test.cpp",
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
deleted file mode 100644
index 2108dc9..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
+++ /dev/null
@@ -1,2631 +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 "bindings/core/v8/ScriptValueSerializer.h"
-
-#include "bindings/core/v8/Transferables.h"
-#include "bindings/core/v8/V8ArrayBuffer.h"
-#include "bindings/core/v8/V8ArrayBufferView.h"
-#include "bindings/core/v8/V8Blob.h"
-#include "bindings/core/v8/V8CompositorProxy.h"
-#include "bindings/core/v8/V8File.h"
-#include "bindings/core/v8/V8FileList.h"
-#include "bindings/core/v8/V8ImageBitmap.h"
-#include "bindings/core/v8/V8ImageData.h"
-#include "bindings/core/v8/V8MessagePort.h"
-#include "bindings/core/v8/V8OffscreenCanvas.h"
-#include "bindings/core/v8/V8SharedArrayBuffer.h"
-#include "core/dom/CompositorProxy.h"
-#include "core/dom/DOMDataView.h"
-#include "core/dom/DOMSharedArrayBuffer.h"
-#include "core/dom/DOMTypedArray.h"
-#include "core/fileapi/Blob.h"
-#include "core/fileapi/File.h"
-#include "core/fileapi/FileList.h"
-#include "platform/RuntimeEnabledFeatures.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebBlobInfo.h"
-#include "wtf/DateMath.h"
-#include "wtf/text/StringHash.h"
-#include "wtf/text/StringUTF8Adaptor.h"
-#include <memory>
-
-// FIXME: consider crashing in debug mode on deserialization errors
-// NOTE: be sure to change wireFormatVersion as necessary!
-
-namespace blink {
-
-namespace {
-
-// This code implements the HTML5 Structured Clone algorithm:
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-passing-of-structured-data
-
-// ZigZag encoding helps VarInt encoding stay small for negative
-// numbers with small absolute values.
-class ZigZag {
- public:
-  static uint32_t encode(uint32_t value) {
-    if (value & (1U << 31))
-      value = ((~value) << 1) + 1;
-    else
-      value <<= 1;
-    return value;
-  }
-
-  static uint32_t decode(uint32_t value) {
-    if (value & 1)
-      value = ~(value >> 1);
-    else
-      value >>= 1;
-    return value;
-  }
-
- private:
-  ZigZag();
-};
-
-const int maxDepth = 20000;
-
-bool shouldCheckForCycles(int depth) {
-  ASSERT(depth >= 0);
-  // Since we are not required to spot the cycle as soon as it
-  // happens we can check for cycles only when the current depth
-  // is a power of two.
-  return !(depth & (depth - 1));
-}
-
-// Returns true if the provided object is to be considered a 'host object', as
-// used in the HTML5 structured clone algorithm.
-bool isHostObject(v8::Local<v8::Object> object) {
-  // If the object has any internal fields, then we won't be able to serialize
-  // or deserialize them; conveniently, this is also a quick way to detect DOM
-  // wrapper objects, because the mechanism for these relies on data stored in
-  // these fields. We should catch external array data as a special case.
-  return object->InternalFieldCount();
-}
-
-}  // namespace
-
-void SerializedScriptValueWriter::writeUndefined() {
-  append(UndefinedTag);
-}
-
-void SerializedScriptValueWriter::writeNull() {
-  append(NullTag);
-}
-
-void SerializedScriptValueWriter::writeTrue() {
-  append(TrueTag);
-}
-
-void SerializedScriptValueWriter::writeFalse() {
-  append(FalseTag);
-}
-
-void SerializedScriptValueWriter::writeBooleanObject(bool value) {
-  append(value ? TrueObjectTag : FalseObjectTag);
-}
-
-void SerializedScriptValueWriter::writeRawStringBytes(
-    v8::Local<v8::String>& string) {
-  int rawLength = string->Length();
-  string->WriteOneByte(byteAt(m_position), 0, rawLength,
-                       v8StringWriteOptions());
-  m_position += rawLength;
-}
-
-void SerializedScriptValueWriter::writeUtf8String(
-    v8::Local<v8::String>& string) {
-  int utf8Length = string->Utf8Length();
-  char* buffer = reinterpret_cast<char*>(byteAt(m_position));
-  string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions());
-  m_position += utf8Length;
-}
-
-void SerializedScriptValueWriter::writeOneByteString(
-    v8::Local<v8::String>& string) {
-  int stringLength = string->Length();
-  int utf8Length = string->Utf8Length();
-  ASSERT(stringLength >= 0 && utf8Length >= 0);
-
-  append(StringTag);
-  doWriteUint32(static_cast<uint32_t>(utf8Length));
-  ensureSpace(utf8Length);
-
-  // ASCII fast path.
-  if (stringLength == utf8Length) {
-    writeRawStringBytes(string);
-  } else {
-    writeUtf8String(string);
-  }
-}
-
-void SerializedScriptValueWriter::writeUCharString(
-    v8::Local<v8::String>& string) {
-  int length = string->Length();
-  ASSERT(length >= 0);
-
-  int size = length * sizeof(UChar);
-  int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size));
-  if ((m_position + 1 + bytes) & 1)
-    append(PaddingTag);
-
-  append(StringUCharTag);
-  doWriteUint32(static_cast<uint32_t>(size));
-  ensureSpace(size);
-
-  ASSERT(!(m_position & 1));
-  uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position));
-  string->Write(buffer, 0, length, v8StringWriteOptions());
-  m_position += size;
-}
-
-void SerializedScriptValueWriter::writeStringObject(const char* data,
-                                                    int length) {
-  ASSERT(length >= 0);
-  append(StringObjectTag);
-  doWriteString(data, length);
-}
-
-void SerializedScriptValueWriter::writeWebCoreString(const String& string) {
-  // Uses UTF8 encoding so we can read it back as either V8 or
-  // WebCore string.
-  append(StringTag);
-  doWriteWebCoreString(string);
-}
-
-void SerializedScriptValueWriter::writeVersion() {
-  append(VersionTag);
-  doWriteUint32(SerializedScriptValue::wireFormatVersion);
-}
-
-void SerializedScriptValueWriter::writeInt32(int32_t value) {
-  append(Int32Tag);
-  doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
-}
-
-void SerializedScriptValueWriter::writeUint32(uint32_t value) {
-  append(Uint32Tag);
-  doWriteUint32(value);
-}
-
-void SerializedScriptValueWriter::writeDate(double numberValue) {
-  append(DateTag);
-  doWriteNumber(numberValue);
-}
-
-void SerializedScriptValueWriter::writeNumber(double number) {
-  append(NumberTag);
-  doWriteNumber(number);
-}
-
-void SerializedScriptValueWriter::writeNumberObject(double number) {
-  append(NumberObjectTag);
-  doWriteNumber(number);
-}
-
-void SerializedScriptValueWriter::writeBlob(const String& uuid,
-                                            const String& type,
-                                            unsigned long long size) {
-  append(BlobTag);
-  doWriteWebCoreString(uuid);
-  doWriteWebCoreString(type);
-  doWriteUint64(size);
-}
-
-void SerializedScriptValueWriter::writeBlobIndex(int blobIndex) {
-  ASSERT(blobIndex >= 0);
-  append(BlobIndexTag);
-  doWriteUint32(blobIndex);
-}
-
-void SerializedScriptValueWriter::writeCompositorProxy(
-    const CompositorProxy& compositorProxy) {
-  append(CompositorProxyTag);
-  doWriteUint64(compositorProxy.elementId());
-  doWriteUint32(compositorProxy.compositorMutableProperties());
-}
-
-void SerializedScriptValueWriter::writeFile(const File& file) {
-  append(FileTag);
-  doWriteFile(file);
-}
-
-void SerializedScriptValueWriter::writeFileIndex(int blobIndex) {
-  append(FileIndexTag);
-  doWriteUint32(blobIndex);
-}
-
-void SerializedScriptValueWriter::writeFileList(const FileList& fileList) {
-  append(FileListTag);
-  uint32_t length = fileList.length();
-  doWriteUint32(length);
-  for (unsigned i = 0; i < length; ++i)
-    doWriteFile(*fileList.item(i));
-}
-
-void SerializedScriptValueWriter::writeFileListIndex(
-    const Vector<int>& blobIndices) {
-  append(FileListIndexTag);
-  uint32_t length = blobIndices.size();
-  doWriteUint32(length);
-  for (unsigned i = 0; i < length; ++i)
-    doWriteUint32(blobIndices[i]);
-}
-
-void SerializedScriptValueWriter::writeArrayBuffer(
-    const DOMArrayBuffer& arrayBuffer) {
-  append(ArrayBufferTag);
-  doWriteArrayBuffer(arrayBuffer);
-}
-
-void SerializedScriptValueWriter::writeArrayBufferView(
-    const DOMArrayBufferView& arrayBufferView) {
-  append(ArrayBufferViewTag);
-#if DCHECK_IS_ON()
-  ASSERT(static_cast<const uint8_t*>(arrayBufferView.bufferBase()->data()) +
-             arrayBufferView.byteOffset() ==
-         static_cast<const uint8_t*>(arrayBufferView.baseAddress()));
-#endif
-  DOMArrayBufferView::ViewType type = arrayBufferView.type();
-
-  switch (type) {
-    case DOMArrayBufferView::TypeInt8:
-      append(ByteArrayTag);
-      break;
-    case DOMArrayBufferView::TypeUint8Clamped:
-      append(UnsignedByteClampedArrayTag);
-      break;
-    case DOMArrayBufferView::TypeUint8:
-      append(UnsignedByteArrayTag);
-      break;
-    case DOMArrayBufferView::TypeInt16:
-      append(ShortArrayTag);
-      break;
-    case DOMArrayBufferView::TypeUint16:
-      append(UnsignedShortArrayTag);
-      break;
-    case DOMArrayBufferView::TypeInt32:
-      append(IntArrayTag);
-      break;
-    case DOMArrayBufferView::TypeUint32:
-      append(UnsignedIntArrayTag);
-      break;
-    case DOMArrayBufferView::TypeFloat32:
-      append(FloatArrayTag);
-      break;
-    case DOMArrayBufferView::TypeFloat64:
-      append(DoubleArrayTag);
-      break;
-    case DOMArrayBufferView::TypeDataView:
-      append(DataViewTag);
-      break;
-    default:
-      ASSERT_NOT_REACHED();
-  }
-  doWriteUint32(arrayBufferView.byteOffset());
-  doWriteUint32(arrayBufferView.byteLength());
-}
-
-// Helper function shared by writeImageData and writeImageBitmap
-void SerializedScriptValueWriter::doWriteImageData(uint32_t width,
-                                                   uint32_t height,
-                                                   const uint8_t* pixelData,
-                                                   uint32_t pixelDataLength) {
-  doWriteUint32(width);
-  doWriteUint32(height);
-  doWriteUint32(pixelDataLength);
-  append(pixelData, pixelDataLength);
-}
-
-void SerializedScriptValueWriter::writeImageData(uint32_t width,
-                                                 uint32_t height,
-                                                 const uint8_t* pixelData,
-                                                 uint32_t pixelDataLength) {
-  append(ImageDataTag);
-  doWriteImageData(width, height, pixelData, pixelDataLength);
-}
-
-void SerializedScriptValueWriter::writeImageBitmap(uint32_t width,
-                                                   uint32_t height,
-                                                   uint32_t isOriginClean,
-                                                   uint32_t isPremultiplied,
-                                                   const uint8_t* pixelData,
-                                                   uint32_t pixelDataLength) {
-  append(ImageBitmapTag);
-  append(isOriginClean);
-  append(isPremultiplied);
-  doWriteImageData(width, height, pixelData, pixelDataLength);
-}
-
-void SerializedScriptValueWriter::writeRegExp(v8::Local<v8::String> pattern,
-                                              v8::RegExp::Flags flags) {
-  append(RegExpTag);
-  v8::String::Utf8Value patternUtf8Value(pattern);
-  doWriteString(*patternUtf8Value, patternUtf8Value.length());
-  doWriteUint32(static_cast<uint32_t>(flags));
-}
-
-void SerializedScriptValueWriter::writeTransferredMessagePort(uint32_t index) {
-  append(MessagePortTag);
-  doWriteUint32(index);
-}
-
-void SerializedScriptValueWriter::writeTransferredArrayBuffer(uint32_t index) {
-  append(ArrayBufferTransferTag);
-  doWriteUint32(index);
-}
-
-void SerializedScriptValueWriter::writeTransferredImageBitmap(uint32_t index) {
-  append(ImageBitmapTransferTag);
-  doWriteUint32(index);
-}
-
-void SerializedScriptValueWriter::writeTransferredOffscreenCanvas(
-    uint32_t width,
-    uint32_t height,
-    uint32_t canvasId,
-    uint32_t clientId,
-    uint32_t sinkId) {
-  append(OffscreenCanvasTransferTag);
-  doWriteUint32(width);
-  doWriteUint32(height);
-  doWriteUint32(canvasId);
-  doWriteUint32(clientId);
-  doWriteUint32(sinkId);
-}
-
-void SerializedScriptValueWriter::writeTransferredSharedArrayBuffer(
-    uint32_t index) {
-  ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled());
-  append(SharedArrayBufferTransferTag);
-  doWriteUint32(index);
-}
-
-void SerializedScriptValueWriter::writeObjectReference(uint32_t reference) {
-  append(ObjectReferenceTag);
-  doWriteUint32(reference);
-}
-
-void SerializedScriptValueWriter::writeObject(uint32_t numProperties) {
-  append(ObjectTag);
-  doWriteUint32(numProperties);
-}
-
-void SerializedScriptValueWriter::writeSparseArray(uint32_t numProperties,
-                                                   uint32_t length) {
-  append(SparseArrayTag);
-  doWriteUint32(numProperties);
-  doWriteUint32(length);
-}
-
-void SerializedScriptValueWriter::writeDenseArray(uint32_t numProperties,
-                                                  uint32_t length) {
-  append(DenseArrayTag);
-  doWriteUint32(numProperties);
-  doWriteUint32(length);
-}
-
-String SerializedScriptValueWriter::takeWireString() {
-  static_assert(sizeof(BufferValueType) == 2,
-                "BufferValueType should be 2 bytes");
-  fillHole();
-  ASSERT((m_position + 1) / sizeof(BufferValueType) <= m_buffer.size());
-  return String(m_buffer.data(), (m_position + 1) / sizeof(BufferValueType));
-}
-
-void SerializedScriptValueWriter::writeReferenceCount(
-    uint32_t numberOfReferences) {
-  append(ReferenceCountTag);
-  doWriteUint32(numberOfReferences);
-}
-
-void SerializedScriptValueWriter::writeGenerateFreshObject() {
-  append(GenerateFreshObjectTag);
-}
-
-void SerializedScriptValueWriter::writeGenerateFreshSparseArray(
-    uint32_t length) {
-  append(GenerateFreshSparseArrayTag);
-  doWriteUint32(length);
-}
-
-void SerializedScriptValueWriter::writeGenerateFreshDenseArray(
-    uint32_t length) {
-  append(GenerateFreshDenseArrayTag);
-  doWriteUint32(length);
-}
-
-void SerializedScriptValueWriter::writeGenerateFreshMap() {
-  append(GenerateFreshMapTag);
-}
-
-void SerializedScriptValueWriter::writeGenerateFreshSet() {
-  append(GenerateFreshSetTag);
-}
-
-void SerializedScriptValueWriter::writeMap(uint32_t length) {
-  append(MapTag);
-  doWriteUint32(length);
-}
-
-void SerializedScriptValueWriter::writeSet(uint32_t length) {
-  append(SetTag);
-  doWriteUint32(length);
-}
-
-void SerializedScriptValueWriter::doWriteFile(const File& file) {
-  doWriteWebCoreString(file.hasBackingFile() ? file.path() : "");
-  doWriteWebCoreString(file.name());
-  doWriteWebCoreString(file.webkitRelativePath());
-  doWriteWebCoreString(file.uuid());
-  doWriteWebCoreString(file.type());
-
-  // FIXME don't use 1 byte to encode a flag.
-  if (file.hasValidSnapshotMetadata()) {
-    doWriteUint32(static_cast<uint8_t>(1));
-
-    long long size;
-    double lastModifiedMS;
-    file.captureSnapshot(size, lastModifiedMS);
-    doWriteUint64(static_cast<uint64_t>(size));
-    doWriteNumber(lastModifiedMS);
-  } else {
-    doWriteUint32(static_cast<uint8_t>(0));
-  }
-
-  doWriteUint32(static_cast<uint8_t>(
-      (file.getUserVisibility() == File::IsUserVisible) ? 1 : 0));
-}
-
-void SerializedScriptValueWriter::doWriteArrayBuffer(
-    const DOMArrayBuffer& arrayBuffer) {
-  uint32_t byteLength = arrayBuffer.byteLength();
-  doWriteUint32(byteLength);
-  append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength);
-}
-
-void SerializedScriptValueWriter::doWriteString(const char* data, int length) {
-  doWriteUint32(static_cast<uint32_t>(length));
-  append(reinterpret_cast<const uint8_t*>(data), length);
-}
-
-void SerializedScriptValueWriter::doWriteWebCoreString(const String& string) {
-  StringUTF8Adaptor stringUTF8(string);
-  doWriteString(stringUTF8.data(), stringUTF8.length());
-}
-
-int SerializedScriptValueWriter::bytesNeededToWireEncode(uint32_t value) {
-  int bytes = 1;
-  while (true) {
-    value >>= SerializedScriptValue::varIntShift;
-    if (!value)
-      break;
-    ++bytes;
-  }
-
-  return bytes;
-}
-
-void SerializedScriptValueWriter::doWriteUint32(uint32_t value) {
-  doWriteUintHelper(value);
-}
-
-void SerializedScriptValueWriter::doWriteUint64(uint64_t value) {
-  doWriteUintHelper(value);
-}
-
-void SerializedScriptValueWriter::doWriteNumber(double number) {
-  append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
-}
-
-void SerializedScriptValueWriter::append(SerializationTag tag) {
-  append(static_cast<uint8_t>(tag));
-}
-
-void SerializedScriptValueWriter::append(uint8_t b) {
-  ensureSpace(1);
-  *byteAt(m_position++) = b;
-}
-
-void SerializedScriptValueWriter::append(const uint8_t* data, int length) {
-  ensureSpace(length);
-  memcpy(byteAt(m_position), data, length);
-  m_position += length;
-}
-
-void SerializedScriptValueWriter::ensureSpace(unsigned extra) {
-  static_assert(sizeof(BufferValueType) == 2,
-                "BufferValueType should be 2 bytes");
-  m_buffer.resize((m_position + extra + 1) /
-                  sizeof(BufferValueType));  // "+ 1" to round up.
-}
-
-void SerializedScriptValueWriter::fillHole() {
-  static_assert(sizeof(BufferValueType) == 2,
-                "BufferValueType should be 2 bytes");
-  // If the writer is at odd position in the buffer, then one of
-  // the bytes in the last UChar is not initialized.
-  if (m_position % 2)
-    *byteAt(m_position) = static_cast<uint8_t>(PaddingTag);
-}
-
-uint8_t* SerializedScriptValueWriter::byteAt(int position) {
-  return reinterpret_cast<uint8_t*>(m_buffer.data()) + position;
-}
-
-int SerializedScriptValueWriter::v8StringWriteOptions() {
-  return v8::String::NO_NULL_TERMINATION;
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::AbstractObjectState::serializeProperties(
-    ScriptValueSerializer& serializer) {
-  while (m_index < m_propertyNames->Length()) {
-    v8::Local<v8::Value> propertyName;
-    if (!m_propertyNames->Get(serializer.context(), m_index)
-             .ToLocal(&propertyName))
-      return serializer.handleError(
-          Status::JSException,
-          "Failed to get a property while cloning an object.", this);
-
-    bool hasProperty = false;
-    if (propertyName->IsString()) {
-      hasProperty = v8CallBoolean(composite()->HasRealNamedProperty(
-          serializer.context(), propertyName.As<v8::String>()));
-    } else if (propertyName->IsUint32()) {
-      hasProperty = v8CallBoolean(composite()->HasRealIndexedProperty(
-          serializer.context(), propertyName.As<v8::Uint32>()->Value()));
-    }
-    if (StateBase* newState = serializer.checkException(this))
-      return newState;
-    if (!hasProperty) {
-      ++m_index;
-      continue;
-    }
-
-    // |propertyName| is v8::String or v8::Uint32, so its serialization cannot
-    // be recursive.
-    serializer.doSerialize(propertyName, nullptr);
-
-    v8::Local<v8::Value> value;
-    if (!composite()->Get(serializer.context(), propertyName).ToLocal(&value))
-      return serializer.handleError(
-          Status::JSException,
-          "Failed to get a property while cloning an object.", this);
-    ++m_index;
-    ++m_numSerializedProperties;
-    // If we return early here, it's either because we have pushed a new state
-    // onto the serialization state stack or because we have encountered an
-    // error (and in both cases we are unwinding the native stack).
-    if (StateBase* newState = serializer.doSerialize(value, this))
-      return newState;
-  }
-  return objectDone(m_numSerializedProperties, serializer);
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::ObjectState::advance(
-    ScriptValueSerializer& serializer) {
-  if (m_propertyNames.IsEmpty()) {
-    if (!composite()
-             ->GetOwnPropertyNames(serializer.context())
-             .ToLocal(&m_propertyNames))
-      return serializer.checkException(this);
-  }
-  return serializeProperties(serializer);
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::ObjectState::objectDone(
-    unsigned numProperties,
-    ScriptValueSerializer& serializer) {
-  return serializer.writeObject(numProperties, this);
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::DenseArrayState::advance(
-    ScriptValueSerializer& serializer) {
-  while (m_arrayIndex < m_arrayLength) {
-    v8::Local<v8::Value> value;
-    if (!composite()
-             .As<v8::Array>()
-             ->Get(serializer.context(), m_arrayIndex)
-             .ToLocal(&value))
-      return serializer.handleError(
-          Status::JSException,
-          "Failed to get an element while cloning an array.", this);
-    m_arrayIndex++;
-    if (StateBase* newState = serializer.checkException(this))
-      return newState;
-    if (StateBase* newState = serializer.doSerialize(value, this))
-      return newState;
-  }
-  return serializeProperties(serializer);
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::DenseArrayState::objectDone(
-    unsigned numProperties,
-    ScriptValueSerializer& serializer) {
-  return serializer.writeDenseArray(numProperties, m_arrayLength, this);
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::SparseArrayState::advance(
-    ScriptValueSerializer& serializer) {
-  return serializeProperties(serializer);
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::SparseArrayState::objectDone(
-    unsigned numProperties,
-    ScriptValueSerializer& serializer) {
-  return serializer.writeSparseArray(
-      numProperties, composite().As<v8::Array>()->Length(), this);
-}
-
-template <typename T>
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::CollectionState<T>::advance(
-    ScriptValueSerializer& serializer) {
-  while (m_index < m_length) {
-    v8::Local<v8::Value> value;
-    if (!m_entries->Get(serializer.context(), m_index).ToLocal(&value))
-      return serializer.handleError(
-          Status::JSException,
-          "Failed to get an element while cloning a collection.", this);
-    m_index++;
-    if (StateBase* newState = serializer.checkException(this))
-      return newState;
-    if (StateBase* newState = serializer.doSerialize(value, this))
-      return newState;
-  }
-  return serializer.writeCollection<T>(m_length, this);
-}
-
-ScriptValueSerializer::ScriptValueSerializer(
-    SerializedScriptValueWriter& writer,
-    WebBlobInfoArray* blobInfo,
-    ScriptState* scriptState)
-    : m_scriptState(scriptState),
-      m_writer(writer),
-      m_tryCatch(scriptState->isolate()),
-      m_depth(0),
-      m_status(Status::Success),
-      m_nextObjectReference(0),
-      m_blobInfo(blobInfo),
-      m_blobDataHandles(nullptr) {
-  DCHECK(!m_tryCatch.HasCaught());
-}
-
-void ScriptValueSerializer::copyTransferables(
-    const Transferables& transferables) {
-  v8::Local<v8::Object> creationContext = m_scriptState->context()->Global();
-
-  // Also kept in separate ObjectPools, iterate and copy the contents
-  // of each kind of transferable vector.
-
-  const auto& messagePorts = transferables.messagePorts;
-  for (size_t i = 0; i < messagePorts.size(); ++i) {
-    v8::Local<v8::Object> v8MessagePort =
-        ToV8(messagePorts[i].get(), creationContext, isolate())
-            .As<v8::Object>();
-    m_transferredMessagePorts.set(v8MessagePort, i);
-  }
-
-  const auto& arrayBuffers = transferables.arrayBuffers;
-  for (size_t i = 0; i < arrayBuffers.size(); ++i) {
-    v8::Local<v8::Object> v8ArrayBuffer =
-        ToV8(arrayBuffers[i].get(), creationContext, isolate())
-            .As<v8::Object>();
-    // Coalesce multiple occurences of the same buffer to the first index.
-    if (!m_transferredArrayBuffers.contains(v8ArrayBuffer))
-      m_transferredArrayBuffers.set(v8ArrayBuffer, i);
-  }
-
-  const auto& imageBitmaps = transferables.imageBitmaps;
-  for (size_t i = 0; i < imageBitmaps.size(); ++i) {
-    v8::Local<v8::Object> v8ImageBitmap =
-        ToV8(imageBitmaps[i].get(), creationContext, isolate())
-            .As<v8::Object>();
-    if (!m_transferredImageBitmaps.contains(v8ImageBitmap))
-      m_transferredImageBitmaps.set(v8ImageBitmap, i);
-  }
-
-  const auto& offscreenCanvases = transferables.offscreenCanvases;
-  for (size_t i = 0; i < offscreenCanvases.size(); ++i) {
-    v8::Local<v8::Object> v8OffscreenCanvas =
-        ToV8(offscreenCanvases[i].get(), creationContext, isolate())
-            .As<v8::Object>();
-    if (!m_transferredOffscreenCanvas.contains(v8OffscreenCanvas))
-      m_transferredOffscreenCanvas.set(v8OffscreenCanvas, i);
-  }
-}
-
-PassRefPtr<SerializedScriptValue> ScriptValueSerializer::serialize(
-    v8::Local<v8::Value> value,
-    Transferables* transferables,
-    ExceptionState& exceptionState) {
-  DCHECK(!m_blobDataHandles);
-
-  RefPtr<SerializedScriptValue> serializedValue =
-      SerializedScriptValue::create();
-
-  m_blobDataHandles = &serializedValue->blobDataHandles();
-  if (transferables)
-    copyTransferables(*transferables);
-
-  v8::HandleScope scope(isolate());
-  writer().writeVersion();
-  StateBase* state = doSerialize(value, nullptr);
-  while (state)
-    state = state->advance(*this);
-
-  switch (m_status) {
-    case Status::Success:
-      transferData(transferables, exceptionState, serializedValue.get());
-      break;
-    case Status::InputError:
-    case Status::DataCloneError:
-      exceptionState.throwDOMException(blink::DataCloneError, m_errorMessage);
-      break;
-    case Status::JSException:
-      exceptionState.rethrowV8Exception(m_tryCatch.Exception());
-      break;
-    default:
-      NOTREACHED();
-  }
-
-  return serializedValue.release();
-}
-
-void ScriptValueSerializer::transferData(
-    Transferables* transferables,
-    ExceptionState& exceptionState,
-    SerializedScriptValue* serializedValue) {
-  serializedValue->setData(m_writer.takeWireString());
-  DCHECK(serializedValue->dataHasOneRef());
-  if (!transferables)
-    return;
-
-  serializedValue->transferImageBitmaps(isolate(), transferables->imageBitmaps,
-                                        exceptionState);
-  if (exceptionState.hadException())
-    return;
-  serializedValue->transferArrayBuffers(isolate(), transferables->arrayBuffers,
-                                        exceptionState);
-  if (exceptionState.hadException())
-    return;
-  serializedValue->transferOffscreenCanvas(
-      isolate(), transferables->offscreenCanvases, exceptionState);
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerialize(
-    v8::Local<v8::Value> value,
-    StateBase* next) {
-  m_writer.writeReferenceCount(m_nextObjectReference);
-
-  if (value.IsEmpty())
-    return handleError(Status::InputError,
-                       "The empty property cannot be cloned.", next);
-
-  uint32_t objectReference;
-  if ((value->IsObject() || value->IsDate() || value->IsRegExp()) &&
-      m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) {
-    // Note that IsObject() also detects wrappers (eg, it will catch the things
-    // that we grey and write below).
-    ASSERT(!value->IsString());
-    m_writer.writeObjectReference(objectReference);
-    return nullptr;
-  }
-  if (value->IsObject())
-    return doSerializeObject(value.As<v8::Object>(), next);
-
-  if (value->IsUndefined()) {
-    m_writer.writeUndefined();
-  } else if (value->IsNull()) {
-    m_writer.writeNull();
-  } else if (value->IsTrue()) {
-    m_writer.writeTrue();
-  } else if (value->IsFalse()) {
-    m_writer.writeFalse();
-  } else if (value->IsInt32()) {
-    m_writer.writeInt32(value.As<v8::Int32>()->Value());
-  } else if (value->IsUint32()) {
-    m_writer.writeUint32(value.As<v8::Uint32>()->Value());
-  } else if (value->IsNumber()) {
-    m_writer.writeNumber(value.As<v8::Number>()->Value());
-  } else if (value->IsString()) {
-    writeString(value);
-  } else {
-    return handleError(Status::DataCloneError, "A value could not be cloned.",
-                       next);
-  }
-  return nullptr;
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeObject(
-    v8::Local<v8::Object> object,
-    StateBase* next) {
-  DCHECK(!object.IsEmpty());
-
-  if (object->IsArrayBufferView()) {
-    return writeAndGreyArrayBufferView(object, next);
-  }
-  if (object->IsArrayBuffer()) {
-    return writeAndGreyArrayBuffer(object, next);
-  }
-  if (object->IsSharedArrayBuffer()) {
-    uint32_t index;
-    if (!m_transferredArrayBuffers.tryGet(object, &index)) {
-      return handleError(Status::DataCloneError,
-                         "A SharedArrayBuffer could not be cloned.", next);
-    }
-    return writeTransferredSharedArrayBuffer(object, index, next);
-  }
-
-  if (object->IsWebAssemblyCompiledModule())
-    return writeWasmCompiledModule(object, next);
-
-  // Transferable only objects
-  if (V8MessagePort::hasInstance(object, isolate())) {
-    uint32_t index;
-    if (!m_transferredMessagePorts.tryGet(object, &index)) {
-      return handleError(Status::DataCloneError,
-                         "A MessagePort could not be cloned.", next);
-    }
-    m_writer.writeTransferredMessagePort(index);
-    return nullptr;
-  }
-  if (V8OffscreenCanvas::hasInstance(object, isolate())) {
-    uint32_t index;
-    if (!m_transferredOffscreenCanvas.tryGet(object, &index)) {
-      return handleError(Status::DataCloneError,
-                         "A OffscreenCanvas could not be cloned.", next);
-    }
-    return writeTransferredOffscreenCanvas(object, next);
-  }
-  if (V8ImageBitmap::hasInstance(object, isolate())) {
-    return writeAndGreyImageBitmap(object, next);
-  }
-
-  greyObject(object);
-
-  if (object->IsDate()) {
-    m_writer.writeDate(object.As<v8::Date>()->ValueOf());
-    return nullptr;
-  }
-  if (object->IsStringObject()) {
-    writeStringObject(object);
-    return nullptr;
-  }
-  if (object->IsNumberObject()) {
-    writeNumberObject(object);
-    return nullptr;
-  }
-  if (object->IsBooleanObject()) {
-    writeBooleanObject(object);
-    return nullptr;
-  }
-  if (object->IsArray()) {
-    return startArrayState(object.As<v8::Array>(), next);
-  }
-  if (object->IsMap()) {
-    return startMapState(object.As<v8::Map>(), next);
-  }
-  if (object->IsSet()) {
-    return startSetState(object.As<v8::Set>(), next);
-  }
-
-  if (V8File::hasInstance(object, isolate())) {
-    return writeFile(object, next);
-  }
-  if (V8Blob::hasInstance(object, isolate())) {
-    return writeBlob(object, next);
-  }
-  if (V8FileList::hasInstance(object, isolate())) {
-    return writeFileList(object, next);
-  }
-  if (V8ImageData::hasInstance(object, isolate())) {
-    writeImageData(object);
-    return nullptr;
-  }
-  if (object->IsRegExp()) {
-    writeRegExp(object);
-    return nullptr;
-  }
-  if (V8CompositorProxy::hasInstance(object, isolate())) {
-    return writeCompositorProxy(object, next);
-  }
-
-  // Since IsNativeError is expensive, this check should always be the last
-  // check.
-  if (isHostObject(object) || object->IsCallable() || object->IsNativeError()) {
-    return handleError(Status::DataCloneError, "An object could not be cloned.",
-                       next);
-  }
-
-  return startObjectState(object, next);
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::doSerializeArrayBuffer(
-    v8::Local<v8::Value> arrayBuffer,
-    StateBase* next) {
-  return doSerialize(arrayBuffer, next);
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::checkException(
-    StateBase* state) {
-  return m_tryCatch.HasCaught() ? handleError(Status::JSException, "", state)
-                                : nullptr;
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::writeObject(
-    uint32_t numProperties,
-    StateBase* state) {
-  m_writer.writeObject(numProperties);
-  return pop(state);
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::writeSparseArray(
-    uint32_t numProperties,
-    uint32_t length,
-    StateBase* state) {
-  m_writer.writeSparseArray(numProperties, length);
-  return pop(state);
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::writeDenseArray(
-    uint32_t numProperties,
-    uint32_t length,
-    StateBase* state) {
-  m_writer.writeDenseArray(numProperties, length);
-  return pop(state);
-}
-
-template <>
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::writeCollection<v8::Map>(uint32_t length,
-                                                StateBase* state) {
-  m_writer.writeMap(length);
-  return pop(state);
-}
-
-template <>
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::writeCollection<v8::Set>(uint32_t length,
-                                                StateBase* state) {
-  m_writer.writeSet(length);
-  return pop(state);
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::handleError(
-    ScriptValueSerializer::Status errorStatus,
-    const String& message,
-    StateBase* state) {
-  DCHECK(errorStatus != Status::Success);
-  m_status = errorStatus;
-  m_errorMessage = message;
-  while (state) {
-    state = pop(state);
-  }
-  return new ErrorState;
-}
-
-bool ScriptValueSerializer::checkComposite(StateBase* top) {
-  ASSERT(top);
-  if (m_depth > maxDepth)
-    return false;
-  if (!shouldCheckForCycles(m_depth))
-    return true;
-  v8::Local<v8::Value> composite = top->composite();
-  for (StateBase* state = top->nextState(); state; state = state->nextState()) {
-    if (state->composite() == composite)
-      return false;
-  }
-  return true;
-}
-
-void ScriptValueSerializer::writeString(v8::Local<v8::Value> value) {
-  v8::Local<v8::String> string = value.As<v8::String>();
-  if (!string->Length() || string->IsOneByte())
-    m_writer.writeOneByteString(string);
-  else
-    m_writer.writeUCharString(string);
-}
-
-void ScriptValueSerializer::writeStringObject(v8::Local<v8::Value> value) {
-  v8::Local<v8::StringObject> stringObject = value.As<v8::StringObject>();
-  v8::String::Utf8Value stringValue(stringObject->ValueOf());
-  m_writer.writeStringObject(*stringValue, stringValue.length());
-}
-
-void ScriptValueSerializer::writeNumberObject(v8::Local<v8::Value> value) {
-  v8::Local<v8::NumberObject> numberObject = value.As<v8::NumberObject>();
-  m_writer.writeNumberObject(numberObject->ValueOf());
-}
-
-void ScriptValueSerializer::writeBooleanObject(v8::Local<v8::Value> value) {
-  v8::Local<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>();
-  m_writer.writeBooleanObject(booleanObject->ValueOf());
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::writeBlob(
-    v8::Local<v8::Value> value,
-    StateBase* next) {
-  Blob* blob = V8Blob::toImpl(value.As<v8::Object>());
-  if (!blob)
-    return nullptr;
-  if (blob->isClosed())
-    return handleError(
-        Status::DataCloneError,
-        "A Blob object has been closed, and could therefore not be cloned.",
-        next);
-  int blobIndex = -1;
-  m_blobDataHandles->set(blob->uuid(), blob->blobDataHandle());
-  if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex))
-    m_writer.writeBlobIndex(blobIndex);
-  else
-    m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
-  return nullptr;
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::writeCompositorProxy(
-    v8::Local<v8::Value> value,
-    StateBase* next) {
-  CompositorProxy* compositorProxy =
-      V8CompositorProxy::toImpl(value.As<v8::Object>());
-  if (!compositorProxy)
-    return nullptr;
-  if (!compositorProxy->connected())
-    return handleError(Status::DataCloneError,
-                       "A CompositorProxy object has been disconnected, and "
-                       "could therefore not be cloned.",
-                       next);
-  m_writer.writeCompositorProxy(*compositorProxy);
-  return nullptr;
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::writeFile(
-    v8::Local<v8::Value> value,
-    StateBase* next) {
-  File* file = V8File::toImpl(value.As<v8::Object>());
-  if (!file)
-    return nullptr;
-  if (file->isClosed())
-    return handleError(
-        Status::DataCloneError,
-        "A File object has been closed, and could therefore not be cloned.",
-        next);
-  int blobIndex = -1;
-  m_blobDataHandles->set(file->uuid(), file->blobDataHandle());
-  if (appendFileInfo(file, &blobIndex)) {
-    ASSERT(blobIndex >= 0);
-    m_writer.writeFileIndex(blobIndex);
-  } else {
-    m_writer.writeFile(*file);
-  }
-  return nullptr;
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::writeFileList(
-    v8::Local<v8::Value> value,
-    StateBase* next) {
-  FileList* fileList = V8FileList::toImpl(value.As<v8::Object>());
-  if (!fileList)
-    return nullptr;
-  unsigned length = fileList->length();
-  Vector<int> blobIndices;
-  for (unsigned i = 0; i < length; ++i) {
-    int blobIndex = -1;
-    const File* file = fileList->item(i);
-    if (file->isClosed())
-      return handleError(
-          Status::DataCloneError,
-          "A File object has been closed, and could therefore not be cloned.",
-          next);
-    m_blobDataHandles->set(file->uuid(), file->blobDataHandle());
-    if (appendFileInfo(file, &blobIndex)) {
-      ASSERT(!i || blobIndex > 0);
-      ASSERT(blobIndex >= 0);
-      blobIndices.push_back(blobIndex);
-    }
-  }
-  if (!blobIndices.isEmpty())
-    m_writer.writeFileListIndex(blobIndices);
-  else
-    m_writer.writeFileList(*fileList);
-  return nullptr;
-}
-
-void ScriptValueSerializer::writeImageData(v8::Local<v8::Value> value) {
-  ImageData* imageData = V8ImageData::toImpl(value.As<v8::Object>());
-  if (!imageData)
-    return;
-  DOMUint8ClampedArray* pixelArray = imageData->data();
-  m_writer.writeImageData(imageData->width(), imageData->height(),
-                          pixelArray->data(), pixelArray->length());
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::writeAndGreyImageBitmap(v8::Local<v8::Object> object,
-                                               StateBase* next) {
-  ImageBitmap* imageBitmap = V8ImageBitmap::toImpl(object);
-  if (!imageBitmap)
-    return nullptr;
-  if (imageBitmap->isNeutered())
-    return handleError(Status::DataCloneError,
-                       "An ImageBitmap is detached and could not be cloned.",
-                       next);
-
-  uint32_t index;
-  if (m_transferredImageBitmaps.tryGet(object, &index)) {
-    m_writer.writeTransferredImageBitmap(index);
-  } else {
-    greyObject(object);
-    RefPtr<Uint8Array> pixelData = imageBitmap->copyBitmapData(
-        imageBitmap->isPremultiplied() ? PremultiplyAlpha
-                                       : DontPremultiplyAlpha,
-        N32ColorType);
-    m_writer.writeImageBitmap(
-        imageBitmap->width(), imageBitmap->height(),
-        static_cast<uint32_t>(imageBitmap->originClean()),
-        static_cast<uint32_t>(imageBitmap->isPremultiplied()),
-        pixelData->data(), imageBitmap->width() * imageBitmap->height() * 4);
-  }
-  return nullptr;
-}
-
-void ScriptValueSerializer::writeRegExp(v8::Local<v8::Value> value) {
-  v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>();
-  m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags());
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::writeAndGreyArrayBufferView(v8::Local<v8::Object> object,
-                                                   StateBase* next) {
-  ASSERT(!object.IsEmpty());
-  DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object);
-  if (!arrayBufferView)
-    return nullptr;
-  if (!arrayBufferView->bufferBase())
-    return handleError(Status::DataCloneError,
-                       "An ArrayBuffer could not be cloned.", next);
-  v8::Local<v8::Value> underlyingBuffer =
-      ToV8(arrayBufferView->bufferBase(), m_scriptState->context()->Global(),
-           isolate());
-  if (underlyingBuffer.IsEmpty())
-    return handleError(Status::DataCloneError,
-                       "An ArrayBuffer could not be cloned.", next);
-  StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
-  if (stateOut)
-    return stateOut;
-  m_writer.writeArrayBufferView(*arrayBufferView);
-  // This should be safe: we serialize something that we know to be a wrapper
-  // (see the toV8 call above), so the call to doSerializeArrayBuffer should
-  // neither cause the system stack to overflow nor should it have potential to
-  // reach this ArrayBufferView again.
-  //
-  // We do need to grey the underlying buffer before we grey its view, however;
-  // ArrayBuffers may be shared, so they need to be given reference IDs, and an
-  // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer
-  // (or without an additional tag that would allow us to do two-stage
-  // construction like we do for Objects and Arrays).
-  greyObject(object);
-  return nullptr;
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::writeWasmCompiledModule(v8::Local<v8::Object> object,
-                                               StateBase* next) {
-  CHECK(RuntimeEnabledFeatures::webAssemblySerializationEnabled());
-  // TODO (mtrofin): explore mechanism avoiding data copying / buffer resizing.
-  v8::Local<v8::WasmCompiledModule> wasmModule =
-      object.As<v8::WasmCompiledModule>();
-  v8::Local<v8::String> wireBytes = wasmModule->GetWasmWireBytes();
-  DCHECK(wireBytes->IsOneByte());
-
-  v8::WasmCompiledModule::SerializedModule data = wasmModule->Serialize();
-  m_writer.append(WasmModuleTag);
-  uint32_t wireBytesLength = static_cast<uint32_t>(wireBytes->Length());
-  // We place a tag so we may evolve the format in which we store the
-  // wire bytes. We plan to move them to a blob.
-  // We want to control how we write the string, though, so we explicitly
-  // call writeRawStringBytes.
-  m_writer.append(RawBytesTag);
-  m_writer.doWriteUint32(wireBytesLength);
-  m_writer.ensureSpace(wireBytesLength);
-  m_writer.writeRawStringBytes(wireBytes);
-  m_writer.doWriteUint32(static_cast<uint32_t>(data.second));
-  m_writer.append(data.first.get(), static_cast<int>(data.second));
-  return nullptr;
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::writeAndGreyArrayBuffer(v8::Local<v8::Object> object,
-                                               StateBase* next) {
-  DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(object);
-  if (!arrayBuffer)
-    return nullptr;
-  if (arrayBuffer->isNeutered())
-    return handleError(Status::DataCloneError,
-                       "An ArrayBuffer is neutered and could not be cloned.",
-                       next);
-
-  uint32_t index;
-  if (m_transferredArrayBuffers.tryGet(object, &index)) {
-    m_writer.writeTransferredArrayBuffer(index);
-  } else {
-    greyObject(object);
-    m_writer.writeArrayBuffer(*arrayBuffer);
-  }
-  return nullptr;
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::writeTransferredOffscreenCanvas(
-    v8::Local<v8::Value> value,
-    StateBase* next) {
-  OffscreenCanvas* offscreenCanvas =
-      V8OffscreenCanvas::toImpl(value.As<v8::Object>());
-  if (!offscreenCanvas)
-    return nullptr;
-  if (offscreenCanvas->isNeutered())
-    return handleError(
-        Status::DataCloneError,
-        "An OffscreenCanvas is detached and could not be cloned.", next);
-  if (offscreenCanvas->renderingContext())
-    return handleError(Status::DataCloneError,
-                       "An OffscreenCanvas with a context could not be cloned.",
-                       next);
-  m_writer.writeTransferredOffscreenCanvas(
-      offscreenCanvas->width(), offscreenCanvas->height(),
-      offscreenCanvas->placeholderCanvasId(), offscreenCanvas->clientId(),
-      offscreenCanvas->sinkId());
-  return nullptr;
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializer::writeTransferredSharedArrayBuffer(
-    v8::Local<v8::Value> value,
-    uint32_t index,
-    StateBase* next) {
-  ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled());
-  DOMSharedArrayBuffer* sharedArrayBuffer =
-      V8SharedArrayBuffer::toImpl(value.As<v8::Object>());
-  if (!sharedArrayBuffer)
-    return 0;
-  m_writer.writeTransferredSharedArrayBuffer(index);
-  return nullptr;
-}
-
-bool ScriptValueSerializer::shouldSerializeDensely(uint32_t length,
-                                                   uint32_t propertyCount) {
-  // Let K be the cost of serializing all property values that are there
-  // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t
-  // key)
-  // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all
-  // properties that are not there)
-  // so densely is better than sparsly whenever 6*propertyCount > length
-  return 6 * propertyCount >= length;
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::startArrayState(
-    v8::Local<v8::Array> array,
-    StateBase* next) {
-  v8::Local<v8::Array> propertyNames;
-  if (!array->GetOwnPropertyNames(context()).ToLocal(&propertyNames))
-    return checkException(next);
-  uint32_t length = array->Length();
-
-  if (shouldSerializeDensely(length, propertyNames->Length())) {
-    // In serializing a dense array, indexed properties are ignored, so we get
-    // non indexed own property names here.
-    if (!array
-             ->GetPropertyNames(context(),
-                                v8::KeyCollectionMode::kIncludePrototypes,
-                                static_cast<v8::PropertyFilter>(
-                                    v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS),
-                                v8::IndexFilter::kSkipIndices)
-             .ToLocal(&propertyNames))
-      return checkException(next);
-
-    m_writer.writeGenerateFreshDenseArray(length);
-    return push(new DenseArrayState(array, propertyNames, next, isolate()));
-  }
-
-  m_writer.writeGenerateFreshSparseArray(length);
-  return push(new SparseArrayState(array, propertyNames, next, isolate()));
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::startMapState(
-    v8::Local<v8::Map> map,
-    StateBase* next) {
-  m_writer.writeGenerateFreshMap();
-  return push(new MapState(map, next));
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::startSetState(
-    v8::Local<v8::Set> set,
-    StateBase* next) {
-  m_writer.writeGenerateFreshSet();
-  return push(new SetState(set, next));
-}
-
-ScriptValueSerializer::StateBase* ScriptValueSerializer::startObjectState(
-    v8::Local<v8::Object> object,
-    StateBase* next) {
-  m_writer.writeGenerateFreshObject();
-  // FIXME: check not a wrapper
-  return push(new ObjectState(object, next));
-}
-
-// Marks object as having been visited by the serializer and assigns it a unique
-// object reference ID.  An object may only be greyed once.
-void ScriptValueSerializer::greyObject(const v8::Local<v8::Object>& object) {
-  ASSERT(!m_objectPool.contains(object));
-  uint32_t objectReference = m_nextObjectReference++;
-  m_objectPool.set(object, objectReference);
-}
-
-bool ScriptValueSerializer::appendBlobInfo(const String& uuid,
-                                           const String& type,
-                                           unsigned long long size,
-                                           int* index) {
-  if (!m_blobInfo)
-    return false;
-  *index = m_blobInfo->size();
-  m_blobInfo->push_back(WebBlobInfo(uuid, type, size));
-  return true;
-}
-
-bool ScriptValueSerializer::appendFileInfo(const File* file, int* index) {
-  if (!m_blobInfo)
-    return false;
-
-  long long size = -1;
-  double lastModifiedMS = invalidFileTime();
-  file->captureSnapshot(size, lastModifiedMS);
-  *index = m_blobInfo->size();
-  // FIXME: transition WebBlobInfo.lastModified to be milliseconds-based also.
-  double lastModified = lastModifiedMS / msPerSecond;
-  m_blobInfo->push_back(WebBlobInfo(file->uuid(), file->path(), file->name(),
-                                    file->type(), lastModified, size));
-  return true;
-}
-
-bool SerializedScriptValueReader::read(v8::Local<v8::Value>* value,
-                                       ScriptValueDeserializer& deserializer) {
-  SerializationTag tag;
-  if (!readTag(&tag))
-    return false;
-  return readWithTag(tag, value, deserializer);
-}
-
-bool SerializedScriptValueReader::readWithTag(
-    SerializationTag tag,
-    v8::Local<v8::Value>* value,
-    ScriptValueDeserializer& deserializer) {
-  switch (tag) {
-    case ReferenceCountTag: {
-      if (!m_version)
-        return false;
-      uint32_t referenceTableSize;
-      if (!doReadUint32(&referenceTableSize))
-        return false;
-      // If this test fails, then the serializer and deserializer disagree about
-      // the assignment of object reference IDs. On the deserialization side,
-      // this means there are too many or too few calls to pushObjectReference.
-      if (referenceTableSize != deserializer.objectReferenceCount())
-        return false;
-      return true;
-    }
-    case InvalidTag:
-      return false;
-    case PaddingTag:
-      return true;
-    case UndefinedTag:
-      *value = v8::Undefined(isolate());
-      break;
-    case NullTag:
-      *value = v8::Null(isolate());
-      break;
-    case TrueTag:
-      *value = v8Boolean(true, isolate());
-      break;
-    case FalseTag:
-      *value = v8Boolean(false, isolate());
-      break;
-    case TrueObjectTag:
-      *value = v8::BooleanObject::New(isolate(), true);
-      deserializer.pushObjectReference(*value);
-      break;
-    case FalseObjectTag:
-      *value = v8::BooleanObject::New(isolate(), false);
-      deserializer.pushObjectReference(*value);
-      break;
-    case StringTag:
-      if (!readString(value))
-        return false;
-      break;
-    case StringUCharTag:
-      if (!readUCharString(value))
-        return false;
-      break;
-    case StringObjectTag:
-      if (!readStringObject(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    case Int32Tag:
-      if (!readInt32(value))
-        return false;
-      break;
-    case Uint32Tag:
-      if (!readUint32(value))
-        return false;
-      break;
-    case DateTag:
-      if (!readDate(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    case NumberTag:
-      if (!readNumber(value))
-        return false;
-      break;
-    case NumberObjectTag:
-      if (!readNumberObject(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    case BlobTag:
-    case BlobIndexTag:
-      if (!readBlob(value, tag == BlobIndexTag))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    case FileTag:
-    case FileIndexTag:
-      if (!readFile(value, tag == FileIndexTag))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    case FileListTag:
-    case FileListIndexTag:
-      if (!readFileList(value, tag == FileListIndexTag))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    case CompositorProxyTag:
-      if (!readCompositorProxy(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-
-    case ImageDataTag:
-      if (!readImageData(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    case ImageBitmapTag:
-      if (!readImageBitmap(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-
-    case RegExpTag:
-      if (!readRegExp(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    case ObjectTag: {
-      uint32_t numProperties;
-      if (!doReadUint32(&numProperties))
-        return false;
-      if (!deserializer.completeObject(numProperties, value))
-        return false;
-      break;
-    }
-    case SparseArrayTag: {
-      uint32_t numProperties;
-      uint32_t length;
-      if (!doReadUint32(&numProperties))
-        return false;
-      if (!doReadUint32(&length))
-        return false;
-      if (!deserializer.completeSparseArray(numProperties, length, value))
-        return false;
-      break;
-    }
-    case DenseArrayTag: {
-      uint32_t numProperties;
-      uint32_t length;
-      if (!doReadUint32(&numProperties))
-        return false;
-      if (!doReadUint32(&length))
-        return false;
-      if (!deserializer.completeDenseArray(numProperties, length, value))
-        return false;
-      break;
-    }
-    case MapTag: {
-      uint32_t length;
-      if (!doReadUint32(&length))
-        return false;
-      if (!deserializer.completeMap(length, value))
-        return false;
-      break;
-    }
-    case SetTag: {
-      uint32_t length;
-      if (!doReadUint32(&length))
-        return false;
-      if (!deserializer.completeSet(length, value))
-        return false;
-      break;
-    }
-    case ArrayBufferViewTag: {
-      if (!m_version)
-        return false;
-      if (!readArrayBufferView(value, deserializer))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    }
-    case WasmModuleTag: {
-      if (!readWasmCompiledModule(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    }
-    case ArrayBufferTag: {
-      if (!m_version)
-        return false;
-      if (!readArrayBuffer(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    }
-    case GenerateFreshObjectTag: {
-      if (!m_version)
-        return false;
-      if (!deserializer.newObject())
-        return false;
-      return true;
-    }
-    case GenerateFreshSparseArrayTag: {
-      if (!m_version)
-        return false;
-      uint32_t length;
-      if (!doReadUint32(&length))
-        return false;
-      if (!deserializer.newSparseArray(length))
-        return false;
-      return true;
-    }
-    case GenerateFreshDenseArrayTag: {
-      if (!m_version)
-        return false;
-      uint32_t length;
-      if (!doReadUint32(&length))
-        return false;
-      if (!deserializer.newDenseArray(length))
-        return false;
-      return true;
-    }
-    case GenerateFreshMapTag: {
-      if (!m_version)
-        return false;
-      if (!deserializer.newMap())
-        return false;
-      return true;
-    }
-    case GenerateFreshSetTag: {
-      if (!m_version)
-        return false;
-      if (!deserializer.newSet())
-        return false;
-      return true;
-    }
-    case MessagePortTag: {
-      if (!m_version)
-        return false;
-      uint32_t index;
-      if (!doReadUint32(&index))
-        return false;
-      if (!deserializer.tryGetTransferredMessagePort(index, value))
-        return false;
-      break;
-    }
-    case ArrayBufferTransferTag: {
-      if (!m_version)
-        return false;
-      uint32_t index;
-      if (!doReadUint32(&index))
-        return false;
-      if (!deserializer.tryGetTransferredArrayBuffer(index, value))
-        return false;
-      break;
-    }
-    case ImageBitmapTransferTag: {
-      if (!m_version)
-        return false;
-      uint32_t index;
-      if (!doReadUint32(&index))
-        return false;
-      if (!deserializer.tryGetTransferredImageBitmap(index, value))
-        return false;
-      break;
-    }
-    case OffscreenCanvasTransferTag: {
-      if (!m_version)
-        return false;
-      uint32_t width, height, canvasId, clientId, sinkId;
-      if (!doReadUint32(&width))
-        return false;
-      if (!doReadUint32(&height))
-        return false;
-      if (!doReadUint32(&canvasId))
-        return false;
-      if (!doReadUint32(&clientId))
-        return false;
-      if (!doReadUint32(&sinkId))
-        return false;
-      if (!deserializer.tryGetTransferredOffscreenCanvas(
-              width, height, canvasId, clientId, sinkId, value))
-        return false;
-      break;
-    }
-    case SharedArrayBufferTransferTag: {
-      if (!m_version)
-        return false;
-      uint32_t index;
-      if (!doReadUint32(&index))
-        return false;
-      if (!deserializer.tryGetTransferredSharedArrayBuffer(index, value))
-        return false;
-      break;
-    }
-    case ObjectReferenceTag: {
-      if (!m_version)
-        return false;
-      uint32_t reference;
-      if (!doReadUint32(&reference))
-        return false;
-      if (!deserializer.tryGetObjectFromObjectReference(reference, value))
-        return false;
-      break;
-    }
-    case DOMFileSystemTag:
-    case CryptoKeyTag:
-      ASSERT_NOT_REACHED();
-    default:
-      return false;
-  }
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReader::readVersion(uint32_t& version) {
-  SerializationTag tag;
-  if (!readTag(&tag)) {
-    // This is a nullary buffer. We're still version 0.
-    version = 0;
-    return true;
-  }
-  if (tag != VersionTag) {
-    // Versions of the format past 0 start with the version tag.
-    version = 0;
-    // Put back the tag.
-    undoReadTag();
-    return true;
-  }
-  // Version-bearing messages are obligated to finish the version tag.
-  return doReadUint32(&version);
-}
-
-void SerializedScriptValueReader::setVersion(uint32_t version) {
-  m_version = version;
-}
-
-bool SerializedScriptValueReader::readTag(SerializationTag* tag) {
-  if (m_position >= m_length)
-    return false;
-  *tag = static_cast<SerializationTag>(m_buffer[m_position++]);
-  return true;
-}
-
-void SerializedScriptValueReader::undoReadTag() {
-  if (m_position > 0)
-    --m_position;
-}
-
-bool SerializedScriptValueReader::readArrayBufferViewSubTag(
-    ArrayBufferViewSubTag* tag) {
-  if (m_position >= m_length)
-    return false;
-  *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]);
-  return true;
-}
-
-bool SerializedScriptValueReader::readString(v8::Local<v8::Value>* value) {
-  uint32_t length;
-  if (!doReadUint32(&length))
-    return false;
-  if (m_position + length > m_length)
-    return false;
-  *value = v8StringFromUtf8(
-      isolate(), reinterpret_cast<const char*>(m_buffer + m_position), length);
-  m_position += length;
-  return true;
-}
-
-bool SerializedScriptValueReader::readUCharString(v8::Local<v8::Value>* value) {
-  uint32_t length;
-  if (!doReadUint32(&length) || (length & 1))
-    return false;
-  if (m_position + length > m_length)
-    return false;
-  ASSERT(!(m_position & 1));
-  if (!v8::String::NewFromTwoByte(
-           isolate(), reinterpret_cast<const uint16_t*>(m_buffer + m_position),
-           v8::NewStringType::kNormal, length / sizeof(UChar))
-           .ToLocal(value))
-    return false;
-  m_position += length;
-  return true;
-}
-
-bool SerializedScriptValueReader::readStringObject(
-    v8::Local<v8::Value>* value) {
-  v8::Local<v8::Value> stringValue;
-  if (!readString(&stringValue) || !stringValue->IsString())
-    return false;
-  *value = v8::StringObject::New(stringValue.As<v8::String>());
-  return true;
-}
-
-bool SerializedScriptValueReader::readWebCoreString(String* string) {
-  uint32_t length;
-  if (!doReadUint32(&length))
-    return false;
-  if (m_position + length > m_length)
-    return false;
-  *string = String::fromUTF8(
-      reinterpret_cast<const char*>(m_buffer + m_position), length);
-  m_position += length;
-  return true;
-}
-
-bool SerializedScriptValueReader::readInt32(v8::Local<v8::Value>* value) {
-  uint32_t rawValue;
-  if (!doReadUint32(&rawValue))
-    return false;
-  *value = v8::Integer::New(isolate(),
-                            static_cast<int32_t>(ZigZag::decode(rawValue)));
-  return true;
-}
-
-bool SerializedScriptValueReader::readUint32(v8::Local<v8::Value>* value) {
-  uint32_t rawValue;
-  if (!doReadUint32(&rawValue))
-    return false;
-  *value = v8::Integer::NewFromUnsigned(isolate(), rawValue);
-  return true;
-}
-
-bool SerializedScriptValueReader::readDate(v8::Local<v8::Value>* value) {
-  double numberValue;
-  if (!doReadNumber(&numberValue))
-    return false;
-  if (!v8DateOrNaN(isolate(), numberValue).ToLocal(value))
-    return false;
-  return true;
-}
-
-bool SerializedScriptValueReader::readNumber(v8::Local<v8::Value>* value) {
-  double number;
-  if (!doReadNumber(&number))
-    return false;
-  *value = v8::Number::New(isolate(), number);
-  return true;
-}
-
-bool SerializedScriptValueReader::readNumberObject(
-    v8::Local<v8::Value>* value) {
-  double number;
-  if (!doReadNumber(&number))
-    return false;
-  *value = v8::NumberObject::New(isolate(), number);
-  return true;
-}
-
-// Helper function used by readImageData and readImageBitmap.
-bool SerializedScriptValueReader::doReadImageDataProperties(
-    uint32_t* width,
-    uint32_t* height,
-    uint32_t* pixelDataLength) {
-  if (!doReadUint32(width))
-    return false;
-  if (!doReadUint32(height))
-    return false;
-  if (!doReadUint32(pixelDataLength))
-    return false;
-  if (m_length - m_position < *pixelDataLength)
-    return false;
-  return true;
-}
-
-bool SerializedScriptValueReader::readImageData(v8::Local<v8::Value>* value) {
-  uint32_t width;
-  uint32_t height;
-  uint32_t pixelDataLength;
-  if (!doReadImageDataProperties(&width, &height, &pixelDataLength))
-    return false;
-  ImageData* imageData = ImageData::create(IntSize(width, height));
-  DOMUint8ClampedArray* pixelArray = imageData->data();
-  ASSERT(pixelArray);
-  ASSERT(pixelArray->length() >= pixelDataLength);
-  memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength);
-  m_position += pixelDataLength;
-  if (!imageData)
-    return false;
-  *value = ToV8(imageData, m_scriptState->context()->Global(), isolate());
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReader::readImageBitmap(v8::Local<v8::Value>* value) {
-  uint32_t isOriginClean;
-  if (!doReadUint32(&isOriginClean))
-    return false;
-  uint32_t isPremultiplied;
-  if (!doReadUint32(&isPremultiplied))
-    return false;
-  uint32_t width;
-  uint32_t height;
-  uint32_t pixelDataLength;
-  if (!doReadImageDataProperties(&width, &height, &pixelDataLength))
-    return false;
-  const void* pixelData = m_buffer + m_position;
-  m_position += pixelDataLength;
-  ImageBitmap* imageBitmap = ImageBitmap::create(
-      pixelData, width, height, isPremultiplied, isOriginClean);
-  if (!imageBitmap)
-    return false;
-  *value = ToV8(imageBitmap, m_scriptState->context()->Global(), isolate());
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReader::readCompositorProxy(
-    v8::Local<v8::Value>* value) {
-  uint32_t attributes;
-  uint64_t element;
-  if (!doReadUint64(&element))
-    return false;
-  if (!doReadUint32(&attributes))
-    return false;
-
-  CompositorProxy* compositorProxy = CompositorProxy::create(
-      m_scriptState->getExecutionContext(), element, attributes);
-  *value = ToV8(compositorProxy, m_scriptState->context()->Global(), isolate());
-  return !value->IsEmpty();
-}
-
-DOMArrayBuffer* SerializedScriptValueReader::doReadArrayBuffer() {
-  uint32_t byteLength;
-  if (!doReadUint32(&byteLength))
-    return nullptr;
-  if (m_position + byteLength > m_length)
-    return nullptr;
-  const void* bufferStart = m_buffer + m_position;
-  m_position += byteLength;
-  return DOMArrayBuffer::create(bufferStart, byteLength);
-}
-
-bool SerializedScriptValueReader::readWasmCompiledModule(
-    v8::Local<v8::Value>* value) {
-  CHECK(RuntimeEnabledFeatures::webAssemblySerializationEnabled());
-  // First, read the tag of the wire bytes.
-  SerializationTag wireBytesFormat = InvalidTag;
-  if (!readTag(&wireBytesFormat))
-    return false;
-  DCHECK(wireBytesFormat == RawBytesTag);
-  // Just like when writing, we don't rely on the default string serialization
-  // mechanics for the wire bytes. We don't even want a string, because
-  // that would lead to a memory copying API implementation on the V8 side.
-  uint32_t wireBytesSize = 0;
-  uint32_t compiledBytesSize = 0;
-  if (!doReadUint32(&wireBytesSize))
-    return false;
-  if (m_position + wireBytesSize > m_length)
-    return false;
-  const uint8_t* wireBytesStart = m_buffer + m_position;
-  m_position += wireBytesSize;
-
-  if (!doReadUint32(&compiledBytesSize))
-    return false;
-  if (m_position + compiledBytesSize > m_length)
-    return false;
-  const uint8_t* compiledBytesStart = m_buffer + m_position;
-  m_position += compiledBytesSize;
-
-  v8::WasmCompiledModule::CallerOwnedBuffer wireBytes = {
-      wireBytesStart, static_cast<size_t>(wireBytesSize)};
-
-  v8::WasmCompiledModule::CallerOwnedBuffer compiledBytes = {
-      compiledBytesStart, static_cast<size_t>(compiledBytesSize)};
-
-  v8::MaybeLocal<v8::WasmCompiledModule> retval =
-      v8::WasmCompiledModule::DeserializeOrCompile(isolate(), compiledBytes,
-                                                   wireBytes);
-
-  return retval.ToLocal(value);
-}
-
-bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value) {
-  DOMArrayBuffer* arrayBuffer = doReadArrayBuffer();
-  if (!arrayBuffer)
-    return false;
-  *value = ToV8(arrayBuffer, m_scriptState->context()->Global(), isolate());
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReader::readArrayBufferView(
-    v8::Local<v8::Value>* value,
-    ScriptValueDeserializer& deserializer) {
-  ArrayBufferViewSubTag subTag;
-  uint32_t byteOffset;
-  uint32_t byteLength;
-  DOMArrayBufferBase* arrayBuffer = nullptr;
-  v8::Local<v8::Value> arrayBufferV8Value;
-  if (!readArrayBufferViewSubTag(&subTag))
-    return false;
-  if (!doReadUint32(&byteOffset))
-    return false;
-  if (!doReadUint32(&byteLength))
-    return false;
-  if (!deserializer.consumeTopOfStack(&arrayBufferV8Value))
-    return false;
-  if (arrayBufferV8Value.IsEmpty())
-    return false;
-  if (arrayBufferV8Value->IsArrayBuffer()) {
-    arrayBuffer = V8ArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>());
-    if (!arrayBuffer)
-      return false;
-  } else if (arrayBufferV8Value->IsSharedArrayBuffer()) {
-    arrayBuffer =
-        V8SharedArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>());
-    if (!arrayBuffer)
-      return false;
-  } else {
-    ASSERT_NOT_REACHED();
-  }
-
-  // Check the offset, length and alignment.
-  int elementByteSize;
-  switch (subTag) {
-    case ByteArrayTag:
-      elementByteSize = sizeof(DOMInt8Array::ValueType);
-      break;
-    case UnsignedByteArrayTag:
-      elementByteSize = sizeof(DOMUint8Array::ValueType);
-      break;
-    case UnsignedByteClampedArrayTag:
-      elementByteSize = sizeof(DOMUint8ClampedArray::ValueType);
-      break;
-    case ShortArrayTag:
-      elementByteSize = sizeof(DOMInt16Array::ValueType);
-      break;
-    case UnsignedShortArrayTag:
-      elementByteSize = sizeof(DOMUint16Array::ValueType);
-      break;
-    case IntArrayTag:
-      elementByteSize = sizeof(DOMInt32Array::ValueType);
-      break;
-    case UnsignedIntArrayTag:
-      elementByteSize = sizeof(DOMUint32Array::ValueType);
-      break;
-    case FloatArrayTag:
-      elementByteSize = sizeof(DOMFloat32Array::ValueType);
-      break;
-    case DoubleArrayTag:
-      elementByteSize = sizeof(DOMFloat64Array::ValueType);
-      break;
-    case DataViewTag:
-      elementByteSize = sizeof(DOMDataView::ValueType);
-      break;
-    default:
-      return false;
-  }
-  const unsigned numElements = byteLength / elementByteSize;
-  const unsigned remainingElements =
-      (arrayBuffer->byteLength() - byteOffset) / elementByteSize;
-  if (byteOffset % elementByteSize || byteOffset > arrayBuffer->byteLength() ||
-      numElements > remainingElements)
-    return false;
-
-  v8::Local<v8::Object> creationContext = m_scriptState->context()->Global();
-  switch (subTag) {
-    case ByteArrayTag:
-      *value = ToV8(DOMInt8Array::create(arrayBuffer, byteOffset, numElements),
-                    creationContext, isolate());
-      break;
-    case UnsignedByteArrayTag:
-      *value = ToV8(DOMUint8Array::create(arrayBuffer, byteOffset, numElements),
-                    creationContext, isolate());
-      break;
-    case UnsignedByteClampedArrayTag:
-      *value = ToV8(
-          DOMUint8ClampedArray::create(arrayBuffer, byteOffset, numElements),
-          creationContext, isolate());
-      break;
-    case ShortArrayTag:
-      *value = ToV8(DOMInt16Array::create(arrayBuffer, byteOffset, numElements),
-                    creationContext, isolate());
-      break;
-    case UnsignedShortArrayTag:
-      *value =
-          ToV8(DOMUint16Array::create(arrayBuffer, byteOffset, numElements),
-               creationContext, isolate());
-      break;
-    case IntArrayTag:
-      *value = ToV8(DOMInt32Array::create(arrayBuffer, byteOffset, numElements),
-                    creationContext, isolate());
-      break;
-    case UnsignedIntArrayTag:
-      *value =
-          ToV8(DOMUint32Array::create(arrayBuffer, byteOffset, numElements),
-               creationContext, isolate());
-      break;
-    case FloatArrayTag:
-      *value =
-          ToV8(DOMFloat32Array::create(arrayBuffer, byteOffset, numElements),
-               creationContext, isolate());
-      break;
-    case DoubleArrayTag:
-      *value =
-          ToV8(DOMFloat64Array::create(arrayBuffer, byteOffset, numElements),
-               creationContext, isolate());
-      break;
-    case DataViewTag:
-      *value = ToV8(DOMDataView::create(arrayBuffer, byteOffset, byteLength),
-                    creationContext, isolate());
-      break;
-  }
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReader::readRegExp(v8::Local<v8::Value>* value) {
-  v8::Local<v8::Value> pattern;
-  if (!readString(&pattern))
-    return false;
-  uint32_t flags;
-  if (!doReadUint32(&flags))
-    return false;
-  if (!v8::RegExp::New(getScriptState()->context(), pattern.As<v8::String>(),
-                       static_cast<v8::RegExp::Flags>(flags))
-           .ToLocal(value))
-    return false;
-  return true;
-}
-
-bool SerializedScriptValueReader::readBlob(v8::Local<v8::Value>* value,
-                                           bool isIndexed) {
-  if (m_version < 3)
-    return false;
-  Blob* blob = nullptr;
-  if (isIndexed) {
-    if (m_version < 6)
-      return false;
-    ASSERT(m_blobInfo);
-    uint32_t index;
-    if (!doReadUint32(&index) || index >= m_blobInfo->size())
-      return false;
-    const WebBlobInfo& info = (*m_blobInfo)[index];
-    blob = Blob::create(
-        getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()));
-  } else {
-    ASSERT(!m_blobInfo);
-    String uuid;
-    String type;
-    uint64_t size;
-    ASSERT(!m_blobInfo);
-    if (!readWebCoreString(&uuid))
-      return false;
-    if (!readWebCoreString(&type))
-      return false;
-    if (!doReadUint64(&size))
-      return false;
-    blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size));
-  }
-  *value = ToV8(blob, m_scriptState->context()->Global(), isolate());
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReader::readFile(v8::Local<v8::Value>* value,
-                                           bool isIndexed) {
-  File* file = nullptr;
-  if (isIndexed) {
-    if (m_version < 6)
-      return false;
-    file = readFileIndexHelper();
-  } else {
-    file = readFileHelper();
-  }
-  if (!file)
-    return false;
-  *value = ToV8(file, m_scriptState->context()->Global(), isolate());
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReader::readFileList(v8::Local<v8::Value>* value,
-                                               bool isIndexed) {
-  if (m_version < 3)
-    return false;
-  uint32_t length;
-  if (!doReadUint32(&length))
-    return false;
-  FileList* fileList = FileList::create();
-  for (unsigned i = 0; i < length; ++i) {
-    File* file = nullptr;
-    if (isIndexed) {
-      if (m_version < 6)
-        return false;
-      file = readFileIndexHelper();
-    } else {
-      file = readFileHelper();
-    }
-    if (!file)
-      return false;
-    fileList->append(file);
-  }
-  *value = ToV8(fileList, m_scriptState->context()->Global(), isolate());
-  return !value->IsEmpty();
-}
-
-File* SerializedScriptValueReader::readFileHelper() {
-  if (m_version < 3)
-    return nullptr;
-  ASSERT(!m_blobInfo);
-  String path;
-  String name;
-  String relativePath;
-  String uuid;
-  String type;
-  uint32_t hasSnapshot = 0;
-  uint64_t size = 0;
-  double lastModifiedMS = 0;
-  if (!readWebCoreString(&path))
-    return nullptr;
-  if (m_version >= 4 && !readWebCoreString(&name))
-    return nullptr;
-  if (m_version >= 4 && !readWebCoreString(&relativePath))
-    return nullptr;
-  if (!readWebCoreString(&uuid))
-    return nullptr;
-  if (!readWebCoreString(&type))
-    return nullptr;
-  if (m_version >= 4 && !doReadUint32(&hasSnapshot))
-    return nullptr;
-  if (hasSnapshot) {
-    if (!doReadUint64(&size))
-      return nullptr;
-    if (!doReadNumber(&lastModifiedMS))
-      return nullptr;
-    if (m_version < 8)
-      lastModifiedMS *= msPerSecond;
-  }
-  uint32_t isUserVisible = 1;
-  if (m_version >= 7 && !doReadUint32(&isUserVisible))
-    return nullptr;
-  const File::UserVisibility userVisibility =
-      (isUserVisible > 0) ? File::IsUserVisible : File::IsNotUserVisible;
-  return File::createFromSerialization(path, name, relativePath, userVisibility,
-                                       hasSnapshot > 0, size, lastModifiedMS,
-                                       getOrCreateBlobDataHandle(uuid, type));
-}
-
-File* SerializedScriptValueReader::readFileIndexHelper() {
-  if (m_version < 3)
-    return nullptr;
-  ASSERT(m_blobInfo);
-  uint32_t index;
-  if (!doReadUint32(&index) || index >= m_blobInfo->size())
-    return nullptr;
-  const WebBlobInfo& info = (*m_blobInfo)[index];
-  // FIXME: transition WebBlobInfo.lastModified to be milliseconds-based also.
-  double lastModifiedMS = info.lastModified() * msPerSecond;
-  return File::createFromIndexedSerialization(
-      info.filePath(), info.fileName(), info.size(), lastModifiedMS,
-      getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()));
-}
-
-bool SerializedScriptValueReader::doReadUint32(uint32_t* value) {
-  return doReadUintHelper(value);
-}
-
-bool SerializedScriptValueReader::doReadUint64(uint64_t* value) {
-  return doReadUintHelper(value);
-}
-
-bool SerializedScriptValueReader::doReadNumber(double* number) {
-  if (m_position + sizeof(double) > m_length)
-    return false;
-  uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number);
-  for (unsigned i = 0; i < sizeof(double); ++i)
-    numberAsByteArray[i] = m_buffer[m_position++];
-  return true;
-}
-
-PassRefPtr<BlobDataHandle>
-SerializedScriptValueReader::getOrCreateBlobDataHandle(const String& uuid,
-                                                       const String& type,
-                                                       long long size) {
-  // The containing ssv may have a BDH for this uuid if this ssv is just being
-  // passed from main to worker thread (for example). We use those values when
-  // creating the new blob instead of cons'ing up a new BDH.
-  //
-  // FIXME: Maybe we should require that it work that way where the ssv must
-  // have a BDH for any blobs it comes across during deserialization. Would
-  // require callers to explicitly populate the collection of BDH's for blobs to
-  // work, which would encourage lifetimes to be considered when passing ssv's
-  // around cross process. At present, we get 'lucky' in some cases because the
-  // blob in the src process happens to still exist at the time the dest process
-  // is deserializing.
-  // For example in sharedWorker.postMessage(...).
-  BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid);
-  if (it != m_blobDataHandles.end()) {
-    // make assertions about type and size?
-    return it->value;
-  }
-  return BlobDataHandle::create(uuid, type, size);
-}
-
-v8::Local<v8::Value> ScriptValueDeserializer::deserialize() {
-  v8::Isolate* isolate = m_reader.getScriptState()->isolate();
-  if (!m_reader.readVersion(m_version) ||
-      m_version > SerializedScriptValue::wireFormatVersion)
-    return v8::Null(isolate);
-  m_reader.setVersion(m_version);
-  v8::EscapableHandleScope scope(isolate);
-  while (!m_reader.isEof()) {
-    if (!doDeserialize())
-      return v8::Null(isolate);
-  }
-  if (stackDepth() != 1 || m_openCompositeReferenceStack.size())
-    return v8::Null(isolate);
-  v8::Local<v8::Value> result = scope.Escape(element(0));
-  return result;
-}
-
-bool ScriptValueDeserializer::newSparseArray(uint32_t) {
-  v8::Local<v8::Array> array =
-      v8::Array::New(m_reader.getScriptState()->isolate(), 0);
-  openComposite(array);
-  return true;
-}
-
-bool ScriptValueDeserializer::newDenseArray(uint32_t length) {
-  v8::Local<v8::Array> array =
-      v8::Array::New(m_reader.getScriptState()->isolate(), length);
-  openComposite(array);
-  return true;
-}
-
-bool ScriptValueDeserializer::newMap() {
-  v8::Local<v8::Map> map = v8::Map::New(m_reader.getScriptState()->isolate());
-  openComposite(map);
-  return true;
-}
-
-bool ScriptValueDeserializer::newSet() {
-  v8::Local<v8::Set> set = v8::Set::New(m_reader.getScriptState()->isolate());
-  openComposite(set);
-  return true;
-}
-
-bool ScriptValueDeserializer::consumeTopOfStack(v8::Local<v8::Value>* object) {
-  if (stackDepth() < 1)
-    return false;
-  *object = element(stackDepth() - 1);
-  pop(1);
-  return true;
-}
-
-bool ScriptValueDeserializer::newObject() {
-  v8::Local<v8::Object> object =
-      v8::Object::New(m_reader.getScriptState()->isolate());
-  if (object.IsEmpty())
-    return false;
-  openComposite(object);
-  return true;
-}
-
-bool ScriptValueDeserializer::completeObject(uint32_t numProperties,
-                                             v8::Local<v8::Value>* value) {
-  v8::Local<v8::Object> object;
-  if (m_version > 0) {
-    v8::Local<v8::Value> composite;
-    if (!closeComposite(&composite))
-      return false;
-    object = composite.As<v8::Object>();
-  } else {
-    object = v8::Object::New(m_reader.getScriptState()->isolate());
-  }
-  if (object.IsEmpty())
-    return false;
-  return initializeObject(object, numProperties, value);
-}
-
-bool ScriptValueDeserializer::completeSparseArray(uint32_t numProperties,
-                                                  uint32_t length,
-                                                  v8::Local<v8::Value>* value) {
-  v8::Local<v8::Array> array;
-  if (m_version > 0) {
-    v8::Local<v8::Value> composite;
-    if (!closeComposite(&composite))
-      return false;
-    array = composite.As<v8::Array>();
-  } else {
-    array = v8::Array::New(m_reader.getScriptState()->isolate());
-  }
-  if (array.IsEmpty())
-    return false;
-  return initializeObject(array, numProperties, value);
-}
-
-bool ScriptValueDeserializer::completeDenseArray(uint32_t numProperties,
-                                                 uint32_t length,
-                                                 v8::Local<v8::Value>* value) {
-  v8::Local<v8::Array> array;
-  if (m_version > 0) {
-    v8::Local<v8::Value> composite;
-    if (!closeComposite(&composite))
-      return false;
-    array = composite.As<v8::Array>();
-  }
-  if (array.IsEmpty())
-    return false;
-  if (!initializeObject(array, numProperties, value))
-    return false;
-  if (length > stackDepth())
-    return false;
-  v8::Local<v8::Context> context = m_reader.getScriptState()->context();
-  for (unsigned i = 0, stackPos = stackDepth() - length; i < length;
-       i++, stackPos++) {
-    v8::Local<v8::Value> elem = element(stackPos);
-    if (!elem->IsUndefined()) {
-      if (!v8CallBoolean(array->CreateDataProperty(context, i, elem)))
-        return false;
-    }
-  }
-  pop(length);
-  return true;
-}
-
-bool ScriptValueDeserializer::completeMap(uint32_t length,
-                                          v8::Local<v8::Value>* value) {
-  ASSERT(m_version > 0);
-  v8::Local<v8::Value> composite;
-  if (!closeComposite(&composite))
-    return false;
-  v8::Local<v8::Map> map = composite.As<v8::Map>();
-  if (map.IsEmpty())
-    return false;
-  v8::Local<v8::Context> context = m_reader.getScriptState()->context();
-  ASSERT(length % 2 == 0);
-  for (unsigned i = stackDepth() - length; i + 1 < stackDepth(); i += 2) {
-    v8::Local<v8::Value> key = element(i);
-    v8::Local<v8::Value> val = element(i + 1);
-    if (map->Set(context, key, val).IsEmpty())
-      return false;
-  }
-  pop(length);
-  *value = map;
-  return true;
-}
-
-bool ScriptValueDeserializer::completeSet(uint32_t length,
-                                          v8::Local<v8::Value>* value) {
-  ASSERT(m_version > 0);
-  v8::Local<v8::Value> composite;
-  if (!closeComposite(&composite))
-    return false;
-  v8::Local<v8::Set> set = composite.As<v8::Set>();
-  if (set.IsEmpty())
-    return false;
-  v8::Local<v8::Context> context = m_reader.getScriptState()->context();
-  for (unsigned i = stackDepth() - length; i < stackDepth(); i++) {
-    v8::Local<v8::Value> key = element(i);
-    if (set->Add(context, key).IsEmpty())
-      return false;
-  }
-  pop(length);
-  *value = set;
-  return true;
-}
-
-void ScriptValueDeserializer::pushObjectReference(
-    const v8::Local<v8::Value>& object) {
-  m_objectPool.push_back(object);
-}
-
-bool ScriptValueDeserializer::tryGetTransferredMessagePort(
-    uint32_t index,
-    v8::Local<v8::Value>* object) {
-  if (!m_transferredMessagePorts)
-    return false;
-  if (index >= m_transferredMessagePorts->size())
-    return false;
-  v8::Local<v8::Object> creationContext =
-      m_reader.getScriptState()->context()->Global();
-  *object = ToV8(m_transferredMessagePorts->at(index).get(), creationContext,
-                 m_reader.getScriptState()->isolate());
-  return !object->IsEmpty();
-}
-
-bool ScriptValueDeserializer::tryGetTransferredArrayBuffer(
-    uint32_t index,
-    v8::Local<v8::Value>* object) {
-  if (!m_arrayBufferContents)
-    return false;
-  if (index >= m_arrayBuffers.size())
-    return false;
-  v8::Local<v8::Value> result = m_arrayBuffers.at(index);
-  if (result.IsEmpty()) {
-    DOMArrayBuffer* buffer =
-        DOMArrayBuffer::create(m_arrayBufferContents->at(index));
-    v8::Isolate* isolate = m_reader.getScriptState()->isolate();
-    v8::Local<v8::Object> creationContext =
-        m_reader.getScriptState()->context()->Global();
-    result = ToV8(buffer, creationContext, isolate);
-    if (result.IsEmpty())
-      return false;
-    m_arrayBuffers[index] = result;
-  }
-  *object = result;
-  return true;
-}
-
-bool ScriptValueDeserializer::tryGetTransferredImageBitmap(
-    uint32_t index,
-    v8::Local<v8::Value>* object) {
-  if (!m_imageBitmapContents)
-    return false;
-  if (index >= m_imageBitmaps.size())
-    return false;
-  v8::Local<v8::Value> result = m_imageBitmaps.at(index);
-  if (result.IsEmpty()) {
-    ImageBitmap* bitmap = ImageBitmap::create(m_imageBitmapContents->at(index));
-    v8::Isolate* isolate = m_reader.getScriptState()->isolate();
-    v8::Local<v8::Object> creationContext =
-        m_reader.getScriptState()->context()->Global();
-    result = ToV8(bitmap, creationContext, isolate);
-    if (result.IsEmpty())
-      return false;
-    m_imageBitmaps[index] = result;
-  }
-  *object = result;
-  return true;
-}
-
-bool ScriptValueDeserializer::tryGetTransferredSharedArrayBuffer(
-    uint32_t index,
-    v8::Local<v8::Value>* object) {
-  ASSERT(RuntimeEnabledFeatures::sharedArrayBufferEnabled());
-  if (!m_arrayBufferContents)
-    return false;
-  if (index >= m_arrayBuffers.size())
-    return false;
-  v8::Local<v8::Value> result = m_arrayBuffers.at(index);
-  if (result.IsEmpty()) {
-    DOMSharedArrayBuffer* buffer =
-        DOMSharedArrayBuffer::create(m_arrayBufferContents->at(index));
-    v8::Isolate* isolate = m_reader.getScriptState()->isolate();
-    v8::Local<v8::Object> creationContext =
-        m_reader.getScriptState()->context()->Global();
-    result = ToV8(buffer, creationContext, isolate);
-    if (result.IsEmpty())
-      return false;
-    m_arrayBuffers[index] = result;
-  }
-  *object = result;
-  return true;
-}
-
-bool ScriptValueDeserializer::tryGetTransferredOffscreenCanvas(
-    uint32_t width,
-    uint32_t height,
-    uint32_t canvasId,
-    uint32_t clientId,
-    uint32_t sinkId,
-    v8::Local<v8::Value>* object) {
-  OffscreenCanvas* offscreenCanvas = OffscreenCanvas::create(width, height);
-  offscreenCanvas->setPlaceholderCanvasId(canvasId);
-  offscreenCanvas->setFrameSinkId(clientId, sinkId);
-  *object = ToV8(offscreenCanvas, m_reader.getScriptState());
-  if ((*object).IsEmpty())
-    return false;
-  return true;
-}
-
-bool ScriptValueDeserializer::tryGetObjectFromObjectReference(
-    uint32_t reference,
-    v8::Local<v8::Value>* object) {
-  if (reference >= m_objectPool.size())
-    return false;
-  *object = m_objectPool[reference];
-  return object;
-}
-
-uint32_t ScriptValueDeserializer::objectReferenceCount() {
-  return m_objectPool.size();
-}
-
-bool ScriptValueDeserializer::initializeObject(v8::Local<v8::Object> object,
-                                               uint32_t numProperties,
-                                               v8::Local<v8::Value>* value) {
-  unsigned length = 2 * numProperties;
-  if (length > stackDepth())
-    return false;
-  v8::Local<v8::Context> context = m_reader.getScriptState()->context();
-  for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) {
-    v8::Local<v8::Value> propertyName = element(i);
-    v8::Local<v8::Value> propertyValue = element(i + 1);
-    bool result = false;
-    if (propertyName->IsString())
-      result = v8CallBoolean(object->CreateDataProperty(
-          context, propertyName.As<v8::String>(), propertyValue));
-    else if (propertyName->IsUint32())
-      result = v8CallBoolean(object->CreateDataProperty(
-          context, propertyName.As<v8::Uint32>()->Value(), propertyValue));
-    else
-      ASSERT_NOT_REACHED();
-    if (!result)
-      return false;
-  }
-  pop(length);
-  *value = object;
-  return true;
-}
-
-bool ScriptValueDeserializer::read(v8::Local<v8::Value>* value) {
-  return m_reader.read(value, *this);
-}
-
-bool ScriptValueDeserializer::doDeserialize() {
-  v8::Local<v8::Value> value;
-  if (!read(&value))
-    return false;
-  if (!value.IsEmpty())
-    push(value);
-  return true;
-}
-
-v8::Local<v8::Value> ScriptValueDeserializer::element(unsigned index) {
-  SECURITY_DCHECK(index < m_stack.size());
-  return m_stack[index];
-}
-
-void ScriptValueDeserializer::openComposite(
-    const v8::Local<v8::Value>& object) {
-  uint32_t newObjectReference = m_objectPool.size();
-  m_openCompositeReferenceStack.push_back(newObjectReference);
-  m_objectPool.push_back(object);
-}
-
-bool ScriptValueDeserializer::closeComposite(v8::Local<v8::Value>* object) {
-  if (!m_openCompositeReferenceStack.size())
-    return false;
-  uint32_t objectReference =
-      m_openCompositeReferenceStack[m_openCompositeReferenceStack.size() - 1];
-  m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() -
-                                       1);
-  if (objectReference >= m_objectPool.size())
-    return false;
-  *object = m_objectPool[objectReference];
-  return true;
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
deleted file mode 100644
index 03ca5c5..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
+++ /dev/null
@@ -1,675 +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 ScriptValueSerializer_h
-#define ScriptValueSerializer_h
-
-#include "base/gtest_prod_util.h"
-#include "bindings/core/v8/SerializationTag.h"
-#include "bindings/core/v8/SerializedScriptValue.h"
-#include "bindings/core/v8/V8Binding.h"
-#include "core/CoreExport.h"
-#include "wtf/HashMap.h"
-#include "wtf/Noncopyable.h"
-#include "wtf/Vector.h"
-#include "wtf/text/WTFString.h"
-#include "wtf/typed_arrays/ArrayBufferContents.h"
-#include <v8.h>
-
-namespace blink {
-
-class CompositorProxy;
-class DOMArrayBuffer;
-class DOMArrayBufferView;
-class File;
-class FileList;
-class StaticBitmapImage;
-
-typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray;
-typedef Vector<RefPtr<StaticBitmapImage>, 1> ImageBitmapContentsArray;
-
-// V8ObjectMap is a map from V8 objects to arbitrary values of type T.
-// V8 objects (or handles to V8 objects) cannot be used as keys in ordinary
-// wtf::HashMaps; this class should be used instead. GCObject must be a subtype
-// of v8::Object.
-// Suggested usage:
-//     V8ObjectMap<v8::Object, int> map;
-//     v8::Local<v8::Object> obj = ...;
-//     map.set(obj, 42);
-template <typename GCObject, typename T>
-class V8ObjectMap {
-  STACK_ALLOCATED();
-
- public:
-  bool contains(const v8::Local<GCObject>& handle) {
-    return m_map.contains(*handle);
-  }
-
-  bool tryGet(const v8::Local<GCObject>& handle, T* valueOut) {
-    typename HandleToT::iterator result = m_map.find(*handle);
-    if (result != m_map.end()) {
-      *valueOut = result->value;
-      return true;
-    }
-    return false;
-  }
-
-  void set(const v8::Local<GCObject>& handle, const T& value) {
-    m_map.set(*handle, value);
-  }
-
- private:
-  // This implementation uses GetIdentityHash(), which sets a hidden property on
-  // the object containing a random integer (or returns the one that had been
-  // previously set). This ensures that the table never needs to be rebuilt
-  // across garbage collections at the expense of doing additional allocation
-  // and making more round trips into V8. Note that since GetIdentityHash() is
-  // defined only on v8::Objects, this V8ObjectMap cannot be used to map
-  // v8::Strings to T (because the public V8 API considers a v8::String to be a
-  // v8::Primitive).
-
-  // If V8 exposes a way to get at the address of the object held by a handle,
-  // then we can produce an alternate implementation that does not need to do
-  // any V8-side allocation; however, it will need to rehash after every garbage
-  // collection because a key object may have been moved.
-  template <typename G>
-  struct V8HandlePtrHash {
-    STATIC_ONLY(V8HandlePtrHash);
-    static v8::Local<G> unsafeHandleFromRawValue(const G* value) {
-      const v8::Local<G>* handle =
-          reinterpret_cast<const v8::Local<G>*>(&value);
-      return *handle;
-    }
-
-    static unsigned hash(const G* key) {
-      return static_cast<unsigned>(
-          unsafeHandleFromRawValue(key)->GetIdentityHash());
-    }
-    static bool equal(const G* a, const G* b) {
-      return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b);
-    }
-    // For HashArg.
-    static const bool safeToCompareToEmptyOrDeleted = false;
-  };
-
-  typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject>> HandleToT;
-  HandleToT m_map;
-};
-
-// SerializedScriptValueWriter is responsible for serializing primitive types
-// and storing information used to reconstruct composite types.
-class CORE_EXPORT SerializedScriptValueWriter {
-  STACK_ALLOCATED();
-  WTF_MAKE_NONCOPYABLE(SerializedScriptValueWriter);
-
- public:
-  typedef UChar BufferValueType;
-
-  SerializedScriptValueWriter() : m_position(0) {}
-
- protected:
-  friend class ScriptValueSerializer;
-
-  String takeWireString();
-
-  // Write functions for primitive types.
-  void writeUndefined();
-  void writeNull();
-  void writeTrue();
-  void writeFalse();
-  void writeBooleanObject(bool value);
-  void writeOneByteString(v8::Local<v8::String>&);
-  void writeRawStringBytes(v8::Local<v8::String>&);
-  void writeUtf8String(v8::Local<v8::String>&);
-  void writeUCharString(v8::Local<v8::String>&);
-  void writeStringObject(const char* data, int length);
-  void writeWebCoreString(const String&);
-  void writeVersion();
-  void writeInt32(int32_t value);
-  void writeUint32(uint32_t value);
-  void writeDate(double numberValue);
-  void writeNumber(double number);
-  void writeNumberObject(double number);
-  void writeBlob(const String& uuid,
-                 const String& type,
-                 unsigned long long size);
-  void writeBlobIndex(int blobIndex);
-  void writeCompositorProxy(const CompositorProxy&);
-  void writeFile(const File&);
-  void writeFileIndex(int blobIndex);
-  void writeFileList(const FileList&);
-  void writeFileListIndex(const Vector<int>& blobIndices);
-  void writeArrayBuffer(const DOMArrayBuffer&);
-  void writeArrayBufferView(const DOMArrayBufferView&);
-  void doWriteImageData(uint32_t width,
-                        uint32_t height,
-                        const uint8_t* pixelData,
-                        uint32_t pixelDataLength);
-  void writeImageData(uint32_t width,
-                      uint32_t height,
-                      const uint8_t* pixelData,
-                      uint32_t pixelDataLength);
-  void writeImageBitmap(uint32_t width,
-                        uint32_t height,
-                        uint32_t isOriginClean,
-                        uint32_t isPremultiplied,
-                        const uint8_t* pixelData,
-                        uint32_t pixelDataLength);
-  void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags);
-  void writeTransferredMessagePort(uint32_t index);
-  void writeTransferredArrayBuffer(uint32_t index);
-  void writeTransferredImageBitmap(uint32_t index);
-  void writeTransferredOffscreenCanvas(uint32_t width,
-                                       uint32_t height,
-                                       uint32_t canvasId,
-                                       uint32_t clientId,
-                                       uint32_t sinkId);
-  void writeTransferredSharedArrayBuffer(uint32_t index);
-  void writeObjectReference(uint32_t reference);
-  void writeObject(uint32_t numProperties);
-  void writeSparseArray(uint32_t numProperties, uint32_t length);
-  void writeDenseArray(uint32_t numProperties, uint32_t length);
-  void writeReferenceCount(uint32_t numberOfReferences);
-  void writeGenerateFreshObject();
-  void writeGenerateFreshSparseArray(uint32_t length);
-  void writeGenerateFreshDenseArray(uint32_t length);
-  void writeGenerateFreshMap();
-  void writeGenerateFreshSet();
-  void writeMap(uint32_t length);
-  void writeSet(uint32_t length);
-
-  void doWriteFile(const File&);
-  void doWriteArrayBuffer(const DOMArrayBuffer&);
-  void doWriteString(const char* data, int length);
-  void doWriteWebCoreString(const String&);
-  int bytesNeededToWireEncode(uint32_t value);
-
-  template <class T>
-  void doWriteUintHelper(T value) {
-    while (true) {
-      uint8_t b = (value & SerializedScriptValue::varIntMask);
-      value >>= SerializedScriptValue::varIntShift;
-      if (!value) {
-        append(b);
-        break;
-      }
-      append(b | (1 << SerializedScriptValue::varIntShift));
-    }
-  }
-
-  void doWriteUint32(uint32_t value);
-  void doWriteUint64(uint64_t value);
-  void doWriteNumber(double number);
-  void append(SerializationTag);
-  void append(uint8_t b);
-  void append(const uint8_t* data, int length);
-  void ensureSpace(unsigned extra);
-  void fillHole();
-  uint8_t* byteAt(int position);
-  int v8StringWriteOptions();
-
- private:
-  Vector<BufferValueType> m_buffer;
-  unsigned m_position;
-};
-
-class CORE_EXPORT ScriptValueSerializer {
-  STACK_ALLOCATED();
-  WTF_MAKE_NONCOPYABLE(ScriptValueSerializer);
-
- protected:
-  class StateBase;
-  enum class Status { Success, InputError, DataCloneError, JSException };
-
- public:
-  ScriptValueSerializer(SerializedScriptValueWriter&,
-                        WebBlobInfoArray*,
-                        ScriptState*);
-  v8::Isolate* isolate() { return m_scriptState->isolate(); }
-  v8::Local<v8::Context> context() { return m_scriptState->context(); }
-
-  PassRefPtr<SerializedScriptValue> serialize(v8::Local<v8::Value>,
-                                              Transferables*,
-                                              ExceptionState&);
-
- protected:
-  class StateBase {
-    USING_FAST_MALLOC(StateBase);
-    WTF_MAKE_NONCOPYABLE(StateBase);
-
-   public:
-    virtual ~StateBase() {}
-
-    // Link to the next state to form a stack.
-    StateBase* nextState() { return m_next; }
-
-    // Composite object we're processing in this state.
-    v8::Local<v8::Value> composite() { return m_composite; }
-
-    // Serializes (a part of) the current composite and returns
-    // the next state to process or null when this is the final
-    // state.
-    virtual StateBase* advance(ScriptValueSerializer&) = 0;
-
-   protected:
-    StateBase(v8::Local<v8::Value> composite, StateBase* next)
-        : m_composite(composite), m_next(next) {}
-
-   private:
-    v8::Local<v8::Value> m_composite;
-    StateBase* m_next;
-  };
-
-  // Dummy state that is used to signal serialization errors.
-  class ErrorState final : public StateBase {
-   public:
-    ErrorState() : StateBase(v8Undefined(), 0) {}
-
-    StateBase* advance(ScriptValueSerializer&) override {
-      delete this;
-      return 0;
-    }
-  };
-
-  template <typename T>
-  class State : public StateBase {
-   public:
-    v8::Local<T> composite() {
-      return v8::Local<T>::Cast(StateBase::composite());
-    }
-
-   protected:
-    State(v8::Local<T> composite, StateBase* next)
-        : StateBase(composite, next) {}
-  };
-
-  class AbstractObjectState : public State<v8::Object> {
-   public:
-    AbstractObjectState(v8::Local<v8::Object> object, StateBase* next)
-        : State<v8::Object>(object, next),
-          m_index(0),
-          m_numSerializedProperties(0) {}
-
-   protected:
-    virtual StateBase* objectDone(unsigned numProperties,
-                                  ScriptValueSerializer&) = 0;
-
-    StateBase* serializeProperties(ScriptValueSerializer&);
-    v8::Local<v8::Array> m_propertyNames;
-
-   private:
-    unsigned m_index;
-    unsigned m_numSerializedProperties;
-  };
-
-  class ObjectState final : public AbstractObjectState {
-   public:
-    ObjectState(v8::Local<v8::Object> object, StateBase* next)
-        : AbstractObjectState(object, next) {}
-
-    StateBase* advance(ScriptValueSerializer&) override;
-
-   protected:
-    StateBase* objectDone(unsigned numProperties,
-                          ScriptValueSerializer&) override;
-  };
-
-  class DenseArrayState final : public AbstractObjectState {
-   public:
-    DenseArrayState(v8::Local<v8::Array> array,
-                    v8::Local<v8::Array> propertyNames,
-                    StateBase* next,
-                    v8::Isolate* isolate)
-        : AbstractObjectState(array, next),
-          m_arrayIndex(0),
-          m_arrayLength(array->Length()) {
-      m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
-    }
-
-    StateBase* advance(ScriptValueSerializer&) override;
-
-   protected:
-    StateBase* objectDone(unsigned numProperties,
-                          ScriptValueSerializer&) override;
-
-   private:
-    uint32_t m_arrayIndex;
-    uint32_t m_arrayLength;
-  };
-
-  class SparseArrayState final : public AbstractObjectState {
-   public:
-    SparseArrayState(v8::Local<v8::Array> array,
-                     v8::Local<v8::Array> propertyNames,
-                     StateBase* next,
-                     v8::Isolate* isolate)
-        : AbstractObjectState(array, next) {
-      m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames);
-    }
-
-    StateBase* advance(ScriptValueSerializer&) override;
-
-   protected:
-    StateBase* objectDone(unsigned numProperties,
-                          ScriptValueSerializer&) override;
-  };
-
-  template <typename T>
-  class CollectionState : public State<T> {
-   public:
-    CollectionState(v8::Local<T> collection, StateBase* next)
-        : State<T>(collection, next),
-          m_entries(collection->AsArray()),
-          m_index(0),
-          m_length(m_entries->Length()) {}
-
-    StateBase* advance(ScriptValueSerializer&) override;
-
-   private:
-    v8::Local<v8::Array> m_entries;
-    uint32_t m_index;
-    uint32_t m_length;
-  };
-
-  typedef CollectionState<v8::Map> MapState;
-  typedef CollectionState<v8::Set> SetState;
-
-  virtual StateBase* doSerializeObject(v8::Local<v8::Object>, StateBase* next);
-
-  // Marks object as having been visited by the serializer and assigns it a
-  // unique object reference ID.  An object may only be greyed once.
-  void greyObject(const v8::Local<v8::Object>&);
-
-  StateBase* handleError(Status errorStatus, const String& message, StateBase*);
-
-  SerializedScriptValueWriter& writer() { return m_writer; }
-
- private:
-  StateBase* doSerialize(v8::Local<v8::Value>, StateBase* next);
-  StateBase* doSerializeArrayBuffer(v8::Local<v8::Value> arrayBuffer,
-                                    StateBase* next);
-  void transferData(Transferables*, ExceptionState&, SerializedScriptValue*);
-
-  StateBase* checkException(StateBase*);
-  StateBase* writeObject(uint32_t numProperties, StateBase*);
-  StateBase* writeSparseArray(uint32_t numProperties,
-                              uint32_t length,
-                              StateBase*);
-  StateBase* writeDenseArray(uint32_t numProperties,
-                             uint32_t length,
-                             StateBase*);
-
-  template <typename T>
-  StateBase* writeCollection(uint32_t length, StateBase*);
-
-  StateBase* push(StateBase* state) {
-    ASSERT(state);
-    ++m_depth;
-    return checkComposite(state) ? state
-                                 : handleError(Status::InputError,
-                                               "Value being cloned is either "
-                                               "cyclic or too deeply nested.",
-                                               state);
-  }
-
-  StateBase* pop(StateBase* state) {
-    ASSERT(state);
-    --m_depth;
-    StateBase* next = state->nextState();
-    delete state;
-    return next;
-  }
-
-  bool checkComposite(StateBase* top);
-  void writeString(v8::Local<v8::Value>);
-  void writeStringObject(v8::Local<v8::Value>);
-  void writeNumberObject(v8::Local<v8::Value>);
-  void writeBooleanObject(v8::Local<v8::Value>);
-  StateBase* writeBlob(v8::Local<v8::Value>, StateBase* next);
-  StateBase* writeCompositorProxy(v8::Local<v8::Value>, StateBase* next);
-  StateBase* writeFile(v8::Local<v8::Value>, StateBase* next);
-  StateBase* writeFileList(v8::Local<v8::Value>, StateBase* next);
-  void writeImageData(v8::Local<v8::Value>);
-  StateBase* writeAndGreyImageBitmap(v8::Local<v8::Object>, StateBase* next);
-  void writeRegExp(v8::Local<v8::Value>);
-  StateBase* writeAndGreyArrayBufferView(v8::Local<v8::Object>,
-                                         StateBase* next);
-  StateBase* writeWasmCompiledModule(v8::Local<v8::Object>, StateBase* next);
-  StateBase* writeAndGreyArrayBuffer(v8::Local<v8::Object>, StateBase* next);
-  StateBase* writeTransferredOffscreenCanvas(v8::Local<v8::Value>,
-                                             StateBase* next);
-  StateBase* writeTransferredSharedArrayBuffer(v8::Local<v8::Value>,
-                                               uint32_t index,
-                                               StateBase* next);
-  static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount);
-
-  StateBase* startArrayState(v8::Local<v8::Array>, StateBase* next);
-  StateBase* startObjectState(v8::Local<v8::Object>, StateBase* next);
-  StateBase* startMapState(v8::Local<v8::Map>, StateBase* next);
-  StateBase* startSetState(v8::Local<v8::Set>, StateBase* next);
-
-  bool appendBlobInfo(const String& uuid,
-                      const String& type,
-                      unsigned long long size,
-                      int* index);
-  bool appendFileInfo(const File*, int* index);
-
-  void copyTransferables(const Transferables&);
-
-  RefPtr<ScriptState> m_scriptState;
-  SerializedScriptValueWriter& m_writer;
-  v8::TryCatch m_tryCatch;
-  int m_depth;
-  Status m_status;
-  String m_errorMessage;
-  typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool;
-  ObjectPool m_objectPool;
-  ObjectPool m_transferredMessagePorts;
-  ObjectPool m_transferredArrayBuffers;
-  ObjectPool m_transferredImageBitmaps;
-  ObjectPool m_transferredOffscreenCanvas;
-  uint32_t m_nextObjectReference;
-  WebBlobInfoArray* m_blobInfo;
-  BlobDataHandleMap* m_blobDataHandles;
-};
-
-class ScriptValueDeserializer;
-
-// SerializedScriptValueReader is responsible for deserializing primitive types
-// and restoring information about saved objects of composite types.
-class CORE_EXPORT SerializedScriptValueReader {
-  STACK_ALLOCATED();
-  WTF_MAKE_NONCOPYABLE(SerializedScriptValueReader);
-
- public:
-  SerializedScriptValueReader(const uint8_t* buffer,
-                              int length,
-                              const WebBlobInfoArray* blobInfo,
-                              BlobDataHandleMap& blobDataHandles,
-                              ScriptState* scriptState)
-      : m_scriptState(scriptState),
-        m_buffer(buffer),
-        m_length(length),
-        m_position(0),
-        m_version(0),
-        m_blobInfo(blobInfo),
-        m_blobDataHandles(blobDataHandles) {
-    ASSERT(!(reinterpret_cast<size_t>(buffer) & 1));
-    ASSERT(length >= 0);
-  }
-
-  bool isEof() const { return m_position >= m_length; }
-
-  ScriptState* getScriptState() const { return m_scriptState.get(); }
-
-  virtual bool read(v8::Local<v8::Value>*, ScriptValueDeserializer&);
-  bool readVersion(uint32_t& version);
-  void setVersion(uint32_t);
-
- protected:
-  v8::Isolate* isolate() const { return m_scriptState->isolate(); }
-  v8::Local<v8::Context> context() const { return m_scriptState->context(); }
-  unsigned length() const { return m_length; }
-  unsigned position() const { return m_position; }
-
-  const uint8_t* allocate(uint32_t size) {
-    const uint8_t* allocated = m_buffer + m_position;
-    m_position += size;
-    return allocated;
-  }
-
-  bool readWithTag(SerializationTag,
-                   v8::Local<v8::Value>*,
-                   ScriptValueDeserializer&);
-
-  bool readTag(SerializationTag*);
-  bool readWebCoreString(String*);
-  bool readUint32(v8::Local<v8::Value>*);
-
-  bool doReadUint32(uint32_t* value);
-
- private:
-  void undoReadTag();
-  bool readArrayBufferViewSubTag(ArrayBufferViewSubTag*);
-  bool readString(v8::Local<v8::Value>*);
-  bool readUCharString(v8::Local<v8::Value>*);
-  bool readStringObject(v8::Local<v8::Value>*);
-  bool readInt32(v8::Local<v8::Value>*);
-  bool readDate(v8::Local<v8::Value>*);
-  bool readNumber(v8::Local<v8::Value>*);
-  bool readNumberObject(v8::Local<v8::Value>*);
-  bool doReadImageDataProperties(uint32_t* width,
-                                 uint32_t* height,
-                                 uint32_t* pixelDataLength);
-  bool readImageData(v8::Local<v8::Value>*);
-  bool readImageBitmap(v8::Local<v8::Value>*);
-  bool readCompositorProxy(v8::Local<v8::Value>*);
-  DOMArrayBuffer* doReadArrayBuffer();
-  bool readArrayBuffer(v8::Local<v8::Value>*);
-  bool readArrayBufferView(v8::Local<v8::Value>*, ScriptValueDeserializer&);
-  bool readWasmCompiledModule(v8::Local<v8::Value>*);
-  bool readRegExp(v8::Local<v8::Value>*);
-  bool readBlob(v8::Local<v8::Value>*, bool isIndexed);
-  bool readFile(v8::Local<v8::Value>*, bool isIndexed);
-  bool readFileList(v8::Local<v8::Value>*, bool isIndexed);
-  File* readFileHelper();
-  File* readFileIndexHelper();
-
-  template <class T>
-  bool doReadUintHelper(T* value) {
-    *value = 0;
-    uint8_t currentByte;
-    int shift = 0;
-    do {
-      if (m_position >= m_length)
-        return false;
-      currentByte = m_buffer[m_position++];
-      *value |= (static_cast<T>(currentByte & SerializedScriptValue::varIntMask)
-                 << shift);
-      shift += SerializedScriptValue::varIntShift;
-    } while (currentByte & (1 << SerializedScriptValue::varIntShift));
-    return true;
-  }
-
-  bool doReadUint64(uint64_t* value);
-  bool doReadNumber(double* number);
-  PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid,
-                                                       const String& type,
-                                                       long long size = -1);
-
-  RefPtr<ScriptState> m_scriptState;
-  const uint8_t* m_buffer;
-  const unsigned m_length;
-  unsigned m_position;
-  uint32_t m_version;
-  const WebBlobInfoArray* m_blobInfo;
-  const BlobDataHandleMap& m_blobDataHandles;
-
-  FRIEND_TEST_ALL_PREFIXES(ScriptValueSerializerTest, Uint64Decode);
-};
-
-class CORE_EXPORT ScriptValueDeserializer {
-  STACK_ALLOCATED();
-  WTF_MAKE_NONCOPYABLE(ScriptValueDeserializer);
-
- public:
-  ScriptValueDeserializer(SerializedScriptValueReader& reader,
-                          MessagePortArray* messagePorts,
-                          ArrayBufferContentsArray* arrayBufferContents,
-                          ImageBitmapContentsArray* imageBitmapContents)
-      : m_reader(reader),
-        m_transferredMessagePorts(messagePorts),
-        m_arrayBufferContents(arrayBufferContents),
-        m_imageBitmapContents(imageBitmapContents),
-        m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0),
-        m_imageBitmaps(imageBitmapContents ? imageBitmapContents->size() : 0),
-        m_version(0) {}
-
-  v8::Local<v8::Value> deserialize();
-  bool newSparseArray(uint32_t);
-  bool newDenseArray(uint32_t length);
-  bool newMap();
-  bool newSet();
-  bool consumeTopOfStack(v8::Local<v8::Value>*);
-  bool newObject();
-  bool completeObject(uint32_t numProperties, v8::Local<v8::Value>*);
-  bool completeSparseArray(uint32_t numProperties,
-                           uint32_t length,
-                           v8::Local<v8::Value>*);
-  bool completeDenseArray(uint32_t numProperties,
-                          uint32_t length,
-                          v8::Local<v8::Value>*);
-  bool completeMap(uint32_t length, v8::Local<v8::Value>*);
-  bool completeSet(uint32_t length, v8::Local<v8::Value>*);
-  void pushObjectReference(const v8::Local<v8::Value>&);
-  bool tryGetTransferredMessagePort(uint32_t index, v8::Local<v8::Value>*);
-  bool tryGetTransferredArrayBuffer(uint32_t index, v8::Local<v8::Value>*);
-  bool tryGetTransferredImageBitmap(uint32_t index, v8::Local<v8::Value>*);
-  bool tryGetTransferredOffscreenCanvas(uint32_t width,
-                                        uint32_t height,
-                                        uint32_t canvasId,
-                                        uint32_t clientId,
-                                        uint32_t sinkId,
-                                        v8::Local<v8::Value>*);
-  bool tryGetTransferredSharedArrayBuffer(uint32_t index,
-                                          v8::Local<v8::Value>*);
-  bool tryGetObjectFromObjectReference(uint32_t reference,
-                                       v8::Local<v8::Value>*);
-  uint32_t objectReferenceCount();
-
- protected:
-  SerializedScriptValueReader& reader() { return m_reader; }
-  virtual bool read(v8::Local<v8::Value>*);
-
- private:
-  bool initializeObject(v8::Local<v8::Object>,
-                        uint32_t numProperties,
-                        v8::Local<v8::Value>*);
-  bool doDeserialize();
-  void push(v8::Local<v8::Value> value) { m_stack.push_back(value); };
-  void pop(unsigned length) {
-    ASSERT(length <= m_stack.size());
-    m_stack.shrink(m_stack.size() - length);
-  }
-  unsigned stackDepth() const { return m_stack.size(); }
-
-  v8::Local<v8::Value> element(unsigned index);
-  void openComposite(const v8::Local<v8::Value>&);
-  bool closeComposite(v8::Local<v8::Value>*);
-
-  SerializedScriptValueReader& m_reader;
-  Vector<v8::Local<v8::Value>> m_stack;
-  Vector<v8::Local<v8::Value>> m_objectPool;
-  Vector<uint32_t> m_openCompositeReferenceStack;
-  MessagePortArray* m_transferredMessagePorts;
-  ArrayBufferContentsArray* m_arrayBufferContents;
-  ImageBitmapContentsArray* m_imageBitmapContents;
-  Vector<v8::Local<v8::Value>> m_arrayBuffers;
-  Vector<v8::Local<v8::Value>> m_imageBitmaps;
-  uint32_t m_version;
-};
-
-}  // namespace blink
-
-#endif  // ScriptValueSerializer_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializerTest.cpp
deleted file mode 100644
index 5c177dc7..0000000
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializerTest.cpp
+++ /dev/null
@@ -1,39 +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 "bindings/core/v8/ScriptValueSerializer.h"
-
-#include "bindings/core/v8/ScriptController.h"
-#include "core/layout/LayoutTestHelper.h"
-#include "wtf/Alignment.h"
-
-namespace blink {
-
-class ScriptValueSerializerTest : public RenderingTest {
- public:
-  FrameSettingOverrideFunction settingOverrider() const override {
-    return &overrideSettings;
-  }
-
- private:
-  static void overrideSettings(Settings& settings) {
-    settings.setScriptEnabled(true);
-  }
-};
-
-TEST_F(ScriptValueSerializerTest, Uint64Decode) {
-  // Even large 64-bit integers should decode properly.
-  const uint64_t expected = 0x123456789abcdef0;
-  WTF_ALIGNED(const uint8_t, buffer[], sizeof(UChar)) = {
-      0xf0, 0xbd, 0xf3, 0xd5, 0x89, 0xcf, 0x95, 0x9a, 0x92, 0x00};
-  BlobDataHandleMap blobDataHandleMap;
-  SerializedScriptValueReader reader(
-      buffer, sizeof(buffer), nullptr, blobDataHandleMap,
-      ScriptState::forMainWorld(document().frame()));
-  uint64_t actual;
-  ASSERT_TRUE(reader.doReadUint64(&actual));
-  EXPECT_EQ(expected, actual);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
index 986d3f3c..b247d2c 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp
@@ -34,7 +34,6 @@
 #include "bindings/core/v8/DOMWrapperWorld.h"
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/ScriptState.h"
-#include "bindings/core/v8/ScriptValueSerializer.h"
 #include "bindings/core/v8/SerializedScriptValueFactory.h"
 #include "bindings/core/v8/Transferables.h"
 #include "bindings/core/v8/V8ArrayBuffer.h"
@@ -205,7 +204,7 @@
   }
 }
 
-std::unique_ptr<ImageBitmapContentsArray>
+std::unique_ptr<SerializedScriptValue::ImageBitmapContentsArray>
 SerializedScriptValue::transferImageBitmapContents(
     v8::Isolate* isolate,
     const ImageBitmapArray& imageBitmaps,
@@ -391,7 +390,7 @@
   return true;
 }
 
-std::unique_ptr<ArrayBufferContentsArray>
+std::unique_ptr<SerializedScriptValue::ArrayBufferContentsArray>
 SerializedScriptValue::transferArrayBufferContents(
     v8::Isolate* isolate,
     const ArrayBufferArray& arrayBuffers,
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp
index 9bc601d..84b662a5 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.cpp
@@ -4,17 +4,9 @@
 
 #include "bindings/core/v8/SerializedScriptValueFactory.h"
 
-#include "bindings/core/v8/ExceptionState.h"
-#include "bindings/core/v8/ScriptValueSerializer.h"
-#include "bindings/core/v8/Transferables.h"
 #include "bindings/core/v8/serialization/V8ScriptValueDeserializer.h"
 #include "bindings/core/v8/serialization/V8ScriptValueSerializer.h"
-#include "core/dom/DOMArrayBuffer.h"
-#include "core/dom/MessagePort.h"
-#include "core/frame/ImageBitmap.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
-#include "wtf/ByteOrder.h"
-#include "wtf/text/StringBuffer.h"
 
 namespace blink {
 
@@ -27,14 +19,8 @@
     WebBlobInfoArray* blobInfo,
     ExceptionState& exceptionState) {
   TRACE_EVENT0("blink", "SerializedScriptValueFactory::create");
-  if (RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) {
-    V8ScriptValueSerializer serializer(ScriptState::current(isolate));
-    serializer.setBlobInfoArray(blobInfo);
-    return serializer.serialize(value, transferables, exceptionState);
-  }
-  SerializedScriptValueWriter writer;
-  ScriptValueSerializer serializer(writer, blobInfo,
-                                   ScriptState::current(isolate));
+  V8ScriptValueSerializer serializer(ScriptState::current(isolate));
+  serializer.setBlobInfoArray(blobInfo);
   return serializer.serialize(value, transferables, exceptionState);
 }
 
@@ -44,35 +30,9 @@
     MessagePortArray* messagePorts,
     const WebBlobInfoArray* blobInfo) {
   TRACE_EVENT0("blink", "SerializedScriptValueFactory::deserialize");
-  if (RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) {
-    V8ScriptValueDeserializer deserializer(ScriptState::current(isolate),
-                                           value);
-    deserializer.setTransferredMessagePorts(messagePorts);
-    deserializer.setBlobInfoArray(blobInfo);
-    return deserializer.deserialize();
-  }
-  // deserialize() can run arbitrary script (e.g., setters), which could result
-  // in |this| being destroyed.  Holding a RefPtr ensures we are alive (along
-  // with our internal data) throughout the operation.
-  RefPtr<SerializedScriptValue> protect(value);
-  if (!value->dataLengthInBytes())
-    return v8::Null(isolate);
-  static_assert(sizeof(SerializedScriptValueWriter::BufferValueType) == 2,
-                "BufferValueType should be 2 bytes");
-  // FIXME: SerializedScriptValue shouldn't use String for its underlying
-  // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
-  // information stored in m_data isn't even encoded in UTF-16. Instead,
-  // unicode characters are encoded as UTF-8 with two code units per UChar.
-  SerializedScriptValueReader reader(value->data(), value->dataLengthInBytes(),
-                                     blobInfo, value->blobDataHandles(),
-                                     ScriptState::current(isolate));
-  ScriptValueDeserializer deserializer(reader, messagePorts,
-                                       value->getArrayBufferContentsArray(),
-                                       value->getImageBitmapContentsArray());
-
-  // deserialize() can run arbitrary script (e.g., setters), which could result
-  // in |this| being destroyed.  Holding a RefPtr ensures we are alive (along
-  // with our internal data) throughout the operation.
+  V8ScriptValueDeserializer deserializer(ScriptState::current(isolate), value);
+  deserializer.setTransferredMessagePorts(messagePorts);
+  deserializer.setBlobInfoArray(blobInfo);
   return deserializer.deserialize();
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h
index 183939e..b597799 100644
--- a/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h
+++ b/third_party/WebKit/Source/bindings/core/v8/SerializedScriptValueFactory.h
@@ -5,7 +5,6 @@
 #ifndef SerializedScriptValueFactory_h
 #define SerializedScriptValueFactory_h
 
-#include "bindings/core/v8/ScriptValueSerializer.h"
 #include "bindings/core/v8/SerializedScriptValue.h"
 #include "core/CoreExport.h"
 #include "wtf/Allocator.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8EventListenerInfo.h b/third_party/WebKit/Source/bindings/core/v8/V8EventListenerInfo.h
index c39b7c6..4b20e36 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8EventListenerInfo.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8EventListenerInfo.h
@@ -19,13 +19,15 @@
                       bool passive,
                       bool once,
                       v8::Local<v8::Object> handler,
-                      v8::MaybeLocal<v8::Function> removeFunction)
+                      v8::MaybeLocal<v8::Function> removeFunction,
+                      int backendNodeId)
       : eventType(eventType),
         useCapture(useCapture),
         passive(passive),
         once(once),
         handler(handler),
-        removeFunction(removeFunction) {}
+        removeFunction(removeFunction),
+        backendNodeId(backendNodeId) {}
 
   AtomicString eventType;
   bool useCapture;
@@ -33,6 +35,7 @@
   bool once;
   v8::Local<v8::Object> handler;
   v8::MaybeLocal<v8::Function> removeFunction;
+  int backendNodeId;
 };
 
 using V8EventListenerInfoList = Vector<V8EventListenerInfo>;
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp
index a794acb..9e61550 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/SerializedScriptValueFuzzer.cpp
@@ -9,7 +9,6 @@
 #include "core/dom/MessagePort.h"
 #include "core/frame/Settings.h"
 #include "core/testing/DummyPageHolder.h"
-#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/testing/BlinkFuzzerTestSupport.h"
 #include "public/platform/WebBlobInfo.h"
 #include "public/platform/WebMessagePortChannel.h"
@@ -51,7 +50,6 @@
   const char kExposeGC[] = "--expose_gc";
   v8::V8::SetFlagsFromString(kExposeGC, sizeof(kExposeGC));
   InitializeBlinkFuzzTest(argc, argv);
-  RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(true);
   pageHolder = DummyPageHolder::create().release();
   pageHolder->frame().settings()->setScriptEnabled(true);
   blobInfoArray = new WebBlobInfoArray();
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp
index 7df19a1..68a6afc8 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueDeserializer.cpp
@@ -32,7 +32,6 @@
                      m_serializedScriptValue->data(),
                      m_serializedScriptValue->dataLengthInBytes(),
                      this) {
-  DCHECK(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled());
   m_deserializer.SetSupportsLegacyWireFormat(true);
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp
index d4cfa6b6..377090f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializer.cpp
@@ -30,7 +30,6 @@
     : m_scriptState(std::move(scriptState)),
       m_serializedScriptValue(SerializedScriptValue::create()),
       m_serializer(m_scriptState->isolate(), this) {
-  DCHECK(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled());
 }
 
 RefPtr<SerializedScriptValue> V8ScriptValueSerializer::serialize(
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
index 7e3a5d0..c9414d97 100644
--- a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
@@ -44,20 +44,6 @@
 namespace blink {
 namespace {
 
-class ScopedEnableV8BasedStructuredClone {
- public:
-  ScopedEnableV8BasedStructuredClone()
-      : m_wasEnabled(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) {
-    RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(true);
-  }
-  ~ScopedEnableV8BasedStructuredClone() {
-    RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(m_wasEnabled);
-  }
-
- private:
-  bool m_wasEnabled;
-};
-
 RefPtr<SerializedScriptValue> serializedValue(const Vector<uint8_t>& bytes) {
   // TODO(jbroman): Fix this once SerializedScriptValue can take bytes without
   // endianness swapping.
@@ -133,7 +119,6 @@
 TEST(V8ScriptValueSerializerTest, RoundTripJSONLikeValue) {
   // Ensure that simple JavaScript objects work.
   // There are more exhaustive tests of JavaScript objects in V8.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   v8::Local<v8::Value> object = eval("({ foo: [1, 2, 3], bar: 'baz' })", scope);
   DCHECK(object->IsObject());
@@ -149,7 +134,6 @@
   // are encountered in V8 (for example, cloning a symbol). It should be an
   // instance of DOMException, and it should have a proper descriptive
   // message.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
   ExceptionState exceptionState(scope.isolate(),
@@ -168,7 +152,6 @@
 TEST(V8ScriptValueSerializerTest, RethrowsScriptError) {
   // Ensure that other exceptions, like those thrown by script, are properly
   // rethrown.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
   ExceptionState exceptionState(scope.isolate(),
@@ -187,7 +170,6 @@
 TEST(V8ScriptValueSerializerTest, DeserializationErrorReturnsNull) {
   // If there's a problem during deserialization, it results in null, but no
   // exception.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
   RefPtr<SerializedScriptValue> invalid =
@@ -201,7 +183,6 @@
 TEST(V8ScriptValueSerializerTest, NeuteringHappensAfterSerialization) {
   // This object will throw an exception before the [[Transfer]] step.
   // As a result, the ArrayBuffer will not be transferred.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ExceptionState exceptionState(scope.isolate(),
                                 ExceptionState::ExecutionContext, "Window",
@@ -222,7 +203,6 @@
 
 TEST(V8ScriptValueSerializerTest, RoundTripImageData) {
   // ImageData objects should serialize and deserialize correctly.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ImageData* imageData = ImageData::create(2, 1, ASSERT_NO_EXCEPTION);
   imageData->data()->data()[0] = 200;
@@ -241,7 +221,6 @@
   // Backward compatibility with existing serialized ImageData objects must be
   // maintained. Add more cases if the format changes; don't remove tests for
   // old versions.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
   RefPtr<SerializedScriptValue> input =
@@ -281,7 +260,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, RoundTripMessagePort) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
 
   WebMessagePortChannel* unownedChannel;
@@ -301,7 +279,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, NeuteredMessagePortThrowsDataCloneError) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ExceptionState exceptionState(scope.isolate(),
                                 ExceptionState::ExecutionContext, "Window",
@@ -320,7 +297,6 @@
 
 TEST(V8ScriptValueSerializerTest,
      UntransferredMessagePortThrowsDataCloneError) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ExceptionState exceptionState(scope.isolate(),
                                 ExceptionState::ExecutionContext, "Window",
@@ -338,7 +314,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, OutOfRangeMessagePortIndex) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
   RefPtr<SerializedScriptValue> input =
@@ -378,7 +353,6 @@
 
 // A more exhaustive set of ImageBitmap cases are covered by LayoutTests.
 TEST(V8ScriptValueSerializerTest, RoundTripImageBitmap) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
 
   // Make a 10x7 red ImageBitmap.
@@ -409,7 +383,6 @@
   // Backward compatibility with existing serialized ImageBitmap objects must be
   // maintained. Add more cases if the format changes; don't remove tests for
   // old versions.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -445,7 +418,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, InvalidImageBitmapDecode) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
   {
@@ -484,7 +456,6 @@
 
 TEST(V8ScriptValueSerializerTest, TransferImageBitmap) {
   // More thorough tests exist in LayoutTests/.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
 
   sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(10, 7);
@@ -518,7 +489,6 @@
 
 TEST(V8ScriptValueSerializerTest, TransferOffscreenCanvas) {
   // More exhaustive tests in LayoutTests/. This is a sanity check.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   OffscreenCanvas* canvas = OffscreenCanvas::create(10, 7);
   canvas->setPlaceholderCanvasId(519);
@@ -537,7 +507,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, RoundTripBlob) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   const char kHelloWorld[] = "Hello world!";
   Blob* blob =
@@ -555,7 +524,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeBlob) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input = serializedValue(
       {0xff, 0x09, 0x3f, 0x00, 0x62, 0x24, 0x64, 0x38, 0x37, 0x35, 0x64,
@@ -573,7 +541,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, RoundTripBlobIndex) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   const char kHelloWorld[] = "Hello world!";
   Blob* blob =
@@ -604,7 +571,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeBlobIndex) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input =
       serializedValue({0xff, 0x09, 0x3f, 0x00, 0x69, 0x00});
@@ -622,7 +588,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeBlobIndexOutOfRange) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input =
       serializedValue({0xff, 0x09, 0x3f, 0x00, 0x69, 0x01});
@@ -641,7 +606,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, RoundTripFileNative) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   File* file = File::create("/native/path");
   v8::Local<v8::Value> wrapper = ToV8(file, scope.getScriptState());
@@ -654,7 +618,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, RoundTripFileBackedByBlob) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   const double modificationTime = 0.0;
   RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create();
@@ -669,7 +632,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, RoundTripFileNativeSnapshot) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   FileMetadata metadata;
   metadata.platformPath = "/native/snapshot";
@@ -686,7 +648,6 @@
 
 TEST(V8ScriptValueSerializerTest, RoundTripFileNonNativeSnapshot) {
   // Preserving behavior, filesystem URL is not preserved across cloning.
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   KURL url(ParsedURLString,
            "filesystem:http://example.com/isolated/hash/non-native-file");
@@ -716,7 +677,6 @@
 };
 
 TEST(V8ScriptValueSerializerTest, DecodeFileV3) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   TimeIntervalChecker timeIntervalChecker;
   RefPtr<SerializedScriptValue> input = serializedValue(
@@ -739,7 +699,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeFileV4) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   TimeIntervalChecker timeIntervalChecker;
   RefPtr<SerializedScriptValue> input = serializedValue(
@@ -765,7 +724,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeFileV4WithSnapshot) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input = serializedValue(
       {0xff, 0x04, 0x3f, 0x00, 0x66, 0x04, 'p', 'a',  't',  'h',  0x04, 'n',
@@ -792,7 +750,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeFileV7) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   TimeIntervalChecker timeIntervalChecker;
   RefPtr<SerializedScriptValue> input = serializedValue(
@@ -818,7 +775,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeFileV8WithSnapshot) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input = serializedValue(
       {0xff, 0x08, 0x3f, 0x00, 0x66, 0x04, 'p',  'a',  't',  'h',  0x04, 'n',
@@ -846,7 +802,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, RoundTripFileIndex) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   File* file = File::create("/native/path");
   v8::Local<v8::Value> wrapper = ToV8(file, scope.getScriptState());
@@ -871,7 +826,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeFileIndex) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input =
       serializedValue({0xff, 0x09, 0x3f, 0x00, 0x65, 0x00});
@@ -890,7 +844,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeFileIndexOutOfRange) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input =
       serializedValue({0xff, 0x09, 0x3f, 0x00, 0x65, 0x01});
@@ -912,7 +865,6 @@
 // fairly basic.
 
 TEST(V8ScriptValueSerializerTest, RoundTripFileList) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   FileList* fileList = FileList::create();
   fileList->append(File::create("/native/path"));
@@ -927,7 +879,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeEmptyFileList) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input =
       serializedValue({0xff, 0x09, 0x3f, 0x00, 0x6c, 0x00});
@@ -939,7 +890,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeFileListWithInvalidLength) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input =
       serializedValue({0xff, 0x09, 0x3f, 0x00, 0x6c, 0x01});
@@ -949,7 +899,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeFileListV8WithoutSnapshot) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   TimeIntervalChecker timeIntervalChecker;
   RefPtr<SerializedScriptValue> input = serializedValue(
@@ -977,7 +926,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, RoundTripFileListIndex) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   FileList* fileList = FileList::create();
   fileList->append(File::create("/native/path"));
@@ -1003,7 +951,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeEmptyFileListIndex) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input =
       serializedValue({0xff, 0x09, 0x3f, 0x00, 0x4c, 0x00});
@@ -1017,7 +964,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeFileListIndexWithInvalidLength) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input =
       serializedValue({0xff, 0x09, 0x3f, 0x00, 0x4c, 0x02});
@@ -1029,7 +975,6 @@
 }
 
 TEST(V8ScriptValueSerializerTest, DecodeFileListIndex) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   RefPtr<SerializedScriptValue> input =
       serializedValue({0xff, 0x09, 0x3f, 0x00, 0x4c, 0x01, 0x00, 0x00});
@@ -1064,7 +1009,6 @@
 
 TEST(V8ScriptValueSerializerTest, RoundTripCompositorProxy) {
   ScopedEnableCompositorWorker enableCompositorWorker;
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   HTMLElement* element = scope.document().body();
   Vector<String> properties{"transform"};
@@ -1088,7 +1032,6 @@
 // TODO(jbroman): Update this if that turns out not to be the case.
 
 TEST(V8ScriptValueSerializerTest, DecodeHardcodedNullValue) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   EXPECT_TRUE(V8ScriptValueDeserializer(scope.getScriptState(),
                                         SerializedScriptValue::nullValue())
diff --git a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp b/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp
deleted file mode 100644
index 2a66441..0000000
--- a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp
+++ /dev/null
@@ -1,667 +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 "bindings/modules/v8/ScriptValueSerializerForModules.h"
-
-#include "bindings/core/v8/SerializationTag.h"
-#include "bindings/core/v8/V8Binding.h"
-#include "bindings/modules/v8/V8CryptoKey.h"
-#include "bindings/modules/v8/V8DOMFileSystem.h"
-#include "bindings/modules/v8/V8RTCCertificate.h"
-#include "bindings/modules/v8/serialization/WebCryptoSubTags.h"
-#include "modules/filesystem/DOMFileSystem.h"
-#include "modules/peerconnection/RTCCertificate.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebRTCCertificate.h"
-#include "public/platform/WebRTCCertificateGenerator.h"
-#include "wtf/PtrUtil.h"
-#include <memory>
-
-namespace blink {
-
-ScriptValueSerializerForModules::ScriptValueSerializerForModules(
-    SerializedScriptValueWriter& writer,
-    WebBlobInfoArray* blobInfo,
-    ScriptState* scriptState)
-    : ScriptValueSerializer(writer, blobInfo, scriptState) {}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializerForModules::writeDOMFileSystem(v8::Local<v8::Value> value,
-                                                    StateBase* next) {
-  DOMFileSystem* fs = V8DOMFileSystem::toImpl(value.As<v8::Object>());
-  if (!fs)
-    return 0;
-  if (!fs->clonable())
-    return handleError(Status::DataCloneError,
-                       "A FileSystem object could not be cloned.", next);
-
-  toSerializedScriptValueWriterForModules(writer()).writeDOMFileSystem(
-      fs->type(), fs->name(), fs->rootURL().getString());
-  return 0;
-}
-
-bool ScriptValueSerializerForModules::writeCryptoKey(
-    v8::Local<v8::Value> value) {
-  CryptoKey* key = V8CryptoKey::toImpl(value.As<v8::Object>());
-  if (!key)
-    return false;
-  return toSerializedScriptValueWriterForModules(writer()).writeCryptoKey(
-      key->key());
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializerForModules::writeRTCCertificate(v8::Local<v8::Value> value,
-                                                     StateBase* next) {
-  RTCCertificate* certificate =
-      V8RTCCertificate::toImpl(value.As<v8::Object>());
-  if (!certificate)
-    return handleError(Status::DataCloneError,
-                       "An RTCCertificate object could not be cloned.", next);
-  toSerializedScriptValueWriterForModules(writer()).writeRTCCertificate(
-      *certificate);
-  return nullptr;
-}
-
-void SerializedScriptValueWriterForModules::writeDOMFileSystem(
-    int type,
-    const String& name,
-    const String& url) {
-  append(DOMFileSystemTag);
-  doWriteUint32(type);
-  doWriteWebCoreString(name);
-  doWriteWebCoreString(url);
-}
-
-bool SerializedScriptValueWriterForModules::writeCryptoKey(
-    const WebCryptoKey& key) {
-  append(static_cast<uint8_t>(CryptoKeyTag));
-
-  switch (key.algorithm().paramsType()) {
-    case WebCryptoKeyAlgorithmParamsTypeAes:
-      doWriteAesKey(key);
-      break;
-    case WebCryptoKeyAlgorithmParamsTypeHmac:
-      doWriteHmacKey(key);
-      break;
-    case WebCryptoKeyAlgorithmParamsTypeRsaHashed:
-      doWriteRsaHashedKey(key);
-      break;
-    case WebCryptoKeyAlgorithmParamsTypeEc:
-      doWriteEcKey(key);
-      break;
-    case WebCryptoKeyAlgorithmParamsTypeNone:
-      doWriteKeyWithoutParams(key);
-      break;
-  }
-
-  doWriteKeyUsages(key.usages(), key.extractable());
-
-  WebVector<uint8_t> keyData;
-  if (!Platform::current()->crypto()->serializeKeyForClone(key, keyData))
-    return false;
-
-  doWriteUint32(keyData.size());
-  append(keyData.data(), keyData.size());
-  return true;
-}
-
-void SerializedScriptValueWriterForModules::writeRTCCertificate(
-    const RTCCertificate& certificate) {
-  append(RTCCertificateTag);
-
-  WebRTCCertificatePEM pem = certificate.certificateShallowCopy()->toPEM();
-  doWriteWebCoreString(pem.privateKey());
-  doWriteWebCoreString(pem.certificate());
-}
-
-void SerializedScriptValueWriterForModules::doWriteHmacKey(
-    const WebCryptoKey& key) {
-  ASSERT(key.algorithm().paramsType() == WebCryptoKeyAlgorithmParamsTypeHmac);
-
-  append(static_cast<uint8_t>(HmacKeyTag));
-  ASSERT(!(key.algorithm().hmacParams()->lengthBits() % 8));
-  doWriteUint32(key.algorithm().hmacParams()->lengthBits() / 8);
-  doWriteAlgorithmId(key.algorithm().hmacParams()->hash().id());
-}
-
-void SerializedScriptValueWriterForModules::doWriteAesKey(
-    const WebCryptoKey& key) {
-  ASSERT(key.algorithm().paramsType() == WebCryptoKeyAlgorithmParamsTypeAes);
-
-  append(static_cast<uint8_t>(AesKeyTag));
-  doWriteAlgorithmId(key.algorithm().id());
-  // Converting the key length from bits to bytes is lossless and makes
-  // it fit in 1 byte.
-  ASSERT(!(key.algorithm().aesParams()->lengthBits() % 8));
-  doWriteUint32(key.algorithm().aesParams()->lengthBits() / 8);
-}
-
-void SerializedScriptValueWriterForModules::doWriteRsaHashedKey(
-    const WebCryptoKey& key) {
-  ASSERT(key.algorithm().rsaHashedParams());
-  append(static_cast<uint8_t>(RsaHashedKeyTag));
-
-  doWriteAlgorithmId(key.algorithm().id());
-  doWriteAsymmetricKeyType(key.type());
-
-  const WebCryptoRsaHashedKeyAlgorithmParams* params =
-      key.algorithm().rsaHashedParams();
-  doWriteUint32(params->modulusLengthBits());
-  doWriteUint32(params->publicExponent().size());
-  append(params->publicExponent().data(), params->publicExponent().size());
-  doWriteAlgorithmId(params->hash().id());
-}
-
-void SerializedScriptValueWriterForModules::doWriteEcKey(
-    const WebCryptoKey& key) {
-  ASSERT(key.algorithm().ecParams());
-  append(static_cast<uint8_t>(EcKeyTag));
-
-  doWriteAlgorithmId(key.algorithm().id());
-  doWriteAsymmetricKeyType(key.type());
-  doWriteNamedCurve(key.algorithm().ecParams()->namedCurve());
-}
-
-void SerializedScriptValueWriterForModules::doWriteKeyWithoutParams(
-    const WebCryptoKey& key) {
-  ASSERT(WebCryptoAlgorithm::isKdf(key.algorithm().id()));
-  append(static_cast<uint8_t>(NoParamsKeyTag));
-
-  doWriteAlgorithmId(key.algorithm().id());
-}
-
-void SerializedScriptValueWriterForModules::doWriteAlgorithmId(
-    WebCryptoAlgorithmId id) {
-  switch (id) {
-    case WebCryptoAlgorithmIdAesCbc:
-      return doWriteUint32(AesCbcTag);
-    case WebCryptoAlgorithmIdHmac:
-      return doWriteUint32(HmacTag);
-    case WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
-      return doWriteUint32(RsaSsaPkcs1v1_5Tag);
-    case WebCryptoAlgorithmIdSha1:
-      return doWriteUint32(Sha1Tag);
-    case WebCryptoAlgorithmIdSha256:
-      return doWriteUint32(Sha256Tag);
-    case WebCryptoAlgorithmIdSha384:
-      return doWriteUint32(Sha384Tag);
-    case WebCryptoAlgorithmIdSha512:
-      return doWriteUint32(Sha512Tag);
-    case WebCryptoAlgorithmIdAesGcm:
-      return doWriteUint32(AesGcmTag);
-    case WebCryptoAlgorithmIdRsaOaep:
-      return doWriteUint32(RsaOaepTag);
-    case WebCryptoAlgorithmIdAesCtr:
-      return doWriteUint32(AesCtrTag);
-    case WebCryptoAlgorithmIdAesKw:
-      return doWriteUint32(AesKwTag);
-    case WebCryptoAlgorithmIdRsaPss:
-      return doWriteUint32(RsaPssTag);
-    case WebCryptoAlgorithmIdEcdsa:
-      return doWriteUint32(EcdsaTag);
-    case WebCryptoAlgorithmIdEcdh:
-      return doWriteUint32(EcdhTag);
-    case WebCryptoAlgorithmIdHkdf:
-      return doWriteUint32(HkdfTag);
-    case WebCryptoAlgorithmIdPbkdf2:
-      return doWriteUint32(Pbkdf2Tag);
-  }
-  ASSERT_NOT_REACHED();
-}
-
-void SerializedScriptValueWriterForModules::doWriteAsymmetricKeyType(
-    WebCryptoKeyType keyType) {
-  switch (keyType) {
-    case WebCryptoKeyTypePublic:
-      doWriteUint32(PublicKeyType);
-      break;
-    case WebCryptoKeyTypePrivate:
-      doWriteUint32(PrivateKeyType);
-      break;
-    case WebCryptoKeyTypeSecret:
-      ASSERT_NOT_REACHED();
-  }
-}
-
-void SerializedScriptValueWriterForModules::doWriteNamedCurve(
-    WebCryptoNamedCurve namedCurve) {
-  switch (namedCurve) {
-    case WebCryptoNamedCurveP256:
-      return doWriteUint32(P256Tag);
-    case WebCryptoNamedCurveP384:
-      return doWriteUint32(P384Tag);
-    case WebCryptoNamedCurveP521:
-      return doWriteUint32(P521Tag);
-  }
-  ASSERT_NOT_REACHED();
-}
-
-void SerializedScriptValueWriterForModules::doWriteKeyUsages(
-    const WebCryptoKeyUsageMask usages,
-    bool extractable) {
-  // Reminder to update this when adding new key usages.
-  static_assert(EndOfWebCryptoKeyUsage == (1 << 7) + 1,
-                "update required when adding new key usages");
-
-  uint32_t value = 0;
-
-  if (extractable)
-    value |= ExtractableUsage;
-
-  if (usages & WebCryptoKeyUsageEncrypt)
-    value |= EncryptUsage;
-  if (usages & WebCryptoKeyUsageDecrypt)
-    value |= DecryptUsage;
-  if (usages & WebCryptoKeyUsageSign)
-    value |= SignUsage;
-  if (usages & WebCryptoKeyUsageVerify)
-    value |= VerifyUsage;
-  if (usages & WebCryptoKeyUsageDeriveKey)
-    value |= DeriveKeyUsage;
-  if (usages & WebCryptoKeyUsageWrapKey)
-    value |= WrapKeyUsage;
-  if (usages & WebCryptoKeyUsageUnwrapKey)
-    value |= UnwrapKeyUsage;
-  if (usages & WebCryptoKeyUsageDeriveBits)
-    value |= DeriveBitsUsage;
-
-  doWriteUint32(value);
-}
-
-ScriptValueSerializer::StateBase*
-ScriptValueSerializerForModules::doSerializeObject(
-    v8::Local<v8::Object> jsObject,
-    StateBase* next) {
-  DCHECK(!jsObject.IsEmpty());
-
-  if (V8DOMFileSystem::hasInstance(jsObject, isolate())) {
-    greyObject(jsObject);
-    return writeDOMFileSystem(jsObject, next);
-  }
-  if (V8CryptoKey::hasInstance(jsObject, isolate())) {
-    greyObject(jsObject);
-    if (!writeCryptoKey(jsObject))
-      return handleError(Status::DataCloneError, "Couldn't serialize key data",
-                         next);
-    return nullptr;
-  }
-  if (V8RTCCertificate::hasInstance(jsObject, isolate())) {
-    greyObject(jsObject);
-    return writeRTCCertificate(jsObject, next);
-  }
-
-  return ScriptValueSerializer::doSerializeObject(jsObject, next);
-}
-
-bool SerializedScriptValueReaderForModules::read(
-    v8::Local<v8::Value>* value,
-    ScriptValueDeserializer& deserializer) {
-  SerializationTag tag;
-  if (!readTag(&tag))
-    return false;
-  switch (tag) {
-    case DOMFileSystemTag:
-      if (!readDOMFileSystem(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    case CryptoKeyTag:
-      if (!readCryptoKey(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    case RTCCertificateTag:
-      if (!readRTCCertificate(value))
-        return false;
-      deserializer.pushObjectReference(*value);
-      break;
-    default:
-      return SerializedScriptValueReader::readWithTag(tag, value, deserializer);
-  }
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReaderForModules::readDOMFileSystem(
-    v8::Local<v8::Value>* value) {
-  uint32_t type;
-  String name;
-  String url;
-  if (!doReadUint32(&type))
-    return false;
-  if (!readWebCoreString(&name))
-    return false;
-  if (!readWebCoreString(&url))
-    return false;
-  DOMFileSystem* fs = DOMFileSystem::create(
-      getScriptState()->getExecutionContext(), name,
-      static_cast<FileSystemType>(type), KURL(ParsedURLString, url));
-  *value = ToV8(fs, getScriptState()->context()->Global(), isolate());
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReaderForModules::readCryptoKey(
-    v8::Local<v8::Value>* value) {
-  uint32_t rawKeyType;
-  if (!doReadUint32(&rawKeyType))
-    return false;
-
-  WebCryptoKeyAlgorithm algorithm;
-  WebCryptoKeyType type = WebCryptoKeyTypeSecret;
-
-  switch (static_cast<CryptoKeySubTag>(rawKeyType)) {
-    case AesKeyTag:
-      if (!doReadAesKey(algorithm, type))
-        return false;
-      break;
-    case HmacKeyTag:
-      if (!doReadHmacKey(algorithm, type))
-        return false;
-      break;
-    case RsaHashedKeyTag:
-      if (!doReadRsaHashedKey(algorithm, type))
-        return false;
-      break;
-    case EcKeyTag:
-      if (!doReadEcKey(algorithm, type))
-        return false;
-      break;
-    case NoParamsKeyTag:
-      if (!doReadKeyWithoutParams(algorithm, type))
-        return false;
-      break;
-    default:
-      return false;
-  }
-
-  WebCryptoKeyUsageMask usages;
-  bool extractable;
-  if (!doReadKeyUsages(usages, extractable))
-    return false;
-
-  uint32_t keyDataLength;
-  if (!doReadUint32(&keyDataLength))
-    return false;
-
-  if (position() + keyDataLength > length())
-    return false;
-
-  const uint8_t* keyData = allocate(keyDataLength);
-  WebCryptoKey key = WebCryptoKey::createNull();
-  if (!Platform::current()->crypto()->deserializeKeyForClone(
-          algorithm, type, extractable, usages, keyData, keyDataLength, key)) {
-    return false;
-  }
-
-  *value = ToV8(CryptoKey::create(key), getScriptState()->context()->Global(),
-                isolate());
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReaderForModules::readRTCCertificate(
-    v8::Local<v8::Value>* value) {
-  String pemPrivateKey;
-  if (!readWebCoreString(&pemPrivateKey))
-    return false;
-  String pemCertificate;
-  if (!readWebCoreString(&pemCertificate))
-    return false;
-
-  std::unique_ptr<WebRTCCertificateGenerator> certificateGenerator =
-      WTF::wrapUnique(Platform::current()->createRTCCertificateGenerator());
-
-  std::unique_ptr<WebRTCCertificate> certificate(
-      certificateGenerator->fromPEM(pemPrivateKey, pemCertificate));
-  if (!certificate)
-    return false;
-  RTCCertificate* jsCertificate = new RTCCertificate(std::move(certificate));
-
-  *value =
-      ToV8(jsCertificate, getScriptState()->context()->Global(), isolate());
-  return !value->IsEmpty();
-}
-
-bool SerializedScriptValueReaderForModules::doReadHmacKey(
-    WebCryptoKeyAlgorithm& algorithm,
-    WebCryptoKeyType& type) {
-  uint32_t lengthBytes;
-  if (!doReadUint32(&lengthBytes))
-    return false;
-  WebCryptoAlgorithmId hash;
-  if (!doReadAlgorithmId(hash))
-    return false;
-  algorithm = WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8);
-  type = WebCryptoKeyTypeSecret;
-  return !algorithm.isNull();
-}
-
-bool SerializedScriptValueReaderForModules::doReadAesKey(
-    WebCryptoKeyAlgorithm& algorithm,
-    WebCryptoKeyType& type) {
-  WebCryptoAlgorithmId id;
-  if (!doReadAlgorithmId(id))
-    return false;
-  uint32_t lengthBytes;
-  if (!doReadUint32(&lengthBytes))
-    return false;
-  algorithm = WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8);
-  type = WebCryptoKeyTypeSecret;
-  return !algorithm.isNull();
-}
-
-bool SerializedScriptValueReaderForModules::doReadRsaHashedKey(
-    WebCryptoKeyAlgorithm& algorithm,
-    WebCryptoKeyType& type) {
-  WebCryptoAlgorithmId id;
-  if (!doReadAlgorithmId(id))
-    return false;
-
-  if (!doReadAsymmetricKeyType(type))
-    return false;
-
-  uint32_t modulusLengthBits;
-  if (!doReadUint32(&modulusLengthBits))
-    return false;
-
-  uint32_t publicExponentSize;
-  if (!doReadUint32(&publicExponentSize))
-    return false;
-
-  if (position() + publicExponentSize > length())
-    return false;
-
-  const uint8_t* publicExponent = allocate(publicExponentSize);
-  WebCryptoAlgorithmId hash;
-  if (!doReadAlgorithmId(hash))
-    return false;
-  algorithm = WebCryptoKeyAlgorithm::createRsaHashed(
-      id, modulusLengthBits, publicExponent, publicExponentSize, hash);
-
-  return !algorithm.isNull();
-}
-
-bool SerializedScriptValueReaderForModules::doReadEcKey(
-    WebCryptoKeyAlgorithm& algorithm,
-    WebCryptoKeyType& type) {
-  WebCryptoAlgorithmId id;
-  if (!doReadAlgorithmId(id))
-    return false;
-
-  if (!doReadAsymmetricKeyType(type))
-    return false;
-
-  WebCryptoNamedCurve namedCurve;
-  if (!doReadNamedCurve(namedCurve))
-    return false;
-
-  algorithm = WebCryptoKeyAlgorithm::createEc(id, namedCurve);
-  return !algorithm.isNull();
-}
-
-bool SerializedScriptValueReaderForModules::doReadKeyWithoutParams(
-    WebCryptoKeyAlgorithm& algorithm,
-    WebCryptoKeyType& type) {
-  WebCryptoAlgorithmId id;
-  if (!doReadAlgorithmId(id))
-    return false;
-  algorithm = WebCryptoKeyAlgorithm::createWithoutParams(id);
-  type = WebCryptoKeyTypeSecret;
-  return !algorithm.isNull();
-}
-
-bool SerializedScriptValueReaderForModules::doReadAlgorithmId(
-    WebCryptoAlgorithmId& id) {
-  uint32_t rawId;
-  if (!doReadUint32(&rawId))
-    return false;
-
-  switch (static_cast<CryptoKeyAlgorithmTag>(rawId)) {
-    case AesCbcTag:
-      id = WebCryptoAlgorithmIdAesCbc;
-      return true;
-    case HmacTag:
-      id = WebCryptoAlgorithmIdHmac;
-      return true;
-    case RsaSsaPkcs1v1_5Tag:
-      id = WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
-      return true;
-    case Sha1Tag:
-      id = WebCryptoAlgorithmIdSha1;
-      return true;
-    case Sha256Tag:
-      id = WebCryptoAlgorithmIdSha256;
-      return true;
-    case Sha384Tag:
-      id = WebCryptoAlgorithmIdSha384;
-      return true;
-    case Sha512Tag:
-      id = WebCryptoAlgorithmIdSha512;
-      return true;
-    case AesGcmTag:
-      id = WebCryptoAlgorithmIdAesGcm;
-      return true;
-    case RsaOaepTag:
-      id = WebCryptoAlgorithmIdRsaOaep;
-      return true;
-    case AesCtrTag:
-      id = WebCryptoAlgorithmIdAesCtr;
-      return true;
-    case AesKwTag:
-      id = WebCryptoAlgorithmIdAesKw;
-      return true;
-    case RsaPssTag:
-      id = WebCryptoAlgorithmIdRsaPss;
-      return true;
-    case EcdsaTag:
-      id = WebCryptoAlgorithmIdEcdsa;
-      return true;
-    case EcdhTag:
-      id = WebCryptoAlgorithmIdEcdh;
-      return true;
-    case HkdfTag:
-      id = WebCryptoAlgorithmIdHkdf;
-      return true;
-    case Pbkdf2Tag:
-      id = WebCryptoAlgorithmIdPbkdf2;
-      return true;
-  }
-
-  return false;
-}
-
-bool SerializedScriptValueReaderForModules::doReadAsymmetricKeyType(
-    WebCryptoKeyType& type) {
-  uint32_t rawType;
-  if (!doReadUint32(&rawType))
-    return false;
-
-  switch (static_cast<AsymmetricCryptoKeyType>(rawType)) {
-    case PublicKeyType:
-      type = WebCryptoKeyTypePublic;
-      return true;
-    case PrivateKeyType:
-      type = WebCryptoKeyTypePrivate;
-      return true;
-  }
-
-  return false;
-}
-
-bool SerializedScriptValueReaderForModules::doReadNamedCurve(
-    WebCryptoNamedCurve& namedCurve) {
-  uint32_t rawName;
-  if (!doReadUint32(&rawName))
-    return false;
-
-  switch (static_cast<NamedCurveTag>(rawName)) {
-    case P256Tag:
-      namedCurve = WebCryptoNamedCurveP256;
-      return true;
-    case P384Tag:
-      namedCurve = WebCryptoNamedCurveP384;
-      return true;
-    case P521Tag:
-      namedCurve = WebCryptoNamedCurveP521;
-      return true;
-  }
-
-  return false;
-}
-
-bool SerializedScriptValueReaderForModules::doReadKeyUsages(
-    WebCryptoKeyUsageMask& usages,
-    bool& extractable) {
-  // Reminder to update this when adding new key usages.
-  static_assert(EndOfWebCryptoKeyUsage == (1 << 7) + 1,
-                "update required when adding new key usages");
-  const uint32_t allPossibleUsages =
-      ExtractableUsage | EncryptUsage | DecryptUsage | SignUsage | VerifyUsage |
-      DeriveKeyUsage | WrapKeyUsage | UnwrapKeyUsage | DeriveBitsUsage;
-
-  uint32_t rawUsages;
-  if (!doReadUint32(&rawUsages))
-    return false;
-
-  // Make sure it doesn't contain an unrecognized usage value.
-  if (rawUsages & ~allPossibleUsages)
-    return false;
-
-  usages = 0;
-
-  extractable = rawUsages & ExtractableUsage;
-
-  if (rawUsages & EncryptUsage)
-    usages |= WebCryptoKeyUsageEncrypt;
-  if (rawUsages & DecryptUsage)
-    usages |= WebCryptoKeyUsageDecrypt;
-  if (rawUsages & SignUsage)
-    usages |= WebCryptoKeyUsageSign;
-  if (rawUsages & VerifyUsage)
-    usages |= WebCryptoKeyUsageVerify;
-  if (rawUsages & DeriveKeyUsage)
-    usages |= WebCryptoKeyUsageDeriveKey;
-  if (rawUsages & WrapKeyUsage)
-    usages |= WebCryptoKeyUsageWrapKey;
-  if (rawUsages & UnwrapKeyUsage)
-    usages |= WebCryptoKeyUsageUnwrapKey;
-  if (rawUsages & DeriveBitsUsage)
-    usages |= WebCryptoKeyUsageDeriveBits;
-
-  return true;
-}
-
-ScriptValueDeserializerForModules::ScriptValueDeserializerForModules(
-    SerializedScriptValueReaderForModules& reader,
-    MessagePortArray* messagePorts,
-    ArrayBufferContentsArray* arrayBufferContents,
-    ImageBitmapContentsArray* imageBitmapContents)
-    : ScriptValueDeserializer(reader,
-                              messagePorts,
-                              arrayBufferContents,
-                              imageBitmapContents) {}
-
-bool ScriptValueDeserializerForModules::read(v8::Local<v8::Value>* value) {
-  return toSerializedScriptValueReaderForModules(reader()).read(value, *this);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.h b/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.h
deleted file mode 100644
index 285552e..0000000
--- a/third_party/WebKit/Source/bindings/modules/v8/ScriptValueSerializerForModules.h
+++ /dev/null
@@ -1,120 +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 ScriptValueSerializerForModules_h
-#define ScriptValueSerializerForModules_h
-
-#include "bindings/core/v8/ScriptValueSerializer.h"
-#include "modules/peerconnection/RTCCertificate.h"
-#include "public/platform/WebCrypto.h"
-#include "public/platform/WebCryptoKey.h"
-#include "public/platform/WebCryptoKeyAlgorithm.h"
-#include <v8.h>
-
-namespace blink {
-
-class SerializedScriptValueWriterForModules final
-    : public SerializedScriptValueWriter {
-  STACK_ALLOCATED();
-  WTF_MAKE_NONCOPYABLE(SerializedScriptValueWriterForModules);
-
- public:
-  SerializedScriptValueWriterForModules() : SerializedScriptValueWriter() {}
-
-  void writeDOMFileSystem(int type, const String& name, const String& url);
-  bool writeCryptoKey(const WebCryptoKey&);
-  void writeRTCCertificate(const RTCCertificate&);
-
- private:
-  void doWriteHmacKey(const WebCryptoKey&);
-  void doWriteAesKey(const WebCryptoKey&);
-  void doWriteRsaHashedKey(const WebCryptoKey&);
-  void doWriteEcKey(const WebCryptoKey&);
-  void doWriteKeyWithoutParams(const WebCryptoKey&);
-  void doWriteAlgorithmId(WebCryptoAlgorithmId);
-  void doWriteAsymmetricKeyType(WebCryptoKeyType);
-  void doWriteNamedCurve(WebCryptoNamedCurve);
-  void doWriteKeyUsages(const WebCryptoKeyUsageMask usages, bool extractable);
-};
-
-DEFINE_TYPE_CASTS(SerializedScriptValueWriterForModules,
-                  SerializedScriptValueWriter,
-                  writer,
-                  true,
-                  true);
-
-class SerializedScriptValueReaderForModules final
-    : public SerializedScriptValueReader {
-  STACK_ALLOCATED();
-  WTF_MAKE_NONCOPYABLE(SerializedScriptValueReaderForModules);
-
- public:
-  SerializedScriptValueReaderForModules(const uint8_t* buffer,
-                                        int length,
-                                        const WebBlobInfoArray* blobInfo,
-                                        BlobDataHandleMap& blobDataHandles,
-                                        ScriptState* scriptState)
-      : SerializedScriptValueReader(buffer,
-                                    length,
-                                    blobInfo,
-                                    blobDataHandles,
-                                    scriptState) {}
-
-  bool read(v8::Local<v8::Value>*, ScriptValueDeserializer&) override;
-
- private:
-  bool readDOMFileSystem(v8::Local<v8::Value>*);
-  bool readCryptoKey(v8::Local<v8::Value>*);
-  bool readRTCCertificate(v8::Local<v8::Value>*);
-  bool doReadHmacKey(WebCryptoKeyAlgorithm&, WebCryptoKeyType&);
-  bool doReadAesKey(WebCryptoKeyAlgorithm&, WebCryptoKeyType&);
-  bool doReadRsaHashedKey(WebCryptoKeyAlgorithm&, WebCryptoKeyType&);
-  bool doReadEcKey(WebCryptoKeyAlgorithm&, WebCryptoKeyType&);
-  bool doReadKeyWithoutParams(WebCryptoKeyAlgorithm&, WebCryptoKeyType&);
-  bool doReadAlgorithmId(WebCryptoAlgorithmId&);
-  bool doReadAsymmetricKeyType(WebCryptoKeyType&);
-  bool doReadNamedCurve(WebCryptoNamedCurve&);
-  bool doReadKeyUsages(WebCryptoKeyUsageMask& usages, bool& extractable);
-};
-
-DEFINE_TYPE_CASTS(SerializedScriptValueReaderForModules,
-                  SerializedScriptValueReader,
-                  reader,
-                  true,
-                  true);
-
-class ScriptValueSerializerForModules final : public ScriptValueSerializer {
-  STACK_ALLOCATED();
-  WTF_MAKE_NONCOPYABLE(ScriptValueSerializerForModules);
-
- public:
-  ScriptValueSerializerForModules(SerializedScriptValueWriter&,
-                                  WebBlobInfoArray*,
-                                  ScriptState*);
-
- private:
-  StateBase* doSerializeObject(v8::Local<v8::Object>, StateBase* next) override;
-
-  StateBase* writeDOMFileSystem(v8::Local<v8::Value>, StateBase* next);
-  bool writeCryptoKey(v8::Local<v8::Value>);
-  StateBase* writeRTCCertificate(v8::Local<v8::Value>, StateBase* next);
-};
-
-class ScriptValueDeserializerForModules final : public ScriptValueDeserializer {
-  STACK_ALLOCATED();
-  WTF_MAKE_NONCOPYABLE(ScriptValueDeserializerForModules);
-
- public:
-  ScriptValueDeserializerForModules(SerializedScriptValueReaderForModules&,
-                                    MessagePortArray* messagePorts,
-                                    ArrayBufferContentsArray*,
-                                    ImageBitmapContentsArray*);
-
- private:
-  bool read(v8::Local<v8::Value>*) override;
-};
-
-}  // namespace blink
-
-#endif  // ScriptValueSerializerForModules_h
diff --git a/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp b/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp
index 621e899..adbf0630 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/SerializedScriptValueForModulesFactory.cpp
@@ -4,12 +4,8 @@
 
 #include "bindings/modules/v8/SerializedScriptValueForModulesFactory.h"
 
-#include "bindings/core/v8/ExceptionState.h"
-#include "bindings/core/v8/SerializedScriptValue.h"
-#include "bindings/modules/v8/ScriptValueSerializerForModules.h"
 #include "bindings/modules/v8/serialization/V8ScriptValueDeserializerForModules.h"
 #include "bindings/modules/v8/serialization/V8ScriptValueSerializerForModules.h"
-#include "core/dom/ExceptionCode.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
 
 namespace blink {
@@ -21,14 +17,8 @@
                                                WebBlobInfoArray* blobInfo,
                                                ExceptionState& exceptionState) {
   TRACE_EVENT0("blink", "SerializedScriptValueFactory::create");
-  if (RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) {
-    V8ScriptValueSerializerForModules serializer(ScriptState::current(isolate));
-    serializer.setBlobInfoArray(blobInfo);
-    return serializer.serialize(value, transferables, exceptionState);
-  }
-  SerializedScriptValueWriterForModules writer;
-  ScriptValueSerializerForModules serializer(writer, blobInfo,
-                                             ScriptState::current(isolate));
+  V8ScriptValueSerializerForModules serializer(ScriptState::current(isolate));
+  serializer.setBlobInfoArray(blobInfo);
   return serializer.serialize(value, transferables, exceptionState);
 }
 
@@ -38,31 +28,10 @@
     MessagePortArray* messagePorts,
     const WebBlobInfoArray* blobInfo) {
   TRACE_EVENT0("blink", "SerializedScriptValueFactory::deserialize");
-  if (RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) {
-    V8ScriptValueDeserializerForModules deserializer(
-        ScriptState::current(isolate), value);
-    deserializer.setTransferredMessagePorts(messagePorts);
-    deserializer.setBlobInfoArray(blobInfo);
-    return deserializer.deserialize();
-  }
-  // deserialize() can run arbitrary script (e.g., setters), which could result
-  // in |this| being destroyed.  Holding a RefPtr ensures we are alive (along
-  // with our internal data) throughout the operation.
-  RefPtr<SerializedScriptValue> protect(value);
-  if (!value->dataLengthInBytes())
-    return v8::Null(isolate);
-  static_assert(sizeof(SerializedScriptValueWriter::BufferValueType) == 2,
-                "BufferValueType should be 2 bytes");
-  // FIXME: SerializedScriptValue shouldn't use String for its underlying
-  // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
-  // information stored in m_data isn't even encoded in UTF-16. Instead,
-  // unicode characters are encoded as UTF-8 with two code units per UChar.
-  SerializedScriptValueReaderForModules reader(
-      value->data(), value->dataLengthInBytes(), blobInfo,
-      value->blobDataHandles(), ScriptState::current(isolate));
-  ScriptValueDeserializerForModules deserializer(
-      reader, messagePorts, value->getArrayBufferContentsArray(),
-      value->getImageBitmapContentsArray());
+  V8ScriptValueDeserializerForModules deserializer(
+      ScriptState::current(isolate), value);
+  deserializer.setTransferredMessagePorts(messagePorts);
+  deserializer.setBlobInfoArray(blobInfo);
   return deserializer.deserialize();
 }
 
diff --git a/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp b/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp
index 863e3519c..a08f28e6 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp
+++ b/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp
@@ -32,20 +32,6 @@
 namespace blink {
 namespace {
 
-class ScopedEnableV8BasedStructuredClone {
- public:
-  ScopedEnableV8BasedStructuredClone()
-      : m_wasEnabled(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()) {
-    RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(true);
-  }
-  ~ScopedEnableV8BasedStructuredClone() {
-    RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(m_wasEnabled);
-  }
-
- private:
-  bool m_wasEnabled;
-};
-
 RefPtr<SerializedScriptValue> serializedValue(const Vector<uint8_t>& bytes) {
   // TODO(jbroman): Fix this once SerializedScriptValue can take bytes without
   // endianness swapping.
@@ -164,7 +150,6 @@
     0x2d, 0x0a};
 
 TEST(V8ScriptValueSerializerForModulesTest, RoundTripRTCCertificate) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
 
   // Make a certificate with the existing key above.
@@ -190,7 +175,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, DecodeRTCCertificate) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
 
   // This is encoded data generated from Chromium (around M55).
@@ -212,7 +196,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, DecodeInvalidRTCCertificate) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
 
   // This is valid, except that "private" is not a valid private key PEM and
@@ -398,7 +381,6 @@
 
 // AES-128-CBC uses AES key params.
 TEST(V8ScriptValueSerializerForModulesTest, RoundTripCryptoKeyAES) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -439,7 +421,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyAES) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -469,7 +450,6 @@
 
 // HMAC-SHA256 uses HMAC key params.
 TEST(V8ScriptValueSerializerForModulesTest, RoundTripCryptoKeyHMAC) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -509,7 +489,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyHMAC) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -543,7 +522,6 @@
 
 // RSA-PSS-SHA256 uses RSA hashed key params.
 TEST(V8ScriptValueSerializerForModulesTest, RoundTripCryptoKeyRSAHashed) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -586,7 +564,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyRSAHashed) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -637,7 +614,6 @@
 
 // ECDSA uses EC key params.
 TEST(V8ScriptValueSerializerForModulesTest, RoundTripCryptoKeyEC) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -680,7 +656,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyEC) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -720,7 +695,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, RoundTripCryptoKeyNoParams) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -754,7 +728,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyNoParams) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -783,7 +756,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyInvalid) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
@@ -887,7 +859,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, RoundTripDOMFileSystem) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
 
   DOMFileSystem* fs = DOMFileSystem::create(
@@ -908,7 +879,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, RoundTripDOMFileSystemNotClonable) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ExceptionState exceptionState(scope.isolate(),
                                 ExceptionState::ExecutionContext, "Window",
@@ -927,7 +897,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, DecodeDOMFileSystem) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
 
   // This is encoded data generated from Chromium (around M56).
@@ -953,7 +922,6 @@
 }
 
 TEST(V8ScriptValueSerializerForModulesTest, DecodeInvalidDOMFileSystem) {
-  ScopedEnableV8BasedStructuredClone enable;
   V8TestingScope scope;
   ScriptState* scriptState = scope.getScriptState();
 
diff --git a/third_party/WebKit/Source/bindings/modules/v8/v8.gni b/third_party/WebKit/Source/bindings/modules/v8/v8.gni
index 6fedd099..9a668b0 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/v8.gni
+++ b/third_party/WebKit/Source/bindings/modules/v8/v8.gni
@@ -16,8 +16,6 @@
                     "DictionaryHelperForModules.cpp",
                     "ModuleBindingsInitializer.cpp",
                     "ModuleBindingsInitializer.h",
-                    "ScriptValueSerializerForModules.cpp",
-                    "ScriptValueSerializerForModules.h",
                     "SerializedScriptValueForModulesFactory.cpp",
                     "SerializedScriptValueForModulesFactory.h",
                     "ToV8ForModules.h",
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5
index d7758bc..6e4735ed 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.json5
+++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -1392,10 +1392,20 @@
     },
     {
       name: "overflow-x",
+      initial_keyword: "visible",
+      keyword_only: true,
+      keywords: [
+        "visible", "hidden", "scroll", "auto", "overlay", "-webkit-paged-x", "-webkit-paged-y",
+      ],
       type_name: "EOverflow",
     },
     {
       name: "overflow-y",
+      initial_keyword: "visible",
+      keyword_only: true,
+      keywords: [
+        "visible", "hidden", "scroll", "auto", "overlay", "-webkit-paged-x", "-webkit-paged-y",
+      ],
       type_name: "EOverflow",
     },
     {
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
index 931f6e2..b11d023 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -126,16 +126,6 @@
   return true;
 }
 
-v8::Local<v8::Value> nodeV8Value(v8::Local<v8::Context> context, Node* node) {
-  v8::Isolate* isolate = context->GetIsolate();
-  if (!node ||
-      !BindingSecurity::shouldAllowAccessTo(
-          currentDOMWindow(isolate), node,
-          BindingSecurity::ErrorReportOption::DoNotReport))
-    return v8::Null(isolate);
-  return ToV8(node, context->Global(), isolate);
-}
-
 }  // namespace
 
 class InspectorRevalidateDOMTask final
@@ -1837,6 +1827,7 @@
   return distributedNodes;
 }
 
+// static
 Node* InspectorDOMAgent::innerFirstChild(Node* node) {
   node = node->firstChild();
   while (isWhitespace(node))
@@ -1844,6 +1835,7 @@
   return node;
 }
 
+// static
 Node* InspectorDOMAgent::innerNextSibling(Node* node) {
   do {
     node = node->nextSibling();
@@ -1851,6 +1843,7 @@
   return node;
 }
 
+// static
 Node* InspectorDOMAgent::innerPreviousSibling(Node* node) {
   do {
     node = node->previousSibling();
@@ -1858,6 +1851,7 @@
   return node;
 }
 
+// static
 unsigned InspectorDOMAgent::innerChildNodeCount(Node* node) {
   unsigned count = 0;
   Node* child = innerFirstChild(node);
@@ -1868,6 +1862,7 @@
   return count;
 }
 
+// static
 Node* InspectorDOMAgent::innerParentNode(Node* node) {
   if (node->isDocumentNode()) {
     Document* document = toDocument(node);
@@ -1878,12 +1873,71 @@
   return node->parentOrShadowHostNode();
 }
 
+// static
 bool InspectorDOMAgent::isWhitespace(Node* node) {
   // TODO: pull ignoreWhitespace setting from the frontend and use here.
   return node && node->getNodeType() == Node::kTextNode &&
          node->nodeValue().stripWhiteSpace().length() == 0;
 }
 
+// static
+v8::Local<v8::Value> InspectorDOMAgent::nodeV8Value(
+    v8::Local<v8::Context> context,
+    Node* node) {
+  v8::Isolate* isolate = context->GetIsolate();
+  if (!node ||
+      !BindingSecurity::shouldAllowAccessTo(
+          currentDOMWindow(isolate), node,
+          BindingSecurity::ErrorReportOption::DoNotReport))
+    return v8::Null(isolate);
+  return ToV8(node, context->Global(), isolate);
+}
+
+// static
+void InspectorDOMAgent::collectNodes(Node* node,
+                                     int depth,
+                                     bool pierce,
+                                     Function<bool(Node*)>* filter,
+                                     HeapVector<Member<Node>>* result) {
+  if (filter && filter->operator()(node))
+    result->push_back(node);
+  if (--depth <= 0)
+    return;
+
+  if (pierce && node->isElementNode()) {
+    Element* element = toElement(node);
+    if (node->isFrameOwnerElement()) {
+      HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(node);
+      if (frameOwner->contentFrame() &&
+          frameOwner->contentFrame()->isLocalFrame()) {
+        if (Document* doc = frameOwner->contentDocument())
+          collectNodes(doc, depth, pierce, filter, result);
+      }
+    }
+
+    ElementShadow* shadow = element->shadow();
+    if (pierce && shadow) {
+      for (ShadowRoot* root = &shadow->youngestShadowRoot(); root;
+           root = root->olderShadowRoot()) {
+        collectNodes(root, depth, pierce, filter, result);
+      }
+    }
+
+    if (isHTMLLinkElement(*element)) {
+      HTMLLinkElement& linkElement = toHTMLLinkElement(*element);
+      if (linkElement.isImport() && linkElement.import() &&
+          innerParentNode(linkElement.import()) == linkElement) {
+        collectNodes(linkElement.import(), depth, pierce, filter, result);
+      }
+    }
+  }
+
+  for (Node* child = innerFirstChild(node); child;
+       child = innerNextSibling(child)) {
+    collectNodes(child, depth, pierce, filter, result);
+  }
+}
+
 void InspectorDOMAgent::domContentLoadedEventFired(LocalFrame* frame) {
   if (frame != m_inspectedFrames->root())
     return;
@@ -2236,7 +2290,8 @@
       : m_nodeId(DOMNodeIds::idForNode(node)) {}
 
   v8::Local<v8::Value> get(v8::Local<v8::Context> context) override {
-    return nodeV8Value(context, DOMNodeIds::nodeForId(m_nodeId));
+    return InspectorDOMAgent::nodeV8Value(context,
+                                          DOMNodeIds::nodeForId(m_nodeId));
   }
 
  private:
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
index e5f9cbc5..0b0212806 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.h
@@ -264,6 +264,12 @@
   static unsigned innerChildNodeCount(Node*);
   static Node* innerParentNode(Node*);
   static bool isWhitespace(Node*);
+  static v8::Local<v8::Value> nodeV8Value(v8::Local<v8::Context>, Node*);
+  static void collectNodes(Node* root,
+                           int depth,
+                           bool pierce,
+                           Function<bool(Node*)>*,
+                           HeapVector<Member<Node>>* result);
 
   Response assertNode(int nodeId, Node*&);
   Response assertElement(int nodeId, Element*&);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
index 05e4a437..ebe550f9 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
@@ -32,6 +32,8 @@
 
 #include "bindings/core/v8/ScriptEventListener.h"
 #include "bindings/core/v8/V8EventTarget.h"
+#include "bindings/core/v8/V8Node.h"
+#include "core/dom/DOMNodeIds.h"
 #include "core/dom/Element.h"
 #include "core/dom/Node.h"
 #include "core/events/Event.h"
@@ -175,16 +177,13 @@
   return removeFunction;
 }
 
-void InspectorDOMDebuggerAgent::eventListenersInfoForTarget(
-    v8::Isolate* isolate,
-    v8::Local<v8::Value> value,
-    V8EventListenerInfoList& eventInformation) {
-  EventTarget* target = V8EventTarget::toImplWithTypeCheck(isolate, value);
-  // We need to handle LocalDOMWindow specially, because LocalDOMWindow wrapper
-  // exists on prototype chain.
-  if (!target)
-    target = toDOMWindow(isolate, value);
-  if (!target || !target->getExecutionContext())
+static void collectEventListeners(v8::Isolate* isolate,
+                                  EventTarget* target,
+                                  v8::Local<v8::Value> targetWrapper,
+                                  Node* targetNode,
+                                  bool reportForAllContexts,
+                                  V8EventListenerInfoList* eventInformation) {
+  if (!target->getExecutionContext())
     return;
 
   ExecutionContext* executionContext = target->getExecutionContext();
@@ -205,8 +204,8 @@
           static_cast<V8AbstractEventListener*>(eventListener);
       v8::Local<v8::Context> context =
           toV8Context(executionContext, v8Listener->world());
-      // Hide listeners from other contexts.
-      if (context != isolate->GetCurrentContext())
+      // Optionally hide listeners from other contexts.
+      if (!reportForAllContexts && context != isolate->GetCurrentContext())
         continue;
       // getListenerObject() may cause JS in the event attribute to get
       // compiled, potentially unsuccessfully.  In that case, the function
@@ -216,14 +215,79 @@
       if (handler.IsEmpty())
         continue;
       bool useCapture = listeners->at(k).capture();
-      eventInformation.push_back(V8EventListenerInfo(
+      int backendNodeId = 0;
+      if (targetNode) {
+        backendNodeId = DOMNodeIds::idForNode(targetNode);
+        targetWrapper = InspectorDOMAgent::nodeV8Value(
+            reportForAllContexts ? context : isolate->GetCurrentContext(),
+            targetNode);
+      }
+      v8::MaybeLocal<v8::Function> removeFunction =
+          !targetWrapper.IsEmpty()
+              ? createRemoveFunction(context, targetWrapper, handler, type,
+                                     useCapture)
+              : v8::MaybeLocal<v8::Function>();
+      eventInformation->push_back(V8EventListenerInfo(
           type, useCapture, listeners->at(k).passive(), listeners->at(k).once(),
-          handler,
-          createRemoveFunction(context, value, handler, type, useCapture)));
+          handler, removeFunction, backendNodeId));
     }
   }
 }
 
+// static
+void InspectorDOMDebuggerAgent::eventListenersInfoForTarget(
+    v8::Isolate* isolate,
+    v8::Local<v8::Value> value,
+    V8EventListenerInfoList* eventInformation) {
+  InspectorDOMDebuggerAgent::eventListenersInfoForTarget(
+      isolate, value, 1, false, eventInformation);
+}
+
+static bool filterNodesWithListeners(Node* node) {
+  Vector<AtomicString> eventTypes = node->eventTypes();
+  for (size_t j = 0; j < eventTypes.size(); ++j) {
+    EventListenerVector* listeners = node->getEventListeners(eventTypes[j]);
+    if (listeners && listeners->size())
+      return true;
+  }
+  return false;
+}
+
+// static
+void InspectorDOMDebuggerAgent::eventListenersInfoForTarget(
+    v8::Isolate* isolate,
+    v8::Local<v8::Value> value,
+    int depth,
+    bool pierce,
+    V8EventListenerInfoList* eventInformation) {
+  // Special-case nodes, respect depth and pierce parameters in case of nodes.
+  Node* node = V8Node::toImplWithTypeCheck(isolate, value);
+  if (node) {
+    if (depth < 0)
+      depth = INT_MAX;
+    HeapVector<Member<Node>> nodes;
+    InspectorDOMAgent::collectNodes(node, depth, pierce,
+                                    WTF::bind(&filterNodesWithListeners).get(),
+                                    &nodes);
+    for (Node* n : nodes) {
+      // We are only interested in listeners from the current context.
+      collectEventListeners(isolate, n, v8::Local<v8::Value>(), n, pierce,
+                            eventInformation);
+    }
+    return;
+  }
+
+  EventTarget* target = V8EventTarget::toImplWithTypeCheck(isolate, value);
+  // We need to handle LocalDOMWindow specially, because LocalDOMWindow wrapper
+  // exists on prototype chain.
+  if (!target)
+    target = toDOMWindow(isolate, value);
+  if (target) {
+    collectEventListeners(isolate, target, value, nullptr, false,
+                          eventInformation);
+  }
+}
+
 InspectorDOMDebuggerAgent::InspectorDOMDebuggerAgent(
     v8::Isolate* isolate,
     InspectorDOMAgent* domAgent,
@@ -467,6 +531,8 @@
 
 Response InspectorDOMDebuggerAgent::getEventListeners(
     const String& objectId,
+    Maybe<int> depth,
+    Maybe<bool> pierce,
     std::unique_ptr<protocol::Array<protocol::DOMDebugger::EventListener>>*
         listenersArray) {
   v8::HandleScope handles(m_isolate);
@@ -483,7 +549,8 @@
       protocol::Array<protocol::DOMDebugger::EventListener>::create();
   V8EventListenerInfoList eventInformation;
   InspectorDOMDebuggerAgent::eventListenersInfoForTarget(
-      context->GetIsolate(), object, eventInformation);
+      context->GetIsolate(), object, depth.fromMaybe(1),
+      pierce.fromMaybe(false), &eventInformation);
   for (const auto& info : eventInformation) {
     if (!info.useCapture)
       continue;
@@ -541,6 +608,8 @@
     if (info.removeFunction.ToLocal(&removeFunction))
       value->setRemoveFunction(
           m_v8Session->wrapObject(context, removeFunction, objectGroupId));
+    if (info.backendNodeId)
+      value->setBackendNodeId(info.backendNodeId);
   }
   return value;
 }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h
index 1656078..7349008e 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h
+++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.h
@@ -58,7 +58,7 @@
  public:
   static void eventListenersInfoForTarget(v8::Isolate*,
                                           v8::Local<v8::Value>,
-                                          V8EventListenerInfoList& listeners);
+                                          V8EventListenerInfoList* listeners);
 
   InspectorDOMDebuggerAgent(v8::Isolate*,
                             InspectorDOMAgent*,
@@ -79,6 +79,8 @@
   Response removeXHRBreakpoint(const String& url) override;
   Response getEventListeners(
       const String& objectId,
+      Maybe<int> depth,
+      Maybe<bool> pierce,
       std::unique_ptr<protocol::Array<protocol::DOMDebugger::EventListener>>*
           listeners) override;
 
@@ -105,6 +107,11 @@
   void didCommitLoadForLocalFrame(LocalFrame*) override;
 
  private:
+  static void eventListenersInfoForTarget(v8::Isolate*,
+                                          v8::Local<v8::Value>,
+                                          int depth,
+                                          bool pierce,
+                                          V8EventListenerInfoList* listeners);
   void pauseOnNativeEventIfNeeded(
       std::unique_ptr<protocol::DictionaryValue> eventData,
       bool synchronous);
diff --git a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
index 1b552c8..312f70a 100644
--- a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
+++ b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
@@ -394,7 +394,7 @@
   if (groupId)
     debugger->muteMetrics(groupId);
   InspectorDOMDebuggerAgent::eventListenersInfoForTarget(isolate, info[0],
-                                                         listenerInfo);
+                                                         &listenerInfo);
   if (groupId)
     debugger->unmuteMetrics(groupId);
 
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json
index 731b2dcb..224f7f28 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.json
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -3263,7 +3263,8 @@
                     { "name": "columnNumber", "type": "integer", "description": "Column number in the script (0-based)." },
                     { "name": "handler", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event handler function value." },
                     { "name": "originalHandler", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event original handler function value." },
-                    { "name": "removeFunction", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event listener remove function." }
+                    { "name": "removeFunction", "$ref": "Runtime.RemoteObject", "optional": true, "description": "Event listener remove function." },
+                    { "name": "backendNodeId", "$ref": "DOM.BackendNodeId", "optional": true, "description": "Node the listener is added to (if any)." }
                 ],
                 "experimental": true
             }
@@ -3335,7 +3336,9 @@
                 "name": "getEventListeners",
                 "experimental": true,
                 "parameters": [
-                    { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Identifier of the object to return listeners for." }
+                    { "name": "objectId", "$ref": "Runtime.RemoteObjectId", "description": "Identifier of the object to return listeners for." },
+                    { "name": "depth", "type": "integer", "optional": true, "description": "The maximum depth at which Node children should be retrieved, defaults to 1. Use -1 for the entire subtree or provide an integer larger than 0.", "experimental": true },
+                    { "name": "pierce", "type": "boolean", "optional": true, "description": "Whether or not iframes and shadow roots should be traversed when returning the subtree (default is false). Reports listeners for all contexts if pierce is enabled.", "experimental": true }
                 ],
                 "returns": [
                     { "name": "listeners", "type": "array", "items": { "$ref": "EventListener" }, "description": "Array of relevant listeners." }
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
index 54a33c0..5265d01 100644
--- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
+++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
@@ -846,7 +846,10 @@
     compositingContainerOffsetFromParentGraphicsLayer +=
         compositingContainer->subpixelAccumulation();
 
-#if DCHECK_IS_ON()
+#if 0 && DCHECK_IS_ON()
+  // TODO(trchen): We should enable this for below comment out |DCHECK()| once
+  // we have simple reproduce case and fix it. See http://crbug.com/646437 for
+  // details.
   const PaintLayer* commonTransformAncestor = nullptr;
   if (compositingContainer && compositingContainer->transform())
     commonTransformAncestor = compositingContainer;
@@ -867,7 +870,9 @@
     // Store the local bounds of the Layer subtree before applying the offset.
     layers[i].compositedBounds = squashedBounds;
 
-#if DCHECK_IS_ON()
+#if 0 && DCHECK_IS_ON()
+    // TODO(trchen): We should enable this |DCHECK()| once we have simple
+    // reproduce case and fix it. See http://crbug.com/646437 for details.
     DCHECK(layers[i].paintLayer->transformAncestor() ==
            commonTransformAncestor);
 #endif
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
index 60568dbb..2e70ff7 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -367,8 +367,6 @@
       other.m_nonInheritedData.m_effectiveDisplay;
   m_nonInheritedData.m_originalDisplay =
       other.m_nonInheritedData.m_originalDisplay;
-  m_nonInheritedData.m_overflowX = other.m_nonInheritedData.m_overflowX;
-  m_nonInheritedData.m_overflowY = other.m_nonInheritedData.m_overflowY;
   m_nonInheritedData.m_verticalAlign = other.m_nonInheritedData.m_verticalAlign;
   m_nonInheritedData.m_position = other.m_nonInheritedData.m_position;
   m_nonInheritedData.m_hasViewportUnits =
@@ -811,8 +809,7 @@
       getWritingMode() != other.getWritingMode())
     return true;
 
-  if (m_nonInheritedData.m_overflowX != other.m_nonInheritedData.m_overflowX ||
-      m_nonInheritedData.m_overflowY != other.m_nonInheritedData.m_overflowY ||
+  if (overflowX() != other.overflowX() || overflowY() != other.overflowY() ||
       clear() != other.clear() || getUnicodeBidi() != other.getUnicodeBidi() ||
       floating() != other.floating() ||
       m_nonInheritedData.m_originalDisplay !=
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index 33dc893..c07a410 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -224,8 +224,6 @@
       // Generated properties are compared in ComputedStyleBase
       return m_effectiveDisplay == other.m_effectiveDisplay &&
              m_originalDisplay == other.m_originalDisplay &&
-             m_overflowX == other.m_overflowX &&
-             m_overflowY == other.m_overflowY &&
              m_verticalAlign == other.m_verticalAlign &&
              m_position == other.m_position &&
              // hasViewportUnits
@@ -251,8 +249,6 @@
 
     unsigned m_effectiveDisplay : 5;  // EDisplay
     unsigned m_originalDisplay : 5;   // EDisplay
-    unsigned m_overflowX : 3;         // EOverflow
-    unsigned m_overflowY : 3;         // EOverflow
     unsigned m_verticalAlign : 4;     // EVerticalAlign
     unsigned m_position : 3;          // EPosition
 
@@ -305,8 +301,6 @@
     m_nonInheritedData.m_effectiveDisplay =
         m_nonInheritedData.m_originalDisplay =
             static_cast<unsigned>(initialDisplay());
-    m_nonInheritedData.m_overflowX = static_cast<unsigned>(initialOverflowX());
-    m_nonInheritedData.m_overflowY = static_cast<unsigned>(initialOverflowY());
     m_nonInheritedData.m_verticalAlign =
         static_cast<unsigned>(initialVerticalAlign());
     m_nonInheritedData.m_position = initialPosition();
@@ -1461,24 +1455,6 @@
     SET_VAR(m_rareNonInheritedData, m_outline.m_offset, v);
   }
 
-  // overflow-x
-  static EOverflow initialOverflowX() { return EOverflow::kVisible; }
-  EOverflow overflowX() const {
-    return static_cast<EOverflow>(m_nonInheritedData.m_overflowX);
-  }
-  void setOverflowX(EOverflow v) {
-    m_nonInheritedData.m_overflowX = static_cast<unsigned>(v);
-  }
-
-  // overflow-y
-  static EOverflow initialOverflowY() { return EOverflow::kVisible; }
-  EOverflow overflowY() const {
-    return static_cast<EOverflow>(m_nonInheritedData.m_overflowY);
-  }
-  void setOverflowY(EOverflow v) {
-    m_nonInheritedData.m_overflowY = static_cast<unsigned>(v);
-  }
-
   // Padding properties.
   static Length initialPadding() { return Length(Fixed); }
 
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
index 88b0c7c..61ad9f6c 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -145,16 +145,6 @@
 
 // Random visual rendering model attributes. Not inherited.
 
-enum class EOverflow : unsigned {
-  kVisible,
-  kHidden,
-  kScroll,
-  kAuto,
-  kOverlay,
-  kWebkitPagedX,
-  kWebkitPagedY
-};
-
 enum class EVerticalAlign : unsigned {
   kBaseline,
   kMiddle,
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 6b29676..4559983 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -2590,9 +2590,9 @@
   if (!frame())
     return;
 
-  frame()->reload(
-      bypassCache ? FrameLoadTypeReloadBypassingCache : FrameLoadTypeReload,
-      ClientRedirectPolicy::NotClientRedirect);
+  frame()->reload(bypassCache ? FrameLoadTypeReloadBypassingCache
+                              : FrameLoadTypeReloadMainResource,
+                  ClientRedirectPolicy::NotClientRedirect);
 }
 
 ClientRect* Internals::selectionBounds(ExceptionState& exceptionState) {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css b/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
index 08a83d8..98ff80f 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
+++ b/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
@@ -323,6 +323,8 @@
     top: 0;
     left: 0;
     cursor: pointer;
+    width: 15px;
+    height: 15px;
 }
 
 .gutter-menu-icon {
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js
index cfd28b0..9dcb217 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js
@@ -45,13 +45,13 @@
 
     this._contentElement = this.element.createChild('div', 'profile-launcher-view-content');
     this._innerContentElement = this._contentElement.createChild('div');
-    var targetSpan = this._contentElement.createChild('span');
-    var selectTargetText = targetSpan.createChild('span');
-    selectTargetText.textContent = Common.UIString('Target:');
-    var targetsSelect = targetSpan.createChild('select', 'chrome-select');
-    new Profiler.TargetsComboBoxController(targetsSelect, targetSpan);
-    this._controlButton = UI.createTextButton('', this._controlButtonClicked.bind(this), 'control-profiling');
-    this._contentElement.appendChild(this._controlButton);
+    var controlDiv = this._contentElement.createChild('div', 'hbox profile-launcher-control');
+    var targetDiv = controlDiv.createChild('div', 'hbox profile-launcher-target');
+    targetDiv.createChild('div').textContent = Common.UIString('Target:');
+    var targetsSelect = targetDiv.createChild('select', 'chrome-select');
+    new Profiler.TargetsComboBoxController(targetsSelect, targetDiv);
+    this._controlButton = UI.createTextButton('', this._controlButtonClicked.bind(this));
+    controlDiv.appendChild(this._controlButton);
     this._recordButtonEnabled = true;
     this._loadButton = UI.createTextButton(Common.UIString('Load'), this._loadButtonClicked.bind(this), 'load-profile');
     this._contentElement.appendChild(this._loadButton);
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css b/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css
index 7b257ec7..eb70b40 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css
@@ -117,9 +117,27 @@
     text-align: left;
 }
 
-.control-profiling {
-    -webkit-align-self: flex-start;
-    margin-right: 50px;
+.profile-launcher-control {
+    align-items: center;
+    flex-wrap: wrap;
+}
+
+.profile-launcher-control > * {
+    margin-top: 10px;
+    margin-right: 6px;
+}
+
+.profile-launcher-control button {
+    min-width: 110px;
+}
+
+.profile-launcher-target {
+    align-items: baseline;
+}
+
+.profile-launcher-target > * {
+    flex: 0 0 auto;
+    margin-right: 8px;
 }
 
 .profile-launcher-view-content h1 {
@@ -178,23 +196,15 @@
 }
 
 .js_profiler.panel select.chrome-select,
-.heap_profiler.panel select.chrome-select
- {
-    font-size: 12px;
+.heap_profiler.panel select.chrome-select {
     width: 150px;
-    margin-left: 10px;
-    margin-right: 10px;
 }
 
 button.load-profile {
-    margin-left: 20px;
+    margin-top: 10px;
+    min-width: 110px;
 }
 
-button.load-profile.multi-target {
-    display: block;
-    margin-top: 14px;
-    margin-left: 0;
-}
 
 .cpu-profile-flame-chart-overview-container {
     overflow: hidden;
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
index 591eb5f5..f04e101 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
@@ -560,7 +560,7 @@
         return;
       }
 
-      this.target().domdebuggerAgent().getEventListeners(this._objectId, mycallback.bind(this));
+      this.target().domdebuggerAgent().getEventListeners(this._objectId, undefined, undefined, mycallback.bind(this));
 
       /**
        * @this {SDK.RemoteObjectImpl}
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js
index 8613bdc..692e451 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/EventsTimelineTreeView.js
@@ -99,7 +99,8 @@
    * @override
    * @param {!UI.Toolbar} toolbar
    */
-  _populateToolbar(toolbar) {
+  populateToolbar(toolbar) {
+    super.populateToolbar(toolbar);
     this._filtersControl.populateToolbar(toolbar);
   }
 
@@ -142,8 +143,7 @@
     super();
     this._categoryFilter = new Timeline.TimelineFilters.Category();
     this._durationFilter = new Timeline.TimelineFilters.IsLong();
-    this._textFilter = new Timeline.TimelineFilters.RegExp();
-    this._filters = [this._categoryFilter, this._durationFilter, this._textFilter];
+    this._filters = [this._categoryFilter, this._durationFilter];
   }
 
   /**
@@ -157,10 +157,6 @@
    * @param {!UI.Toolbar} toolbar
    */
   populateToolbar(toolbar) {
-    this._textFilterUI = new UI.ToolbarInput(Common.UIString('Filter'));
-    this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, textFilterChanged, this);
-    toolbar.appendToolbarItem(this._textFilterUI);
-
     var durationFilterUI = new UI.ToolbarComboBox(durationFilterChanged.bind(this));
     for (var durationMs of Timeline.EventsTimelineTreeView.Filters._durationFilterPresetsMs) {
       durationFilterUI.addOption(durationFilterUI.createOption(
@@ -188,15 +184,6 @@
     /**
      * @this {Timeline.EventsTimelineTreeView.Filters}
      */
-    function textFilterChanged() {
-      var searchQuery = this._textFilterUI.value();
-      this._textFilter.setRegExp(searchQuery ? createPlainTextSearchRegex(searchQuery, 'i') : null);
-      this._notifyFiltersChanged();
-    }
-
-    /**
-     * @this {Timeline.EventsTimelineTreeView.Filters}
-     */
     function durationFilterChanged() {
       var duration = durationFilterUI.selectedOption().value;
       var minimumRecordDuration = parseInt(duration, 10);
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
index 2f19b974..8f038cc1 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -47,7 +47,8 @@
   init(filters) {
     this._linkifier = new Components.Linkifier();
 
-    this._filters = filters.slice();
+    this._textFilter = new Timeline.TimelineFilters.RegExp();
+    this._filters = [...filters, this._textFilter];
 
     const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([]);
     this.populateColumns(columns);
@@ -55,7 +56,7 @@
     this._splitWidget = new UI.SplitWidget(true, true, 'timelineTreeViewDetailsSplitWidget');
     var mainView = new UI.VBox();
     var toolbar = new UI.Toolbar('', mainView.element);
-    this._populateToolbar(toolbar);
+    this.populateToolbar(toolbar);
 
     this._dataGrid = new DataGrid.SortableDataGrid(columns);
     this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._sortingChanged, this);
@@ -109,9 +110,22 @@
   }
 
   /**
+   * @protected
    * @param {!UI.Toolbar} toolbar
    */
-  _populateToolbar(toolbar) {
+  populateToolbar(toolbar) {
+    this._textFilterUI = new UI.ToolbarInput(Common.UIString('Filter'), 0, 0, true);
+    this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, textFilterChanged, this);
+    toolbar.appendToolbarItem(this._textFilterUI);
+
+    /**
+     * @this {Timeline.TimelineTreeView}
+     */
+    function textFilterChanged() {
+      var searchQuery = this._textFilterUI.value();
+      this._textFilter.setRegExp(searchQuery ? createPlainTextSearchRegex(searchQuery, 'i') : null);
+      this.refreshTree();
+    }
   }
 
   /**
@@ -574,7 +588,8 @@
    * @override
    * @param {!UI.Toolbar} toolbar
    */
-  _populateToolbar(toolbar) {
+  populateToolbar(toolbar) {
+    super.populateToolbar(toolbar);
     this._groupByCombobox = new UI.ToolbarComboBox(this._onGroupByChanged.bind(this));
     /**
      * @param {string} name
diff --git a/third_party/WebKit/Source/modules/app_banner/OWNERS b/third_party/WebKit/Source/modules/app_banner/OWNERS
index 92faaaf..d5bee6b2 100644
--- a/third_party/WebKit/Source/modules/app_banner/OWNERS
+++ b/third_party/WebKit/Source/modules/app_banner/OWNERS
@@ -1,2 +1,4 @@
 dominickn@chromium.org
 mlamouri@chromium.org
+
+# COMPONENT: Content>WebApps
diff --git a/third_party/WebKit/Source/modules/permissions/OWNERS b/third_party/WebKit/Source/modules/permissions/OWNERS
index 2d28246..e9ad8e9 100644
--- a/third_party/WebKit/Source/modules/permissions/OWNERS
+++ b/third_party/WebKit/Source/modules/permissions/OWNERS
@@ -1 +1,3 @@
 mlamouri@chromium.org
+
+# COMPONENT: Blink>PermissionsAPI
diff --git a/third_party/WebKit/Source/modules/presentation/OWNERS b/third_party/WebKit/Source/modules/presentation/OWNERS
index 357df4fc..9a20d44e 100644
--- a/third_party/WebKit/Source/modules/presentation/OWNERS
+++ b/third_party/WebKit/Source/modules/presentation/OWNERS
@@ -2,3 +2,5 @@
 imcheng@chromium.org
 mfoltz@chromium.org
 mlamouri@chromium.org
+
+# COMPONENT: Blink>PresentationAPI
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
index 6f37b391..7c192ecc 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -1151,6 +1151,13 @@
                                             GLenum format,
                                             GLenum type,
                                             DOMArrayBufferView* data) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texImage2D(target, level, internalformat, width,
                                         height, border, format, type, data);
 }
@@ -1165,6 +1172,13 @@
                                             GLenum type,
                                             DOMArrayBufferView* data,
                                             GLuint srcOffset) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperDOMArrayBufferView(TexImage2D, target, level, internalformat,
                                    width, height, 1, border, format, type, 0, 0,
                                    0, data, NullNotReachable, srcOffset);
@@ -1180,6 +1194,13 @@
                                             GLenum type,
                                             ImageData* pixels) {
   DCHECK(pixels);
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperImageData(TexImage2D, target, level, internalformat, 0, format,
                           type, 1, 0, 0, 0, pixels,
                           getTextureSourceSubRectangle(width, height), 0);
@@ -1195,6 +1216,13 @@
                                             GLenum type,
                                             HTMLImageElement* image,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLImageElement(TexImage2D, target, level, internalformat,
                                  format, type, 0, 0, 0, image,
                                  getTextureSourceSubRectangle(width, height), 1,
@@ -1211,6 +1239,13 @@
                                             GLenum type,
                                             HTMLCanvasElement* canvas,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLCanvasElement(
       TexImage2D, target, level, internalformat, format, type, 0, 0, 0, canvas,
       getTextureSourceSubRectangle(width, height), 1, 0, exceptionState);
@@ -1226,6 +1261,13 @@
                                             GLenum type,
                                             HTMLVideoElement* video,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLVideoElement(
       TexImage2D, target, level, internalformat, format, type, 0, 0, 0, video,
       getTextureSourceSubRectangle(width, height), 1, 0, exceptionState);
@@ -1242,6 +1284,13 @@
                                             ImageBitmap* bitmap,
                                             ExceptionState& exceptionState) {
   DCHECK(bitmap);
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperImageBitmap(
       TexImage2D, target, level, internalformat, format, type, 0, 0, 0, bitmap,
       getTextureSourceSubRectangle(width, height), 1, 0, exceptionState);
@@ -1253,6 +1302,13 @@
                                             GLenum format,
                                             GLenum type,
                                             ImageData* imageData) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texImage2D(target, level, internalformat, format,
                                         type, imageData);
 }
@@ -1264,6 +1320,13 @@
                                             GLenum type,
                                             HTMLImageElement* image,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texImage2D(target, level, internalformat, format,
                                         type, image, exceptionState);
 }
@@ -1275,6 +1338,13 @@
                                             GLenum type,
                                             HTMLCanvasElement* canvas,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texImage2D(target, level, internalformat, format,
                                         type, canvas, exceptionState);
 }
@@ -1286,6 +1356,13 @@
                                             GLenum type,
                                             HTMLVideoElement* video,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texImage2D(target, level, internalformat, format,
                                         type, video, exceptionState);
 }
@@ -1297,6 +1374,13 @@
                                             GLenum type,
                                             ImageBitmap* imageBitMap,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texImage2D(target, level, internalformat, format,
                                         type, imageBitMap, exceptionState);
 }
@@ -1310,6 +1394,13 @@
                                                GLenum format,
                                                GLenum type,
                                                DOMArrayBufferView* pixels) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texSubImage2D(target, level, xoffset, yoffset,
                                            width, height, format, type, pixels);
 }
@@ -1324,6 +1415,13 @@
                                                GLenum type,
                                                DOMArrayBufferView* pixels,
                                                GLuint srcOffset) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperDOMArrayBufferView(TexSubImage2D, target, level, 0, width,
                                    height, 1, 0, format, type, xoffset, yoffset,
                                    0, pixels, NullNotReachable, srcOffset);
@@ -1339,6 +1437,13 @@
                                                GLenum type,
                                                ImageData* pixels) {
   DCHECK(pixels);
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperImageData(TexSubImage2D, target, level, 0, 0, format, type, 1,
                           xoffset, yoffset, 0, pixels,
                           getTextureSourceSubRectangle(width, height), 0);
@@ -1354,6 +1459,13 @@
                                                GLenum type,
                                                HTMLImageElement* image,
                                                ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLImageElement(
       TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, image,
       getTextureSourceSubRectangle(width, height), 1, 0, exceptionState);
@@ -1369,6 +1481,13 @@
                                                GLenum type,
                                                HTMLCanvasElement* canvas,
                                                ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLCanvasElement(TexSubImage2D, target, level, 0, format, type,
                                   xoffset, yoffset, 0, canvas,
                                   getTextureSourceSubRectangle(width, height),
@@ -1385,6 +1504,13 @@
                                                GLenum type,
                                                HTMLVideoElement* video,
                                                ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLVideoElement(
       TexSubImage2D, target, level, 0, format, type, xoffset, yoffset, 0, video,
       getTextureSourceSubRectangle(width, height), 1, 0, exceptionState);
@@ -1401,6 +1527,13 @@
                                                ImageBitmap* bitmap,
                                                ExceptionState& exceptionState) {
   DCHECK(bitmap);
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperImageBitmap(TexSubImage2D, target, level, 0, format, type,
                             xoffset, yoffset, 0, bitmap,
                             getTextureSourceSubRectangle(width, height), 1, 0,
@@ -1414,6 +1547,13 @@
                                                GLenum format,
                                                GLenum type,
                                                ImageData* pixels) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texSubImage2D(target, level, xoffset, yoffset,
                                            format, type, pixels);
 }
@@ -1426,6 +1566,13 @@
                                                GLenum type,
                                                HTMLImageElement* image,
                                                ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texSubImage2D(target, level, xoffset, yoffset,
                                            format, type, image, exceptionState);
 }
@@ -1438,6 +1585,13 @@
                                                GLenum type,
                                                HTMLCanvasElement* canvas,
                                                ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texSubImage2D(
       target, level, xoffset, yoffset, format, type, canvas, exceptionState);
 }
@@ -1462,6 +1616,13 @@
                                                GLenum type,
                                                ImageBitmap* bitmap,
                                                ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::texSubImage2D(
       target, level, xoffset, yoffset, format, type, bitmap, exceptionState);
 }
@@ -1520,6 +1681,13 @@
                                             GLenum type,
                                             DOMArrayBufferView* pixels,
                                             GLuint srcOffset) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperDOMArrayBufferView(
       TexImage3D, target, level, internalformat, width, height, depth, border,
       format, type, 0, 0, 0, pixels, NullNotReachable, srcOffset);
@@ -1587,6 +1755,13 @@
                                             GLenum type,
                                             HTMLImageElement* image,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLImageElement(TexImage3D, target, level, internalformat,
                                  format, type, 0, 0, 0, image,
                                  getTextureSourceSubRectangle(width, height),
@@ -1604,6 +1779,13 @@
                                             GLenum type,
                                             HTMLCanvasElement* canvas,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLCanvasElement(TexImage3D, target, level, internalformat,
                                   format, type, 0, 0, 0, canvas,
                                   getTextureSourceSubRectangle(width, height),
@@ -1621,6 +1803,13 @@
                                             GLenum type,
                                             HTMLVideoElement* video,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLVideoElement(TexImage3D, target, level, internalformat,
                                  format, type, 0, 0, 0, video,
                                  getTextureSourceSubRectangle(width, height),
@@ -1638,6 +1827,13 @@
                                             GLenum type,
                                             ImageBitmap* bitmap,
                                             ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperImageBitmap(TexImage3D, target, level, internalformat, format,
                             type, 0, 0, 0, bitmap,
                             getTextureSourceSubRectangle(width, height), depth,
@@ -1656,6 +1852,13 @@
                                                GLenum type,
                                                DOMArrayBufferView* pixels,
                                                GLuint srcOffset) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperDOMArrayBufferView(
       TexSubImage3D, target, level, 0, width, height, depth, 0, format, type,
       xoffset, yoffset, zoffset, pixels, NullNotReachable, srcOffset);
@@ -1705,6 +1908,13 @@
                                                GLenum type,
                                                ImageData* pixels) {
   DCHECK(pixels);
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperImageData(TexSubImage3D, target, level, 0, 0, format, type,
                           depth, xoffset, yoffset, zoffset, pixels,
                           getTextureSourceSubRectangle(width, height),
@@ -1723,6 +1933,13 @@
                                                GLenum type,
                                                HTMLImageElement* image,
                                                ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLImageElement(TexSubImage3D, target, level, 0, format, type,
                                  xoffset, yoffset, zoffset, image,
                                  getTextureSourceSubRectangle(width, height),
@@ -1741,6 +1958,13 @@
                                                GLenum type,
                                                HTMLCanvasElement* canvas,
                                                ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLCanvasElement(TexSubImage3D, target, level, 0, format, type,
                                   xoffset, yoffset, zoffset, canvas,
                                   getTextureSourceSubRectangle(width, height),
@@ -1759,6 +1983,13 @@
                                                GLenum type,
                                                HTMLVideoElement* video,
                                                ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperHTMLVideoElement(TexSubImage3D, target, level, 0, format, type,
                                  xoffset, yoffset, zoffset, video,
                                  getTextureSourceSubRectangle(width, height),
@@ -1777,6 +2008,13 @@
                                                GLenum type,
                                                ImageBitmap* bitmap,
                                                ExceptionState& exceptionState) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "texSubImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   texImageHelperImageBitmap(TexSubImage3D, target, level, 0, format, type,
                             xoffset, yoffset, zoffset, bitmap,
                             getTextureSourceSubRectangle(width, height), depth,
@@ -1814,6 +2052,13 @@
     GLsizei height,
     GLint border,
     DOMArrayBufferView* data) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::compressedTexImage2D(target, level, internalformat,
                                                   width, height, border, data);
 }
@@ -1830,6 +2075,11 @@
     GLuint srcLengthOverride) {
   if (isContextLost())
     return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   if (!validateTexture2DBinding("compressedTexImage2D", target))
     return;
   if (!validateCompressedTexFormat("compressedTexImage2D", internalformat))
@@ -1861,6 +2111,11 @@
                                                       GLintptr offset) {
   if (isContextLost())
     return;
+  if (!m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage2D",
+                      "no bound PIXEL_UNPACK_BUFFER");
+    return;
+  }
   contextGL()->CompressedTexImage2D(target, level, internalformat, width,
                                     height, border, imageSize,
                                     reinterpret_cast<uint8_t*>(offset));
@@ -1875,6 +2130,13 @@
     GLsizei height,
     GLenum format,
     DOMArrayBufferView* data) {
+  if (isContextLost())
+    return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   WebGLRenderingContextBase::compressedTexSubImage2D(
       target, level, xoffset, yoffset, width, height, format, data);
 }
@@ -1892,6 +2154,11 @@
     GLuint srcLengthOverride) {
   if (isContextLost())
     return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage2D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   if (!validateTexture2DBinding("compressedTexSubImage2D", target))
     return;
   if (!validateCompressedTexFormat("compressedTexSubImage2D", format))
@@ -1924,6 +2191,11 @@
                                                          GLintptr offset) {
   if (isContextLost())
     return;
+  if (!m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage2D",
+                      "no bound PIXEL_UNPACK_BUFFER");
+    return;
+  }
   contextGL()->CompressedTexSubImage2D(target, level, xoffset, yoffset, width,
                                        height, format, imageSize,
                                        reinterpret_cast<uint8_t*>(offset));
@@ -1942,6 +2214,11 @@
     GLuint srcLengthOverride) {
   if (isContextLost())
     return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   if (!validateTexture3DBinding("compressedTexImage3D", target))
     return;
   if (!validateCompressedTexFormat("compressedTexImage3D", internalformat))
@@ -1975,6 +2252,11 @@
                                                       GLintptr offset) {
   if (isContextLost())
     return;
+  if (!m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "compressedTexImage3D",
+                      "no bound PIXEL_UNPACK_BUFFER");
+    return;
+  }
   contextGL()->CompressedTexImage3D(target, level, internalformat, width,
                                     height, depth, border, imageSize,
                                     reinterpret_cast<uint8_t*>(offset));
@@ -1995,6 +2277,11 @@
     GLuint srcLengthOverride) {
   if (isContextLost())
     return;
+  if (m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage3D",
+                      "a buffer is bound to PIXEL_UNPACK_BUFFER");
+    return;
+  }
   if (!validateTexture3DBinding("compressedTexSubImage3D", target))
     return;
   if (!validateCompressedTexFormat("compressedTexSubImage3D", format))
@@ -2030,6 +2317,11 @@
                                                          GLintptr offset) {
   if (isContextLost())
     return;
+  if (!m_boundPixelUnpackBuffer) {
+    synthesizeGLError(GL_INVALID_OPERATION, "compressedTexSubImage3D",
+                      "no bound PIXEL_UNPACK_BUFFER");
+    return;
+  }
   contextGL()->CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset,
                                        width, height, depth, format, imageSize,
                                        reinterpret_cast<uint8_t*>(offset));
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
index 83cf3d4..f934de0 100644
--- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
+++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -912,10 +912,6 @@
       status: "experimental",
     },
     {
-      name: "V8BasedStructuredClone",
-      status: "stable",
-    },
-    {
       name: "V8IdleTasks",
     },
     {
diff --git a/third_party/WebKit/Source/platform/json/OWNERS b/third_party/WebKit/Source/platform/json/OWNERS
index cda1f0a..19f9406 100644
--- a/third_party/WebKit/Source/platform/json/OWNERS
+++ b/third_party/WebKit/Source/platform/json/OWNERS
@@ -1,3 +1,5 @@
 esprehn@chromium.org
 pfeldman@chromium.org
 iclelland@chromium.org
+
+# COMPONENT: Blink>Internals
diff --git a/third_party/WebKit/Source/platform/text/TextRun.h b/third_party/WebKit/Source/platform/text/TextRun.h
index c6c78ce..2d4660a1 100644
--- a/third_party/WebKit/Source/platform/text/TextRun.h
+++ b/third_party/WebKit/Source/platform/text/TextRun.h
@@ -183,19 +183,19 @@
   }
 
   UChar32 codepointAt(unsigned i) const {
+    SECURITY_DCHECK(i < m_len);
     if (is8Bit())
       return (*this)[i];
     UChar32 codepoint;
-    SECURITY_DCHECK(i < m_len);
     U16_GET(characters16(), 0, i, m_len, codepoint);
     return codepoint;
   }
 
   UChar32 codepointAtAndNext(unsigned& i) const {
+    SECURITY_DCHECK(i < m_len);
     if (is8Bit())
       return (*this)[i++];
     UChar32 codepoint;
-    SECURITY_DCHECK(i < m_len);
     U16_NEXT(characters16(), i, m_len, codepoint);
     return codepoint;
   }
diff --git a/third_party/WebKit/public/platform/modules/permissions/OWNERS b/third_party/WebKit/public/platform/modules/permissions/OWNERS
index 393b01f..ff69b875 100644
--- a/third_party/WebKit/public/platform/modules/permissions/OWNERS
+++ b/third_party/WebKit/public/platform/modules/permissions/OWNERS
@@ -2,3 +2,5 @@
 
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
+
+# COMPONENT: Blink>PermissionsAPI
diff --git a/third_party/WebKit/public/platform/modules/presentation/OWNERS b/third_party/WebKit/public/platform/modules/presentation/OWNERS
index 2f15bc6..bc1b773 100644
--- a/third_party/WebKit/public/platform/modules/presentation/OWNERS
+++ b/third_party/WebKit/public/platform/modules/presentation/OWNERS
@@ -5,3 +5,5 @@
 
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
+
+# COMPONENT: Blink>PresentationAPI
diff --git a/tools/chrome_proxy/webdriver/compression_regression.py b/tools/chrome_proxy/webdriver/compression_regression.py
index 3c9c2bf..f6b1ee6 100644
--- a/tools/chrome_proxy/webdriver/compression_regression.py
+++ b/tools/chrome_proxy/webdriver/compression_regression.py
@@ -2,22 +2,98 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import datetime
+import json
+import math
+import subprocess
+import time
+
 import common
 from common import TestDriver
 from common import IntegrationTest
 
-# Technically not an Integration test, but we'll use the same infrastructure.
-#
-# This tests hits a test page and computes the compression rate for each of the
-# resource types on it. These metrics are then output to the console. After
-# metrics from several releases have been manually captured from the console,
-# this test be changed to check compression rates against the known good rates
-# and alert if they fall outside a tolerance.
-class CompressionRegression(IntegrationTest):
+# The maximum number of data points that will be saved.
+MAX_DATA_POINTS = 365
 
-  # TODO(robertogden): Once month-long metric gathering is up, remove print
-  # statements and make into a true test.
+# The persistant storage for compression data is kept in Google Storage with
+# this bucket name.
+BUCKET = 'chrome_proxy_compression'
+
+# The data file name in the Google Storage bucket, above. The data file is also
+# saved locally under the same name.
+DATA_FILE = 'compression_data.json'
+
+class CompressionRegression(IntegrationTest):
+  """This class is responsible for alerting the Chrome Proxy team to regression
+  in the compression metrics of the proxy. At present, this class will simply
+  gather data and save it to a Google Storage bucket. Once enough data has been
+  gathered to form a reasonable model, alerting will be added to check for
+  regression.
+
+  Before running the test, this class will fetch the JSON data file from Google
+  Storage in a subprocess and store it on the local disk with the same file
+  name. The data is then read from that file. After running the test, if the
+  data has changed the file will be uploaded back to Google Storage.
+
+  The JSON data object and data dict object used widely in this class has the
+  following structure:
+  {
+    "2017-02-29": {
+      "html": 0.314,
+      "jpg": 0.1337,
+      "png": 0.1234,
+      "mp4": 0.9876
+    }
+  }
+  where keys are date stamps in the form "YYYY-MM-DD", and each key in the child
+  object is the resource type with its compression value.
+
+  Also frequently referenced is the compression_average dict object, which
+  contains the compression data just now gathered from Chrome in
+  getCurrentCompressionMetrics(). That object has the following structure:
+  {
+    "test/html": 0.314,
+    "image/jpg": 0.1337,
+    "image/png": 0.1234,
+    "video/mp4": 0.9876
+  }
+  where keys are the content type with its compression value.
+
+  Due to the complexity of several methods in this class, a number of local
+  unit tests can be found at the bottom of this file.
+
+  Please note that while this test uses the IntegrationTest framework, it is
+  classified as a regression test.
+  """
+
   def testCompression(self):
+      """This function is the main test function for regression compression
+      checking and facilitates the test with all of the helper functions'
+      behavior.
+      """
+      compression_average = self.getCurrentCompressionMetrics()
+      self.fetchFromGoogleStorage()
+      data = {}
+      with open(DATA_FILE, 'r') as data_fp:
+        data = json.load(data_fp)
+      if self.updateDataObject(compression_average, data):
+        with open(DATA_FILE, 'w') as data_fp:
+          json.dump(data, data_fp)
+        self.uploadToGoogleStorage()
+
+  def getCurrentCompressionMetrics(self):
+    """This function uses the ChromeDriver framework to open Chrome and navigate
+    to a number of static resources of different types, like jpg, png, mp4, gif,
+    html. Multiple resources of a single type are supported. This function will
+    check that each resource was fetched via the Chrome Proxy, and then compute
+    the compression as a percentage from the Content-Length and
+    X-Original-Content-Length headers where compression = 1 - (cl / xocl). The
+    function will then return the average compression for each of the resource
+    types.
+
+    Returns:
+      a dict object mapping resource type to compression
+    """
     def AddToCompression(compression, key, value):
       if key in compression:
         compression[key].append(value)
@@ -25,22 +101,119 @@
         compression[key] = [value]
     with TestDriver() as t:
       t.AddChromeArg('--enable-spdy-proxy-auth')
-      t.LoadURL('http://check.googlezip.net/metrics/')
-      print ''
+      t.AddChromeArg('--data-reduction-proxy-server-experiments-disabled')
+      t.LoadURL('http://check.googlezip.net/metrics/local.gif')
+      t.LoadURL('http://check.googlezip.net/metrics/local.png')
+      t.LoadURL('http://check.googlezip.net/metrics/local.jpg')
+      t.LoadURL(
+        'http://check.googlezip.net/cacheable/video/buck_bunny_tiny.html')
       compression = {}
       for response in t.GetHTTPResponses():
-        if not response.url.endswith('webp'):
-          cl = response.response_headers['content-length']
-          ocl = response.response_headers['x-original-content-length']
-          compression_rate = 1.0 - (float(cl) / float(ocl))
-          if 'html' in response.response_headers['content-type']:
-            AddToCompression(compression, 'html', compression_rate)
-          else:
-            resource = response.url[response.url.rfind('/'):]
-            AddToCompression(compression, resource[resource.rfind('.') + 1:],
-              compression_rate)
-      for url in sorted(compression):
-        average = sum(compression[url]) / float(len(compression[url]))
-        print url, average
+        # Check that the response was proxied.
+        self.assertHasChromeProxyViaHeader(response)
+        # Compute compression metrics.
+        cl = response.response_headers['content-length']
+        ocl = response.response_headers['x-original-content-length']
+        content_type = response.response_headers['content-type']
+        compression_rate = 1.0 - (float(cl) / float(ocl))
+        if 'html' in response.response_headers['content-type']:
+          AddToCompression(compression, 'html', compression_rate)
+        else:
+          resource = response.url[response.url.rfind('/'):]
+          AddToCompression(compression, resource[resource.rfind('.') + 1:],
+            compression_rate)
+      # Compute the average compression for each resource type.
+      compression_average = {}
+      for resource_type in compression:
+        compression_average[resource_type] = (sum(compression[resource_type]) /
+          float(len(compression[resource_type])))
+      return compression_average
+
+  def updateDataObject(self, compression_average, data,
+      today=datetime.date.today()):
+    """This function handles the updating of the data object when new data is
+    available. Given the existing data object, the results of the
+    getCurrentCompressionMetrics() func, and a date object, it will check if
+    data exists for today. If it does, the method will do nothing and return
+    False. Otherwise, it will update the data object with the compression data.
+    If needed, it will also find the least recent entry in the data object and
+    remove it.
+
+    Args:
+      compression_average: the compression data from
+        getCurrentCompressionMetrics()
+      data: the current data object, a dict
+      today: a date object, specifiable here for testing purposes.
+    Returns:
+      True iff the data object was changed
+    """
+    datestamp = today.strftime('%Y-%m-%d')
+    # Check if this data has already been recorded.
+    if datestamp in data:
+      return False
+    # Append new data, removing the least recent if needed.
+    data[datestamp] = compression_average
+    if len(data) > MAX_DATA_POINTS:
+      min_date = None
+      for date_str in data:
+        date = datetime.date(*[int(d) for d in date_str.split('-')])
+        if min_date == None or date < min_date:
+          min_date = date
+      del data[min_date.strftime('%Y-%m-%d')]
+    return True
+
+  def uploadToGoogleStorage(self):
+    """This function uses the gsutil command to upload the local data file to
+    Google Storage.
+    """
+    gs_location = 'gs://%s/%s' % (BUCKET, DATA_FILE)
+    cmd = ['gsutil', 'cp', DATA_FILE, gs_location]
+    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    stdout, stderr = proc.communicate()
+    if proc.returncode:
+      raise Exception('Uploading to Google Storage failed! output: %s %s' %
+        (stdout, stderr))
+
+  def fetchFromGoogleStorage(self):
+    """This function uses the gsutil command to fetch the local data file from
+    Google Storage.
+    """
+    gs_location = 'gs://%s/%s' % (BUCKET, DATA_FILE)
+    cmd = ['gsutil', 'cp', gs_location, DATA_FILE]
+    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    stdout, stderr = proc.communicate()
+    if proc.returncode:
+      raise Exception('Fetching to Google Storage failed! output: %s %s' %
+        (stdout, stderr))
+
+  def test0UpdateDataObject_NoUpdate(self):
+    """This unit test asserts that the updateDataObject() function doesn't
+    update the data object when today is already contained in the data object.
+    """
+    data = { '2017-02-06': {'hello': 'world'}}
+    new_data = {'Benoit': 'Mandelbrot'}
+    test_day = datetime.date(2017, 02, 06)
+    changed = self.updateDataObject(new_data, data, today=test_day)
+    self.assertFalse(changed, "No data should have been recorded!")
+
+  def test0UpdateDataObject_Update(self):
+    """This unit test asserts that the updateDataObject() function updates the
+    data object when there is new data available, also removing the least recent
+    data point.
+    """
+    start_date = datetime.date(2017, 2, 6)
+    data = {}
+    for i in range(MAX_DATA_POINTS):
+      date_obj = start_date + datetime.timedelta(days=i)
+      datestamp = date_obj.strftime('%Y-%m-%d')
+      data[datestamp] = {'hello': 'world'}
+    new_data = {'Benoit': 'Mandelbrot'}
+    test_day = datetime.date(2017, 02, 06) + datetime.timedelta(
+      days=(MAX_DATA_POINTS))
+    changed = self.updateDataObject(new_data, data, today=test_day)
+    self.assertTrue(changed, "Data should have been recorded!")
+    self.assertNotIn('2017-02-06', data)
+    self.assertIn(test_day.strftime('%Y-%m-%d'), data)
+
 if __name__ == '__main__':
   IntegrationTest.RunAllTests()
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 1e7d499..a8d3666 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -1809,7 +1809,7 @@
       'gn_args': ('ozone_auto_platforms=false ozone_platform_wayland=true '
                   'ozone_platform_x11=true ozone_platform_gbm=true '
                   'enable_package_mash_services=true use_ash=false '
-                  'use_xkbcommon=true'),
+                  'use_jessie_sysroot=true use_xkbcommon=true'),
     },
 
     'pdf_xfa': {
diff --git a/tools/perf/benchmarks/media.py b/tools/perf/benchmarks/media.py
index 5c6faf38..02ae46d 100644
--- a/tools/perf/benchmarks/media.py
+++ b/tools/perf/benchmarks/media.py
@@ -74,7 +74,7 @@
     return 'media.media_cns_cases'
 
 
-@benchmark.Disabled('android')  # crbug.com/671628, WebView: crbug.com/419689.
+@benchmark.Disabled('l', 'android-webview')  # WebView: crbug.com/419689.
 class MediaAndroid(perf_benchmark.PerfBenchmark):
   """Obtains media metrics for key user scenarios on Android."""
   test = media.Media
@@ -85,18 +85,9 @@
 
   @classmethod
   def ShouldDisable(cls, possible_browser):
-    # crbug.com/672059
     if possible_browser.platform.GetOSName() != "android":
       return True
-    # crbug.com/448092
-    if cls.IsSvelte(possible_browser):
-        return True
-
-    # crbug.com/647372
-    if possible_browser.platform.GetDeviceTypeName() == 'Nexus 5X':
-      return True
-
-    return False
+    return cls.IsSvelte(possible_browser)
 
   @classmethod
   def Name(cls):
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index 4910aaa1..60d37720 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -27,6 +27,8 @@
     "ax_range.h",
     "ax_relative_bounds.cc",
     "ax_relative_bounds.h",
+    "ax_role_properties.cc",
+    "ax_role_properties.h",
     "ax_serializable_tree.cc",
     "ax_serializable_tree.h",
     "ax_text_utils.cc",
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc
new file mode 100644
index 0000000..aa712fa
--- /dev/null
+++ b/ui/accessibility/ax_role_properties.cc
@@ -0,0 +1,35 @@
+// 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 "ui/accessibility/ax_role_properties.h"
+
+namespace ui {
+
+bool IsRoleClickable(AXRole role) {
+  switch (role) {
+    case AX_ROLE_BUTTON:
+    case AX_ROLE_CHECK_BOX:
+    case AX_ROLE_COLOR_WELL:
+    case AX_ROLE_DISCLOSURE_TRIANGLE:
+    case AX_ROLE_IMAGE_MAP_LINK:
+    case AX_ROLE_LINK:
+    case AX_ROLE_LIST_BOX_OPTION:
+    case AX_ROLE_MENU_BUTTON:
+    case AX_ROLE_MENU_ITEM:
+    case AX_ROLE_MENU_ITEM_CHECK_BOX:
+    case AX_ROLE_MENU_ITEM_RADIO:
+    case AX_ROLE_MENU_LIST_OPTION:
+    case AX_ROLE_MENU_LIST_POPUP:
+    case AX_ROLE_POP_UP_BUTTON:
+    case AX_ROLE_RADIO_BUTTON:
+    case AX_ROLE_SWITCH:
+    case AX_ROLE_TAB:
+    case AX_ROLE_TOGGLE_BUTTON:
+      return true;
+    default:
+      return false;
+  }
+}
+
+}  // namespace ui
diff --git a/ui/accessibility/ax_role_properties.h b/ui/accessibility/ax_role_properties.h
new file mode 100644
index 0000000..7d9ab796
--- /dev/null
+++ b/ui/accessibility/ax_role_properties.h
@@ -0,0 +1,19 @@
+// 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 UI_ACCESSIBILITY_AX_ROLE_PROPERTIES_H_
+#define UI_ACCESSIBILITY_AX_ROLE_PROPERTIES_H_
+
+#include "ui/accessibility/ax_enums.h"
+#include "ui/accessibility/ax_export.h"
+
+namespace ui {
+
+// Checks if the given role should belong to a control that can respond to
+// clicks.
+AX_EXPORT bool IsRoleClickable(AXRole role);
+
+}  // namespace ui
+
+#endif  // UI_ACCESSIBILITY_AX_ROLE_PROPERTIES_H_
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm
index 5bfa69c..3cf4db2 100644
--- a/ui/accessibility/platform/ax_platform_node_mac.mm
+++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -11,6 +11,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/ax_role_properties.h"
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
 #include "ui/base/l10n/l10n_util.h"
 #import "ui/gfx/mac/coordinate_conversion.h"
@@ -304,7 +305,28 @@
 }
 
 - (NSArray*)accessibilityActionNames {
-  return nil;
+  base::scoped_nsobject<NSMutableArray> axActions(
+      [[NSMutableArray alloc] init]);
+
+  // VoiceOver expects the "press" action to be first.
+  if (ui::IsRoleClickable(node_->GetData().role))
+    [axActions addObject:NSAccessibilityPressAction];
+
+  return axActions.autorelease();
+}
+
+- (void)accessibilityPerformAction:(NSString*)action {
+  DCHECK([[self accessibilityActionNames] containsObject:action]);
+  ui::AXActionData data;
+  if ([action isEqualToString:NSAccessibilityPressAction])
+    data.action = ui::AX_ACTION_DO_DEFAULT;
+
+  // Note ui::AX_ACTIONs which are just overwriting an accessibility attribute
+  // are already implemented in -accessibilitySetValue:forAttribute:, so ignore
+  // those here.
+
+  if (data.action != ui::AX_ACTION_NONE)
+    node_->GetDelegate()->AccessibilityPerformAction(data);
 }
 
 - (NSArray*)accessibilityAttributeNames {
diff --git a/ui/views/widget/native_widget_mac_accessibility_unittest.mm b/ui/views/widget/native_widget_mac_accessibility_unittest.mm
index 3d641d19..f7d373665 100644
--- a/ui/views/widget/native_widget_mac_accessibility_unittest.mm
+++ b/ui/views/widget/native_widget_mac_accessibility_unittest.mm
@@ -39,19 +39,27 @@
 
   // Add a child view and resize to fit the child.
   void FitBoundsToNewChild(View* view) {
-    View::AddChildView(view);
+    AddChildView(view);
     // Fit the parent widget to the size of the child for accurate hit tests.
     SetBoundsRect(view->bounds());
   }
 
+  bool mouse_was_pressed() const { return mouse_was_pressed_; }
+
   // View:
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
     View::GetAccessibleNodeData(node_data);
     node_data->role = role_;
   }
 
+  bool OnMousePressed(const ui::MouseEvent& event) override {
+    mouse_was_pressed_ = true;
+    return false;
+  }
+
  private:
   ui::AXRole role_;
+  bool mouse_was_pressed_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(FlexibleRoleTestView);
 };
@@ -72,14 +80,16 @@
     test::WidgetTest::TearDown();
   }
 
-  id AttributeValueAtMidpoint(NSString* attribute) {
+  id A11yElementAtMidpoint() {
     // Accessibility hit tests come in Cocoa screen coordinates.
     NSPoint midpoint_in_screen_ = gfx::ScreenPointToNSPoint(
         widget_->GetWindowBoundsInScreen().CenterPoint());
-    id hit =
+    return
         [widget_->GetNativeWindow() accessibilityHitTest:midpoint_in_screen_];
-    id value = [hit accessibilityAttributeValue:attribute];
-    return value;
+  }
+
+  id AttributeValueAtMidpoint(NSString* attribute) {
+    return [A11yElementAtMidpoint() accessibilityAttributeValue:attribute];
   }
 
   Textfield* AddChildTextfield(const gfx::Size& size) {
@@ -311,14 +321,11 @@
   view->SetSize(GetWidgetBounds().size());
   widget()->GetContentsView()->AddChildView(view);
 
-  // Get the FlexibleRoleTestView accessibility object.
-  NSPoint midpoint = gfx::ScreenPointToNSPoint(GetWidgetBounds().CenterPoint());
-  id ax_node = [widget()->GetNativeWindow() accessibilityHitTest:midpoint];
+  // Make sure the accessibility object tested is the correct one.
+  id ax_node = A11yElementAtMidpoint();
   EXPECT_TRUE(ax_node);
-
-  // Make sure it's the correct accessibility object.
-  id value = [ax_node accessibilityAttributeValue:NSAccessibilityRoleAttribute];
-  EXPECT_NSEQ(NSAccessibilityGroupRole, value);
+  EXPECT_NSEQ(NSAccessibilityGroupRole,
+              AttributeValueAtMidpoint(NSAccessibilityRoleAttribute));
 
   // Make sure |view| is focusable, then focus/unfocus it.
   view->SetFocusBehavior(View::FocusBehavior::ALWAYS);
@@ -413,4 +420,20 @@
             textfield->GetSelectedRange());
 }
 
+// Test performing a 'click' on Views with clickable roles work.
+TEST_F(NativeWidgetMacAccessibilityTest, PressAction) {
+  FlexibleRoleTestView* view = new FlexibleRoleTestView(ui::AX_ROLE_BUTTON);
+  widget()->GetContentsView()->AddChildView(view);
+  view->SetSize(GetWidgetBounds().size());
+
+  id ax_node = A11yElementAtMidpoint();
+  EXPECT_NSEQ(NSAccessibilityButtonRole,
+              AttributeValueAtMidpoint(NSAccessibilityRoleAttribute));
+
+  EXPECT_TRUE([[ax_node accessibilityActionNames]
+      containsObject:NSAccessibilityPressAction]);
+  [ax_node accessibilityPerformAction:NSAccessibilityPressAction];
+  EXPECT_TRUE(view->mouse_was_pressed());
+}
+
 }  // namespace views
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
index 2ed13112..814eced 100644
--- a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
+++ b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
@@ -4,6 +4,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-tooltip/paper-tooltip.html">
 <link rel="import" href="cr_policy_indicator_behavior.html">
 <link rel="import" href="cr_policy_pref_behavior.html">
+<link rel="import" href="cr_policy_vars_css.html">
 
 <dom-module id="cr-policy-pref-indicator">
   <link rel="import" type="css" href="cr_policy_indicator.css">
diff --git a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
index dcb58c4..5526eb5 100644
--- a/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
+++ b/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
@@ -40,5 +40,12 @@
     var matches = pref && pref.value == pref.recommendedValue;
     return this.getPolicyIndicatorTooltip(
         type, pref.controlledByName || '', matches);
-  }
+  },
+
+  /**
+   * @return {boolean} Whether the policy indicator is on. Useful for testing.
+   */
+  isActive: function() {
+    return this.isIndicatorVisible(this.indicatorType);
+  },
 });