diff --git a/DEPS b/DEPS
index bac8e56..e40b8800 100644
--- a/DEPS
+++ b/DEPS
@@ -167,11 +167,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '2d8a95ee71b5a459eb7dfa26400bfd089e7b268a',
+  'skia_revision': '7fd7a8aef06c2f97eaa64a87e33e2a2245acb4e7',
   # 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': '5697a8371da8791c2f8a2a1177d0349b537d4665',
+  'v8_revision': 'd372b6c1137a069dcbff58166df8c46240d06aee',
   # 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.
@@ -179,7 +179,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'd200a77a22cf4241ab0e5714f4479ca300334bf1',
+  'angle_revision': '32bee0fd038e1c3a5d5660aff8080b433b11e1fd',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -230,7 +230,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': '51c8a7860a5a92b0ab57c8a1d092d3bf523fa727',
+  'catapult_revision': '383a4e801d419cda7368487d17cd2388face3144',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -862,7 +862,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '1f67cf3bf610fc9b1d33d693c326e1071a7a2496',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'f1f2e8606a69ac3dd9d5add3fd38425debbdc5c5',
       'condition': 'checkout_linux',
   },
 
@@ -887,7 +887,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3481902904a9e103f8391bc5e17385f537cadbab',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6a1d77869d77b61189247ce8b47ac9d86684a6c2',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -956,7 +956,7 @@
   },
 
   'src/third_party/glslang/src':
-    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '4b97a1108114107a8082a55e9e0721a40f9536d3',
+    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '1ff0c181bb37b06371e2ffa2810d473c5e01c9b7',
 
   'src/third_party/google_toolbox_for_mac/src': {
       'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'),
@@ -1252,7 +1252,7 @@
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '6f26bce0b1c4e8ce0e13332f7c0083788def5fdf',
 
   'src/third_party/openscreen/src':
-    Var('chromium_git') + '/openscreen' + '@' + '4ca3339848cc889648ba6c70edfbef944cdf1ffb',
+    Var('chromium_git') + '/openscreen' + '@' + 'af60f62955c6101bbc4223f30e7685a824369058',
 
   'src/third_party/openxr/src': {
     'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '46d7cb392019e934e2944bdd317be8ed5176b3f2',
@@ -1280,7 +1280,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '14bf0b9d81222e3c379f94c73180b6505eef892f',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '561ba7ee890b2ae08a5ec9bc3ef1301ba3a3ef16',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1470,7 +1470,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '2701c130839edbeb226735b0775966b6423d9e83',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'f17976d01993391c002d7a333bd1d882f2741180',
+    Var('webrtc_git') + '/src.git' + '@' + 'd62ac3f0b8308a77c0944d444b5de7686c389a07',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1532,7 +1532,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b21973d2c0c9f937332eee787d6d14df96288ce8',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@847b3f98194ef5d4efbb0ff2e643fe0de895448b',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index 23a51d4..2f87aa4 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -386,6 +386,7 @@
 shared_library("libwebviewchromium") {
   deps = [
     ":webview_entry_point",
+    "//components/about_ui:about_ui_android",
   ]
   configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
   configs += [ "//build/config/android:hide_all_but_jni" ]
diff --git a/android_webview/browser/metrics/memory_metrics_logger.cc b/android_webview/browser/metrics/memory_metrics_logger.cc
index 71a6930..b08af5a 100644
--- a/android_webview/browser/metrics/memory_metrics_logger.cc
+++ b/android_webview/browser/metrics/memory_metrics_logger.cc
@@ -36,7 +36,9 @@
     return;
   }
 
+  uint64_t total_private_footprint_kb = 0;
   for (const auto& process_dump : dump->process_dumps()) {
+    total_private_footprint_kb += process_dump.os_dump().private_footprint_kb;
     switch (process_dump.process_type()) {
       case memory_instrumentation::mojom::ProcessType::BROWSER: {
         MEMORY_METRICS_HISTOGRAM_MB(
@@ -67,6 +69,10 @@
         break;
     }
   }
+  if (total_private_footprint_kb) {
+    MEMORY_METRICS_HISTOGRAM_MB("Memory.Total.PrivateMemoryFootprint",
+                                total_private_footprint_kb / 1024);
+  }
   if (done_callback)
     std::move(done_callback).Run(true);
 }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/MemoryMetricsLoggerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/MemoryMetricsLoggerTest.java
index f08905e..f4f9f7d0 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/MemoryMetricsLoggerTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/MemoryMetricsLoggerTest.java
@@ -54,6 +54,9 @@
         Assert.assertNotEquals(0,
                 RecordHistogram.getHistogramTotalCountForTesting(
                         "Memory.Renderer.PrivateMemoryFootprint"));
+        Assert.assertNotEquals(0,
+                RecordHistogram.getHistogramTotalCountForTesting(
+                        "Memory.Total.PrivateMemoryFootprint"));
     }
 
     @Test
@@ -64,9 +67,13 @@
         Assert.assertNotEquals(0,
                 RecordHistogram.getHistogramTotalCountForTesting(
                         "Memory.Browser.PrivateMemoryFootprint"));
+        // Verify no renderer record in single process mode.
         Assert.assertEquals(0,
                 RecordHistogram.getHistogramTotalCountForTesting(
                         "Memory.Renderer.PrivateMemoryFootprint"));
+        Assert.assertNotEquals(0,
+                RecordHistogram.getHistogramTotalCountForTesting(
+                        "Memory.Total.PrivateMemoryFootprint"));
     }
 
     /**
diff --git a/ash/display/unified_mouse_warp_controller.cc b/ash/display/unified_mouse_warp_controller.cc
index a0b6a03..e8faa97 100644
--- a/ash/display/unified_mouse_warp_controller.cc
+++ b/ash/display/unified_mouse_warp_controller.cc
@@ -45,9 +45,7 @@
 }  // namespace
 
 UnifiedMouseWarpController::UnifiedMouseWarpController()
-    : current_cursor_display_id_(display::kInvalidDisplayId),
-      update_location_for_test_(false),
-      display_boundaries_computed_(false) {}
+    : update_location_for_test_(false), display_boundaries_computed_(false) {}
 
 UnifiedMouseWarpController::~UnifiedMouseWarpController() = default;
 
@@ -85,16 +83,6 @@
   const display::Display display =
       display::Screen::GetScreen()->GetDisplayNearestWindow(
           const_cast<aura::Window*>(host->window()));
-  if (current_cursor_display_id_ != display::kInvalidDisplayId &&
-      current_cursor_display_id_ != display.id()) {
-    aura::client::CursorClient* cursor_client =
-        aura::client::GetCursorClient(target->GetRootWindow());
-    if (cursor_client) {
-      cursor_client->SetDisplay(display);
-      current_cursor_display_id_ = display::kInvalidDisplayId;
-    }
-  }
-
   return WarpMouseCursorInNativeCoords(display.id(), point_in_native,
                                        point_in_unified_host,
                                        update_location_for_test_);
@@ -149,10 +137,6 @@
   const std::vector<DisplayEdge>& potential_edges = edges_iter->second;
   for (const auto& edge : potential_edges) {
     if (edge.edge_native_bounds_in_source_display.Contains(point_in_native)) {
-      // Wait updating the cursor until the cursor moves to the new display
-      // to avoid showing the wrong sized cursor at the source display.
-      current_cursor_display_id_ = edge.source_display_id;
-
       AshWindowTreeHost* target_ash_host =
           GetMirroringAshWindowTreeHostForDisplayId(edge.target_display_id);
       MoveCursorTo(target_ash_host, point_in_unified_host,
diff --git a/ash/display/unified_mouse_warp_controller.h b/ash/display/unified_mouse_warp_controller.h
index 25824b6..303a76c 100644
--- a/ash/display/unified_mouse_warp_controller.h
+++ b/ash/display/unified_mouse_warp_controller.h
@@ -75,8 +75,6 @@
   // the surrounding displays.
   std::map<int64_t, std::vector<DisplayEdge>> displays_edges_map_;
 
-  int64_t current_cursor_display_id_;
-
   bool update_location_for_test_;
 
   // True if the edge boundaries between displays (where mouse cursor should
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index e2d490c..7a15611 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -1337,7 +1337,9 @@
 
   if (state.IsShelfAutoHidden()) {
     shelf_in_screen_portion =
-        ShelfConfig::Get()->hidden_shelf_in_screen_portion();
+        home_launcher_animation_state_ == kShowing
+            ? shelf_size
+            : ShelfConfig::Get()->hidden_shelf_in_screen_portion();
   } else if (state.visibility_state == SHELF_HIDDEN ||
              work_area->IsKeyboardShown()) {
     shelf_in_screen_portion = 0;
@@ -1789,6 +1791,13 @@
       state.visibility_state == SHELF_VISIBLE) {
     return 1.0f;
   }
+  // The shelf should not become transparent during the animation to or from
+  // HomeLauncher.
+  if (chromeos::switches::ShouldShowShelfHotseat() && IsTabletModeEnabled() &&
+      home_launcher_animation_state_ != kFinished) {
+    return 1.0f;
+  }
+
   // In Chrome OS Material Design, when shelf is hidden during auto hide state,
   // target bounds are also hidden. So the window can extend to the edge of
   // screen.
diff --git a/build/android/pylib/local/emulator/avd.py b/build/android/pylib/local/emulator/avd.py
index e08d9a9..fab9061 100644
--- a/build/android/pylib/local/emulator/avd.py
+++ b/build/android/pylib/local/emulator/avd.py
@@ -428,7 +428,7 @@
   def __str__(self):
     return '%s|%s' % (self._avd_name, (self._emulator_serial or id(self)))
 
-  def Start(self, read_only=True, snapshot_save=False):
+  def Start(self, read_only=True, snapshot_save=False, window=False):
     """Starts the emulator running an instance of the given AVD."""
     with tempfile_ext.TemporaryFileName() as socket_path, (contextlib.closing(
         socket.socket(socket.AF_UNIX))) as sock:
@@ -439,7 +439,6 @@
           self._avd_name,
           '-report-console',
           'unix:%s' % socket_path,
-          '-no-window',
       ]
       if read_only:
         emulator_cmd.append('-read-only')
@@ -448,6 +447,13 @@
       emulator_env = {}
       if self._emulator_home:
         emulator_env['ANDROID_EMULATOR_HOME'] = self._emulator_home
+      if window:
+        if 'DISPLAY' in os.environ:
+          emulator_env['DISPLAY'] = os.environ.get('DISPLAY')
+        else:
+          raise AvdException('Emulator failed to start: DISPLAY not defined')
+      else:
+        emulator_cmd.append('-no-window')
       sock.listen(1)
 
       logging.info('Starting emulator.')
diff --git a/build/android/pylib/local/emulator/local_emulator_environment.py b/build/android/pylib/local/emulator/local_emulator_environment.py
index 24eed16..22470c0 100644
--- a/build/android/pylib/local/emulator/local_emulator_environment.py
+++ b/build/android/pylib/local/emulator/local_emulator_environment.py
@@ -23,6 +23,7 @@
     elif args.emulator_count >= _MAX_ANDROID_EMULATORS:
       logging.warning('--emulator-count capped at 16.')
     self._emulator_count = min(_MAX_ANDROID_EMULATORS, args.emulator_count)
+    self._emulator_window = args.emulator_window
     self._emulator_instances = []
     self._device_serials = []
 
@@ -36,7 +37,7 @@
 
     def start_emulator_instance(e):
       try:
-        e.Start()
+        e.Start(window=self._emulator_window)
         return e
       except avd.AvdException:
         logging.exception('Failed to start emulator instance.')
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 48401e0f..0f6cc50 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -320,6 +320,11 @@
       type=int,
       default=1,
       help='Number of emulators to use.')
+  parser.add_argument(
+      '--emulator-window',
+      action='store_true',
+      default=False,
+      help='Enable graphical window display on the emulator.')
 
 
 def AddGTestOptions(parser):
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 9567d8b2..919d1d9 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8899992290423399568
\ No newline at end of file
+8899962685313080352
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 5cb0aa2..cc32eff 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8899994743731329152
\ No newline at end of file
+8899968699888303648
\ No newline at end of file
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 86ed8f7..09cd244 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -371,6 +371,7 @@
     TRACE_EVENT0("cc", "LayerTreeHost::AnimationHost::PushProperties");
     DCHECK(host_impl->mutator_host());
     mutator_host_->PushPropertiesTo(host_impl->mutator_host());
+    MoveChangeTrackingToLayers(sync_tree);
 
     // Updating elements affects whether animations are in effect based on their
     // properties so run after pushing updated animation properties.
@@ -405,6 +406,27 @@
   }
 }
 
+void LayerTreeHost::MoveChangeTrackingToLayers(LayerTreeImpl* tree_impl) {
+  // This is only true for single-thread compositing (i.e. not via Blink).
+  bool property_trees_changed_on_active_tree =
+      tree_impl->IsActiveTree() && tree_impl->property_trees()->changed;
+
+  if (property_trees_changed_on_active_tree) {
+    // Property trees may store damage status. We preserve the sync tree damage
+    // status by pushing the damage status from sync tree property trees to main
+    // thread property trees or by moving it onto the layers.
+    if (root_layer_) {
+      if (property_trees_.sequence_number ==
+          tree_impl->property_trees()->sequence_number)
+        tree_impl->property_trees()->PushChangeTrackingTo(&property_trees_);
+      else
+        tree_impl->MoveChangeTrackingToLayers();
+    }
+  } else {
+    tree_impl->MoveChangeTrackingToLayers();
+  }
+}
+
 void LayerTreeHost::ImageDecodesFinished(
     const std::vector<std::pair<int, bool>>& results) {
   // Issue stored callbacks and remove them from the pending list.
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index a3a89a6..104cc54 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -525,6 +525,7 @@
   void PushLayerTreePropertiesTo(LayerTreeImpl* tree_impl);
   void PushSurfaceRangesTo(LayerTreeImpl* tree_impl);
   void PushLayerTreeHostPropertiesTo(LayerTreeHostImpl* host_impl);
+  void MoveChangeTrackingToLayers(LayerTreeImpl* tree_impl);
 
   MutatorHost* mutator_host() const { return mutator_host_; }
 
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 05e38a9..3ccf340 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1420,6 +1420,7 @@
     ]
     deps = [
       "//android_webview:common",
+      "//components/about_ui:about_ui_android",
       "//components/crash/android:crashpad_main",
       "//weblayer:weblayer_lib",
     ]
@@ -2468,7 +2469,6 @@
     "java/src/org/chromium/chrome/browser/complex_tasks/endpoint_fetcher/EndpointFetcher.java",
     "java/src/org/chromium/chrome/browser/complex_tasks/endpoint_fetcher/EndpointResponse.java",
     "java/src/org/chromium/chrome/browser/component_updater/UpdateScheduler.java",
-    "java/src/org/chromium/chrome/browser/component_updater/VrAssetsComponentInstaller.java",
     "java/src/org/chromium/chrome/browser/compositor/CompositorView.java",
     "java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java",
     "java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java",
@@ -2731,4 +2731,8 @@
       "feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java",
     ]
   }
+
+  if (enable_vr) {
+    sources += [ "java/src/org/chromium/chrome/browser/component_updater/VrAssetsComponentInstaller.java" ]
+  }
 }
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
index b5f1bb9..44883b4 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
@@ -40,9 +40,10 @@
     interface FeedSurfaceCreator {
         /**
          * Creates the {@link FeedSurfaceCoordinator} for the specified mode.
+         * @param isInNightMode Whether or not the feed surface is going to display in night mode.
          * @return The {@link FeedSurfaceCoordinator}.
          */
-        FeedSurfaceCoordinator createFeedSurfaceCoordinator();
+        FeedSurfaceCoordinator createFeedSurfaceCoordinator(boolean isInNightMode);
     }
 
     ExploreSurfaceCoordinator(ChromeActivity activity, ViewGroup parentView,
@@ -60,8 +61,8 @@
                 ExploreSurfaceViewBinder::bind);
         mFeedSurfaceCreator = new FeedSurfaceCreator() {
             @Override
-            public FeedSurfaceCoordinator createFeedSurfaceCoordinator() {
-                return internalCreateFeedSurfaceCoordinator(mHasHeader);
+            public FeedSurfaceCoordinator createFeedSurfaceCoordinator(boolean isInNightMode) {
+                return internalCreateFeedSurfaceCoordinator(mHasHeader, isInNightMode);
             }
         };
     }
@@ -85,7 +86,8 @@
         return false;
     }
 
-    private FeedSurfaceCoordinator internalCreateFeedSurfaceCoordinator(boolean hasHeader) {
+    private FeedSurfaceCoordinator internalCreateFeedSurfaceCoordinator(
+            boolean hasHeader, boolean isInNightMode) {
         if (mExploreSurfaceNavigationDelegate == null) {
             mExploreSurfaceNavigationDelegate = new ExploreSurfaceNavigationDelegate(mActivity);
         }
@@ -104,7 +106,7 @@
                     (SectionHeaderView) inflater.inflate(R.layout.ss_feed_header, null, false);
         }
         return new FeedSurfaceCoordinator(mActivity, null, null, null, sectionHeaderView,
-                exploreSurfaceActionHandler, false, this);
+                exploreSurfaceActionHandler, isInNightMode, this);
         // TODO(crbug.com/982018): Customize surface background for incognito and dark mode.
         // TODO(crbug.com/982018): Hide signin promo UI in incognito mode.
     }
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
index a4ebf7ad..1593afd 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -100,7 +100,8 @@
                         : mExploreSurfaceCoordinator.getFeedSurfaceCreator(),
                 mSurfaceMode == SurfaceMode.SINGLE_PANE ? this::initializeSecondaryTasksSurface
                                                         : null,
-                mSurfaceMode, mStartSurfaceLocationBarDelegate);
+                mSurfaceMode, mStartSurfaceLocationBarDelegate,
+                mActivity.getNightModeStateProvider());
     }
 
     // Implements StartSurface.
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
index 1eb2e558..3fb5be3 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -27,6 +27,7 @@
 import org.chromium.base.ObserverList;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.feed.FeedSurfaceCoordinator;
+import org.chromium.chrome.browser.night_mode.NightModeStateProvider;
 import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModel;
@@ -93,6 +94,7 @@
     private boolean mIsIncognito;
     @Nullable
     private Delegate mDelegate;
+    private NightModeStateProvider mNightModeStateProvider;
     @Nullable
     UrlFocusChangeListener mUrlFocusChangeListener;
     @Nullable
@@ -102,13 +104,15 @@
             @Nullable PropertyModel propertyModel,
             @Nullable ExploreSurfaceCoordinator.FeedSurfaceCreator feedSurfaceCreator,
             @Nullable SecondaryTasksSurfaceInitializer secondaryTasksSurfaceInitializer,
-            @SurfaceMode int surfaceMode, @Nullable Delegate delegate) {
+            @SurfaceMode int surfaceMode, @Nullable Delegate delegate,
+            NightModeStateProvider nightModeStateProvider) {
         mController = controller;
         mPropertyModel = propertyModel;
         mFeedSurfaceCreator = feedSurfaceCreator;
         mSecondaryTasksSurfaceInitializer = secondaryTasksSurfaceInitializer;
         mSurfaceMode = surfaceMode;
         mDelegate = delegate;
+        mNightModeStateProvider = nightModeStateProvider;
 
         if (mPropertyModel != null) {
             assert mSurfaceMode == SurfaceMode.SINGLE_PANE || mSurfaceMode == SurfaceMode.TWO_PANES
@@ -258,7 +262,8 @@
             if (mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE)
                     && mPropertyModel.get(FEED_SURFACE_COORDINATOR) == null) {
                 mPropertyModel.set(FEED_SURFACE_COORDINATOR,
-                        mFeedSurfaceCreator.createFeedSurfaceCoordinator());
+                        mFeedSurfaceCreator.createFeedSurfaceCoordinator(
+                                mNightModeStateProvider.isInNightMode()));
             }
 
             mPropertyModel.set(IS_SHOWING_OVERVIEW, true);
@@ -361,8 +366,9 @@
 
         if (isVisible && mPropertyModel.get(IS_SHOWING_OVERVIEW)
                 && mPropertyModel.get(FEED_SURFACE_COORDINATOR) == null) {
-            mPropertyModel.set(
-                    FEED_SURFACE_COORDINATOR, mFeedSurfaceCreator.createFeedSurfaceCoordinator());
+            mPropertyModel.set(FEED_SURFACE_COORDINATOR,
+                    mFeedSurfaceCreator.createFeedSurfaceCoordinator(
+                            mNightModeStateProvider.isInNightMode()));
         }
 
         mPropertyModel.set(IS_EXPLORE_SURFACE_VISIBLE, isVisible);
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index becf40d..c60bb3d 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -135,7 +135,7 @@
 
     <!-- Overlay panel dimensions -->
     <dimen name="overlay_panel_bar_height_legacy">56dp</dimen>
-    <dimen name="overlay_panel_bar_height">60dp</dimen>
+    <dimen name="overlay_panel_bar_height">70dp</dimen>
     <dimen name="preview_tab_favicon_size">24dp</dimen>
 
     <!-- Autofill keyboard accessory dimensions -->
diff --git a/chrome/android/java/res_download/layout/download_rename_extension_custom_dialog.xml b/chrome/android/java/res_download/layout/download_rename_extension_custom_dialog.xml
index 5f055b2..f49fb4e 100644
--- a/chrome/android/java/res_download/layout/download_rename_extension_custom_dialog.xml
+++ b/chrome/android/java/res_download/layout/download_rename_extension_custom_dialog.xml
@@ -9,8 +9,7 @@
     <LinearLayout
         android:orientation="vertical"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        style="@style/AlertDialogContent">
+        android:layout_height="wrap_content">
 
         <TextView
             android:id="@+id/subtitle"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java
index a23e373..64d58d21 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java
@@ -227,7 +227,8 @@
     private void onFaviconAvailable(String pageUrl, Bitmap favicon) {
         if (favicon == null) {
             if (mDefaultFaviconHelper == null) mDefaultFaviconHelper = new DefaultFaviconHelper();
-            favicon = mDefaultFaviconHelper.getDefaultFaviconBitmap(mContext, pageUrl, true);
+            favicon = mDefaultFaviconHelper.getDefaultFaviconBitmap(
+                    mContext.getResources(), pageUrl, true);
         }
         for (int i = 0; i < mHistory.getEntryCount(); i++) {
             NavigationEntry entry = mHistory.getEntryAtIndex(i);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java
index 3bb830fa..586a8f581 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java
@@ -132,7 +132,7 @@
         Bitmap originalFavicon = TabFavicon.getBitmap(tab);
         if (originalFavicon == null) {
             originalFavicon = mDefaultFaviconHelper.getDefaultFaviconBitmap(
-                    mContext, tab.getUrl(), !isDarkTheme);
+                    mContext.getResources(), tab.getUrl(), !isDarkTheme);
         }
 
         TitleBitmapFactory titleBitmapFactory =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java
index 3679840..5dda11b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.compositor.bottombar.ephemeraltab;
 
 import android.content.Context;
-import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 
@@ -213,11 +212,9 @@
          */
         public void loadFavicon(final String url, Callback<Drawable> callback) {
             FaviconHelper.FaviconImageCallback imageCallback = (bitmap, iconUrl) -> {
-                Drawable drawable = faviconDrawable(bitmap, url);
-                if (drawable == null) {
-                    drawable = mDefaultFaviconHelper.getDefaultFaviconDrawable(mContext, url, true);
-                }
-
+                Drawable drawable =
+                        FaviconUtils.getIconDrawableWithFilter(bitmap, url, mIconGenerator,
+                                mDefaultFaviconHelper, mContext.getResources(), mFaviconSize);
                 callback.onResult(drawable);
             };
 
@@ -225,14 +222,5 @@
                     Profile.getLastUsedProfile(), url, mFaviconSize, imageCallback);
         }
 
-        /**
-         * Generates a rounded bitmap for the given favicon. If the given favicon is null, generates
-         * a favicon from the URL instead.
-         */
-        private Drawable faviconDrawable(Bitmap image, String url) {
-            if (url == null) return null;
-            return FaviconUtils.getIconDrawableWithFilter(
-                    image, url, mIconGenerator, mContext.getResources(), mFaviconSize);
-        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java
index d23d3ca..2df4c53 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconHelper.java
@@ -4,7 +4,7 @@
 
 package org.chromium.chrome.browser.favicon;
 
-import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
@@ -75,14 +75,13 @@
             return NewTabPage.isNTPUrl(url) ? R.drawable.chromelogo16 : R.drawable.default_favicon;
         }
 
-        private Bitmap createBitmap(Context context, String url, boolean useDarkIcon) {
-            Bitmap origBitmap =
-                    BitmapFactory.decodeResource(context.getResources(), getResourceId(url));
+        private Bitmap createBitmap(Resources resources, String url, boolean useDarkIcon) {
+            Bitmap origBitmap = BitmapFactory.decodeResource(resources, getResourceId(url));
             Bitmap tintedBitmap = Bitmap.createBitmap(
                     origBitmap.getWidth(), origBitmap.getHeight(), Bitmap.Config.ARGB_8888);
             Canvas c = new Canvas(tintedBitmap);
             @ColorInt
-            int tintColor = ApiCompatibilityUtils.getColor(context.getResources(),
+            int tintColor = ApiCompatibilityUtils.getColor(resources,
                     useDarkIcon ? R.color.default_icon_color : R.color.default_icon_color_white);
             Paint p = new Paint();
             p.setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN));
@@ -92,17 +91,18 @@
 
         /**
          * Generate a default favicon bitmap for the given URL.
-         * @param context The context used to fetch the default icons.
+         * @param resources The {@link Resources} to fetch the icons.
          * @param url The URL of the page whose icon is being generated.
          * @param useDarkIcon Whether a dark icon should be used.
          * @return The favicon.
          */
-        public Bitmap getDefaultFaviconBitmap(Context context, String url, boolean useDarkIcon) {
+        public Bitmap getDefaultFaviconBitmap(
+                Resources resources, String url, boolean useDarkIcon) {
             boolean isNtp = NewTabPage.isNTPUrl(url);
             Bitmap bitmap = isNtp ? (useDarkIcon ? mChromeDarkBitmap : mChromeLightBitmap)
                                   : (useDarkIcon ? mDefaultDarkBitmap : mDefaultLightBitmap);
             if (bitmap != null) return bitmap;
-            bitmap = createBitmap(context, url, useDarkIcon);
+            bitmap = createBitmap(resources, url, useDarkIcon);
             if (isNtp && useDarkIcon) {
                 mChromeDarkBitmap = bitmap;
             } else if (isNtp) {
@@ -117,15 +117,15 @@
 
         /**
          * Generate a default favicon drawable for the given URL.
-         * @param context The context used to fetch the default icons.
+         * @param resources The {@link Resources} used to fetch the default icons.
          * @param url The URL of the page whose icon is being generated.
          * @param useDarkIcon Whether a dark icon should be used.
          * @return The favicon.
          */
         public Drawable getDefaultFaviconDrawable(
-                Context context, String url, boolean useDarkIcon) {
+                Resources resources, String url, boolean useDarkIcon) {
             return new BitmapDrawable(
-                    context.getResources(), getDefaultFaviconBitmap(context, url, useDarkIcon));
+                    resources, getDefaultFaviconBitmap(resources, url, useDarkIcon));
         }
 
         /** Clears any of the cached default drawables. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconUtils.java
index a9b9194..6295eb0b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/favicon/FaviconUtils.java
@@ -92,18 +92,25 @@
 
     /**
      * Creates a {@link Drawable} with the provided icon, or a fallback monogram, with bilinear
-     * scaling through {@link Bitmap#createScaledBitmap(Bitmap, int, int, boolean)}.
+     * scaling through {@link Bitmap#createScaledBitmap(Bitmap, int, int, boolean)}, or a fallback
+     * default favicon.
      * @param icon {@link Bitmap} with the icon to display. If null, a fallback monogram will be
      *         generated.
      * @param url Url to generate a monogram. Used only if {@code icon} is null.
      * @param iconGenerator RoundedIconGenerator to generate a monogram. Used only if {@code icon}
      *         is null.
+     * @param defaultFaviconHelper Helper to generate default favicons.
      * @param resources {@link Resources} to create a {@link BitmapDrawable}.
      * @param iconSize Width and height of the returned icon.
      * @return A {@link Drawable} to be displayed as the favicon.
      */
-    public static Drawable getIconDrawableWithFilter(@Nullable Bitmap icon, String url,
-            RoundedIconGenerator iconGenerator, Resources resources, int iconSize) {
+    public static Drawable getIconDrawableWithFilter(@Nullable Bitmap icon, @Nullable String url,
+            RoundedIconGenerator iconGenerator,
+            FaviconHelper.DefaultFaviconHelper defaultFaviconHelper, Resources resources,
+            int iconSize) {
+        if (url == null) {
+            return defaultFaviconHelper.getDefaultFaviconDrawable(resources, url, true);
+        }
         if (icon == null) {
             icon = iconGenerator.generateIconForUrl(url);
             return new BitmapDrawable(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
index 4bdefd1..0069b03 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
@@ -95,8 +95,8 @@
             mTitleView.setTextColor(
                     ApiCompatibilityUtils.getColor(getResources(), R.color.default_red));
         } else {
-            setIconDrawable(
-                    mFaviconHelper.getDefaultFaviconDrawable(getContext(), item.getUrl(), true));
+            setIconDrawable(mFaviconHelper.getDefaultFaviconDrawable(
+                    getContext().getResources(), item.getUrl(), true));
             if (mHistoryManager != null) requestIcon();
 
             mTitleView.setTextColor(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsRowAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsRowAdapter.java
index 3adaf4084..94bf5135 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsRowAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsRowAdapter.java
@@ -297,7 +297,7 @@
                 viewHolder.domainView.setText("");
                 viewHolder.domainView.setVisibility(View.GONE);
             }
-            loadForeignFavicon(viewHolder, sessionTab.url);
+            loadFavicon(viewHolder, sessionTab.url, FaviconLocality.FOREIGN);
         }
 
         @Override
@@ -530,7 +530,7 @@
                 viewHolder.domainView.setText(domain);
                 viewHolder.domainView.setVisibility(View.VISIBLE);
             }
-            loadLocalFavicon(viewHolder, tab.url);
+            loadFavicon(viewHolder, tab.url, FaviconLocality.LOCAL);
         }
 
         @Override
@@ -667,7 +667,7 @@
     }
 
     /**
-     * Creates an RecentTabsRowAdapter used to populate an ExpandableList with other
+     * Creates a RecentTabsRowAdapter used to populate an ExpandableList with other
      * devices and foreign tab cells.
      *
      * @param activity The Android activity this adapter will work in.
@@ -702,17 +702,20 @@
         public FaviconImageCallback imageCallback;
     }
 
-    private Drawable faviconDrawable(Bitmap image, String url) {
-        if (url == null) return null;
-        return FaviconUtils.getIconDrawableWithFilter(
-                image, url, mIconGenerator, mActivity.getResources(), mFaviconSize);
+    @IntDef({FaviconLocality.LOCAL, FaviconLocality.FOREIGN})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface FaviconLocality {
+        int LOCAL = 0;
+        int FOREIGN = 1;
     }
 
-    private void loadForeignFavicon(final ViewHolder viewHolder, final String url) {
+    private void loadFavicon(
+            final ViewHolder viewHolder, final String url, @FaviconLocality int locality) {
         Drawable image;
         if (url == null) {
             // URL is null for print jobs, for example.
-            image = mDefaultFaviconHelper.getDefaultFaviconDrawable(mActivity, url, true);
+            image = mDefaultFaviconHelper.getDefaultFaviconDrawable(
+                    mActivity.getResources(), url, true);
         } else {
             image = mFaviconCache.getLocalFaviconImage(url);
             if (image == null) {
@@ -720,45 +723,26 @@
                     @Override
                     public void onFaviconAvailable(Bitmap bitmap, String iconUrl) {
                         if (this != viewHolder.imageCallback) return;
-                        Drawable image = faviconDrawable(bitmap, url);
-                        image = image == null ? mDefaultFaviconHelper.getDefaultFaviconDrawable(
-                                        mActivity, url, true)
-                                              : image;
-                        mFaviconCache.putLocalFaviconImage(url, image);
-                        viewHolder.imageView.setImageDrawable(image);
+                        Drawable faviconDrawable = FaviconUtils.getIconDrawableWithFilter(bitmap,
+                                url, mIconGenerator, mDefaultFaviconHelper,
+                                mActivity.getResources(), mFaviconSize);
+                        mFaviconCache.putLocalFaviconImage(url, faviconDrawable);
+                        viewHolder.imageView.setImageDrawable(faviconDrawable);
                     }
                 };
                 viewHolder.imageCallback = imageCallback;
-                mRecentTabsManager.getForeignFaviconForUrl(url, mFaviconSize, imageCallback);
-                image = mDefaultFaviconHelper.getDefaultFaviconDrawable(mActivity, url, true);
-            }
-        }
-        viewHolder.imageView.setImageDrawable(image);
-    }
+                switch (locality) {
+                    case FaviconLocality.LOCAL:
+                        mRecentTabsManager.getLocalFaviconForUrl(url, mFaviconSize, imageCallback);
+                        break;
+                    case FaviconLocality.FOREIGN:
+                        mRecentTabsManager.getForeignFaviconForUrl(
+                                url, mFaviconSize, imageCallback);
+                        break;
+                }
 
-    private void loadLocalFavicon(final ViewHolder viewHolder, final String url) {
-        Drawable image;
-        if (url == null) {
-            // URL is null for print jobs, for example.
-            image = mDefaultFaviconHelper.getDefaultFaviconDrawable(mActivity, url, true);
-        } else {
-            image = mFaviconCache.getLocalFaviconImage(url);
-            if (image == null) {
-                FaviconImageCallback imageCallback = new FaviconImageCallback() {
-                    @Override
-                    public void onFaviconAvailable(Bitmap bitmap, String iconUrl) {
-                        if (this != viewHolder.imageCallback) return;
-                        Drawable image = faviconDrawable(bitmap, url);
-                        image = image == null ? mDefaultFaviconHelper.getDefaultFaviconDrawable(
-                                                        mActivity, url, true)
-                                              : image;
-                        mFaviconCache.putLocalFaviconImage(url, image);
-                        viewHolder.imageView.setImageDrawable(image);
-                    }
-                };
-                viewHolder.imageCallback = imageCallback;
-                mRecentTabsManager.getLocalFaviconForUrl(url, mFaviconSize, imageCallback);
-                image = mDefaultFaviconHelper.getDefaultFaviconDrawable(mActivity, url, true);
+                image = mDefaultFaviconHelper.getDefaultFaviconDrawable(
+                        mActivity.getResources(), url, true);
             }
         }
         viewHolder.imageView.setImageDrawable(image);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index e7f9b5d..0e2456c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -217,11 +217,11 @@
 
         StatusView statusView = findViewById(R.id.location_bar_status);
         statusView.setCompositeTouchDelegate(mCompositeTouchDelegate);
-        mStatusViewCoordinator = new StatusViewCoordinator(mIsTablet, statusView);
+        mStatusViewCoordinator = new StatusViewCoordinator(mIsTablet, statusView, mUrlCoordinator);
+        mUrlCoordinator.addTextChangedListener(mStatusViewCoordinator);
 
         updateShouldAnimateIconChanges();
         mUrlBar.setOnKeyListener(new UrlBarKeyListener());
-        mUrlCoordinator.addUrlTextChangeListener(mStatusViewCoordinator);
 
         // mLocationBar's direction is tied to this UrlBar's text direction. Icons inside the
         // location bar, e.g. lock, refresh, X, should be reversed if UrlBar's text is RTL.
@@ -1118,6 +1118,5 @@
         String textWithoutAutocomplete = mUrlCoordinator.getTextWithoutAutocomplete();
         String textWithAutocomplete = mUrlCoordinator.getTextWithAutocomplete();
         mAutocompleteCoordinator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete);
-        mStatusViewCoordinator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
index c7956f5..af4f428 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
@@ -13,12 +13,14 @@
 import android.provider.Settings;
 import android.support.v13.view.inputmethod.EditorInfoCompat;
 import android.support.v4.text.BidiFormatter;
+import android.support.v4.util.ObjectsCompat;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.Layout;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
+import android.text.TextWatcher;
 import android.text.style.ReplacementSpan;
 import android.util.AttributeSet;
 import android.view.GestureDetector;
@@ -97,7 +99,8 @@
     private int mUrlDirection;
 
     private UrlBarDelegate mUrlBarDelegate;
-    private UrlTextChangeListener mTextChangeListener;
+    private UrlTextChangeListener mUrlTextChangeListener;
+    private TextWatcher mTextChangedListener;
     private UrlBarTextContextMenuDelegate mTextContextMenuDelegate;
     private UrlDirectionListener mUrlDirectionListener;
 
@@ -590,7 +593,22 @@
      * @param listener The listener to be notified.
      */
     public void setUrlTextChangeListener(UrlTextChangeListener listener) {
-        mTextChangeListener = listener;
+        mUrlTextChangeListener = listener;
+    }
+
+    /**
+     * Set the listener to be notified when the view's text has changed.
+     * @param textChangedListener The listener to be notified.
+     */
+    public void setTextChangedListener(TextWatcher textChangedListener) {
+        if (ObjectsCompat.equals(mTextChangedListener, textChangedListener)) {
+            return;
+        } else if (mTextChangedListener != null) {
+            removeTextChangedListener(mTextChangedListener);
+        }
+
+        mTextChangedListener = textChangedListener;
+        addTextChangedListener(mTextChangedListener);
     }
 
     /**
@@ -950,12 +968,13 @@
         if (DEBUG) {
             Log.i(TAG, "onAutocompleteTextStateChanged: DIS[%b]", updateDisplay);
         }
-        if (mTextChangeListener == null) return;
+        if (mUrlTextChangeListener == null) return;
         if (updateDisplay) limitDisplayableLength();
         // crbug.com/764749
         Log.w(TAG, "Text change observed, triggering autocomplete.");
 
-        mTextChangeListener.onTextChanged(getTextWithoutAutocomplete(), getTextWithAutocomplete());
+        mUrlTextChangeListener.onTextChanged(
+                getTextWithoutAutocomplete(), getTextWithAutocomplete());
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java
index 8aa56a0..a9053d2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.omnibox;
 
+import android.text.TextWatcher;
 import android.view.ActionMode;
 
 import androidx.annotation.IntDef;
@@ -60,6 +61,11 @@
         mMediator.addUrlTextChangeListener(listener);
     }
 
+    /** @see TextWatcher */
+    public void addTextChangedListener(TextWatcher textWatcher) {
+        mMediator.addTextChangedListener(textWatcher);
+    }
+
     /** @see UrlBarMediator#setUrlBarData(UrlBarData, int, int) */
     public boolean setUrlBarData(
             UrlBarData data, @ScrollType int scrollType, @SelectionState int state) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java
index 0808de1..1ff4b2c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java
@@ -8,8 +8,10 @@
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.net.Uri;
+import android.text.Editable;
 import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.TextWatcher;
 import android.text.format.DateUtils;
 import android.view.ActionMode;
 
@@ -41,7 +43,8 @@
 /**
  * Handles collecting and pushing state information to the UrlBar model.
  */
-class UrlBarMediator implements UrlBar.UrlBarTextContextMenuDelegate, UrlBar.UrlTextChangeListener {
+class UrlBarMediator
+        implements UrlBar.UrlBarTextContextMenuDelegate, UrlBar.UrlTextChangeListener, TextWatcher {
     private final PropertyModel mModel;
 
     private Callback<Boolean> mOnFocusChangeCallback;
@@ -58,6 +61,7 @@
     private static final int NUM_OF_BUCKETS = 100;
 
     private final List<UrlTextChangeListener> mUrlTextChangeListeners = new ArrayList<>();
+    private final List<TextWatcher> mTextChangedListeners = new ArrayList<>();
 
     public UrlBarMediator(PropertyModel model) {
         mModel = model;
@@ -66,6 +70,7 @@
         mModel.set(UrlBarProperties.SHOW_CURSOR, false);
         mModel.set(UrlBarProperties.TEXT_CONTEXT_MENU_DELEGATE, this);
         mModel.set(UrlBarProperties.URL_TEXT_CHANGE_LISTENER, this);
+        mModel.set(UrlBarProperties.TEXT_CHANGED_LISTENER, this);
         setUseDarkTextColors(true);
     }
 
@@ -81,6 +86,11 @@
         mUrlTextChangeListeners.add(listener);
     }
 
+    /** @see android.widget.TextView#addTextChangedListener */
+    public void addTextChangedListener(TextWatcher textWatcher) {
+        mTextChangedListeners.add(textWatcher);
+    }
+
     /**
      * Updates the text content of the UrlBar.
      *
@@ -355,6 +365,7 @@
         return url.substring(0, pathIndex);
     }
 
+    /** @see UrlTextChangeListener */
     @Override
     public void onTextChanged(String textWithoutAutocomplete, String textWithAutocomplete) {
         for (int i = 0; i < mUrlTextChangeListeners.size(); i++) {
@@ -363,6 +374,30 @@
         }
     }
 
+    /** @see TextWatcher */
+    @Override
+    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        for (int i = 0; i < mTextChangedListeners.size(); i++) {
+            mTextChangedListeners.get(i).beforeTextChanged(s, start, count, after);
+        }
+    }
+
+    /** @see TextWatcher */
+    @Override
+    public void onTextChanged(CharSequence s, int start, int before, int count) {
+        for (int i = 0; i < mTextChangedListeners.size(); i++) {
+            mTextChangedListeners.get(i).onTextChanged(s, start, before, count);
+        }
+    }
+
+    /** @see TextWatcher */
+    @Override
+    public void afterTextChanged(Editable editable) {
+        for (int i = 0; i < mTextChangedListeners.size(); i++) {
+            mTextChangedListeners.get(i).afterTextChanged(editable);
+        }
+    }
+
     private void recordPasteMetrics(String text) {
         boolean isUrl = BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
                                 .isFullBrowserStarted()
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java
index 584624b..f4115cb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.omnibox;
 
+import android.text.TextWatcher;
 import android.view.ActionMode;
 
 import org.chromium.base.Callback;
@@ -115,10 +116,14 @@
     public static final WritableObjectPropertyKey<UrlDirectionListener> URL_DIRECTION_LISTENER =
             new WritableObjectPropertyKey<>();
 
-    /** The callback to be notified on text changes. */
+    /** The callback to be notified on url text changes. @see UrlTextChangeListener. */
     public static final WritableObjectPropertyKey<UrlTextChangeListener> URL_TEXT_CHANGE_LISTENER =
             new WritableObjectPropertyKey<>();
 
+    /** The callback to be notified on text changes. @see TextWatcher. */
+    public static final WritableObjectPropertyKey<TextWatcher> TEXT_CHANGED_LISTENER =
+            new WritableObjectPropertyKey<>();
+
     /** Specifies whether dark text colors should be used in the view. */
     public static final WritableBooleanPropertyKey USE_DARK_TEXT_COLORS =
             new WritableBooleanPropertyKey();
@@ -130,5 +135,5 @@
     public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {ACTION_MODE_CALLBACK,
             ALLOW_FOCUS, AUTOCOMPLETE_TEXT, DELEGATE, FOCUS_CHANGE_CALLBACK, SHOW_CURSOR,
             TEXT_CONTEXT_MENU_DELEGATE, TEXT_STATE, URL_DIRECTION_LISTENER,
-            URL_TEXT_CHANGE_LISTENER, USE_DARK_TEXT_COLORS, WINDOW_DELEGATE};
+            URL_TEXT_CHANGE_LISTENER, TEXT_CHANGED_LISTENER, USE_DARK_TEXT_COLORS, WINDOW_DELEGATE};
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
index de17795..f1f986b5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
@@ -73,6 +73,8 @@
             view.setUrlDirectionListener(model.get(UrlBarProperties.URL_DIRECTION_LISTENER));
         } else if (UrlBarProperties.URL_TEXT_CHANGE_LISTENER.equals(propertyKey)) {
             view.setUrlTextChangeListener(model.get(UrlBarProperties.URL_TEXT_CHANGE_LISTENER));
+        } else if (UrlBarProperties.TEXT_CHANGED_LISTENER.equals(propertyKey)) {
+            view.setTextChangedListener(model.get(UrlBarProperties.TEXT_CHANGED_LISTENER));
         } else if (UrlBarProperties.WINDOW_DELEGATE.equals(propertyKey)) {
             view.setWindowDelegate(model.get(UrlBarProperties.WINDOW_DELEGATE));
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
index 50124f1..c3aa3bd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
@@ -18,7 +18,7 @@
 import org.chromium.base.library_loader.LibraryProcessType;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omnibox.SearchEngineLogoUtils;
-import org.chromium.chrome.browser.omnibox.UrlBar;
+import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
 import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinatorFactory;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.toolbar.ToolbarCommonPropertiesModel;
@@ -89,15 +89,18 @@
     private StatusMediatorDelegate mDelegate;
     private Resources mResources;
     private ToolbarCommonPropertiesModel mToolbarCommonPropertiesModel;
+    private UrlBarEditingTextStateProvider mUrlBarEditingTextStateProvider;
     private String mUrlBarTextWithAutocomplete = "";
     private boolean mUrlBarTextIsValidUrl;
 
-    StatusMediator(PropertyModel model, Resources resources) {
+    StatusMediator(PropertyModel model, Resources resources,
+            UrlBarEditingTextStateProvider urlBarEditingTextStateProvider) {
         mModel = model;
         mDelegate = new StatusMediatorDelegate();
         updateColorTheme();
 
         mResources = resources;
+        mUrlBarEditingTextStateProvider = urlBarEditingTextStateProvider;
     }
 
     /**
@@ -497,8 +500,13 @@
         return 0;
     }
 
-    /** @see {@link UrlBar.UrlTextChangeListener} */
-    void onTextChanged(String urlTextWithoutAutocomplete, String urlTextWithAutocomplete) {
+    /** @see android.text.TextWatcher#onTextChanged */
+    void onTextChanged(CharSequence charSequence) {
+        // TODO (crbug.com/1012870): This is a workaround for the linked bug. Once the bug is fixed,
+        //                           it should be removed.
+        String urlTextWithAutocomplete = TextUtils.isEmpty(charSequence)
+                ? ""
+                : mUrlBarEditingTextStateProvider.getTextWithAutocomplete();
         if (TextUtils.equals(mUrlBarTextWithAutocomplete, urlTextWithAutocomplete)) {
             return;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java
index aaeca95..75545f9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java
@@ -5,13 +5,15 @@
 package org.chromium.chrome.browser.omnibox.status;
 
 import android.content.res.Resources;
+import android.text.Editable;
+import android.text.TextWatcher;
 import android.view.View;
 
 import androidx.annotation.DrawableRes;
 
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.omnibox.UrlBar;
+import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
 import org.chromium.chrome.browser.page_info.PageInfoController;
 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -21,7 +23,7 @@
  * A component for displaying a status icon (e.g. security icon or navigation icon) and optional
  * verbose status text.
  */
-public class StatusViewCoordinator implements View.OnClickListener, UrlBar.UrlTextChangeListener {
+public class StatusViewCoordinator implements View.OnClickListener, TextWatcher {
     private final StatusView mStatusView;
     private final StatusMediator mMediator;
     private final PropertyModel mModel;
@@ -34,8 +36,10 @@
      * Creates a new StatusViewCoordinator.
      * @param isTablet Whether the UI is shown on a tablet.
      * @param statusView The status view, used to supply and manipulate child views.
+     * @param urlBarEditingTextStateProvider The url coordinator.
      */
-    public StatusViewCoordinator(boolean isTablet, StatusView statusView) {
+    public StatusViewCoordinator(boolean isTablet, StatusView statusView,
+            UrlBarEditingTextStateProvider urlBarEditingTextStateProvider) {
         mIsTablet = isTablet;
         mStatusView = statusView;
 
@@ -44,7 +48,8 @@
                          .build();
 
         PropertyModelChangeProcessor.create(mModel, mStatusView, new StatusViewBinder());
-        mMediator = new StatusMediator(mModel, mStatusView.getResources());
+        mMediator = new StatusMediator(
+                mModel, mStatusView.getResources(), urlBarEditingTextStateProvider);
 
         Resources res = mStatusView.getResources();
         mMediator.setUrlMinWidth(res.getDimensionPixelSize(R.dimen.location_bar_min_url_width)
@@ -216,7 +221,13 @@
     }
 
     @Override
-    public void onTextChanged(String textWithoutAutocomplete, String textWithAutocomplete) {
-        mMediator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete);
+    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+    @Override
+    public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
+        mMediator.onTextChanged(charSequence);
     }
+
+    @Override
+    public void afterTextChanged(Editable editable) {}
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetrics.java
index 099df817..29c4ec0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetrics.java
@@ -38,6 +38,28 @@
     }
 
     /**
+     * AndroidSearchEngineChoiceEventsV2 defined in tools/metrics/histograms/enums.xml. These values
+     * are persisted to logs. Entries should not be renumbered and numeric values should never be
+     * reused.
+     */
+    @IntDef({EventsV2.CHOICE_REQUEST_RECEIVED, EventsV2.CHOICE_SKIPPED,
+            EventsV2.CHOICE_REQUEST_NO_DATA, EventsV2.CHOICE_REQUEST_VALID,
+            EventsV2.CHOICE_REQUEST_METADATA_NULL, EventsV2.CHOICE_REQUEST_PARSE_FAILED,
+            EventsV2.PREVIOUS_CHOICE_REQUEST_FAILED, EventsV2.CHOICE_REQUEST_SUCCESS})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface EventsV2 {
+        int CHOICE_REQUEST_RECEIVED = 0;
+        int CHOICE_SKIPPED = 1;
+        int CHOICE_REQUEST_NO_DATA = 1;
+        int CHOICE_REQUEST_VALID = 2;
+        int CHOICE_REQUEST_METADATA_NULL = 3;
+        int CHOICE_REQUEST_PARSE_FAILED = 4;
+        int PREVIOUS_CHOICE_REQUEST_FAILED = 5;
+        int CHOICE_REQUEST_SUCCESS = 6;
+        int MAX = 7;
+    }
+
+    /**
      * Records an event to the search choice histogram. See {@link Events} and histograms.xml for
      * more details.
      * @param event The {@link Events} to be reported.
@@ -47,6 +69,16 @@
                 "Android.SearchEngineChoice.Events", event, Events.MAX);
     }
 
+    /**
+     * Records an event to the search choice histogram. See {@link EventsV2} and histograms.xml for
+     * more details.
+     * @param event The {@link EventsV2} to be reported.
+     */
+    public static void recordEventV2(@EventsV2 int event) {
+        RecordHistogram.recordEnumeratedHistogram(
+                "Android.SearchEngineChoice.EventsV2", event, EventsV2.MAX);
+    }
+
     /** Records the search engine type before the user made a choice about which engine to use. */
     public static void recordSearchEngineTypeBeforeChoice() {
         @SearchEngineType
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
index eaff0c3..c988892 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -37,7 +37,9 @@
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.ui.base.DeviceFormFactor;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * A utility {@code class} meant to help determine whether or not certain features are supported by
@@ -69,29 +71,11 @@
 public class FeatureUtilities {
     private static final String TAG = "FeatureUtilities";
 
+    private static Map<String, Boolean> sFlags = new HashMap<>();
     private static Boolean sHasGoogleAccountAuthenticator;
     private static Boolean sHasRecognitionIntentHandler;
-
-    private static Boolean sIsBottomToolbarEnabled;
-    private static Boolean sIsAdaptiveToolbarEnabled;
-    private static Boolean sIsLabeledBottomToolbarEnabled;
-    private static Boolean sIsNightModeAvailable;
-    private static Boolean sNightModeDefaultToLight;
-    private static Boolean sIsNightModeForCustomTabsAvailable;
-    private static Boolean sShouldPrioritizeBootstrapTasks;
-    private static Boolean sIsGridTabSwitcherEnabled;
-    private static Boolean sIsStartSurfaceEnabled;
     private static Boolean sIsTabGroupsAndroidEnabled;
     private static Boolean sIsTabToGtsAnimationEnabled;
-    private static Boolean sFeedEnabled;
-    private static Boolean sServiceManagerForBackgroundPrefetch;
-    private static Boolean sIsNetworkServiceWarmUpEnabled;
-    private static Boolean sIsImmersiveUiModeEnabled;
-    private static Boolean sServiceManagerForDownloadResumption;
-    private static Boolean sIsClickToCallOpenDialerDirectlyEnabled;
-
-    private static Boolean sDownloadAutoResumptionEnabledInNative;
-
     private static String sReachedCodeProfilerTrialGroup;
 
     /**
@@ -216,47 +200,30 @@
     }
 
     private static void cacheServiceManagerForDownloadResumption() {
-        boolean resumptionDownloadInReducedMode =
-                ChromeFeatureList.isEnabled(ChromeFeatureList.SERVICE_MANAGER_FOR_DOWNLOAD);
-
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.SERVICE_MANAGER_FOR_DOWNLOAD_RESUMPTION_KEY,
-                resumptionDownloadInReducedMode);
+        cacheFlag(ChromePreferenceManager.SERVICE_MANAGER_FOR_DOWNLOAD_RESUMPTION_KEY,
+                ChromeFeatureList.SERVICE_MANAGER_FOR_DOWNLOAD);
     }
 
     /**
      * @return if DownloadResumptionBackgroundTask should load native in service manager only mode.
      */
     public static boolean isServiceManagerForDownloadResumptionEnabled() {
-        if (sServiceManagerForDownloadResumption == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sServiceManagerForDownloadResumption = prefManager.readBoolean(
-                    ChromePreferenceManager.SERVICE_MANAGER_FOR_DOWNLOAD_RESUMPTION_KEY, false);
-        }
-        return sServiceManagerForDownloadResumption;
+        return isFlagEnabled(
+                ChromePreferenceManager.SERVICE_MANAGER_FOR_DOWNLOAD_RESUMPTION_KEY, false);
     }
 
     public static void cacheServiceManagerForBackgroundPrefetch() {
-        boolean backgroundPrefetchInReducedMode = ChromeFeatureList.isEnabled(
+        cacheFlag(ChromePreferenceManager.SERVICE_MANAGER_FOR_BACKGROUND_PREFETCH_KEY,
                 ChromeFeatureList.SERVICE_MANAGER_FOR_BACKGROUND_PREFETCH);
-
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.SERVICE_MANAGER_FOR_BACKGROUND_PREFETCH_KEY,
-                backgroundPrefetchInReducedMode);
     }
 
     /**
      * @return if PrefetchBackgroundTask should load native in service manager only mode.
      */
     public static boolean isServiceManagerForBackgroundPrefetchEnabled() {
-        if (sServiceManagerForBackgroundPrefetch == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sServiceManagerForBackgroundPrefetch = prefManager.readBoolean(
-                    ChromePreferenceManager.SERVICE_MANAGER_FOR_BACKGROUND_PREFETCH_KEY, false);
-        }
-        return sServiceManagerForBackgroundPrefetch && isFeedEnabled();
+        return isFlagEnabled(
+                       ChromePreferenceManager.SERVICE_MANAGER_FOR_BACKGROUND_PREFETCH_KEY, false)
+                && isFeedEnabled();
     }
 
     /**
@@ -264,25 +231,15 @@
      * native is loaded.
      */
     public static void cacheFeedEnabled() {
-        boolean feedEnabled =
-                ChromeFeatureList.isEnabled(ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS);
-
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.INTEREST_FEED_CONTENT_SUGGESTIONS_KEY, feedEnabled);
-        sFeedEnabled = feedEnabled;
+        cacheFlag(ChromePreferenceManager.INTEREST_FEED_CONTENT_SUGGESTIONS_KEY,
+                ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS);
     }
 
     /**
      * @return Whether or not the Feed is enabled (based on the cached value in SharedPrefs).
      */
     public static boolean isFeedEnabled() {
-        if (sFeedEnabled == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sFeedEnabled = prefManager.readBoolean(
-                    ChromePreferenceManager.INTEREST_FEED_CONTENT_SUGGESTIONS_KEY, false);
-        }
-        return sFeedEnabled;
+        return isFlagEnabled(ChromePreferenceManager.INTEREST_FEED_CONTENT_SUGGESTIONS_KEY, false);
     }
 
     /**
@@ -290,13 +247,7 @@
      */
     @CalledByNative
     public static boolean isDownloadAutoResumptionEnabledInNative() {
-        if (sDownloadAutoResumptionEnabledInNative == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sDownloadAutoResumptionEnabledInNative = prefManager.readBoolean(
-                    ChromePreferenceManager.DOWNLOAD_AUTO_RESUMPTION_IN_NATIVE_KEY, true);
-        }
-        return sDownloadAutoResumptionEnabledInNative;
+        return isFlagEnabled(ChromePreferenceManager.DOWNLOAD_AUTO_RESUMPTION_IN_NATIVE_KEY, true);
     }
 
     /**
@@ -304,9 +255,8 @@
      * be made available immediately.
      */
     public static void cacheBottomToolbarEnabled() {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.BOTTOM_TOOLBAR_ENABLED_KEY,
-                ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_DUET));
+        cacheFlag(
+                ChromePreferenceManager.BOTTOM_TOOLBAR_ENABLED_KEY, ChromeFeatureList.CHROME_DUET);
     }
 
     /**
@@ -314,9 +264,8 @@
      * be made available immediately.
      */
     public static void cacheAdaptiveToolbarEnabled() {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.ADAPTIVE_TOOLBAR_ENABLED_KEY,
-                ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_DUET_ADAPTIVE));
+        cacheFlag(ChromePreferenceManager.ADAPTIVE_TOOLBAR_ENABLED_KEY,
+                ChromeFeatureList.CHROME_DUET_ADAPTIVE);
     }
 
     /**
@@ -324,9 +273,8 @@
      * be made available immediately.
      */
     public static void cacheLabeledBottomToolbarEnabled() {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.LABELED_BOTTOM_TOOLBAR_ENABLED_KEY,
-                ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_DUET_LABELED));
+        cacheFlag(ChromePreferenceManager.LABELED_BOTTOM_TOOLBAR_ENABLED_KEY,
+                ChromeFeatureList.CHROME_DUET_LABELED);
     }
 
     /**
@@ -334,23 +282,16 @@
      * value can be made available immediately.
      */
     private static void cacheDownloadAutoResumptionEnabledInNative() {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.DOWNLOAD_AUTO_RESUMPTION_IN_NATIVE_KEY,
-                ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOADS_AUTO_RESUMPTION_NATIVE));
+        cacheFlag(ChromePreferenceManager.DOWNLOAD_AUTO_RESUMPTION_IN_NATIVE_KEY,
+                ChromeFeatureList.DOWNLOADS_AUTO_RESUMPTION_NATIVE);
     }
 
     /**
      * @return Whether or not the bottom toolbar is enabled.
      */
     public static boolean isBottomToolbarEnabled() {
-        if (sIsBottomToolbarEnabled == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sIsBottomToolbarEnabled = prefManager.readBoolean(
-                    ChromePreferenceManager.BOTTOM_TOOLBAR_ENABLED_KEY, false);
-        }
         // TODO(crbug.com/944228): TabGroupsAndroid and ChromeDuet are incompatible for now.
-        return sIsBottomToolbarEnabled
+        return isFlagEnabled(ChromePreferenceManager.BOTTOM_TOOLBAR_ENABLED_KEY, false)
                 && !DeviceFormFactor.isNonMultiDisplayContextOnTablet(
                         ContextUtils.getApplicationContext())
                 && !isTabGroupsAndroidEnabled();
@@ -360,33 +301,23 @@
      * Set whether the bottom toolbar is enabled for tests. Reset to null at the end of tests.
      */
     public static void setIsBottomToolbarEnabledForTests(Boolean enabled) {
-        sIsBottomToolbarEnabled = enabled;
+        sFlags.put(ChromePreferenceManager.BOTTOM_TOOLBAR_ENABLED_KEY, enabled);
     }
 
     /**
      * @return Whether or not the adaptive toolbar is enabled.
      */
     public static boolean isAdaptiveToolbarEnabled() {
-        if (sIsAdaptiveToolbarEnabled == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sIsAdaptiveToolbarEnabled = prefManager.readBoolean(
-                    ChromePreferenceManager.ADAPTIVE_TOOLBAR_ENABLED_KEY, true);
-        }
-        return sIsAdaptiveToolbarEnabled && isBottomToolbarEnabled() && !isGridTabSwitcherEnabled();
+        return isFlagEnabled(ChromePreferenceManager.ADAPTIVE_TOOLBAR_ENABLED_KEY, true)
+                && isBottomToolbarEnabled() && !isGridTabSwitcherEnabled();
     }
 
     /**
      * @return Whether or not the labeled bottom toolbar is enabled.
      */
     public static boolean isLabeledBottomToolbarEnabled() {
-        if (sIsLabeledBottomToolbarEnabled == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sIsLabeledBottomToolbarEnabled = prefManager.readBoolean(
-                    ChromePreferenceManager.LABELED_BOTTOM_TOOLBAR_ENABLED_KEY, false);
-        }
-        return sIsLabeledBottomToolbarEnabled && isBottomToolbarEnabled();
+        return isFlagEnabled(ChromePreferenceManager.LABELED_BOTTOM_TOOLBAR_ENABLED_KEY, false)
+                && isBottomToolbarEnabled();
     }
 
     /**
@@ -406,13 +337,7 @@
      *         enabled).
      */
     public static boolean isNightModeAvailable() {
-        if (sIsNightModeAvailable == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sIsNightModeAvailable = prefManager.readBoolean(
-                    ChromePreferenceManager.NIGHT_MODE_AVAILABLE_KEY, false);
-        }
-        return sIsNightModeAvailable;
+        return isFlagEnabled(ChromePreferenceManager.NIGHT_MODE_AVAILABLE_KEY, false);
     }
 
     /**
@@ -421,7 +346,7 @@
      */
     @VisibleForTesting
     public static void setNightModeAvailableForTesting(@Nullable Boolean available) {
-        sIsNightModeAvailable = available;
+        sFlags.put(ChromePreferenceManager.NIGHT_MODE_AVAILABLE_KEY, available);
     }
 
     /**
@@ -447,16 +372,10 @@
      * @return Whether or not to default to the light theme when the night mode feature is enabled.
      */
     public static boolean isNightModeDefaultToLight() {
-        if (BuildInfo.isAtLeastQ()) sNightModeDefaultToLight = false;
-
-        if (sNightModeDefaultToLight == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sNightModeDefaultToLight = prefManager.readBoolean(
-                    ChromePreferenceManager.NIGHT_MODE_DEFAULT_TO_LIGHT, false);
+        if (BuildInfo.isAtLeastQ()) {
+            return false;
         }
-
-        return sNightModeDefaultToLight;
+        return isFlagEnabled(ChromePreferenceManager.NIGHT_MODE_DEFAULT_TO_LIGHT, false);
     }
 
     /**
@@ -465,7 +384,7 @@
      */
     @VisibleForTesting
     public static void setNightModeDefaultToLightForTesting(@Nullable Boolean available) {
-        sNightModeDefaultToLight = available;
+        sFlags.put(ChromePreferenceManager.NIGHT_MODE_DEFAULT_TO_LIGHT, available);
     }
 
     /**
@@ -473,9 +392,8 @@
      * enabled), so the value is immediately available on next start-up.
      */
     public static void cacheNightModeForCustomTabsAvailable() {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.NIGHT_MODE_CCT_AVAILABLE_KEY,
-                ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_NIGHT_MODE_CCT));
+        cacheFlag(ChromePreferenceManager.NIGHT_MODE_CCT_AVAILABLE_KEY,
+                ChromeFeatureList.ANDROID_NIGHT_MODE_CCT);
     }
 
     /**
@@ -483,13 +401,7 @@
      *         enabled) for custom tabs.
      */
     public static boolean isNightModeForCustomTabsAvailable() {
-        if (sIsNightModeForCustomTabsAvailable == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sIsNightModeForCustomTabsAvailable = prefManager.readBoolean(
-                    ChromePreferenceManager.NIGHT_MODE_CCT_AVAILABLE_KEY, true);
-        }
-        return sIsNightModeForCustomTabsAvailable;
+        return isFlagEnabled(ChromePreferenceManager.NIGHT_MODE_CCT_AVAILABLE_KEY, true);
     }
 
     /**
@@ -497,18 +409,15 @@
      * testing. Should be reset back to NULL after the test has finished.
      */
     public static void setNightModeForCustomTabsAvailableForTesting(Boolean available) {
-        sIsNightModeForCustomTabsAvailable = available;
+        sFlags.put(ChromePreferenceManager.NIGHT_MODE_CCT_AVAILABLE_KEY, available);
     }
 
     /**
      * Cache whether or not command line is enabled on non-rooted devices.
      */
     private static void cacheCommandLineOnNonRootedEnabled() {
-        boolean isCommandLineOnNonRootedEnabled =
-                ChromeFeatureList.isEnabled(ChromeFeatureList.COMMAND_LINE_ON_NON_ROOTED);
-        ChromePreferenceManager manager = ChromePreferenceManager.getInstance();
-        manager.writeBoolean(ChromePreferenceManager.COMMAND_LINE_ON_NON_ROOTED_ENABLED_KEY,
-                isCommandLineOnNonRootedEnabled);
+        cacheFlag(ChromePreferenceManager.COMMAND_LINE_ON_NON_ROOTED_ENABLED_KEY,
+                ChromeFeatureList.COMMAND_LINE_ON_NON_ROOTED);
     }
 
     /**
@@ -519,22 +428,15 @@
     }
 
     private static void cacheStartSurfaceEnabled() {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.START_SURFACE_ENABLED_KEY,
-                ChromeFeatureList.isEnabled(ChromeFeatureList.START_SURFACE_ANDROID));
+        cacheFlag(ChromePreferenceManager.START_SURFACE_ENABLED_KEY,
+                ChromeFeatureList.START_SURFACE_ANDROID);
     }
 
     /**
      * @return Whether the Start Surface is enabled.
      */
     public static boolean isStartSurfaceEnabled() {
-        if (sIsStartSurfaceEnabled == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sIsStartSurfaceEnabled = prefManager.readBoolean(
-                    ChromePreferenceManager.START_SURFACE_ENABLED_KEY, false);
-        }
-        return sIsStartSurfaceEnabled;
+        return isFlagEnabled(ChromePreferenceManager.START_SURFACE_ENABLED_KEY, false);
     }
 
     private static void cacheGridTabSwitcherEnabled() {
@@ -553,16 +455,11 @@
      * @return Whether the Grid Tab Switcher UI is enabled and available for use.
      */
     public static boolean isGridTabSwitcherEnabled() {
-        if (sIsGridTabSwitcherEnabled == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sIsGridTabSwitcherEnabled = prefManager.readBoolean(
-                    ChromePreferenceManager.GRID_TAB_SWITCHER_ENABLED_KEY, false);
-        }
         // TODO(yusufo): AccessibilityLayout check should not be here and the flow should support
         // changing that setting while Chrome is alive.
         // Having Tab Groups implies Grid Tab Switcher.
-        return sIsGridTabSwitcherEnabled || isTabGroupsAndroidEnabled();
+        return isFlagEnabled(ChromePreferenceManager.GRID_TAB_SWITCHER_ENABLED_KEY, false)
+                || isTabGroupsAndroidEnabled();
     }
 
     /**
@@ -571,7 +468,7 @@
      */
     @VisibleForTesting
     public static void setGridTabSwitcherEnabledForTesting(@Nullable Boolean enabled) {
-        sIsGridTabSwitcherEnabled = enabled;
+        sFlags.put(ChromePreferenceManager.GRID_TAB_SWITCHER_ENABLED_KEY, enabled);
     }
 
     private static void cacheTabGroupsAndroidEnabled() {
@@ -664,9 +561,8 @@
      * can be made available immediately.
      */
     public static void cachePrioritizeBootstrapTasks() {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.PRIORITIZE_BOOTSTRAP_TASKS_KEY,
-                ChromeFeatureList.isEnabled(ChromeFeatureList.PRIORITIZE_BOOTSTRAP_TASKS));
+        cacheFlag(ChromePreferenceManager.PRIORITIZE_BOOTSTRAP_TASKS_KEY,
+                ChromeFeatureList.PRIORITIZE_BOOTSTRAP_TASKS);
     }
 
     /**
@@ -674,13 +570,7 @@
      *         prioritization experiment is enabled).
      */
     public static boolean shouldPrioritizeBootstrapTasks() {
-        if (sShouldPrioritizeBootstrapTasks == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-
-            sShouldPrioritizeBootstrapTasks = prefManager.readBoolean(
-                    ChromePreferenceManager.PRIORITIZE_BOOTSTRAP_TASKS_KEY, true);
-        }
-        return sShouldPrioritizeBootstrapTasks;
+        return isFlagEnabled(ChromePreferenceManager.PRIORITIZE_BOOTSTRAP_TASKS_KEY, true);
     }
 
     /**
@@ -697,30 +587,19 @@
      * @return whether warming up network service is enabled.
      */
     public static boolean isNetworkServiceWarmUpEnabled() {
-        if (sIsNetworkServiceWarmUpEnabled == null) {
-            ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
-            sIsNetworkServiceWarmUpEnabled = prefManager.readBoolean(
-                    ChromePreferenceManager.NETWORK_SERVICE_WARM_UP_ENABLED_KEY, false);
-        }
-        return sIsNetworkServiceWarmUpEnabled;
+        return isFlagEnabled(ChromePreferenceManager.NETWORK_SERVICE_WARM_UP_ENABLED_KEY, false);
     }
 
     private static void cacheImmersiveUiModeEnabled() {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.IMMERSIVE_UI_MODE_ENABLED,
-                ChromeFeatureList.isEnabled(ChromeFeatureList.IMMERSIVE_UI_MODE));
+        cacheFlag(ChromePreferenceManager.IMMERSIVE_UI_MODE_ENABLED,
+                ChromeFeatureList.IMMERSIVE_UI_MODE);
     }
 
     /**
      * @return Whether immersive ui mode is enabled.
      */
     public static boolean isImmersiveUiModeEnabled() {
-        if (sIsImmersiveUiModeEnabled == null) {
-            sIsImmersiveUiModeEnabled = ChromePreferenceManager.getInstance().readBoolean(
-                    ChromePreferenceManager.IMMERSIVE_UI_MODE_ENABLED, false);
-        }
-
-        return sIsImmersiveUiModeEnabled;
+        return isFlagEnabled(ChromePreferenceManager.IMMERSIVE_UI_MODE_ENABLED, false);
     }
 
     /**
@@ -733,19 +612,16 @@
     }
 
     public static void cacheSwapPixelFormatToFixConvertFromTranslucentEnabled() {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT,
-                ChromeFeatureList.isEnabled(
-                        ChromeFeatureList.SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT));
+        cacheFlag(ChromePreferenceManager.SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT,
+                ChromeFeatureList.SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT);
     }
 
     /**
      * Cache the value of the flag whether or not to directly open the dialer for click to call.
      */
     public static void cacheClickToCallOpenDialerDirectlyEnabled() {
-        ChromePreferenceManager.getInstance().writeBoolean(
-                ChromePreferenceManager.CLICK_TO_CALL_OPEN_DIALER_DIRECTLY_KEY,
-                ChromeFeatureList.isEnabled(ChromeFeatureList.CLICK_TO_CALL_OPEN_DIALER_DIRECTLY));
+        cacheFlag(ChromePreferenceManager.CLICK_TO_CALL_OPEN_DIALER_DIRECTLY_KEY,
+                ChromeFeatureList.CLICK_TO_CALL_OPEN_DIALER_DIRECTLY);
     }
 
     /**
@@ -753,12 +629,7 @@
      *         value in SharedPrefs).
      */
     public static boolean isClickToCallOpenDialerDirectlyEnabled() {
-        if (sIsClickToCallOpenDialerDirectlyEnabled == null) {
-            sIsClickToCallOpenDialerDirectlyEnabled =
-                    ChromePreferenceManager.getInstance().readBoolean(
-                            ChromePreferenceManager.CLICK_TO_CALL_OPEN_DIALER_DIRECTLY_KEY, false);
-        }
-        return sIsClickToCallOpenDialerDirectlyEnabled;
+        return isFlagEnabled(ChromePreferenceManager.CLICK_TO_CALL_OPEN_DIALER_DIRECTLY_KEY, false);
     }
 
     /**
@@ -768,7 +639,7 @@
     @VisibleForTesting
     public static void setIsClickToCallOpenDialerDirectlyEnabledForTesting(
             @Nullable Boolean isEnabled) {
-        sIsClickToCallOpenDialerDirectlyEnabled = isEnabled;
+        sFlags.put(ChromePreferenceManager.CLICK_TO_CALL_OPEN_DIALER_DIRECTLY_KEY, isEnabled);
     }
 
     /**
@@ -828,6 +699,20 @@
         }
     }
 
+    private static void cacheFlag(String preferenceName, String featureName) {
+        ChromePreferenceManager.getInstance().writeBoolean(
+                preferenceName, ChromeFeatureList.isEnabled(featureName));
+    }
+
+    private static boolean isFlagEnabled(String preferenceName, boolean defaultValue) {
+        Boolean flag = sFlags.get(preferenceName);
+        if (flag == null) {
+            flag = ChromePreferenceManager.getInstance().readBoolean(preferenceName, defaultValue);
+            sFlags.put(preferenceName, flag);
+        }
+        return flag;
+    }
+
     @NativeMethods
     interface Natives {
         void setCustomTabVisible(boolean visible);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/OWNERS
new file mode 100644
index 0000000..a86aa489c
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/OWNERS
@@ -0,0 +1,5 @@
+file://chrome/android/java/src/org/chromium/chrome/browser/gesturenav/OWNERS
+
+# TEAM: chrome-android-app@chromium.org
+# COMPONENT: UI>Browser>Mobile
+# OS: Android
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java
index 0d5084f5..5db5123 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java
@@ -9,6 +9,7 @@
 import android.content.Context;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
+import android.text.TextWatcher;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -35,15 +36,30 @@
 @Config(manifest = Config.NONE)
 public class UrlBarMediatorUnitTest {
     @Mock
-    UrlBar.UrlTextChangeListener mMockListener;
+    UrlBar.UrlTextChangeListener mMockUrlTextListener;
     @Mock
-    UrlBar.UrlTextChangeListener mAnotherMockListener;
+    UrlBar.UrlTextChangeListener mAnotherUrlTextMockListener;
+    @Mock
+    TextWatcher mMockTextWatcher;
+    @Mock
+    TextWatcher mAnotherMockTextWatcher;
+
+    PropertyModel mModel;
+    UrlBarMediator mMediator;
 
     @Before
     public void setUp() {
         RecordHistogram.setDisabledForTests(true);
         RecordUserAction.setDisabledForTests(true);
         MockitoAnnotations.initMocks(this);
+
+        mModel = new PropertyModel(UrlBarProperties.ALL_KEYS);
+        mMediator = new UrlBarMediator(mModel) {
+            @Override
+            protected String sanitizeTextForPaste(String text) {
+                return text.trim();
+            }
+        };
     }
 
     @After
@@ -54,9 +70,6 @@
 
     @Test
     public void setUrlData_SendsUpdates() {
-        PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
-        UrlBarMediator mediator = new UrlBarMediator(model);
-
         UrlBarData baseData = UrlBarData.create(
                 "http://www.example.com", spannable("www.example.com"), 0, 14, "Blah");
         UrlBarData dataWithDifferentDisplay = UrlBarData.create(
@@ -64,77 +77,68 @@
         UrlBarData dataWithDifferentEditing = UrlBarData.create(
                 "http://www.example.com", spannable("www.example.com"), 0, 14, "Bar");
 
-        Assert.assertTrue(mediator.setUrlBarData(baseData, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
+        Assert.assertTrue(mMediator.setUrlBarData(baseData, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
 
         @SuppressWarnings("unchecked")
         PropertyObserver<PropertyKey> observer = Mockito.mock(PropertyObserver.class);
-        model.addObserver(observer);
+        mModel.addObserver(observer);
         Mockito.<PropertyObserver>reset(observer);
 
-        Assert.assertTrue(mediator.setUrlBarData(
+        Assert.assertTrue(mMediator.setUrlBarData(
                 dataWithDifferentDisplay, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
-        Assert.assertTrue(mediator.setUrlBarData(
+        Assert.assertTrue(mMediator.setUrlBarData(
                 dataWithDifferentEditing, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
-        Assert.assertTrue(mediator.setUrlBarData(
+        Assert.assertTrue(mMediator.setUrlBarData(
                 dataWithDifferentEditing, UrlBar.ScrollType.SCROLL_TO_BEGINNING, 4));
 
         Mockito.verify(observer, Mockito.times(3))
-                .onPropertyChanged(model, UrlBarProperties.TEXT_STATE);
+                .onPropertyChanged(mModel, UrlBarProperties.TEXT_STATE);
     }
 
     @Test
     public void setUrlData_PreventsDuplicateUpdates() {
-        PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
-        UrlBarMediator mediator = new UrlBarMediator(model);
-
         UrlBarData data1 = UrlBarData.create(
                 "http://www.example.com", spannable("www.example.com"), 0, 0, "Blah");
         UrlBarData data2 = UrlBarData.create(
                 "http://www.example.com", spannable("www.example.com"), 0, 0, "Blah");
 
-        Assert.assertTrue(mediator.setUrlBarData(data1, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
+        Assert.assertTrue(mMediator.setUrlBarData(data1, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
 
         @SuppressWarnings("unchecked")
         PropertyObserver<PropertyKey> observer = Mockito.mock(PropertyObserver.class);
-        model.addObserver(observer);
+        mModel.addObserver(observer);
         Mockito.<PropertyObserver>reset(observer);
 
-        Assert.assertFalse(mediator.setUrlBarData(data1, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
-        Assert.assertFalse(mediator.setUrlBarData(data2, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
+        Assert.assertFalse(mMediator.setUrlBarData(data1, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
+        Assert.assertFalse(mMediator.setUrlBarData(data2, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
 
         Mockito.verifyZeroInteractions(observer);
     }
 
     @Test
     public void setUrlData_ScrollStateForDataUrl() {
-        PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
-        UrlBarMediator mediator = new UrlBarMediator(model);
-
         String displayText = "data:text/html,blah";
         UrlBarData data = UrlBarData.create(
                 "data:text/html,blah,blah", spannable(displayText), 0, displayText.length(), null);
-        Assert.assertTrue(mediator.setUrlBarData(data, UrlBar.ScrollType.SCROLL_TO_TLD,
+        Assert.assertTrue(mMediator.setUrlBarData(data, UrlBar.ScrollType.SCROLL_TO_TLD,
                 UrlBarCoordinator.SelectionState.SELECT_ALL));
 
         // The scroll state should be overridden to SCROLL_TO_BEGINNING for file-type schemes.
         Assert.assertEquals(UrlBar.ScrollType.SCROLL_TO_BEGINNING,
-                model.get(UrlBarProperties.TEXT_STATE).scrollType);
+                mModel.get(UrlBarProperties.TEXT_STATE).scrollType);
     }
 
     @Test
     public void setUrlData_ScrollStateForAboutUrl() {
-        PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
-        UrlBarMediator mediator = new UrlBarMediator(model);
-
         String displayText = "about:blank#verylongurl.totallylegit.notsuspicious.url.com";
         UrlBarData data = UrlBarData.create(
                 displayText, spannable(displayText), 0, displayText.length(), null);
-        Assert.assertTrue(mediator.setUrlBarData(data, UrlBar.ScrollType.SCROLL_TO_TLD,
+        Assert.assertTrue(mMediator.setUrlBarData(data, UrlBar.ScrollType.SCROLL_TO_TLD,
                 UrlBarCoordinator.SelectionState.SELECT_ALL));
 
         // The scroll state should be overridden to SCROLL_TO_BEGINNING for file-type schemes.
         Assert.assertEquals(UrlBar.ScrollType.SCROLL_TO_BEGINNING,
-                model.get(UrlBarProperties.TEXT_STATE).scrollType);
+                mModel.get(UrlBarProperties.TEXT_STATE).scrollType);
     }
 
     @Test
@@ -222,74 +226,78 @@
 
     @Test
     public void pasteTextValidation() {
-        PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
-        UrlBarMediator mediator = new UrlBarMediator(model) {
-            @Override
-            protected String sanitizeTextForPaste(String text) {
-                return text.trim();
-            }
-        };
-
         ClipboardManager clipboard =
                 (ClipboardManager) RuntimeEnvironment.application.getSystemService(
                         Context.CLIPBOARD_SERVICE);
         clipboard.setPrimaryClip(null);
-        Assert.assertNull(mediator.getTextToPaste());
+        Assert.assertNull(mMediator.getTextToPaste());
 
         clipboard.setPrimaryClip(ClipData.newPlainText("", ""));
-        Assert.assertEquals("", mediator.getTextToPaste());
+        Assert.assertEquals("", mMediator.getTextToPaste());
 
         clipboard.setPrimaryClip(ClipData.newPlainText("", "test"));
-        Assert.assertEquals("test", mediator.getTextToPaste());
+        Assert.assertEquals("test", mMediator.getTextToPaste());
 
         clipboard.setPrimaryClip(ClipData.newPlainText("", "    test     "));
-        Assert.assertEquals("test", mediator.getTextToPaste());
+        Assert.assertEquals("test", mMediator.getTextToPaste());
     }
 
     @Test
     public void cutCopyReplacementTextValidation() {
-        PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
-        UrlBarMediator mediator = new UrlBarMediator(model);
         String url = "https://www.test.com/blah";
         String displayText = "test.com/blah";
         String editingText = "www.test.com/blah";
-        mediator.setUrlBarData(UrlBarData.create(url, displayText, 0, 12, editingText),
+        mMediator.setUrlBarData(UrlBarData.create(url, displayText, 0, 12, editingText),
                 UrlBar.ScrollType.NO_SCROLL, UrlBarCoordinator.SelectionState.SELECT_ALL);
 
         // Replacement is only valid if selecting the full text.
-        Assert.assertNull(mediator.getReplacementCutCopyText(editingText, 1, 2));
+        Assert.assertNull(mMediator.getReplacementCutCopyText(editingText, 1, 2));
 
         // Editing text will be replaced with the full URL if selecting all of the text.
         Assert.assertEquals(
-                url, mediator.getReplacementCutCopyText(editingText, 0, editingText.length()));
+                url, mMediator.getReplacementCutCopyText(editingText, 0, editingText.length()));
 
         // If selecting just the URL portion of the editing text, it should be replaced with the
         // unformatted URL.
         Assert.assertEquals(
-                "https://www.test.com", mediator.getReplacementCutCopyText(editingText, 0, 12));
+                "https://www.test.com", mMediator.getReplacementCutCopyText(editingText, 0, 12));
 
         // If the path changed in the editing text changed but the domain is untouched, it should
         // be replaced with the full domain from the unformatted URL.
         Assert.assertEquals("https://www.test.com/foo",
-                mediator.getReplacementCutCopyText("www.test.com/foo", 0, 16));
+                mMediator.getReplacementCutCopyText("www.test.com/foo", 0, 16));
     }
 
     @Test
     public void urlTextChangeListenerCompositeObserver() {
-        PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
-        UrlBarMediator mediator = new UrlBarMediator(model);
-        mediator.addUrlTextChangeListener(mMockListener);
+        mMediator.addUrlTextChangeListener(mMockUrlTextListener);
 
         String text = "foo";
         String textWithAutocomplete = "foo.bar";
-        mediator.onTextChanged(text, textWithAutocomplete);
-        Mockito.verify(mMockListener, Mockito.times(1)).onTextChanged(text, textWithAutocomplete);
-
-        mediator.addUrlTextChangeListener(mAnotherMockListener);
-        mediator.onTextChanged(text, textWithAutocomplete);
-        Mockito.verify(mMockListener, Mockito.times(2)).onTextChanged(text, textWithAutocomplete);
-        Mockito.verify(mAnotherMockListener, Mockito.times(1))
+        mMediator.onTextChanged(text, textWithAutocomplete);
+        Mockito.verify(mMockUrlTextListener, Mockito.times(1))
                 .onTextChanged(text, textWithAutocomplete);
+
+        mMediator.addUrlTextChangeListener(mAnotherUrlTextMockListener);
+        mMediator.onTextChanged(text, textWithAutocomplete);
+        Mockito.verify(mMockUrlTextListener, Mockito.times(2))
+                .onTextChanged(text, textWithAutocomplete);
+        Mockito.verify(mAnotherUrlTextMockListener, Mockito.times(1))
+                .onTextChanged(text, textWithAutocomplete);
+    }
+
+    @Test
+    public void textWatcherCompositeObserver() {
+        mMediator.addTextChangedListener(mMockTextWatcher);
+
+        CharSequence text = "foo";
+        mMediator.onTextChanged(text, 0, 1, 2);
+        Mockito.verify(mMockTextWatcher, Mockito.times(1)).onTextChanged(text, 0, 1, 2);
+
+        mMediator.addTextChangedListener(mAnotherMockTextWatcher);
+        mMediator.onTextChanged(text, 0, 1, 2);
+        Mockito.verify(mMockTextWatcher, Mockito.times(2)).onTextChanged(text, 0, 1, 2);
+        Mockito.verify(mAnotherMockTextWatcher, Mockito.times(1)).onTextChanged(text, 0, 1, 2);
     }
 
     private static SpannableStringBuilder spannable(String text) {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java
index 79186452..988c67ea 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java
@@ -25,6 +25,7 @@
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
 import org.chromium.chrome.browser.toolbar.ToolbarCommonPropertiesModel;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -42,6 +43,8 @@
     @Mock
     ToolbarCommonPropertiesModel mToolbarCommonPropertiesModel;
     @Mock
+    UrlBarEditingTextStateProvider mUrlBarEditingTextStateProvider;
+    @Mock
     StatusMediator.StatusMediatorDelegate mDelegate;
     @Mock
     Bitmap mBitmap;
@@ -56,7 +59,7 @@
         MockitoAnnotations.initMocks(this);
 
         mModel = new PropertyModel(StatusProperties.ALL_KEYS);
-        mMediator = new StatusMediator(mModel, mResources);
+        mMediator = new StatusMediator(mModel, mResources, mUrlBarEditingTextStateProvider);
         mMediator.setToolbarCommonPropertiesModel(mToolbarCommonPropertiesModel);
         mMediator.setDelegateForTesting(mDelegate);
     }
@@ -123,7 +126,7 @@
 
         mMediator.setUrlHasFocus(true);
         mMediator.setShowIconsWhenUrlFocused(true);
-        mMediator.onTextChanged("", "testing");
+        mMediator.onTextChanged(TEST_SEARCH_URL);
         Assert.assertEquals(R.drawable.ic_globe_24dp, mModel.get(StatusProperties.STATUS_ICON_RES));
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/OWNERS
new file mode 100644
index 0000000..4cf87a226
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/OWNERS
@@ -0,0 +1 @@
+file://chrome/android/java/src/org/chromium/chrome/browser/search_engines/OWNERS
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetricsTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetricsTest.java
index 53a08c73..5ea613e 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetricsTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetricsTest.java
@@ -156,4 +156,15 @@
                 .getDefaultSearchEngineTemplateUrl();
         assertFalse(SearchEngineChoiceMetrics.isSearchEnginePossiblyDifferent());
     }
+
+    @Test
+    @SmallTest
+    public void recordEventV2_sanityCheck() {
+        SearchEngineChoiceMetrics.recordEventV2(
+                SearchEngineChoiceMetrics.EventsV2.CHOICE_REQUEST_VALID);
+        assertEquals(1,
+                ShadowRecordHistogram.getHistogramValueCountForTesting(
+                        "Android.SearchEngineChoice.EventsV2",
+                        SearchEngineChoiceMetrics.EventsV2.CHOICE_REQUEST_VALID));
+    }
 }
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index fa86825..bdfbd3e2a 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -104,6 +104,12 @@
 #define IDC_CONTENT_LINK_SEND_TAB_TO_SELF_SINGLE_TARGET  35019
 #define IDC_QRCODE_GENERATOR            35020
 
+// Page-manipulation commands that target a specified tab, which may not be the
+// active one.
+#define IDC_MUTE_TARGET_SITE            35050
+#define IDC_PIN_TARGET_TAB              35051
+#define IDC_DUPLICATE_TARGET_TAB        35052
+
 // Clipboard commands
 #define IDC_CUT                         36000
 #define IDC_COPY                        36001
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index e7a238b..7ef7f55 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -8254,12 +8254,21 @@
         <message name="IDS_DUPLICATE_TAB_MAC" desc="The Mac menu item for duplicating the selected tab(s).">
           Duplicate Tab
         </message>
+        <message name="IDS_DUPLICATE_TARGET_TAB_MAC" desc="The Mac menu item for duplicating the selected tab(s).">
+          Duplicate Selected Tab
+        </message>
         <message name="IDS_MUTE_SITE_MAC" desc="The Mac menu item for muting the selected tab(s).">
           Mute Site
         </message>
         <message name="IDS_PIN_TAB_MAC" desc="The Mac menu item for pinning the selected tab(s).">
           Pin Tab
         </message>
+        <message name="IDS_MUTE_TARGET_SITE_MAC" desc="The Mac menu item for muting the selected tab(s).">
+          Mute Selected Site
+        </message>
+        <message name="IDS_PIN_TARGET_TAB_MAC" desc="The Mac menu item for pinning the selected tab(s).">
+          Pin Selected Tab
+        </message>
         <!-- Help menu -->
         <message name="IDS_FEEDBACK_MAC" desc="The Mac menu item to report a bug in the Help menu.">
           Report an Issue...
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 101401f..a2948865 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1675,6 +1675,9 @@
      kOsCrOS,
      FEATURE_VALUE_TYPE(
          chromeos::features::kBluetoothAggressiveAppearanceFilter)},
+    {"cryptauth-v2-devicesync", flag_descriptions::kCryptAuthV2DeviceSyncName,
+     flag_descriptions::kCryptAuthV2DeviceSyncDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kCryptAuthV2DeviceSync)},
     {"cryptauth-v2-enrollment", flag_descriptions::kCryptAuthV2EnrollmentName,
      flag_descriptions::kCryptAuthV2EnrollmentDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kCryptAuthV2Enrollment)},
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc
index 2c83890..04a4a21 100644
--- a/chrome/browser/background/background_mode_manager.cc
+++ b/chrome/browser/background/background_mode_manager.cc
@@ -67,6 +67,7 @@
 #include "extensions/common/permissions/permission_set.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image_family.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/win/app_icon.h"
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index c001b762..9a91407 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -19,7 +19,6 @@
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process_platform_part.h"
-#include "chrome/browser/shell_integration.h"
 #include "chrome/common/buildflags.h"
 #include "media/media_buildflags.h"
 
@@ -266,12 +265,6 @@
   virtual resource_coordinator::ResourceCoordinatorParts*
   resource_coordinator_parts() = 0;
 
-  // Returns the default web client state of Chrome (i.e., was it the user's
-  // default browser) at the time a previous check was made sometime between
-  // process startup and now.
-  virtual shell_integration::DefaultWebClientState
-  CachedDefaultWebClientState() = 0;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(BrowserProcess);
 };
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index a68d42d..07b6117 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -881,11 +881,6 @@
   return resource_coordinator_parts_.get();
 }
 
-shell_integration::DefaultWebClientState
-BrowserProcessImpl::CachedDefaultWebClientState() {
-  return cached_default_web_client_state_;
-}
-
 // static
 void BrowserProcessImpl::RegisterPrefs(PrefRegistrySimple* registry) {
   registry->RegisterBooleanPref(prefs::kDefaultBrowserSettingEnabled,
@@ -1150,8 +1145,6 @@
           ->Clone());
 #endif
 
-  CacheDefaultWebClientState();
-
   platform_part_->PreMainMessageLoopRun();
 
   if (base::FeatureList::IsEnabled(network_time::kNetworkTimeServiceQuerying)) {
@@ -1340,14 +1333,6 @@
   }
 }
 
-void BrowserProcessImpl::CacheDefaultWebClientState() {
-#if defined(OS_CHROMEOS)
-  cached_default_web_client_state_ = shell_integration::IS_DEFAULT;
-#elif !defined(OS_ANDROID)
-  cached_default_web_client_state_ = shell_integration::GetDefaultBrowser();
-#endif
-}
-
 void BrowserProcessImpl::Pin() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index dadcf85..d17ae49 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -191,8 +191,6 @@
   resource_coordinator::TabManager* GetTabManager() override;
   resource_coordinator::ResourceCoordinatorParts* resource_coordinator_parts()
       override;
-  shell_integration::DefaultWebClientState CachedDefaultWebClientState()
-      override;
 
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
@@ -226,8 +224,6 @@
 
   void ApplyDefaultBrowserPolicy();
 
-  void CacheDefaultWebClientState();
-
   // Methods called to control our lifetime. The browser process can be "pinned"
   // to make sure it keeps running.
   void Pin();
@@ -395,9 +391,6 @@
 
   std::unique_ptr<gcm::GCMDriver> gcm_driver_;
 
-  shell_integration::DefaultWebClientState cached_default_web_client_state_ =
-      shell_integration::UNKNOWN_DEFAULT;
-
   std::unique_ptr<resource_coordinator::ResourceCoordinatorParts>
       resource_coordinator_parts_;
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index abc1c93..62a90a4 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -309,6 +309,7 @@
 #include "media/base/media_switches.h"
 #include "media/media_buildflags.h"
 #include "media/mojo/buildflags.h"
+#include "media/webrtc/webrtc_switches.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -456,6 +457,7 @@
 #if defined(OS_WIN) || defined(OS_MACOSX) || \
     (defined(OS_LINUX) && !defined(OS_CHROMEOS))
 #include "chrome/browser/browser_switcher/browser_switcher_navigation_throttle.h"
+#include "services/service_manager/sandbox/features.h"
 #endif
 
 #if defined(OS_LINUX)
@@ -3895,22 +3897,43 @@
 }
 
 void ChromeContentBrowserClient::WillStartServiceManager() {
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX) || \
+    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
   if (startup_data_) {
     auto* chrome_feature_list_creator =
         startup_data_->chrome_feature_list_creator();
     // This has to run very early before ServiceManagerContext is created.
-    const base::Value* force_network_in_process_value =
+    const policy::PolicyMap& policies =
         chrome_feature_list_creator->browser_policy_connector()
             ->GetPolicyService()
             ->GetPolicies(policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME,
-                                                  std::string()))
-            .GetValue(policy::key::kForceNetworkInProcess);
+                                                  std::string()));
+
+#if defined(OS_WIN)
+    const base::Value* force_network_in_process_value =
+        policies.GetValue(policy::key::kForceNetworkInProcess);
     bool force_network_in_process = false;
     if (force_network_in_process_value)
       force_network_in_process_value->GetAsBoolean(&force_network_in_process);
     if (force_network_in_process)
       content::ForceInProcessNetworkService(true);
+#endif
+    bool enable_audio_process =
+        base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess);
+    bool enable_audio_sandbox = base::FeatureList::IsEnabled(
+        service_manager::features::kAudioServiceSandbox);
+    const base::Value* audio_sandbox_enabled_policy_value =
+        policies.GetValue(policy::key::kAudioSandboxEnabled);
+    if (audio_sandbox_enabled_policy_value)
+      audio_sandbox_enabled_policy_value->GetAsBoolean(&enable_audio_sandbox);
+    service_manager::EnableAudioSandbox(enable_audio_sandbox);
+    if (!enable_audio_sandbox || !enable_audio_process) {
+      // Disabling the audio process or audio sandbox implies disabling APM in
+      // the audio service for security reasons. Append a switch so that this
+      // is communicated to the audio and renderer processes.
+      base::CommandLine::ForCurrentProcess()->AppendSwitch(
+          switches::kForceDisableWebRtcApmInAudioService);
+    }
   }
 #endif
 }
diff --git a/chrome/browser/chromeos/accessibility/magnification_manager.cc b/chrome/browser/chromeos/accessibility/magnification_manager.cc
index c5b32b2..97ce57d 100644
--- a/chrome/browser/chromeos/accessibility/magnification_manager.cc
+++ b/chrome/browser/chromeos/accessibility/magnification_manager.cc
@@ -26,6 +26,7 @@
 #include "content/public/browser/notification_source.h"
 #include "content/public/common/service_manager_connection.h"
 #include "services/service_manager/public/cpp/connector.h"
+#include "ui/views/accessibility/ax_event_manager.h"
 
 namespace chromeos {
 
@@ -94,6 +95,18 @@
       ash::prefs::kAccessibilityScreenMagnifierScale);
 }
 
+void MagnificationManager::OnViewEvent(views::View* view,
+                                       ax::mojom::Event event_type) {
+  if (!fullscreen_magnifier_enabled_ && !IsDockedMagnifierEnabled())
+    return;
+
+  if (event_type != ax::mojom::Event::kFocus &&
+      event_type != ax::mojom::Event::kSelection)
+    return;
+
+  HandleFocusChanged(view->GetBoundsInScreen(), false);
+}
+
 void MagnificationManager::SetProfileForTest(Profile* profile) {
   SetProfile(profile);
 }
@@ -108,10 +121,12 @@
   registrar_.Add(this, content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE,
                  content::NotificationService::AllSources());
   user_manager::UserManager::Get()->AddSessionStateObserver(this);
+  views::AXEventManager::Get()->AddObserver(this);
 }
 
 MagnificationManager::~MagnificationManager() {
   CHECK(this == g_magnification_manager);
+  views::AXEventManager::Get()->RemoveObserver(this);
   user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
 }
 
@@ -280,17 +295,22 @@
   if (node_details->is_editable_node)
     return;
 
-  const gfx::Rect& bounds_in_screen = node_details->node_bounds_in_screen;
+  HandleFocusChanged(node_details->node_bounds_in_screen,
+                     node_details->is_editable_node);
+}
+
+void MagnificationManager::HandleFocusChanged(const gfx::Rect& bounds_in_screen,
+                                              bool is_editable) {
   if (bounds_in_screen.IsEmpty())
     return;
 
   // Fullscreen magnifier and docked magnifier are mutually exclusive.
   if (fullscreen_magnifier_enabled_) {
     ash::Shell::Get()->magnification_controller()->HandleFocusedNodeChanged(
-        node_details->is_editable_node, node_details->node_bounds_in_screen);
+        is_editable, bounds_in_screen);
     return;
   }
-  DCHECK(docked_magnifier_enabled);
+  DCHECK(IsDockedMagnifierEnabled());
   ash::DockedMagnifierController::Get()->CenterOnPoint(
       bounds_in_screen.CenterPoint());
 }
diff --git a/chrome/browser/chromeos/accessibility/magnification_manager.h b/chrome/browser/chromeos/accessibility/magnification_manager.h
index 4aec427..68cd4ba 100644
--- a/chrome/browser/chromeos/accessibility/magnification_manager.h
+++ b/chrome/browser/chromeos/accessibility/magnification_manager.h
@@ -10,6 +10,7 @@
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
+#include "ui/views/accessibility/ax_event_observer.h"
 
 class PrefChangeRegistrar;
 class Profile;
@@ -30,7 +31,8 @@
 // either Fullscreen or Docked magnifier is enabled.
 class MagnificationManager
     : public content::NotificationObserver,
-      public user_manager::UserManager::UserSessionStateObserver {
+      public user_manager::UserManager::UserSessionStateObserver,
+      public views::AXEventObserver {
  public:
   // Creates an instance of MagnificationManager. This should be called once.
   static void Initialize();
@@ -59,6 +61,9 @@
   // Loads the Fullscreen magnifier scale from the pref.
   double GetSavedScreenMagnifierScale() const;
 
+  // views::AXEventObserver:
+  void OnViewEvent(views::View* view, ax::mojom::Event event_type) override;
+
   void SetProfileForTest(Profile* profile);
 
  private:
@@ -85,6 +90,9 @@
   // Called when received content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE.
   void HandleFocusChangedInPage(const content::NotificationDetails& details);
 
+  // Called in response to AXEventObserver.
+  void HandleFocusChanged(const gfx::Rect& bounds_in_screen, bool is_editable);
+
   Profile* profile_ = nullptr;
 
   bool fullscreen_magnifier_enabled_ = false;
diff --git a/chrome/browser/chromeos/chrome_content_browser_client_chromeos_part_browsertest.cc b/chrome/browser/chromeos/chrome_content_browser_client_chromeos_part_browsertest.cc
index 6db4fc8..1804a37 100644
--- a/chrome/browser/chromeos/chrome_content_browser_client_chromeos_part_browsertest.cc
+++ b/chrome/browser/chromeos/chrome_content_browser_client_chromeos_part_browsertest.cc
@@ -15,7 +15,15 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/common/web_preferences.h"
 
-using ChromeContentBrowserClientChromeOsPartTest = InProcessBrowserTest;
+class ChromeContentBrowserClientChromeOsPartTest : public InProcessBrowserTest {
+ public:
+  ChromeContentBrowserClientChromeOsPartTest() {
+    feature_list_.InitAndEnableFeature(chromeos::features::kSplitSettings);
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
 
 IN_PROC_BROWSER_TEST_F(ChromeContentBrowserClientChromeOsPartTest,
                        SettingsWindowFontSize) {
@@ -28,9 +36,6 @@
   const int kDefaultFontSize = kDefaultPrefs.default_font_size;
   const int kDefaultFixedFontSize = kDefaultPrefs.default_fixed_font_size;
 
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(chromeos::features::kSplitSettings);
-
   // Set the browser font sizes to non-default values.
   Profile* profile = browser()->profile();
   PrefService* profile_prefs = profile->GetPrefs();
diff --git a/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc b/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc
index ed9852c7..c4884a7c 100644
--- a/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc
@@ -82,12 +82,21 @@
   StartTest();
 }
 
-IN_PROC_BROWSER_TEST_F(AudioPlayerBrowserTest, NativeMediaKey) {
-  // The HardwareMediaKeyHandling feature makes key handling flaky.
-  // See https://crbug.com/902519.
-  base::test::ScopedFeatureList disable_media_key_handling;
-  disable_media_key_handling.InitAndDisableFeature(
-      media::kHardwareMediaKeyHandling);
+class AudioPlayerBrowserTestWithoutHardwareMediaKeyHandling
+    : public AudioPlayerBrowserTest {
+ public:
+  AudioPlayerBrowserTestWithoutHardwareMediaKeyHandling() {
+    // The HardwareMediaKeyHandling feature makes key handling flaky.
+    // See https://crbug.com/902519.
+    feature_list_.InitAndDisableFeature(media::kHardwareMediaKeyHandling);
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(AudioPlayerBrowserTestWithoutHardwareMediaKeyHandling,
+                       NativeMediaKey) {
   set_test_case_name("mediaKeyNative");
   StartTest();
 }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
index 8a31418..8e97311 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -1547,7 +1547,15 @@
         chromeos::features::kEnableFileManagerFormatDialog);
   }
 
-  feature_list_.InitWithFeatures(enabled_features, disabled_features);
+  // This is destroyed in |TearDown()|. We cannot initialize this in the
+  // constructor due to this feature values' above dependence on virtual
+  // method calls, but by convention subclasses of this fixture may initialize
+  // ScopedFeatureList instances in their own constructor. Ensuring construction
+  // here and destruction in |TearDown()| ensures that we preserve an acceptable
+  // relative lifetime ordering between this ScopedFeatureList and those of any
+  // subclasses.
+  feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
+  feature_list_->InitWithFeatures(enabled_features, disabled_features);
 
   extensions::ExtensionApiTest::SetUpCommandLine(command_line);
 }
@@ -1697,6 +1705,11 @@
   ui::SelectFileDialog::SetFactory(nullptr);
 }
 
+void FileManagerBrowserTestBase::TearDown() {
+  extensions::ExtensionApiTest::TearDown();
+  feature_list_.reset();
+}
+
 bool FileManagerBrowserTestBase::GetTabletMode() const {
   return false;
 }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h
index c8112228..30780b4b 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h
@@ -51,6 +51,7 @@
   void SetUpInProcessBrowserTestFixture() override;
   void SetUpOnMainThread() override;
   void TearDownOnMainThread() override;
+  void TearDown() override;
 
   // Mandatory overrides for each File Manager test extension type.
   virtual GuestMode GetGuestMode() const = 0;
@@ -146,7 +147,7 @@
   // Called during tests to determine if SMB file shares is enabled.
   bool IsSmbEnabled() const;
 
-  base::test::ScopedFeatureList feature_list_;
+  std::unique_ptr<base::test::ScopedFeatureList> feature_list_;
   crostini::FakeCrostiniFeatures crostini_features_;
 
   std::unique_ptr<DownloadsTestVolume> local_volume_;
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index 5f4dd49..5dfb413 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -3880,10 +3880,25 @@
                                     2);
 }
 
+class DownloadTestWithOptionalSafetyTipsFeature
+    : public DownloadTest,
+      public ::testing::WithParamInterface<bool> {
+ public:
+  DownloadTestWithOptionalSafetyTipsFeature() {
+    if (GetParam())
+      feature_list_.InitAndEnableFeature(features::kSafetyTipUI);
+    else
+      feature_list_.InitAndDisableFeature(features::kSafetyTipUI);
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
 // Tests that the Safety Tip status of the initiating page is used for the
 // histogram rather than the status of the download URL, and that downloads in
 // new tabs are not tracked.
-IN_PROC_BROWSER_TEST_F(DownloadTest, SafetyTips) {
+IN_PROC_BROWSER_TEST_P(DownloadTestWithOptionalSafetyTipsFeature, SafetyTips) {
   embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
   ASSERT_TRUE(embedded_test_server()->Start());
   net::EmbeddedTestServer download_server;
@@ -3907,34 +3922,30 @@
   // disabled. The same metrics should be recorded either way.
   SetSafetyTipBadRepPatterns(
       {embedded_test_server()->GetURL("/").host() + "/"});
-  for (const auto& enable_feature : {true, false}) {
-    base::test::ScopedFeatureList feature_list;
-    if (enable_feature) {
-      feature_list.InitAndEnableFeature(features::kSafetyTipUI);
-    } else {
-      feature_list.InitAndDisableFeature(features::kSafetyTipUI);
-    }
 
-    base::HistogramTester histogram_tester;
-    ui_test_utils::NavigateToURL(
-        browser(), embedded_test_server()->GetURL("/simple.html"));
-    DownloadAndWait(browser(), download_url);
-    histogram_tester.ExpectUniqueSample(
-        "Security.SafetyTips.DownloadStarted",
-        security_state::SafetyTipStatus::kBadReputation, 1);
+  base::HistogramTester histogram_tester;
+  ui_test_utils::NavigateToURL(browser(),
+                               embedded_test_server()->GetURL("/simple.html"));
+  DownloadAndWait(browser(), download_url);
+  histogram_tester.ExpectUniqueSample(
+      "Security.SafetyTips.DownloadStarted",
+      security_state::SafetyTipStatus::kBadReputation, 1);
 
-    // Test that no Safety Tip status is recorded for a download in a new tab.
-    ui_test_utils::NavigateToURL(
-        browser(), embedded_test_server()->GetURL("/simple.html"));
-    DownloadAndWaitWithDisposition(browser(), download_url,
-                                   WindowOpenDisposition::NEW_BACKGROUND_TAB,
-                                   ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
-    histogram_tester.ExpectUniqueSample(
-        "Security.SafetyTips.DownloadStarted",
-        security_state::SafetyTipStatus::kBadReputation, 1);
-  }
+  // Test that no Safety Tip status is recorded for a download in a new tab.
+  ui_test_utils::NavigateToURL(browser(),
+                               embedded_test_server()->GetURL("/simple.html"));
+  DownloadAndWaitWithDisposition(browser(), download_url,
+                                 WindowOpenDisposition::NEW_BACKGROUND_TAB,
+                                 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
+  histogram_tester.ExpectUniqueSample(
+      "Security.SafetyTips.DownloadStarted",
+      security_state::SafetyTipStatus::kBadReputation, 1);
 }
 
+INSTANTIATE_TEST_SUITE_P(/* no prefix */,
+                         DownloadTestWithOptionalSafetyTipsFeature,
+                         ::testing::Bool());
+
 // Tests that opening the downloads page will cause file existence check.
 IN_PROC_BROWSER_TEST_F(DownloadTest, FileExistenceCheckOpeningDownloadsPage) {
   base::ScopedAllowBlockingForTesting allow_blocking;
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index 6fb972a..62328d8 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -13,19 +13,15 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/json/json_string_value_serializer.h"
-#include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/one_shot_event.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/lock.h"
-#include "base/task/post_task.h"
 #include "base/threading/thread_checker.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/activity_log/activity_action_constants.h"
 #include "chrome/browser/extensions/activity_log/counting_policy.h"
 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
@@ -42,8 +38,6 @@
 #include "components/sync_preferences/pref_service_syncable.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/api_activity_monitor.h"
@@ -346,59 +340,9 @@
   }
 }
 
-// A global, thread-safe record of activity log state.
-class ActivityLogState {
- public:
-  ActivityLogState() {}
-  ~ActivityLogState() {}
-
-  void AddActiveContext(content::BrowserContext* context) {
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
-    base::AutoLock lock(lock_);
-    contexts_.insert(context);
-  }
-
-  void RemoveActiveContext(content::BrowserContext* context) {
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
-    base::AutoLock lock(lock_);
-    contexts_.erase(context);
-  }
-
-  bool IsActiveContext(content::BrowserContext* context) {
-    base::AutoLock lock(lock_);
-    return contexts_.count(context) > 0;
-  }
-
-  void AddWhitelistedId(const std::string& id) {
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
-    base::AutoLock lock(lock_);
-    whitelisted_ids_.insert(id);
-  }
-
-  // We don't remove the id entry from g_activity_log_state because it may be
-  // loaded in multiple profiles, and being whitelisted for the ActivityLog
-  // is a global permission.
-
-  bool IsWhitelistedId(const std::string& id) {
-    base::AutoLock lock(lock_);
-    return whitelisted_ids_.count(id) > 0;
-  }
-
- private:
-  std::set<const content::BrowserContext*> contexts_;
-  std::set<std::string> whitelisted_ids_;
-  base::Lock lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(ActivityLogState);
-};
-
-base::LazyInstance<ActivityLogState>::DestructorAtExit g_activity_log_state =
-    LAZY_INSTANCE_INITIALIZER;
-
 // Returns the ActivityLog associated with the given |browser_context| after
 // checking that |browser_context| is valid.
 ActivityLog* SafeGetActivityLog(content::BrowserContext* browser_context) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   // There's a chance that the |browser_context| was deleted some time during
   // the thread hops.
   // TODO(devlin): We should probably be doing this more extensively throughout
@@ -411,44 +355,26 @@
 }
 
 // Calls into the ActivityLog to log an api event or function call.
-// Must be called on the UI thread.
-void LogApiActivityOnUI(content::BrowserContext* browser_context,
-                        const std::string& extension_id,
-                        const std::string& activity_name,
-                        std::unique_ptr<base::ListValue> args,
-                        Action::ActionType type) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  ActivityLog* activity_log = SafeGetActivityLog(browser_context);
-  if (!activity_log || !activity_log->ShouldLog(extension_id))
-    return;
-  auto action = base::MakeRefCounted<Action>(extension_id, base::Time::Now(),
-                                             type, activity_name);
-  action->set_args(std::move(args));
-  activity_log->LogAction(action);
-}
-
-// Generic thread-safe handler for API calls and events.
 void LogApiActivity(content::BrowserContext* browser_context,
                     const std::string& extension_id,
                     const std::string& activity_name,
                     const base::ListValue& args,
                     Action::ActionType type) {
-  ActivityLogState& state = g_activity_log_state.Get();
-  if (!state.IsActiveContext(browser_context) ||
-      state.IsWhitelistedId(extension_id))
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (ActivityLogAPI::IsExtensionWhitelisted(extension_id))
     return;
-  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    base::PostTask(
-        FROM_HERE, {BrowserThread::UI},
-        base::BindOnce(&LogApiActivityOnUI, browser_context, extension_id,
-                       activity_name, args.CreateDeepCopy(), type));
+
+  ActivityLog* activity_log = SafeGetActivityLog(browser_context);
+  if (!activity_log || !activity_log->ShouldLog(extension_id))
     return;
-  }
-  LogApiActivityOnUI(browser_context, extension_id, activity_name,
-                     args.CreateDeepCopy(), type);
+
+  auto action = base::MakeRefCounted<Action>(extension_id, base::Time::Now(),
+                                             type, activity_name);
+  action->set_args(args.CreateDeepCopy());
+  activity_log->LogAction(action);
 }
 
-// Handler for API events. Thread-safe.
+// Handler for API events.
 void LogApiEvent(content::BrowserContext* browser_context,
                  const std::string& extension_id,
                  const std::string& event_name,
@@ -457,7 +383,7 @@
                  Action::ACTION_API_EVENT);
 }
 
-// Handler for API function calls. Thread-safe.
+// Handler for API function calls.
 void LogApiFunction(content::BrowserContext* browser_context,
                     const std::string& extension_id,
                     const std::string& event_name,
@@ -466,18 +392,21 @@
                  Action::ACTION_API_CALL);
 }
 
-// Calls into the ActivityLog to log a webRequest usage.
-// Must be called on the UI thread.
-void LogWebRequestActivityOnUI(content::BrowserContext* browser_context,
-                               const std::string& extension_id,
-                               const GURL& url,
-                               bool is_incognito,
-                               const std::string& api_call,
-                               std::unique_ptr<base::DictionaryValue> details) {
+// Handler for webRequest use.
+void LogWebRequestActivity(content::BrowserContext* browser_context,
+                           const std::string& extension_id,
+                           const GURL& url,
+                           bool is_incognito,
+                           const std::string& api_call,
+                           std::unique_ptr<base::DictionaryValue> details) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (ActivityLogAPI::IsExtensionWhitelisted(extension_id))
+    return;
+
   ActivityLog* activity_log = SafeGetActivityLog(browser_context);
   if (!activity_log || !activity_log->ShouldLog(extension_id))
     return;
+
   auto action = base::MakeRefCounted<Action>(
       extension_id, base::Time::Now(), Action::ACTION_WEB_REQUEST, api_call);
   action->set_page_url(url);
@@ -487,28 +416,6 @@
   activity_log->LogAction(action);
 }
 
-// Handler for webRequest use. Thread-safe.
-void LogWebRequestActivity(content::BrowserContext* browser_context,
-                           const std::string& extension_id,
-                           const GURL& url,
-                           bool is_incognito,
-                           const std::string& api_call,
-                           std::unique_ptr<base::DictionaryValue> details) {
-  ActivityLogState& state = g_activity_log_state.Get();
-  if (!state.IsActiveContext(browser_context) ||
-      state.IsWhitelistedId(extension_id))
-    return;
-  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    base::PostTask(FROM_HERE, {BrowserThread::UI},
-                   base::BindOnce(&LogWebRequestActivityOnUI, browser_context,
-                                  extension_id, url, is_incognito, api_call,
-                                  std::move(details)));
-    return;
-  }
-  LogWebRequestActivityOnUI(browser_context, extension_id, url, is_incognito,
-                            api_call, std::move(details));
-}
-
 void SetActivityHandlers() {
   // Set up event handlers. We don't have to worry about unsetting these,
   // because we check whether or not the activity log is active for the context
@@ -617,8 +524,6 @@
 ActivityLog::~ActivityLog() {
   if (database_policy_)
     database_policy_->Close();
-  if (is_active_)
-    g_activity_log_state.Get().RemoveActiveContext(profile_);
 }
 
 // MAINTAIN STATUS. ------------------------------------------------------------
@@ -660,7 +565,7 @@
                                     const Extension* extension) {
   if (!ActivityLogAPI::IsExtensionWhitelisted(extension->id()))
     return;
-  g_activity_log_state.Get().AddWhitelistedId(extension->id());
+
   ++active_consumers_;
 
   if (!extension_system_->ready().is_signaled())
@@ -869,10 +774,6 @@
   if (should_be_active == is_active_)
     return;
 
-  ActivityLogState& state = g_activity_log_state.Get();
-  content::BrowserContext* off_the_record =
-      profile_->HasOffTheRecordProfile() ? profile_->GetOffTheRecordProfile()
-                                         : nullptr;
   bool has_db = db_enabled_ && database_policy_;
   bool old_is_active = is_active_;
 
@@ -882,21 +783,10 @@
       ChooseDatabasePolicy();
     }
 
-    state.AddActiveContext(profile_);
-    if (off_the_record)
-      state.AddActiveContext(off_the_record);
-    registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
-                   content::NotificationService::AllSources());
-    registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
-                   content::NotificationService::AllSources());
     is_active_ = true;
   } else {
     if (has_db && !needs_db)
       db_enabled_ = false;
-    state.RemoveActiveContext(profile_);
-    if (off_the_record)
-      state.RemoveActiveContext(off_the_record);
-    registrar_.RemoveAll();
     is_active_ = false;
   }
 
@@ -912,28 +802,6 @@
   }
 }
 
-void ActivityLog::Observe(int type,
-                          const content::NotificationSource& source,
-                          const content::NotificationDetails& details) {
-  DCHECK(is_active_);
-  switch (type) {
-    case chrome::NOTIFICATION_PROFILE_CREATED: {
-      Profile* profile = content::Source<Profile>(source).ptr();
-      if (profile_->IsSameProfile(profile))
-        g_activity_log_state.Get().AddActiveContext(profile);
-      break;
-    }
-    case chrome::NOTIFICATION_PROFILE_DESTROYED: {
-      Profile* profile = content::Source<Profile>(source).ptr();
-      if (profile_->IsSameProfile(profile))
-        g_activity_log_state.Get().RemoveActiveContext(profile);
-      break;
-    }
-    default:
-      NOTREACHED();
-  }
-}
-
 void ActivityLog::OnExtensionSystemReady() {
   if (active_consumers_ != cached_consumer_count_) {
     CheckActive(false);
diff --git a/chrome/browser/extensions/activity_log/activity_log.h b/chrome/browser/extensions/activity_log/activity_log.h
index f67e3ca..a30613e 100644
--- a/chrome/browser/extensions/activity_log/activity_log.h
+++ b/chrome/browser/extensions/activity_log/activity_log.h
@@ -19,8 +19,6 @@
 #include "base/threading/thread.h"
 #include "chrome/browser/extensions/activity_log/activity_actions.h"
 #include "chrome/browser/extensions/activity_log/activity_log_policy.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
 #include "extensions/browser/browser_context_keyed_api_factory.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_registry_observer.h"
@@ -47,8 +45,7 @@
 // each profile.
 //
 class ActivityLog : public BrowserContextKeyedAPI,
-                    public ExtensionRegistryObserver,
-                    public content::NotificationObserver {
+                    public ExtensionRegistryObserver {
  public:
   // Observers can listen for activity events. There is probably only one
   // observer: the activityLogPrivate API.
@@ -174,11 +171,6 @@
   // whether or not a consumer is active. Otherwise, checks active_consumers_.
   void CheckActive(bool use_cached);
 
-  // content::NotificationObserver:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
-
   // Called once the ExtensionSystem is ready.
   void OnExtensionSystemReady();
 
@@ -240,8 +232,6 @@
   // reasons.
   bool is_active_;
 
-  content::NotificationRegistrar registrar_;
-
   base::WeakPtrFactory<ActivityLog> weak_factory_{this};
 
   FRIEND_TEST_ALL_PREFIXES(ActivityLogApiTest, TriggerEvent);
diff --git a/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc b/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc
index 9d49d65..69ddd3f 100644
--- a/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc
+++ b/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc
@@ -39,12 +39,40 @@
   return "";
 }
 
+api::media_perception_private::ComponentInstallationError
+GetComponentInstallationErrorForCrOSComponentManagerError(
+    const component_updater::CrOSComponentManager::Error error) {
+  switch (error) {
+    case component_updater::CrOSComponentManager::Error::ERROR_MAX:
+    case component_updater::CrOSComponentManager::Error::NONE:
+      return api::media_perception_private::COMPONENT_INSTALLATION_ERROR_NONE;
+    case component_updater::CrOSComponentManager::Error::UNKNOWN_COMPONENT:
+      return api::media_perception_private::
+          COMPONENT_INSTALLATION_ERROR_UNKNOWN_COMPONENT;
+    case component_updater::CrOSComponentManager::Error::INSTALL_FAILURE:
+      return api::media_perception_private::
+          COMPONENT_INSTALLATION_ERROR_INSTALL_FAILURE;
+    case component_updater::CrOSComponentManager::Error::MOUNT_FAILURE:
+      return api::media_perception_private::
+          COMPONENT_INSTALLATION_ERROR_MOUNT_FAILURE;
+    case component_updater::CrOSComponentManager::Error::
+        COMPATIBILITY_CHECK_FAILED:
+      return api::media_perception_private::
+          COMPONENT_INSTALLATION_ERROR_COMPATIBILITY_CHECK_FAILED;
+    case component_updater::CrOSComponentManager::Error::NOT_FOUND:
+      return api::media_perception_private::
+          COMPONENT_INSTALLATION_ERROR_NOT_FOUND;
+  }
+  NOTREACHED() << "Reached component error type not in switch.";
+  return api::media_perception_private::COMPONENT_INSTALLATION_ERROR_NONE;
+}
+
 void OnLoadComponent(
     MediaPerceptionAPIDelegate::LoadCrOSComponentCallback load_callback,
     component_updater::CrOSComponentManager::Error error,
     const base::FilePath& mount_point) {
   std::move(load_callback)
-      .Run(error == component_updater::CrOSComponentManager::Error::NONE,
+      .Run(GetComponentInstallationErrorForCrOSComponentManagerError(error),
            mount_point);
 }
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 2218134..17195be4 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -576,6 +576,11 @@
     "expiry_milestone": 82
   },
   {
+    "name": "cryptauth-v2-devicesync",
+    "owners": [ "khorimoto", "nohle" ],
+    "expiry_milestone": 85
+  },
+  {
     "name": "cryptauth-v2-enrollment",
     "owners": [ "khorimoto", "nohle" ],
     "expiry_milestone": 82
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 399f067..8f2ff3d0 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3282,6 +3282,10 @@
 const char kCrostiniWebUIInstallerDescription[] =
     "Enable the new WebUI Crostini Installer.";
 
+const char kCryptAuthV2DeviceSyncName[] = "CryptAuth v2 DeviceSync";
+const char kCryptAuthV2DeviceSyncDescription[] =
+    "Use the CryptAuth v2 DeviceSync protocol.";
+
 const char kCryptAuthV2EnrollmentName[] = "CryptAuth v2 Enrollment";
 const char kCryptAuthV2EnrollmentDescription[] =
     "Use the CryptAuth v2 Enrollment protocol.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 31a5fc3..d9b73ef 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1947,6 +1947,9 @@
 extern const char kCrostiniWebUIInstallerName[];
 extern const char kCrostiniWebUIInstallerDescription[];
 
+extern const char kCryptAuthV2DeviceSyncName[];
+extern const char kCryptAuthV2DeviceSyncDescription[];
+
 extern const char kCryptAuthV2EnrollmentName[];
 extern const char kCryptAuthV2EnrollmentDescription[];
 
diff --git a/chrome/browser/media/webrtc/webrtc_text_log_handler.cc b/chrome/browser/media/webrtc/webrtc_text_log_handler.cc
index ccd7694..c012626 100644
--- a/chrome/browser/media/webrtc/webrtc_text_log_handler.cc
+++ b/chrome/browser/media/webrtc/webrtc_text_log_handler.cc
@@ -38,6 +38,7 @@
 #include "net/base/network_interfaces.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/service_manager/sandbox/features.h"
+#include "services/service_manager/sandbox/sandbox_type.h"
 
 #if defined(OS_LINUX)
 #include "base/linux_util.h"
@@ -472,21 +473,26 @@
                       ", gl-version=" + gpu_info.gl_version);
 
   // AudioService features
-  auto enabled_or_disabled_string = [](auto& feature) {
+  auto enabled_or_disabled_feature_string = [](auto& feature) {
     return base::FeatureList::IsEnabled(feature) ? "enabled" : "disabled";
   };
+  auto enabled_or_disabled_bool_string = [](bool value) {
+    return value ? "enabled" : "disabled";
+  };
   LogToCircularBuffer(base::StrCat(
       {"AudioService: AudioStreams=",
-       enabled_or_disabled_string(features::kAudioServiceAudioStreams),
+       enabled_or_disabled_feature_string(features::kAudioServiceAudioStreams),
        ", OutOfProcess=",
-       enabled_or_disabled_string(features::kAudioServiceOutOfProcess),
+       enabled_or_disabled_feature_string(features::kAudioServiceOutOfProcess),
        ", LaunchOnStartup=",
-       enabled_or_disabled_string(features::kAudioServiceLaunchOnStartup),
+       enabled_or_disabled_feature_string(
+           features::kAudioServiceLaunchOnStartup),
        ", Sandbox=",
-       enabled_or_disabled_string(
-           service_manager::features::kAudioServiceSandbox),
+       enabled_or_disabled_bool_string(
+           service_manager::IsAudioSandboxEnabled()),
        ", ApmInAudioService=",
-       enabled_or_disabled_string(features::kWebRtcApmInAudioService)}));
+       enabled_or_disabled_bool_string(
+           media::IsWebRtcApmInAudioServiceEnabled())}));
 
   // Audio manager
   // On some platforms, this can vary depending on build flags and failure
diff --git a/chrome/browser/metrics/perf/heap_collector.cc b/chrome/browser/metrics/perf/heap_collector.cc
index 47f536a..435323f 100644
--- a/chrome/browser/metrics/perf/heap_collector.cc
+++ b/chrome/browser/metrics/perf/heap_collector.cc
@@ -445,8 +445,7 @@
   task_runner->PostTask(
       FROM_HERE,
       base::BindOnce(&HeapCollector::SaveSerializedPerfProto, heap_collector,
-                     std::move(sampled_profile), PerfProtoType::PERF_TYPE_DATA,
-                     std::move(output)));
+                     std::move(sampled_profile), std::move(output)));
 }
 
 }  // namespace metrics
diff --git a/chrome/browser/metrics/perf/metric_collector.cc b/chrome/browser/metrics/perf/metric_collector.cc
index 5e70c11..01fca98 100644
--- a/chrome/browser/metrics/perf/metric_collector.cc
+++ b/chrome/browser/metrics/perf/metric_collector.cc
@@ -270,7 +270,6 @@
 
 void MetricCollector::SaveSerializedPerfProto(
     std::unique_ptr<SampledProfile> sampled_profile,
-    PerfProtoType type,
     std::string serialized_proto) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (serialized_proto.empty()) {
@@ -278,30 +277,13 @@
     return;
   }
 
-  switch (type) {
-    case PerfProtoType::PERF_TYPE_DATA: {
-      PerfDataProto perf_data_proto;
-      if (!perf_data_proto.ParseFromString(serialized_proto)) {
-        AddToUmaHistogram(CollectionAttemptStatus::PROTOBUF_NOT_PARSED);
-        return;
-      }
-      RemoveUnknownFieldsFromMessagesWithStrings(&perf_data_proto);
-      sampled_profile->mutable_perf_data()->Swap(&perf_data_proto);
-      break;
-    }
-    case PerfProtoType::PERF_TYPE_STAT: {
-      PerfStatProto perf_stat_proto;
-      if (!perf_stat_proto.ParseFromString(serialized_proto)) {
-        AddToUmaHistogram(CollectionAttemptStatus::PROTOBUF_NOT_PARSED);
-        return;
-      }
-      sampled_profile->mutable_perf_stat()->Swap(&perf_stat_proto);
-      break;
-    }
-    case PerfProtoType::PERF_TYPE_UNSUPPORTED:
-      AddToUmaHistogram(CollectionAttemptStatus::PROTOBUF_NOT_PARSED);
-      return;
+  PerfDataProto perf_data_proto;
+  if (!perf_data_proto.ParseFromString(serialized_proto)) {
+    AddToUmaHistogram(CollectionAttemptStatus::PROTOBUF_NOT_PARSED);
+    return;
   }
+  RemoveUnknownFieldsFromMessagesWithStrings(&perf_data_proto);
+  sampled_profile->mutable_perf_data()->Swap(&perf_data_proto);
 
   sampled_profile->set_ms_after_boot(base::SysInfo::Uptime().InMilliseconds());
   DCHECK(!login_time_.is_null());
diff --git a/chrome/browser/metrics/perf/metric_collector.h b/chrome/browser/metrics/perf/metric_collector.h
index 6ac323a..05ab4ec 100644
--- a/chrome/browser/metrics/perf/metric_collector.h
+++ b/chrome/browser/metrics/perf/metric_collector.h
@@ -75,13 +75,6 @@
   }
 
  protected:
-  // Perf proto type.
-  enum class PerfProtoType {
-    PERF_TYPE_DATA,
-    PERF_TYPE_STAT,
-    PERF_TYPE_UNSUPPORTED,
-  };
-
   // Enumeration representing success and various failure modes for collecting
   // profile data. These values are persisted to logs. Entries should not be
   // renumbered and numeric values should never be reused.
@@ -149,11 +142,9 @@
   // Collector specific logic for stopping the current collection.
   virtual void StopCollection() {}
 
-  // Parses the given serialized perf proto of the given type (data or stat).
-  // If valid, it adds it to the given sampled_profile and stores it in the
-  // local profile data cache.
+  // Parses the given serialized perf data proto. If valid, it adds it to the
+  // given sampled_profile and stores it in the local profile data cache.
   void SaveSerializedPerfProto(std::unique_ptr<SampledProfile> sampled_profile,
-                               PerfProtoType type,
                                std::string serialized_proto);
 
   // Returns a const reference to the collection_params.
diff --git a/chrome/browser/metrics/perf/metric_collector_unittest.cc b/chrome/browser/metrics/perf/metric_collector_unittest.cc
index 6c4f27f..7faef79 100644
--- a/chrome/browser/metrics/perf/metric_collector_unittest.cc
+++ b/chrome/browser/metrics/perf/metric_collector_unittest.cc
@@ -58,32 +58,6 @@
   return proto;
 }
 
-// Returns an example PerfStatProto. The contents don't have to make sense. They
-// just need to constitute a semantically valid protobuf.
-// |result| is an output parameter that will contain the created protobuf.
-PerfStatProto GetExamplePerfStatProto() {
-  PerfStatProto proto;
-  proto.set_command_line(
-      "perf stat -a -e cycles -e instructions -e branches -- sleep 2");
-
-  PerfStatProto_PerfStatLine* line1 = proto.add_line();
-  line1->set_time_ms(1000);
-  line1->set_count(2000);
-  line1->set_event_name("cycles");
-
-  PerfStatProto_PerfStatLine* line2 = proto.add_line();
-  line2->set_time_ms(2000);
-  line2->set_count(5678);
-  line2->set_event_name("instructions");
-
-  PerfStatProto_PerfStatLine* line3 = proto.add_line();
-  line3->set_time_ms(3000);
-  line3->set_count(9999);
-  line3->set_event_name("branches");
-
-  return proto;
-}
-
 // Creates a serialized data stream containing a string with a field tag number.
 std::string SerializeStringFieldWithTag(int field, const std::string& value) {
   std::string result;
@@ -115,7 +89,6 @@
       std::unique_ptr<SampledProfile> sampled_profile) override {
     PerfDataProto perf_data_proto = GetExamplePerfDataProto();
     SaveSerializedPerfProto(std::move(sampled_profile),
-                            PerfProtoType::PERF_TYPE_DATA,
                             perf_data_proto.SerializeAsString());
   }
 
@@ -124,7 +97,6 @@
   using MetricCollector::Init;
   using MetricCollector::IsRunning;
   using MetricCollector::login_time;
-  using MetricCollector::PerfProtoType;
   using MetricCollector::RecordUserLogin;
   using MetricCollector::SaveSerializedPerfProto;
   using MetricCollector::ScheduleIntervalCollection;
@@ -149,8 +121,7 @@
  public:
   MetricCollectorTest()
       : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
-        perf_data_proto_(GetExamplePerfDataProto()),
-        perf_stat_proto_(GetExamplePerfStatProto()) {}
+        perf_data_proto_(GetExamplePerfDataProto()) {}
 
   void SaveProfile(std::unique_ptr<SampledProfile> sampled_profile) {
     cached_profile_data_.resize(cached_profile_data_.size() + 1);
@@ -191,16 +162,14 @@
 
   std::unique_ptr<TestMetricCollector> metric_collector_;
 
-  // Store sample perf data/stat protobufs for testing.
+  // Store sample perf data protobuf for testing.
   PerfDataProto perf_data_proto_;
-  PerfStatProto perf_stat_proto_;
 
   DISALLOW_COPY_AND_ASSIGN(MetricCollectorTest);
 };
 
 TEST_F(MetricCollectorTest, CheckSetup) {
   EXPECT_GT(perf_data_proto_.ByteSize(), 0);
-  EXPECT_GT(perf_stat_proto_.ByteSize(), 0);
 
   // Timer is active after user logs in.
   EXPECT_TRUE(metric_collector_->IsRunning());
@@ -211,9 +180,8 @@
   auto sampled_profile = std::make_unique<SampledProfile>();
   sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
 
-  metric_collector_->SaveSerializedPerfProto(
-      std::move(sampled_profile),
-      TestMetricCollector::PerfProtoType::PERF_TYPE_DATA, std::string());
+  metric_collector_->SaveSerializedPerfProto(std::move(sampled_profile),
+                                             std::string());
   task_environment_.RunUntilIdle();
 
   EXPECT_TRUE(cached_profile_data_.empty());
@@ -224,9 +192,7 @@
   sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
 
   metric_collector_->SaveSerializedPerfProto(
-      std::move(sampled_profile),
-      TestMetricCollector::PerfProtoType::PERF_TYPE_DATA,
-      perf_data_proto_.SerializeAsString());
+      std::move(sampled_profile), perf_data_proto_.SerializeAsString());
   task_environment_.RunUntilIdle();
   ASSERT_EQ(1U, cached_profile_data_.size());
 
@@ -236,7 +202,6 @@
   EXPECT_TRUE(profile.has_ms_after_login());
 
   ASSERT_TRUE(profile.has_perf_data());
-  EXPECT_FALSE(profile.has_perf_stat());
   EXPECT_EQ(perf_data_proto_.SerializeAsString(),
             profile.perf_data().SerializeAsString());
 }
@@ -294,9 +259,8 @@
   sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
 
   // Perf data protos are saved from the collector task runner.
-  metric_collector_->SaveSerializedPerfProto(
-      std::move(sampled_profile),
-      TestMetricCollector::PerfProtoType::PERF_TYPE_DATA, perf_data_string);
+  metric_collector_->SaveSerializedPerfProto(std::move(sampled_profile),
+                                             perf_data_string);
   task_environment_.RunUntilIdle();
 
   ASSERT_EQ(1U, cached_profile_data_.size());
@@ -344,30 +308,6 @@
             stored_metadata.perf_command_line_whole().unknown_fields().size());
 }
 
-TEST_F(MetricCollectorTest, PerfStatProto) {
-  auto sampled_profile = std::make_unique<SampledProfile>();
-  sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
-
-  // Perf data protos are saved from the collector task runner.
-  metric_collector_->SaveSerializedPerfProto(
-      std::move(sampled_profile),
-      TestMetricCollector::PerfProtoType::PERF_TYPE_STAT,
-      perf_stat_proto_.SerializeAsString());
-  task_environment_.RunUntilIdle();
-
-  ASSERT_EQ(1U, cached_profile_data_.size());
-
-  const SampledProfile& profile = cached_profile_data_[0];
-  EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
-  EXPECT_TRUE(profile.has_ms_after_boot());
-  EXPECT_TRUE(profile.has_ms_after_login());
-
-  EXPECT_FALSE(profile.has_perf_data());
-  ASSERT_TRUE(profile.has_perf_stat());
-  EXPECT_EQ(perf_stat_proto_.SerializeAsString(),
-            profile.perf_stat().SerializeAsString());
-}
-
 // Change |sampled_profile| between calls to SaveSerializedPerfProto().
 TEST_F(MetricCollectorTest, MultipleCalls) {
   auto sampled_profile = std::make_unique<SampledProfile>();
@@ -375,18 +315,14 @@
 
   // Perf data protos are saved from the collector task runner.
   metric_collector_->SaveSerializedPerfProto(
-      std::move(sampled_profile),
-      TestMetricCollector::PerfProtoType::PERF_TYPE_DATA,
-      perf_data_proto_.SerializeAsString());
+      std::move(sampled_profile), perf_data_proto_.SerializeAsString());
   task_environment_.RunUntilIdle();
 
   sampled_profile = std::make_unique<SampledProfile>();
   sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION);
   sampled_profile->set_ms_after_restore(3000);
   metric_collector_->SaveSerializedPerfProto(
-      std::move(sampled_profile),
-      TestMetricCollector::PerfProtoType::PERF_TYPE_STAT,
-      perf_stat_proto_.SerializeAsString());
+      std::move(sampled_profile), perf_data_proto_.SerializeAsString());
   task_environment_.RunUntilIdle();
 
   sampled_profile = std::make_unique<SampledProfile>();
@@ -394,20 +330,10 @@
   sampled_profile->set_suspend_duration_ms(60000);
   sampled_profile->set_ms_after_resume(1500);
   metric_collector_->SaveSerializedPerfProto(
-      std::move(sampled_profile),
-      TestMetricCollector::PerfProtoType::PERF_TYPE_DATA,
-      perf_data_proto_.SerializeAsString());
+      std::move(sampled_profile), perf_data_proto_.SerializeAsString());
   task_environment_.RunUntilIdle();
 
-  sampled_profile = std::make_unique<SampledProfile>();
-  sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
-  metric_collector_->SaveSerializedPerfProto(
-      std::move(sampled_profile),
-      TestMetricCollector::PerfProtoType::PERF_TYPE_STAT,
-      perf_stat_proto_.SerializeAsString());
-  task_environment_.RunUntilIdle();
-
-  ASSERT_EQ(4U, cached_profile_data_.size());
+  ASSERT_EQ(3U, cached_profile_data_.size());
 
   {
     const SampledProfile& profile = cached_profile_data_[0];
@@ -415,7 +341,6 @@
     EXPECT_TRUE(profile.has_ms_after_boot());
     EXPECT_TRUE(profile.has_ms_after_login());
     ASSERT_TRUE(profile.has_perf_data());
-    EXPECT_FALSE(profile.has_perf_stat());
     EXPECT_EQ(perf_data_proto_.SerializeAsString(),
               profile.perf_data().SerializeAsString());
   }
@@ -426,10 +351,9 @@
     EXPECT_TRUE(profile.has_ms_after_boot());
     EXPECT_TRUE(profile.has_ms_after_login());
     EXPECT_EQ(3000, profile.ms_after_restore());
-    EXPECT_FALSE(profile.has_perf_data());
-    ASSERT_TRUE(profile.has_perf_stat());
-    EXPECT_EQ(perf_stat_proto_.SerializeAsString(),
-              profile.perf_stat().SerializeAsString());
+    ASSERT_TRUE(profile.has_perf_data());
+    EXPECT_EQ(perf_data_proto_.SerializeAsString(),
+              profile.perf_data().SerializeAsString());
   }
 
   {
@@ -440,21 +364,9 @@
     EXPECT_EQ(60000, profile.suspend_duration_ms());
     EXPECT_EQ(1500, profile.ms_after_resume());
     ASSERT_TRUE(profile.has_perf_data());
-    EXPECT_FALSE(profile.has_perf_stat());
     EXPECT_EQ(perf_data_proto_.SerializeAsString(),
               profile.perf_data().SerializeAsString());
   }
-
-  {
-    const SampledProfile& profile = cached_profile_data_[3];
-    EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
-    EXPECT_TRUE(profile.has_ms_after_boot());
-    EXPECT_TRUE(profile.has_ms_after_login());
-    EXPECT_FALSE(profile.has_perf_data());
-    ASSERT_TRUE(profile.has_perf_stat());
-    EXPECT_EQ(perf_stat_proto_.SerializeAsString(),
-              profile.perf_stat().SerializeAsString());
-  }
 }
 
 TEST_F(MetricCollectorTest, StopTimer) {
@@ -590,7 +502,6 @@
   EXPECT_TRUE(profile.has_ms_after_boot());
 
   ASSERT_TRUE(profile.has_perf_data());
-  EXPECT_FALSE(profile.has_perf_stat());
   EXPECT_EQ(perf_data_proto_.SerializeAsString(),
             profile.perf_data().SerializeAsString());
 
diff --git a/chrome/browser/metrics/perf/metric_provider_unittest.cc b/chrome/browser/metrics/perf/metric_provider_unittest.cc
index 0f2b53ac..c136a8a 100644
--- a/chrome/browser/metrics/perf/metric_provider_unittest.cc
+++ b/chrome/browser/metrics/perf/metric_provider_unittest.cc
@@ -68,7 +68,6 @@
       std::unique_ptr<SampledProfile> sampled_profile) override {
     PerfDataProto perf_data_proto = GetExamplePerfDataProto();
     SaveSerializedPerfProto(std::move(sampled_profile),
-                            PerfProtoType::PERF_TYPE_DATA,
                             perf_data_proto.SerializeAsString());
   }
 
diff --git a/chrome/browser/metrics/perf/perf_events_collector.cc b/chrome/browser/metrics/perf/perf_events_collector.cc
index b0f49d915..2a8f643 100644
--- a/chrome/browser/metrics/perf/perf_events_collector.cc
+++ b/chrome/browser/metrics/perf/perf_events_collector.cc
@@ -136,12 +136,6 @@
 const char kPerfRecordCacheMissesCmd[] =
     "perf record -a -e cache-misses -c 10007";
 
-const char kPerfStatMemoryBandwidthCmd[] =
-    "perf stat -a -e cycles -e instructions "
-    "-e uncore_imc/data_reads/ -e uncore_imc/data_writes/ "
-    "-e cpu/event=0xD0,umask=0x11,name=MEM_UOPS_RETIRED-STLB_MISS_LOADS/ "
-    "-e cpu/event=0xD0,umask=0x12,name=MEM_UOPS_RETIRED-STLB_MISS_STORES/";
-
 const std::vector<RandomSelector::WeightAndValue> GetDefaultCommands_x86_64(
     const CPUIdentity& cpuid) {
   using WeightAndValue = RandomSelector::WeightAndValue;
@@ -160,18 +154,8 @@
   }
 
   if (cpu_uarch == "IvyBridge" || cpu_uarch == "Haswell" ||
-      cpu_uarch == "Broadwell") {
-    cmds.push_back(WeightAndValue(45.0, kPerfRecordCyclesCmd));
-    cmds.push_back(WeightAndValue(20.0, callgraph_cmd));
-    cmds.push_back(WeightAndValue(15.0, kPerfRecordLBRCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordInstructionTLBMissesCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordDataTLBMissesCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfStatMemoryBandwidthCmd));
-    cmds.push_back(WeightAndValue(5.0, kPerfRecordCacheMissesCmd));
-    return cmds;
-  }
-  if (cpu_uarch == "SandyBridge" || cpu_uarch == "Skylake" ||
-      cpu_uarch == "Kabylake") {
+      cpu_uarch == "Broadwell" || cpu_uarch == "SandyBridge" ||
+      cpu_uarch == "Skylake" || cpu_uarch == "Kabylake") {
     cmds.push_back(WeightAndValue(50.0, kPerfRecordCyclesCmd));
     cmds.push_back(WeightAndValue(20.0, callgraph_cmd));
     cmds.push_back(WeightAndValue(15.0, kPerfRecordLBRCmd));
@@ -391,18 +375,6 @@
   command_selector_.SetOdds(commands);
 }
 
-internal::MetricCollector::PerfProtoType PerfCollector::GetPerfProtoType(
-    const std::vector<std::string>& args) {
-  if (args.size() > 1 && args[0] == "perf") {
-    if (args[1] == "record" || args[1] == "mem")
-      return PerfProtoType::PERF_TYPE_DATA;
-    if (args[1] == "stat")
-      return PerfProtoType::PERF_TYPE_STAT;
-  }
-
-  return PerfProtoType::PERF_TYPE_UNSUPPORTED;
-}
-
 std::unique_ptr<PerfOutputCall> PerfCollector::CreatePerfOutputCall(
     base::TimeDelta duration,
     const std::vector<std::string>& perf_args,
@@ -416,7 +388,6 @@
 void PerfCollector::OnPerfOutputComplete(
     std::unique_ptr<WindowedIncognitoObserver> incognito_observer,
     std::unique_ptr<SampledProfile> sampled_profile,
-    PerfProtoType type,
     bool has_cycles,
     std::string perf_stdout) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -426,14 +397,13 @@
   perf_output_call_ = nullptr;
 
   ParseOutputProtoIfValid(std::move(incognito_observer),
-                          std::move(sampled_profile), type, has_cycles,
+                          std::move(sampled_profile), has_cycles,
                           std::move(perf_stdout));
 }
 
 void PerfCollector::ParseOutputProtoIfValid(
     std::unique_ptr<WindowedIncognitoObserver> incognito_observer,
     std::unique_ptr<SampledProfile> sampled_profile,
-    PerfProtoType type,
     bool has_cycles,
     std::string perf_stdout) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -457,7 +427,7 @@
       base::BindOnce(&OnCollectProcessTypes, sampled_profile.get()),
       base::BindOnce(&PerfCollector::SaveSerializedPerfProto,
                      weak_factory_.GetWeakPtr(), std::move(sampled_profile),
-                     type, std::move(perf_stdout)));
+                     std::move(perf_stdout)));
   DCHECK(posted);
 }
 
@@ -487,8 +457,7 @@
 namespace internal {
 
 bool CommandSamplesCPUCycles(const std::vector<std::string>& args) {
-  // First two arguments are "perf record", "perf stat", etc. We are only
-  // interested in "perf record".
+  // Command must start with "perf record".
   if (args.size() < 4 || args[0] != "perf" || args[1] != "record")
     return false;
   for (size_t i = 2; i + 1 < args.size(); ++i) {
@@ -515,7 +484,6 @@
   std::vector<std::string> command =
       base::SplitString(command_selector_.Select(), kPerfCommandDelimiter,
                         base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-  PerfProtoType type = GetPerfProtoType(command);
   bool has_cycles = internal::CommandSamplesCPUCycles(command);
 
   DCHECK(sampled_profile->has_trigger_event());
@@ -525,7 +493,7 @@
       collection_params().collection_duration, command,
       base::BindOnce(&PerfCollector::OnPerfOutputComplete,
                      weak_factory_.GetWeakPtr(), std::move(incognito_observer),
-                     std::move(sampled_profile), type, has_cycles));
+                     std::move(sampled_profile), has_cycles));
 }
 
 // static
diff --git a/chrome/browser/metrics/perf/perf_events_collector.h b/chrome/browser/metrics/perf/perf_events_collector.h
index 2a13c9e..95c20c2c 100644
--- a/chrome/browser/metrics/perf/perf_events_collector.h
+++ b/chrome/browser/metrics/perf/perf_events_collector.h
@@ -40,10 +40,6 @@
   const char* ToolName() const override;
 
  protected:
-  // Returns the perf proto type associated with the given vector of perf
-  // arguments, starting with "perf" itself in |args[0]|.
-  static PerfProtoType GetPerfProtoType(const std::vector<std::string>& args);
-
   // For testing to mock PerfOutputCall.
   virtual std::unique_ptr<PerfOutputCall> CreatePerfOutputCall(
       base::TimeDelta duration,
@@ -53,19 +49,17 @@
   void OnPerfOutputComplete(
       std::unique_ptr<WindowedIncognitoObserver> incognito_observer,
       std::unique_ptr<SampledProfile> sampled_profile,
-      PerfProtoType type,
       bool has_cycles,
       std::string perf_stdout);
 
-  // Parses a PerfDataProto or PerfStatProto from serialized data |perf_stdout|,
-  // if non-empty. Which proto to use depends on |subcommand|. If |perf_stdout|
-  // is empty, it is counted as an error. |incognito_observer| indicates
-  // whether an incognito window had been opened during the profile collection
-  // period. If there was an incognito window, discard the incoming data.
+  // Parses a PerfDataProto from serialized data |perf_stdout|, if non-empty.
+  // If |perf_stdout| is empty, it is counted as an error. |incognito_observer|
+  // indicates whether an incognito window had been opened during the profile
+  // collection period. If there was an incognito window, discard the incoming
+  // data.
   void ParseOutputProtoIfValid(
       std::unique_ptr<WindowedIncognitoObserver> incognito_observer,
       std::unique_ptr<SampledProfile> sampled_profile,
-      PerfProtoType type,
       bool has_cycles,
       std::string perf_stdout);
 
diff --git a/chrome/browser/metrics/perf/perf_events_collector_unittest.cc b/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
index aef04f68..5025ee2 100644
--- a/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
+++ b/chrome/browser/metrics/perf/perf_events_collector_unittest.cc
@@ -37,11 +37,6 @@
     "perf record -a -e dTLB-misses -c 2003";
 const char kPerfRecordCacheMissesCmd[] =
     "perf record -a -e cache-misses -c 10007";
-const char kPerfStatMemoryBandwidthCmd[] =
-    "perf stat -a -e cycles -e instructions "
-    "-e uncore_imc/data_reads/ -e uncore_imc/data_writes/ "
-    "-e cpu/event=0xD0,umask=0x11,name=MEM_UOPS_RETIRED-STLB_MISS_LOADS/ "
-    "-e cpu/event=0xD0,umask=0x12,name=MEM_UOPS_RETIRED-STLB_MISS_STORES/";
 
 // Converts a protobuf to serialized format as a byte vector.
 std::vector<uint8_t> SerializeMessageToVector(
@@ -80,32 +75,6 @@
   return proto;
 }
 
-// Returns an example PerfStatProto. The contents don't have to make sense. They
-// just need to constitute a semantically valid protobuf.
-// |result| is an output parameter that will contain the created protobuf.
-PerfStatProto GetExamplePerfStatProto() {
-  PerfStatProto proto;
-  proto.set_command_line(
-      "perf stat -a -e cycles -e instructions -e branches -- sleep 2");
-
-  PerfStatProto_PerfStatLine* line1 = proto.add_line();
-  line1->set_time_ms(1000);
-  line1->set_count(2000);
-  line1->set_event_name("cycles");
-
-  PerfStatProto_PerfStatLine* line2 = proto.add_line();
-  line2->set_time_ms(2000);
-  line2->set_count(5678);
-  line2->set_event_name("instructions");
-
-  PerfStatProto_PerfStatLine* line3 = proto.add_line();
-  line3->set_time_ms(3000);
-  line3->set_count(9999);
-  line3->set_event_name("branches");
-
-  return proto;
-}
-
 // A mock PerfOutputCall class for testing, which outputs example perf data
 // after the profile duration elapses.
 class FakePerfOutputCall : public PerfOutputCall {
@@ -187,7 +156,6 @@
   using PerfCollector::IsRunning;
   using PerfCollector::max_frequencies_mhz;
   using PerfCollector::ParseOutputProtoIfValid;
-  using PerfCollector::PerfProtoType;
   using PerfCollector::RecordUserLogin;
   using PerfCollector::set_profile_done_callback;
 
@@ -301,9 +269,7 @@
 // ParseOutputProtoIfValid().
 TEST_F(PerfCollectorTest, IncognitoWindowOpened) {
   PerfDataProto perf_data_proto = GetExamplePerfDataProto();
-  PerfStatProto perf_stat_proto = GetExamplePerfStatProto();
   EXPECT_GT(perf_data_proto.ByteSize(), 0);
-  EXPECT_GT(perf_stat_proto.ByteSize(), 0);
   task_environment_.RunUntilIdle();
 
   auto sampled_profile = std::make_unique<SampledProfile>();
@@ -311,10 +277,9 @@
 
   auto incognito_observer =
       TestIncognitoObserver::CreateWithIncognitoLaunched(false);
-  perf_collector_->ParseOutputProtoIfValid(
-      std::move(incognito_observer), std::move(sampled_profile),
-      TestPerfCollector::PerfProtoType::PERF_TYPE_DATA, true,
-      perf_data_proto.SerializeAsString());
+  perf_collector_->ParseOutputProtoIfValid(std::move(incognito_observer),
+                                           std::move(sampled_profile), true,
+                                           perf_data_proto.SerializeAsString());
 
   // Run the BrowserTaskEnvironment queue until it's empty as the above
   // ParseOutputProtoIfValid call posts a task to asynchronously collect process
@@ -328,56 +293,18 @@
   EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile1.trigger_event());
   EXPECT_TRUE(profile1.has_ms_after_login());
   ASSERT_TRUE(profile1.has_perf_data());
-  EXPECT_FALSE(profile1.has_perf_stat());
   EXPECT_EQ(SerializeMessageToVector(perf_data_proto),
             SerializeMessageToVector(profile1.perf_data()));
   EXPECT_GT(profile1.cpu_max_frequency_mhz_size(), 0);
   cached_profile_data_.clear();
 
   sampled_profile = std::make_unique<SampledProfile>();
-  sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION);
-  sampled_profile->set_ms_after_restore(3000);
-  incognito_observer =
-      TestIncognitoObserver::CreateWithIncognitoLaunched(false);
-  perf_collector_->ParseOutputProtoIfValid(
-      std::move(incognito_observer), std::move(sampled_profile),
-      TestPerfCollector::PerfProtoType::PERF_TYPE_STAT, false,
-      perf_stat_proto.SerializeAsString());
-  task_environment_.RunUntilIdle();
-
-  ASSERT_EQ(1U, cached_profile_data_.size());
-
-  const SampledProfile& profile2 = cached_profile_data_[0];
-  EXPECT_EQ(SampledProfile::RESTORE_SESSION, profile2.trigger_event());
-  EXPECT_TRUE(profile2.has_ms_after_login());
-  EXPECT_EQ(3000, profile2.ms_after_restore());
-  EXPECT_FALSE(profile2.has_perf_data());
-  ASSERT_TRUE(profile2.has_perf_stat());
-  EXPECT_EQ(SerializeMessageToVector(perf_stat_proto),
-            SerializeMessageToVector(profile2.perf_stat()));
-  EXPECT_EQ(profile2.cpu_max_frequency_mhz_size(), 0);
-  cached_profile_data_.clear();
-
-  sampled_profile = std::make_unique<SampledProfile>();
   sampled_profile->set_trigger_event(SampledProfile::RESUME_FROM_SUSPEND);
   // An incognito window opens.
   incognito_observer = TestIncognitoObserver::CreateWithIncognitoLaunched(true);
-  perf_collector_->ParseOutputProtoIfValid(
-      std::move(incognito_observer), std::move(sampled_profile),
-      TestPerfCollector::PerfProtoType::PERF_TYPE_DATA, true,
-      perf_data_proto.SerializeAsString());
-  task_environment_.RunUntilIdle();
-
-  EXPECT_TRUE(cached_profile_data_.empty());
-
-  sampled_profile = std::make_unique<SampledProfile>();
-  sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
-  // Incognito window is still open.
-  incognito_observer = TestIncognitoObserver::CreateWithIncognitoLaunched(true);
-  perf_collector_->ParseOutputProtoIfValid(
-      std::move(incognito_observer), std::move(sampled_profile),
-      TestPerfCollector::PerfProtoType::PERF_TYPE_STAT, false,
-      perf_stat_proto.SerializeAsString());
+  perf_collector_->ParseOutputProtoIfValid(std::move(incognito_observer),
+                                           std::move(sampled_profile), true,
+                                           perf_data_proto.SerializeAsString());
   task_environment_.RunUntilIdle();
 
   EXPECT_TRUE(cached_profile_data_.empty());
@@ -389,24 +316,22 @@
   // Incognito window closes.
   incognito_observer =
       TestIncognitoObserver::CreateWithIncognitoLaunched(false);
-  perf_collector_->ParseOutputProtoIfValid(
-      std::move(incognito_observer), std::move(sampled_profile),
-      TestPerfCollector::PerfProtoType::PERF_TYPE_DATA, true,
-      perf_data_proto.SerializeAsString());
+  perf_collector_->ParseOutputProtoIfValid(std::move(incognito_observer),
+                                           std::move(sampled_profile), true,
+                                           perf_data_proto.SerializeAsString());
   task_environment_.RunUntilIdle();
 
   ASSERT_EQ(1U, cached_profile_data_.size());
 
-  const SampledProfile& profile3 = cached_profile_data_[0];
-  EXPECT_EQ(SampledProfile::RESUME_FROM_SUSPEND, profile3.trigger_event());
-  EXPECT_TRUE(profile3.has_ms_after_login());
-  EXPECT_EQ(60000, profile3.suspend_duration_ms());
-  EXPECT_EQ(1500, profile3.ms_after_resume());
-  ASSERT_TRUE(profile3.has_perf_data());
-  EXPECT_FALSE(profile3.has_perf_stat());
+  const SampledProfile& profile2 = cached_profile_data_[0];
+  EXPECT_EQ(SampledProfile::RESUME_FROM_SUSPEND, profile2.trigger_event());
+  EXPECT_TRUE(profile2.has_ms_after_login());
+  EXPECT_EQ(60000, profile2.suspend_duration_ms());
+  EXPECT_EQ(1500, profile2.ms_after_resume());
+  ASSERT_TRUE(profile2.has_perf_data());
   EXPECT_EQ(SerializeMessageToVector(perf_data_proto),
-            SerializeMessageToVector(profile3.perf_data()));
-  EXPECT_GT(profile3.cpu_max_frequency_mhz_size(), 0);
+            SerializeMessageToVector(profile2.perf_data()));
+  EXPECT_GT(profile2.cpu_max_frequency_mhz_size(), 0);
 }
 
 TEST_F(PerfCollectorTest, DefaultCommandsBasedOnUarch_IvyBridge) {
@@ -424,16 +349,11 @@
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
                    [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfStatMemoryBandwidthCmd;
+                     return cmd.value == kPerfRecordLBRCmd;
                    });
   EXPECT_NE(cmds.end(), found);
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordLBRCmd;
-                       });
-  EXPECT_NE(cmds.end(), found);
-  found = std::find_if(cmds.begin(), cmds.end(),
-                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
                          return cmd.value == kPerfRecordCacheMissesCmd;
                        });
   EXPECT_NE(cmds.end(), found);
@@ -454,13 +374,8 @@
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
                    [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfStatMemoryBandwidthCmd;
+                     return cmd.value == kPerfRecordLBRCmd;
                    });
-  EXPECT_EQ(cmds.end(), found) << "SandyBridge does not support this command";
-  found = std::find_if(cmds.begin(), cmds.end(),
-                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordLBRCmd;
-                       });
   EXPECT_NE(cmds.end(), found);
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
@@ -484,13 +399,8 @@
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
                    [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfStatMemoryBandwidthCmd;
+                     return cmd.value == kPerfRecordLBRCmdAtom;
                    });
-  EXPECT_EQ(cmds.end(), found) << "Goldmont does not support this command";
-  found = std::find_if(cmds.begin(), cmds.end(),
-                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordLBRCmdAtom;
-                       });
   EXPECT_NE(cmds.end(), found);
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
@@ -549,16 +459,11 @@
   auto found =
       std::find_if(cmds.begin(), cmds.end(),
                    [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                     return cmd.value == kPerfStatMemoryBandwidthCmd;
+                     return cmd.value == kPerfRecordLBRCmd;
                    });
   EXPECT_EQ(cmds.end(), found) << "x86_32 does not support this command";
   found = std::find_if(cmds.begin(), cmds.end(),
                        [](const RandomSelector::WeightAndValue& cmd) -> bool {
-                         return cmd.value == kPerfRecordLBRCmd;
-                       });
-  EXPECT_EQ(cmds.end(), found) << "x86_32 does not support this command";
-  found = std::find_if(cmds.begin(), cmds.end(),
-                       [](const RandomSelector::WeightAndValue& cmd) -> bool {
                          return cmd.value == kPerfRecordCacheMissesCmd;
                        });
   EXPECT_EQ(cmds.end(), found) << "x86_32 does not support this command";
@@ -981,10 +886,7 @@
                                                  "-c", "1000003"}));
 
   EXPECT_FALSE(internal::CommandSamplesCPUCycles(
-      {"perf", "stat", "-a", "-e", "cycles", "-e", "instructions", "-e",
-       "uncore_imc/data_reads/", "-e", "uncore_imc/data_writes/", "-e",
-       "cpu/event=0xD0,umask=0x11,name=MEM_UOPS_RETIRED-STLB_MISS_LOADS/", "-e",
-       "cpu/event=0xD0,umask=0x12,name=MEM_UOPS_RETIRED-STLB_MISS_STORES/"}));
+      {"perf", "stat", "-a", "-e", "cycles", "-e", "instructions"}));
 }
 
 }  // namespace metrics
diff --git a/chrome/browser/metrics/perf/perf_output.h b/chrome/browser/metrics/perf/perf_output.h
index 59729e5c..0439563 100644
--- a/chrome/browser/metrics/perf/perf_output.h
+++ b/chrome/browser/metrics/perf/perf_output.h
@@ -31,7 +31,6 @@
   // The callback may delete this object.
   // The argument is one of:
   // - Output from "perf record", in PerfDataProto format, OR
-  // - Output from "perf stat", in PerfStatProto format, OR
   // - The empty string if there was an error.
   // The output is transferred to |perf_stdout|.
   using DoneCallback = base::OnceCallback<void(std::string perf_stdout)>;
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
index 317b092..7ab0245 100644
--- a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
+++ b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
@@ -82,7 +82,6 @@
     auto observer = WindowedIncognitoMonitor::CreateObserver();
     if (!observer->IncognitoActive()) {
       SaveSerializedPerfProto(std::move(sampled_profile),
-                              PerfProtoType::PERF_TYPE_DATA,
                               perf_data_proto.SerializeAsString());
     }
   }
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc
index 8861d30..dbecc14e 100644
--- a/chrome/browser/net/profile_network_context_service.cc
+++ b/chrome/browser/net/profile_network_context_service.cc
@@ -237,12 +237,6 @@
 void ProfileNetworkContextService::RegisterLocalStatePrefs(
     PrefRegistrySimple* registry) {
   registry->RegisterListPref(prefs::kHSTSPolicyBypassList);
-#if defined(OS_CHROMEOS)
-  // Note that the default value is not relevant because the pref is only
-  // evaluated when it is managed.
-  registry->RegisterBooleanPref(prefs::kBuiltinCertificateVerifierEnabled,
-                                false);
-#endif
 }
 
 void ProfileNetworkContextService::DisableQuicIfNotAllowed() {
@@ -506,7 +500,7 @@
   network_context_params->enable_expect_ct_reporting = true;
 
 #if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
-  if (!in_memory &&
+  if (!in_memory && !network_context_params->use_builtin_cert_verifier &&
       TrialComparisonCertVerifierController::MaybeAllowedForProfile(profile_)) {
     network::mojom::TrialComparisonCertVerifierConfigClientPtr config_client;
     auto config_client_request = mojo::MakeRequest(&config_client);
@@ -556,6 +550,8 @@
   }
 
 #if defined(OS_CHROMEOS)
+  // Note: On non-ChromeOS platforms, the |use_builtin_cert_verifier| param
+  // value is inherited from CreateDefaultNetworkContextParams.
   network_context_params->use_builtin_cert_verifier =
       using_builtin_cert_verifier_;
 
diff --git a/chrome/browser/net/profile_network_context_service.h b/chrome/browser/net/profile_network_context_service.h
index 6ebf38e..e2e7144 100644
--- a/chrome/browser/net/profile_network_context_service.h
+++ b/chrome/browser/net/profile_network_context_service.h
@@ -75,6 +75,9 @@
                            DefaultCacheSize);
   FRIEND_TEST_ALL_PREFIXES(ProfileNetworkContextServiceDiskCacheBrowsertest,
                            DiskCacheSize);
+  FRIEND_TEST_ALL_PREFIXES(
+      ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest,
+      Test);
 
   // Checks |quic_allowed_|, and disables QUIC if needed.
   void DisableQuicIfNotAllowed();
diff --git a/chrome/browser/net/profile_network_context_service_browsertest.cc b/chrome/browser/net/profile_network_context_service_browsertest.cc
index 97492911..5f063b2 100644
--- a/chrome/browser/net/profile_network_context_service_browsertest.cc
+++ b/chrome/browser/net/profile_network_context_service_browsertest.cc
@@ -55,6 +55,13 @@
 #include "net/base/features.h"
 #endif  // defined(OS_CHROMEOS)
 
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+#include "chrome/browser/policy/policy_test_utils.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/policy_constants.h"
+#include "net/base/features.h"
+#endif
+
 // Most tests for this class are in NetworkContextConfigurationBrowserTest.
 class ProfileNetworkContextServiceBrowsertest : public InProcessBrowserTest {
  public:
@@ -355,8 +362,62 @@
 
   EXPECT_TRUE(IsActiveProfileUsingBuiltinCertVerifier());
 }
+#elif BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+class ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest
+    : public policy::PolicyTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  void SetUpInProcessBrowserTestFixture() override {
+    scoped_feature_list_.InitWithFeatureState(
+        net::features::kCertVerifierBuiltinFeature,
+        /*enabled=*/GetParam());
+    policy::PolicyTest::SetUpInProcessBrowserTestFixture();
+  }
 
-#endif  // defined(OS_CHROMEOS)
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_P(
+    ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest,
+    Test) {
+  ProfileNetworkContextService* profile_network_context_service =
+      ProfileNetworkContextServiceFactory::GetForContext(browser()->profile());
+  base::FilePath empty_relative_partition_path;
+  network::mojom::NetworkContextParamsPtr network_context_params_ptr =
+      profile_network_context_service->CreateNetworkContextParams(
+          /*in_memory=*/false, empty_relative_partition_path);
+  EXPECT_EQ(GetParam(), network_context_params_ptr->use_builtin_cert_verifier);
+
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
+  // If the BuiltinCertificateVerifierEnabled policy is set it should override
+  // the feature flag.
+  policy::PolicyMap policies;
+  SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
+            std::make_unique<base::Value>(true));
+  UpdateProviderPolicy(policies);
+
+  network_context_params_ptr =
+      profile_network_context_service->CreateNetworkContextParams(
+          /*in_memory=*/false, empty_relative_partition_path);
+  EXPECT_TRUE(network_context_params_ptr->use_builtin_cert_verifier);
+
+  SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
+            std::make_unique<base::Value>(false));
+  UpdateProviderPolicy(policies);
+
+  network_context_params_ptr =
+      profile_network_context_service->CreateNetworkContextParams(
+          /*in_memory=*/false, empty_relative_partition_path);
+  EXPECT_FALSE(network_context_params_ptr->use_builtin_cert_verifier);
+#endif
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest,
+    ::testing::Bool());
+#endif
 
 class CorsExtraSafelistedHeaderNamesTest : public InProcessBrowserTest {
  public:
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc
index fd00b37..dcc5b84 100644
--- a/chrome/browser/net/system_network_context_manager.cc
+++ b/chrome/browser/net/system_network_context_manager.cc
@@ -59,6 +59,7 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "net/base/features.h"
 #include "net/net_buildflags.h"
 #include "net/third_party/uri_template/uri_template.h"
 #include "services/network/network_service.h"
@@ -253,6 +254,20 @@
          base::FeatureList::IsEnabled(features::kAsyncDns);
 }
 
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+bool ShouldUseBuiltinCertVerifier(PrefService* local_state) {
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
+  const PrefService::Preference* builtin_cert_verifier_enabled_pref =
+      local_state->FindPreference(prefs::kBuiltinCertificateVerifierEnabled);
+  if (builtin_cert_verifier_enabled_pref->IsManaged())
+    return builtin_cert_verifier_enabled_pref->GetValue()->GetBool();
+#endif
+
+  return base::FeatureList::IsEnabled(
+      net::features::kCertVerifierBuiltinFeature);
+}
+#endif
+
 }  // namespace
 
 // SharedURLLoaderFactory backed by a SystemNetworkContextManager and its
@@ -538,6 +553,13 @@
   registry->RegisterBooleanPref(prefs::kQuickCheckEnabled, true);
 
   registry->RegisterIntegerPref(prefs::kMaxConnectionsPerProxy, -1);
+
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
+  // Note that the default value is not relevant because the pref is only
+  // evaluated when it is managed.
+  registry->RegisterBooleanPref(prefs::kBuiltinCertificateVerifierEnabled,
+                                false);
+#endif
 }
 
 void SystemNetworkContextManager::OnNetworkServiceCreated(
@@ -758,6 +780,11 @@
   }
 #endif
 
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+  network_context_params->use_builtin_cert_verifier =
+      ShouldUseBuiltinCertVerifier(local_state_);
+#endif
+
   return network_context_params;
 }
 
diff --git a/chrome/browser/net/system_network_context_manager_browsertest.cc b/chrome/browser/net/system_network_context_manager_browsertest.cc
index c283951c..4f73f562 100644
--- a/chrome/browser/net/system_network_context_manager_browsertest.cc
+++ b/chrome/browser/net/system_network_context_manager_browsertest.cc
@@ -28,6 +28,13 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+#include "chrome/browser/policy/policy_test_utils.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/policy_constants.h"
+#include "net/base/features.h"
+#endif
+
 #if defined(OS_WIN)
 #include "base/win/win_util.h"
 #endif
@@ -440,3 +447,53 @@
     ,
     SystemNetworkContextManagerCertificateTransparencyBrowsertest,
     ::testing::Values(base::nullopt, true, false));
+
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+class SystemNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest
+    : public policy::PolicyTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  void SetUpInProcessBrowserTestFixture() override {
+    scoped_feature_list_.InitWithFeatureState(
+        net::features::kCertVerifierBuiltinFeature,
+        /*enabled=*/GetParam());
+    policy::PolicyTest::SetUpInProcessBrowserTestFixture();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_P(
+    SystemNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest,
+    Test) {
+  // If no BuiltinCertificateVerifierEnabled policy is set, the
+  // use_builtin_cert_verifier param should be set from the feature flag.
+  EXPECT_EQ(GetParam(), g_browser_process->system_network_context_manager()
+                            ->CreateDefaultNetworkContextParams()
+                            ->use_builtin_cert_verifier);
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
+  // If the BuiltinCertificateVerifierEnabled policy is set it should override
+  // the feature flag.
+  policy::PolicyMap policies;
+  SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
+            std::make_unique<base::Value>(true));
+  UpdateProviderPolicy(policies);
+  EXPECT_TRUE(g_browser_process->system_network_context_manager()
+                  ->CreateDefaultNetworkContextParams()
+                  ->use_builtin_cert_verifier);
+
+  SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
+            std::make_unique<base::Value>(false));
+  UpdateProviderPolicy(policies);
+  EXPECT_FALSE(g_browser_process->system_network_context_manager()
+                   ->CreateDefaultNetworkContextParams()
+                   ->use_builtin_cert_verifier);
+#endif  // BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    SystemNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest,
+    ::testing::Bool());
+#endif  // BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
index 9ed594fd..61620ad 100644
--- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
+++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
@@ -144,8 +144,10 @@
       database_provider, top_host_provider_.get(),
       content::BrowserContext::GetDefaultStoragePartition(profile)
           ->GetURLLoaderFactoryForBrowserProcess());
-  prediction_manager_ =
-      std::make_unique<optimization_guide::PredictionManager>();
+  if (optimization_guide::features::IsOptimizationTargetPredictionEnabled()) {
+    prediction_manager_ =
+        std::make_unique<optimization_guide::PredictionManager>();
+  }
 }
 
 void OptimizationGuideKeyedService::MaybeLoadHintForNavigation(
@@ -164,9 +166,10 @@
     const std::vector<optimization_guide::proto::OptimizationTarget>&
         optimization_targets) {
   DCHECK(hints_manager_);
-  DCHECK(prediction_manager_);
   hints_manager_->RegisterOptimizationTypes(optimization_types);
-  prediction_manager_->RegisterOptimizationTargets(optimization_targets);
+
+  if (prediction_manager_)
+    prediction_manager_->RegisterOptimizationTargets(optimization_targets);
 }
 
 optimization_guide::OptimizationGuideDecision
@@ -184,6 +187,13 @@
       &optimization_target_decision, &optimization_type_decision,
       optimization_metadata);
 
+  if (prediction_manager_) {
+    optimization_target_decision = prediction_manager_->ShouldTargetNavigation(
+        navigation_handle, optimization_target);
+    // TODO(crbug/1001194): Add feature param for propagating decision that
+    // allows for us to collect metrics without tainting the data.
+  }
+
   LogDecisions(navigation_handle, optimization_target,
                optimization_target_decision, optimization_type,
                optimization_type_decision);
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc
index cea83a5..7af9ff0 100644
--- a/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc
+++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc
@@ -249,6 +249,13 @@
 };
 
 IN_PROC_BROWSER_TEST_F(OptimizationGuideKeyedServiceBrowserTest,
+                       PredictionManagerNotCreatedIfFeatureDisabled) {
+  ASSERT_FALSE(
+      OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile())
+          ->GetPredictionManager());
+}
+
+IN_PROC_BROWSER_TEST_F(OptimizationGuideKeyedServiceBrowserTest,
                        TopHostProviderNotSetIfNotAllowed) {
   ASSERT_FALSE(
       OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile())
@@ -664,3 +671,61 @@
   EXPECT_EQ("whatever.com", top_hosts[0]);
   EXPECT_EQ("somehost.com", top_hosts[1]);
 }
+
+class OptimizationGuideKeyedServiceTargetPredictionEnabledBrowserTest
+    : public OptimizationGuideKeyedServiceBrowserTest {
+ public:
+  OptimizationGuideKeyedServiceTargetPredictionEnabledBrowserTest() = default;
+  ~OptimizationGuideKeyedServiceTargetPredictionEnabledBrowserTest() override =
+      default;
+
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(
+        optimization_guide::features::kOptimizationTargetPrediction);
+
+    OptimizationGuideKeyedServiceBrowserTest::SetUp();
+  }
+
+  void TearDown() override {
+    OptimizationGuideKeyedServiceBrowserTest::TearDown();
+
+    scoped_feature_list_.Reset();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(
+    OptimizationGuideKeyedServiceTargetPredictionEnabledBrowserTest,
+    PredictionManagerIsCreated) {
+  ASSERT_TRUE(
+      OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile())
+          ->GetPredictionManager());
+}
+
+IN_PROC_BROWSER_TEST_F(
+    OptimizationGuideKeyedServiceTargetPredictionEnabledBrowserTest,
+    PredictionManagerDecisionOverridesHintsManager) {
+  PushHintsComponentAndWaitForCompletion();
+  RegisterWithKeyedService();
+
+  ukm::TestAutoSetUkmRecorder ukm_recorder;
+  base::HistogramTester histogram_tester;
+
+  ui_test_utils::NavigateToURL(browser(), url_with_hints());
+
+  EXPECT_EQ(RetryForHistogramUntilCountReached(
+                histogram_tester, "OptimizationGuide.LoadedHint.Result", 1),
+            1);
+  // There should be a hint that matches this URL.
+  histogram_tester.ExpectUniqueSample("OptimizationGuide.LoadedHint.Result",
+                                      true, 1);
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
+            last_consumer_decision());
+  histogram_tester.ExpectUniqueSample(
+      "OptimizationGuide.TargetDecision.PainfulPageLoad",
+      static_cast<int>(optimization_guide::OptimizationTargetDecision::
+                           kModelNotAvailableOnClient),
+      1);
+}
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc
index 130bfc3..97379b8c 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc
@@ -30,7 +30,8 @@
   void SetUp() override {
     scoped_feature_list_.InitWithFeatures(
         {optimization_guide::features::kOptimizationHints,
-         optimization_guide::features::kOptimizationGuideKeyedService},
+         optimization_guide::features::kOptimizationGuideKeyedService,
+         optimization_guide::features::kOptimizationTargetPrediction},
         {});
     InProcessBrowserTest::SetUp();
   }
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index b74c87f..cf28f9e 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -731,9 +731,6 @@
   { key::kUnifiedDesktopEnabledByDefault,
     prefs::kUnifiedDesktopEnabledByDefault,
     base::Value::Type::BOOLEAN },
-  { key::kBuiltinCertificateVerifierEnabled,
-    prefs::kBuiltinCertificateVerifierEnabled,
-    base::Value::Type::BOOLEAN },
   { key::kArcEnabled,
     arc::prefs::kArcEnabled,
     base::Value::Type::BOOLEAN },
@@ -862,6 +859,12 @@
     base::Value::Type::BOOLEAN },
 #endif  // defined(OS_CHROMEOS)
 
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
+  { key::kBuiltinCertificateVerifierEnabled,
+    prefs::kBuiltinCertificateVerifierEnabled,
+    base::Value::Type::BOOLEAN },
+#endif
+
 // Metrics reporting is controlled by a platform specific policy for ChromeOS
 #if defined(OS_CHROMEOS)
   { key::kDeviceMetricsReportingEnabled,
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index d0a2d47..7076085 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -269,6 +269,12 @@
 #include "chrome/browser/ui/toolbar/media_router_action_controller.h"
 #endif
 
+#if defined(OS_WIN) || defined(OS_MACOSX) || \
+    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+#include "media/webrtc/webrtc_switches.h"
+#include "services/service_manager/sandbox/features.h"
+#endif
+
 using content::BrowserThread;
 using safe_browsing::ReusedPasswordAccountType;
 using testing::_;
@@ -5820,4 +5826,66 @@
   EXPECT_TRUE(prefs->GetBoolean(prefs::kSharedClipboardEnabled));
 }
 
+#if defined(OS_WIN) || defined(OS_MACOSX) || \
+    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+
+class AudioSandboxEnabledTest
+    : public InProcessBrowserTest,
+      public ::testing::WithParamInterface<
+          /*policy::key::kAllowAudioSandbox=*/base::Optional<bool>> {
+ public:
+  // InProcessBrowserTest implementation:
+  void SetUp() override {
+    EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_))
+        .WillRepeatedly(testing::Return(true));
+    policy::PolicyMap values;
+    if (GetParam().has_value()) {
+      values.Set(policy::key::kAudioSandboxEnabled,
+                 policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
+                 policy::POLICY_SOURCE_CLOUD,
+                 std::make_unique<base::Value>(*GetParam()), nullptr);
+    }
+    policy_provider_.UpdateChromePolicy(values);
+    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
+        &policy_provider_);
+
+    InProcessBrowserTest::SetUp();
+  }
+
+ private:
+  policy::MockConfigurationPolicyProvider policy_provider_;
+};
+
+IN_PROC_BROWSER_TEST_P(AudioSandboxEnabledTest, IsRespected) {
+  base::Optional<bool> enable_sandbox_via_policy = GetParam();
+  bool is_sandbox_enabled_by_default = base::FeatureList::IsEnabled(
+      service_manager::features::kAudioServiceSandbox);
+  bool is_apm_enabled_by_default =
+      base::FeatureList::IsEnabled(features::kWebRtcApmInAudioService);
+
+  ASSERT_EQ(enable_sandbox_via_policy.value_or(is_sandbox_enabled_by_default),
+            service_manager::IsAudioSandboxEnabled());
+  ASSERT_EQ(
+      is_apm_enabled_by_default && service_manager::IsAudioSandboxEnabled(),
+      media::IsWebRtcApmInAudioServiceEnabled());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    Enabled,
+    AudioSandboxEnabledTest,
+    ::testing::Values(/*policy::key::kAudioSandboxEnabled=*/true));
+
+INSTANTIATE_TEST_SUITE_P(
+    Disabled,
+    AudioSandboxEnabledTest,
+    ::testing::Values(/*policy::key::kAudioSandboxEnabled=*/false));
+
+INSTANTIATE_TEST_SUITE_P(
+    NotSet,
+    AudioSandboxEnabledTest,
+    ::testing::Values(/*policy::key::kAudioSandboxEnabled=*/base::nullopt));
+
+#endif  //  defined(OS_WIN) || defined (OS_MACOSX) || (defined(OS_LINUX) &&
+        //  !defined(OS_CHROMEOS))
+
 }  // namespace policy
diff --git a/chrome/browser/recovery/recovery_install_global_error.cc b/chrome/browser/recovery/recovery_install_global_error.cc
index e51586b..4a0988c7 100644
--- a/chrome/browser/recovery/recovery_install_global_error.cc
+++ b/chrome/browser/recovery/recovery_install_global_error.cc
@@ -19,6 +19,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/prefs/pref_service.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/image/image.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/native_theme/native_theme.h"
 
diff --git a/chrome/browser/resource_coordinator/decision_details.cc b/chrome/browser/resource_coordinator/decision_details.cc
index 487bb46d..449cd63d 100644
--- a/chrome/browser/resource_coordinator/decision_details.cc
+++ b/chrome/browser/resource_coordinator/decision_details.cc
@@ -37,6 +37,8 @@
     "Tab is currently capturing a window or screen",
     "Tab is sharing its BrowsingInstance with another tab",
     "Tab is currently connected to a bluetooth device",
+    "Tab is currently holding a WebLock",
+    "Tab is currently holding an IndexedDB lock",
 };
 static_assert(base::size(kDecisionFailureReasonStrings) ==
                   static_cast<size_t>(DecisionFailureReason::MAX),
@@ -144,6 +146,12 @@
     case DecisionFailureReason::LIVE_STATE_USING_BLUETOOTH:
       ukm->SetFailureLiveStateUsingBluetooth(1);
       break;
+    case DecisionFailureReason::LIVE_STATE_USING_WEBLOCK:
+      ukm->SetFailureLiveStateUsingWebLock(1);
+      break;
+    case DecisionFailureReason::LIVE_STATE_USING_INDEXEDDB_LOCK:
+      ukm->SetFailureLiveStateUsingIndexedDBLock(1);
+      break;
     case DecisionFailureReason::MAX:
       NOTREACHED();
       break;
diff --git a/chrome/browser/resource_coordinator/decision_details.h b/chrome/browser/resource_coordinator/decision_details.h
index 95bdc72..73dfb5e 100644
--- a/chrome/browser/resource_coordinator/decision_details.h
+++ b/chrome/browser/resource_coordinator/decision_details.h
@@ -82,6 +82,12 @@
   // The tab is opted out of the intervention as it's currently connected to a
   // bluetooth device.
   LIVE_STATE_USING_BLUETOOTH,
+  // The tab is opted out of the intervention as it's currently holding at least
+  // one WebLock.
+  LIVE_STATE_USING_WEBLOCK,
+  // The tab is opted out of the intervention as it's currently holding at least
+  // one IndexedDB lock.
+  LIVE_STATE_USING_INDEXEDDB_LOCK,
   // This must remain last.
   MAX,
 };
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
index 4339c51..a9333d0e 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -542,6 +542,16 @@
     CanFreezeHeuristicsChecks(decision_details);
     CheckIfTabIsUsedInBackground(decision_details,
                                  InterventionType::kProactive);
+
+    if (is_holding_weblock_) {
+      decision_details->AddReason(
+          DecisionFailureReason::LIVE_STATE_USING_WEBLOCK);
+    }
+
+    if (is_holding_indexeddb_lock_) {
+      decision_details->AddReason(
+          DecisionFailureReason::LIVE_STATE_USING_INDEXEDDB_LOCK);
+    }
   }
 
   if (decision_details->reasons().empty()) {
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
index d1a58e6..468baac 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
@@ -934,4 +934,60 @@
       ->SetIsConnectedToBluetoothDevice(false);
 }
 
+TEST_F(TabLifecycleUnitTest, CannotFreezeIfHoldingWebLock) {
+  TabLifecycleUnit tab_lifecycle_unit(GetTabLifecycleUnitSource(), &observers_,
+                                      usage_clock_.get(), web_contents_,
+                                      tab_strip_model_.get());
+  TabLoadTracker::Get()->TransitionStateForTesting(web_contents_,
+                                                   LoadingState::LOADED);
+  // Advance time enough that the tab is urgent discardable.
+  test_clock_.Advance(kBackgroundUrgentProtectionTime);
+  ExpectCanDiscardTrueAllReasons(&tab_lifecycle_unit);
+
+  DecisionDetails decision_details;
+  EXPECT_TRUE(tab_lifecycle_unit.CanFreeze(&decision_details));
+
+  tab_lifecycle_unit.SetIsHoldingWebLock(true);
+
+  // A tab holding a WebLock can't be frozen.
+  decision_details.Clear();
+  EXPECT_FALSE(tab_lifecycle_unit.CanFreeze(&decision_details));
+  EXPECT_FALSE(decision_details.IsPositive());
+  EXPECT_EQ(DecisionFailureReason::LIVE_STATE_USING_WEBLOCK,
+            decision_details.FailureReason());
+
+  // This tab should still be discardable.
+  ExpectCanDiscardTrueAllReasons(&tab_lifecycle_unit);
+
+  tab_lifecycle_unit.SetIsHoldingWebLock(false);
+}
+
+TEST_F(TabLifecycleUnitTest, CannotFreezeIfHoldingIndexedDBLock) {
+  TabLifecycleUnit tab_lifecycle_unit(GetTabLifecycleUnitSource(), &observers_,
+                                      usage_clock_.get(), web_contents_,
+                                      tab_strip_model_.get());
+  TabLoadTracker::Get()->TransitionStateForTesting(web_contents_,
+                                                   LoadingState::LOADED);
+  // Advance time enough that the tab is urgent discardable.
+  test_clock_.Advance(kBackgroundUrgentProtectionTime);
+  ExpectCanDiscardTrueAllReasons(&tab_lifecycle_unit);
+
+  DecisionDetails decision_details;
+  EXPECT_TRUE(tab_lifecycle_unit.CanFreeze(&decision_details));
+
+  tab_lifecycle_unit.SetIsHoldingIndexedDBLock(true);
+
+  // A tab holding an IndexedDB Lock can't be frozen.
+  decision_details.Clear();
+  EXPECT_FALSE(tab_lifecycle_unit.CanFreeze(&decision_details));
+  EXPECT_FALSE(decision_details.IsPositive());
+  EXPECT_EQ(DecisionFailureReason::LIVE_STATE_USING_INDEXEDDB_LOCK,
+            decision_details.FailureReason());
+
+  // This tab should still be discardable.
+  ExpectCanDiscardTrueAllReasons(&tab_lifecycle_unit);
+
+  tab_lifecycle_unit.SetIsHoldingIndexedDBLock(false);
+}
+
 }  // namespace resource_coordinator
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision.html b/chrome/browser/resources/chromeos/add_supervision/add_supervision.html
index 2fdc636..ab70c9b 100644
--- a/chrome/browser/resources/chromeos/add_supervision/add_supervision.html
+++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision.html
@@ -62,7 +62,8 @@
             width: 100%;
           }
         </style>
-        <div id="offlineContentDiv">
+        <div id="offlineContentDiv" role="dialog"
+            aria-label="$i18n{pageTitle}">
           <div>
             <svg xmlns="http://www.w3.org/2000/svg" class="error-icon" width="32px" height="32px" viewBox="0 0 22 22">
               <path d="M11 15h2v2h-2v-2zm0-8h2v6h-2V7zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z">
@@ -81,7 +82,8 @@
             </cr-button>
           </div>
         </div>
-        <div id="webviewDiv">
+        <div id="webviewDiv" role="dialog"
+            aria-label="$i18n{pageTitle}">
           <webview id="webview"></webview>
         </div>
       </template>
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/phonetic_data.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/phonetic_data.js
index 7bd54868..76fc9e8 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/phonetic_data.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/phonetic_data.js
@@ -58,5 +58,8 @@
   // language code to do a lookup.
   if (!PhoneticData.phoneticMap_[language])
     language = language.split('-')[0];
+  // If language still isn't in the map, return empty string.
+  if (!PhoneticData.phoneticMap_[language])
+    return '';
   return PhoneticData.phoneticMap_[language][character] || '';
 };
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index 5e3941a1..b9c391a 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -1083,15 +1083,28 @@
     return matchEl.classList.contains(CLASSES.SELECTED);
   });
 
+  const wasFocused = matchEls[selected].contains(document.activeElement);
+
   populateAutocompleteMatches(result.matches);
 
   if (result.matches.length === 0) {
+    if (wasFocused) {
+      $(IDS.REALBOX).focus();
+    }
     return;
   }
 
   const newMatchEls = Array.from($(IDS.REALBOX_MATCHES).children);
   const newSelected = Math.min(newMatchEls.length - 1, selected);
-  selectMatchEl(newMatchEls[newSelected]);
+  const newSelectedEl = newMatchEls[newSelected];
+
+  selectMatchEl(newSelectedEl);
+
+  if (wasFocused) {
+    const removeIcon = newSelectedEl.querySelector(`.${CLASSES.REMOVE_ICON}`);
+    assert(removeIcon || newSelectedEl).focus();
+  }
+
   updateRealboxOutput({
     moveCursorToEnd: true,
     inline: '',
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js
index 4c990dd..d85d80a2 100644
--- a/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -1009,9 +1009,10 @@
 
     // TODO(raymes): Give pageIndicator_ the same API as toolbar_.
     if (this.pageIndicator_) {
+      const lastIndex = this.pageIndicator_.index;
       this.pageIndicator_.index = visiblePage;
       if (this.documentDimensions_.pageDimensions.length > 1 &&
-          hasScrollbars.vertical) {
+          hasScrollbars.vertical && lastIndex !== undefined) {
         this.pageIndicator_.style.visibility = 'visible';
       } else {
         this.pageIndicator_.style.visibility = 'hidden';
diff --git a/chrome/browser/resources/reset_password/reset_password.html b/chrome/browser/resources/reset_password/reset_password.html
index 2c201ac..a16273e 100644
--- a/chrome/browser/resources/reset_password/reset_password.html
+++ b/chrome/browser/resources/reset_password/reset_password.html
@@ -5,7 +5,6 @@
   <meta name="viewport" content="width=device-width">
   <title>$i18n{title}</title>
   <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
-  <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js"></script>
   <script type="module" src="reset_password.js"></script>
   <style>
     html {
diff --git a/chrome/browser/resources/reset_password/reset_password.js b/chrome/browser/resources/reset_password/reset_password.js
index 2be3afd..886c65c 100644
--- a/chrome/browser/resources/reset_password/reset_password.js
+++ b/chrome/browser/resources/reset_password/reset_password.js
@@ -7,6 +7,7 @@
 import 'chrome://resources/cr_elements/icons.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
 import 'chrome://resources/polymer/v3_0/paper-styles/color.js';
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
 import './reset_password.mojom-lite.js';
 
 import {$} from 'chrome://resources/js/util.m.js';
diff --git a/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc b/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc
index b067adc1..d8f1eb1 100644
--- a/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc
@@ -12,6 +12,7 @@
 #include "components/sync/driver/sync_driver_switches.h"
 #include "components/sync/engine/sync_engine_switches.h"
 #include "components/sync/nigori/cryptographer.h"
+#include "content/public/test/test_launcher.h"
 
 namespace {
 
@@ -317,18 +318,11 @@
   EXPECT_TRUE(WaitForClientBookmarkWithTitle("scypt-encrypted bookmark"));
 }
 
-// See crbug.com/915219 about THREAD_SANITIZER. This data race is hard to avoid
-// as overriding g_feature_list after it has been used is needed for this test.
-#if defined(THREAD_SANITIZER)
-#define MAYBE_CannotDecryptScryptKeyEncryptedDataWhenScryptDisabled \
-  DISABLED_CannotDecryptScryptKeyEncryptedDataWhenScryptDisabled
-#else
-#define MAYBE_CannotDecryptScryptKeyEncryptedDataWhenScryptDisabled \
-  CannotDecryptScryptKeyEncryptedDataWhenScryptDisabled
-#endif
+// See crbug.com/915219. This test needs to be rewritten to not rely on
+// FeatureList mutation after browser threads have started.
 IN_PROC_BROWSER_TEST_F(
     SingleClientCustomPassphraseForceDisableScryptSyncTest,
-    MAYBE_CannotDecryptScryptKeyEncryptedDataWhenScryptDisabled) {
+    DISABLED_CannotDecryptScryptKeyEncryptedDataWhenScryptDisabled) {
   sync_pb::NigoriSpecifics nigori;
   {
     // Creating a Nigori and injecting an encrypted bookmark both require key
@@ -399,48 +393,42 @@
       expected, {KeyDerivationParams::CreateForPbkdf2(), "hunter2"}));
 }
 
-// TODO(https://crbug.com/952074): re-enable once flakiness is addressed.
-#if defined(THREAD_SANITIZER)
-#define MAYBE_PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode \
-  DISABLED_PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode
-#else
-#define MAYBE_PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode \
-  PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode
-#endif
+class SingleClientCustomPassphraseSyncTestInDirectoryMode
+    : public SingleClientCustomPassphraseSyncTest {
+ public:
+  SingleClientCustomPassphraseSyncTestInDirectoryMode() {
+    if (content::IsPreTest()) {
+      // TODO(crbug.com/922900): Don't disable scrypt derivation and use it as
+      // key derivation method in ShouldLoadUSSCustomPassphraseInDirectoryMode,
+      // once USS implementation support it for new passphrases.
+      feature_list_.InitWithFeatures(
+          /*enabled_features=*/{switches::kSyncUSSBookmarks,
+                                switches::kSyncUSSPasswords,
+                                switches::kSyncUSSNigori},
+          /*disabled_features=*/{
+              switches::kSyncUseScryptForNewCustomPassphrases});
+    } else {
+      // We should be able to decrypt bookmarks with passphrase, which was set
+      // when kSyncUSSNigori was enabled, without providing it again once
+      // kSyncUSSNigori is disabled.
+      feature_list_.InitAndDisableFeature(switches::kSyncUSSNigori);
+    }
+  }
 
-IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest,
-                       MAYBE_PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode) {
-  base::test::ScopedFeatureList override_features;
-  // TODO(crbug.com/922900): Don't disable scrypt derivation and use it as key
-  // derivation method in ShouldLoadUSSCustomPassphraseInDirectoryMode, once
-  // USS implementation support it for new passphrases.
-  override_features.InitWithFeatures(
-      /*enabled_features=*/{switches::kSyncUSSBookmarks,
-                            switches::kSyncUSSPasswords,
-                            switches::kSyncUSSNigori},
-      /*disabled_features=*/{switches::kSyncUseScryptForNewCustomPassphrases});
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTestInDirectoryMode,
+                       PRE_ShouldLoadUSSCustomPassphraseInDirectoryMode) {
   ASSERT_TRUE(SetupSync());
   ASSERT_TRUE(WaitForNigori(PassphraseType::kKeystorePassphrase));
   GetSyncService()->GetUserSettings()->SetEncryptionPassphrase("hunter2");
   ASSERT_TRUE(WaitForNigori(PassphraseType::kCustomPassphrase));
 }
 
-// TODO(https://crbug.com/952074): re-enable once flakiness is addressed.
-#if defined(THREAD_SANITIZER)
-#define MAYBE_ShouldLoadUSSCustomPassphraseInDirectoryMode \
-  DISABLED_ShouldLoadUSSCustomPassphraseInDirectoryMode
-#else
-#define MAYBE_ShouldLoadUSSCustomPassphraseInDirectoryMode \
-  ShouldLoadUSSCustomPassphraseInDirectoryMode
-#endif
-
-IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest,
-                       MAYBE_ShouldLoadUSSCustomPassphraseInDirectoryMode) {
-  // We should be able to decrypt bookmarks with passphrase, which was set when
-  // kSyncUSSNigori was enabled, without providing it again once kSyncUSSNigori
-  // is disabled.
-  base::test::ScopedFeatureList override_features;
-  override_features.InitAndDisableFeature(switches::kSyncUSSNigori);
+IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTestInDirectoryMode,
+                       ShouldLoadUSSCustomPassphraseInDirectoryMode) {
   const KeyParams key_params = {KeyDerivationParams::CreateForPbkdf2(),
                                 "hunter2"};
   InjectEncryptedServerBookmark(
@@ -451,47 +439,41 @@
   EXPECT_TRUE(WaitForClientBookmarkWithTitle("some bookmark"));
 }
 
-// TODO(https://crbug.com/952074): re-enable once flakiness is addressed.
-#if defined(THREAD_SANITIZER)
-#define MAYBE_PRE_ShouldLoadDirectoryCustomPassphraseInUSSMode \
-  DISABLED_PRE_ShouldLoadDirectoryCustomPassphraseInUSSMode
-#else
-#define MAYBE_PRE_ShouldLoadDirectoryCustomPassphraseInUSSMode \
-  PRE_ShouldLoadDirectoryCustomPassphraseInUSSMode
-#endif
+class SingleClientCustomPassphraseSyncTestInUSSMode
+    : public SingleClientCustomPassphraseSyncTest {
+ public:
+  SingleClientCustomPassphraseSyncTestInUSSMode() {
+    if (content::IsPreTest()) {
+      feature_list_.InitWithFeatures(
+          /*enabled_features=*/{switches::
+                                    kSyncUseScryptForNewCustomPassphrases},
+          /*disabled_features=*/{switches::kSyncUSSNigori});
+    } else {
+      // We should be able to decrypt bookmarks with passphrase, which was set
+      // when kSyncUSSNigori was disabled, without providing it again once
+      // kSyncUSSNigori is enabled.
+      feature_list_.InitWithFeatures(
+          /*enabled_features=*/{switches::kSyncUSSBookmarks,
+                                switches::kSyncUSSPasswords,
+                                switches::kSyncUSSNigori},
+          /*disabled_features=*/{});
+    }
+  }
 
-IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest,
-                       MAYBE_PRE_ShouldLoadDirectoryCustomPassphraseInUSSMode) {
-  base::test::ScopedFeatureList override_features;
-  override_features.InitWithFeatures(
-      /*enabled_features=*/{switches::kSyncUseScryptForNewCustomPassphrases},
-      /*disabled_features=*/{switches::kSyncUSSNigori});
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTestInUSSMode,
+                       PRE_ShouldLoadDirectoryCustomPassphraseInUSSMode) {
   ASSERT_TRUE(SetupSync());
   ASSERT_TRUE(WaitForNigori(PassphraseType::kKeystorePassphrase));
   GetSyncService()->GetUserSettings()->SetEncryptionPassphrase("hunter2");
   ASSERT_TRUE(WaitForNigori(PassphraseType::kCustomPassphrase));
 }
 
-// TODO(https://crbug.com/952074): re-enable once flakiness is addressed.
-#if defined(THREAD_SANITIZER)
-#define MAYBE_ShouldLoadDirectoryCustomPassphraseInUSSMode \
-  DISABLED_ShouldLoadDirectoryCustomPassphraseInUSSMode
-#else
-#define MAYBE_ShouldLoadDirectoryCustomPassphraseInUSSMode \
-  ShouldLoadDirectoryCustomPassphraseInUSSMode
-#endif
-
-IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTest,
-                       MAYBE_ShouldLoadDirectoryCustomPassphraseInUSSMode) {
-  // We should be able to decrypt bookmarks with passphrase, which was set when
-  // kSyncUSSNigori was disabled, without providing it again once kSyncUSSNigori
-  // is enabled.
-  base::test::ScopedFeatureList override_features;
-  override_features.InitWithFeatures(
-      /*enabled_features=*/{switches::kSyncUSSBookmarks,
-                            switches::kSyncUSSPasswords,
-                            switches::kSyncUSSNigori},
-      /*disabled_features=*/{});
+IN_PROC_BROWSER_TEST_F(SingleClientCustomPassphraseSyncTestInUSSMode,
+                       ShouldLoadDirectoryCustomPassphraseInUSSMode) {
   NigoriSpecifics nigori;
   ASSERT_TRUE(GetServerNigori(GetFakeServer(), &nigori));
   std::string decoded_scrypt_salt;
diff --git a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
index 94eba27..9b57b2d 100644
--- a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
@@ -21,6 +21,7 @@
 #include "components/sync/driver/profile_sync_service.h"
 #include "components/sync/driver/sync_driver_switches.h"
 #include "components/sync/syncable/directory_cryptographer.h"
+#include "content/public/test/test_launcher.h"
 
 namespace {
 
@@ -249,12 +250,24 @@
   DISALLOW_COPY_AND_ASSIGN(SingleClientPasswordsSyncUssMigratorTest);
 };
 
-// Creates and syncs two passwords before USS being enabled.
-IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncUssMigratorTest,
-                       PRE_ExerciseUssMigrator) {
-  base::test::ScopedFeatureList override_features;
-  override_features.InitAndDisableFeature(switches::kSyncUSSPasswords);
+class SingleClientPasswordsSyncUssMigratorTestWithUssTransition
+    : public SingleClientPasswordsSyncUssMigratorTest {
+ public:
+  SingleClientPasswordsSyncUssMigratorTestWithUssTransition() {
+    if (content::IsPreTest())
+      feature_list_.InitAndDisableFeature(switches::kSyncUSSPasswords);
+    else
+      feature_list_.InitAndEnableFeature(switches::kSyncUSSPasswords);
+  }
 
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// Creates and syncs two passwords before USS being enabled.
+IN_PROC_BROWSER_TEST_F(
+    SingleClientPasswordsSyncUssMigratorTestWithUssTransition,
+    PRE_ExerciseUssMigrator) {
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
   AddLogin(GetPasswordStore(0), CreateTestPasswordForm(0));
   AddLogin(GetPasswordStore(0), CreateTestPasswordForm(1));
@@ -262,20 +275,11 @@
   ASSERT_EQ(2, GetPasswordCount(0));
 }
 
-// TODO(https://crbug.com/952074): re-enable once flakiness is addressed.
-#if defined(THREAD_SANITIZER)
-#define MAYBE_ExerciseUssMigrator DISABLED_ExerciseUssMigrator
-#else
-#define MAYBE_ExerciseUssMigrator ExerciseUssMigrator
-#endif
-
 // Now that local passwords, the local sync directory and the sever are
 // populated with two passwords, USS is enabled for passwords.
-IN_PROC_BROWSER_TEST_F(SingleClientPasswordsSyncUssMigratorTest,
-                       MAYBE_ExerciseUssMigrator) {
-  base::test::ScopedFeatureList override_features;
-  override_features.InitAndEnableFeature(switches::kSyncUSSPasswords);
-
+IN_PROC_BROWSER_TEST_F(
+    SingleClientPasswordsSyncUssMigratorTestWithUssTransition,
+    ExerciseUssMigrator) {
   base::HistogramTester histogram_tester;
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
   ASSERT_EQ(2, GetPasswordCount(0));
diff --git a/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc b/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
index 6fbdee3..f8a8c4a 100644
--- a/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_custom_passphrase_sync_test.cc
@@ -182,8 +182,6 @@
 IN_PROC_BROWSER_TEST_F(
     TwoClientCustomPassphraseSyncTestWithScryptEncryptionEnabled,
     ClientsCanSyncData) {
-  ScopedScryptFeatureToggler toggler(/*force_disabled=*/false,
-                                     /*use_for_new_passphrases=*/true);
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
   ASSERT_TRUE(AllModelsMatchVerifier());
 
@@ -205,19 +203,11 @@
   EXPECT_TRUE(WaitForBookmarksToMatchVerifier());
 }
 
-#if defined(THREAD_SANITIZER)
-// https://crbug.com/915219. This data race is hard to avoid as overriding
-// g_feature_list after it has been used is needed for this test.
-#define MAYBE_ClientsCanSyncDataWhenScryptEncryptionEnabledInOne \
-  DISABLED_ClientsCanSyncDataWhenScryptEncryptionEnabledInOne
-#else
-#define MAYBE_ClientsCanSyncDataWhenScryptEncryptionEnabledInOne \
-  ClientsCanSyncDataWhenScryptEncryptionEnabledInOne
-#endif
-
+// See crbug.com/915219. This test needs to be rewritten to not rely on
+// FeatureList mutation after browser threads have started.
 IN_PROC_BROWSER_TEST_F(
     TwoClientCustomPassphraseSyncTest,
-    MAYBE_ClientsCanSyncDataWhenScryptEncryptionEnabledInOne) {
+    DISABLED_ClientsCanSyncDataWhenScryptEncryptionEnabledInOne) {
   ScopedScryptFeatureToggler toggler(/*force_disabled=*/false,
                                      /*use_for_new_passphrases=*/false);
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 9f4b861..f89dbfe8 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2657,6 +2657,7 @@
       "views/bookmarks/bookmark_menu_controller_views.h",
       "views/bookmarks/bookmark_menu_delegate.cc",
       "views/bookmarks/bookmark_menu_delegate.h",
+      "views/browser_commands_views.cc",
       "views/browser_dialogs_views.cc",
       "views/bubble_anchor_util_views.cc",
       "views/bubble_anchor_util_views.h",
diff --git a/chrome/browser/ui/app_list/internal_app/internal_app_item.cc b/chrome/browser/ui/app_list/internal_app/internal_app_item.cc
index de4fbf8..dc267f39 100644
--- a/chrome/browser/ui/app_list/internal_app/internal_app_item.cc
+++ b/chrome/browser/ui/app_list/internal_app/internal_app_item.cc
@@ -6,6 +6,7 @@
 
 #include "ash/public/cpp/app_list/app_list_config.h"
 #include "base/metrics/histogram_macros.h"
+#include "chrome/browser/apps/app_service/app_service_metrics.h"
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/internal_app/internal_app_context_menu.h"
 #include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
@@ -14,15 +15,6 @@
 // static
 const char InternalAppItem::kItemType[] = "InternalAppItem";
 
-// TODO(crbug.com/826982): move UMA_HISTOGRAM_ENUMERATION code to
-// built_in_chromeos_apps.cc when the AppService feature is enabled by default.
-
-// static
-void InternalAppItem::RecordActiveHistogram(const std::string& app_id) {
-  app_list::InternalAppName name = app_list::GetInternalAppNameByAppId(app_id);
-  UMA_HISTOGRAM_ENUMERATION("Apps.AppListInternalApp.Activate", name);
-}
-
 InternalAppItem::InternalAppItem(
     Profile* profile,
     AppListModelUpdater* model_updater,
@@ -49,7 +41,7 @@
 }
 
 void InternalAppItem::Activate(int event_flags) {
-  RecordActiveHistogram(id());
+  apps::RecordAppLaunch(id(), apps::mojom::LaunchSource::kFromAppListGrid);
   app_list::OpenInternalApp(id(), profile(), event_flags);
 }
 
diff --git a/chrome/browser/ui/app_list/search/internal_app_result.cc b/chrome/browser/ui/app_list/search/internal_app_result.cc
index 4876afed..2302238 100644
--- a/chrome/browser/ui/app_list/search/internal_app_result.cc
+++ b/chrome/browser/ui/app_list/search/internal_app_result.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "chrome/browser/apps/app_service/app_service_metrics.h"
 #include "chrome/browser/chromeos/release_notes/release_notes_storage.h"
 #include "chrome/browser/favicon/large_icon_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -24,21 +25,6 @@
 
 namespace app_list {
 
-// TODO(crbug.com/826982): move UMA_HISTOGRAM_ENUMERATION code to
-// built_in_chromeos_apps.cc when the AppService feature is enabled by default.
-
-// static
-void InternalAppResult::RecordShowHistogram(const std::string& app_id) {
-  InternalAppName name = GetInternalAppNameByAppId(app_id);
-  UMA_HISTOGRAM_ENUMERATION("Apps.AppListSearchResultInternalApp.Show", name);
-}
-
-// static
-void InternalAppResult::RecordOpenHistogram(const std::string& app_id) {
-  InternalAppName name = GetInternalAppNameByAppId(app_id);
-  UMA_HISTOGRAM_ENUMERATION("Apps.AppListSearchResultInternalApp.Open", name);
-}
-
 InternalAppResult::InternalAppResult(Profile* profile,
                                      const std::string& app_id,
                                      AppListControllerDelegate* controller,
@@ -76,7 +62,7 @@
     SetPositionPriority(1.0f);
   }
 
-  RecordShowHistogram(app_id);
+  apps::RecordBuiltInAppSearchResult(app_id);
 }
 
 InternalAppResult::~InternalAppResult() = default;
@@ -86,7 +72,7 @@
 }
 
 void InternalAppResult::Open(int event_flags) {
-  RecordOpenHistogram(id());
+  apps::RecordAppLaunch(id(), apps::mojom::LaunchSource::kFromAppListQuery);
 
   if (id() == ash::kInternalAppIdContinueReading &&
       url_for_continuous_reading_.is_valid()) {
diff --git a/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_browsertest.cc b/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_browsertest.cc
deleted file mode 100644
index d0f1d85..0000000
--- a/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_browsertest.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.h"
-#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_view.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/test/test_browser_dialog.h"
-
-namespace autofill {
-
-class WebauthnOfferDialogBrowsertest : public DialogBrowserTest {
- public:
-  WebauthnOfferDialogBrowsertest() = default;
-
-  // DialogBrowserTest:
-  void ShowUi(const std::string& name) override {
-    content::WebContents* web_contents =
-        browser()->tab_strip_model()->GetActiveWebContents();
-
-    // Do lazy initialization of WebauthnOfferDialogControllerImpl.
-    WebauthnOfferDialogControllerImpl::CreateForWebContents(web_contents);
-    WebauthnOfferDialogControllerImpl* controller =
-        WebauthnOfferDialogControllerImpl::FromWebContents(web_contents);
-    DCHECK(controller);
-    controller->ShowOfferDialog(base::DoNothing());
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WebauthnOfferDialogBrowsertest);
-};
-
-IN_PROC_BROWSER_TEST_F(WebauthnOfferDialogBrowsertest, InvokeUi_default) {
-  ShowAndVerifyUi();
-}
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.cc b/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.cc
index 5a4aa38..ab1a9ad 100644
--- a/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.cc
@@ -13,15 +13,25 @@
     content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents) {}
 
-WebauthnOfferDialogControllerImpl::~WebauthnOfferDialogControllerImpl() =
-    default;
+WebauthnOfferDialogControllerImpl::~WebauthnOfferDialogControllerImpl() {
+  // This part of code is executed only if browser window is closed when the
+  // dialog is visible. In this case the controller is destroyed before
+  // WebauthnOfferDialogViewImpl::dtor() being called, but the reference to
+  // controller is not reset. Need to reset via
+  // WebauthnOfferDialogViewImpl::Hide() to avoid crash.
+  if (dialog_model_) {
+    dialog_model_->SetDialogState(
+        WebauthnOfferDialogModel::DialogState::kInactive);
+  }
+}
 
 void WebauthnOfferDialogControllerImpl::ShowOfferDialog(
     AutofillClient::WebauthnOfferDialogCallback callback) {
   DCHECK(!dialog_model_);
 
   offer_dialog_callback_ = std::move(callback);
-  dialog_model_ = WebauthnOfferDialogView::CreateAndShow(this);
+  dialog_view_ = WebauthnOfferDialogView::CreateAndShow(this);
+  dialog_model_ = dialog_view_->GetDialogModel();
 }
 
 bool WebauthnOfferDialogControllerImpl::CloseDialog() {
@@ -40,6 +50,7 @@
 
 void WebauthnOfferDialogControllerImpl::OnDialogClosed() {
   dialog_model_ = nullptr;
+  dialog_view_ = nullptr;
   offer_dialog_callback_.Reset();
 }
 
diff --git a/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.h b/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.h
index 38970656..f51c2e4a 100644
--- a/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.h
+++ b/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.h
@@ -14,6 +14,7 @@
 namespace autofill {
 
 class WebauthnOfferDialogModel;
+class WebauthnOfferDialogView;
 
 // Implementation of the per-tab controller to control the
 // WebauthnOfferDialogView. Lazily initialized when used.
@@ -34,6 +35,8 @@
   void OnDialogClosed() override;
   content::WebContents* GetWebContents() override;
 
+  WebauthnOfferDialogView* dialog_view() { return dialog_view_; }
+
  protected:
   explicit WebauthnOfferDialogControllerImpl(
       content::WebContents* web_contents);
@@ -47,6 +50,7 @@
   AutofillClient::WebauthnOfferDialogCallback offer_dialog_callback_;
 
   WebauthnOfferDialogModel* dialog_model_ = nullptr;
+  WebauthnOfferDialogView* dialog_view_ = nullptr;
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
 
diff --git a/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_view.h b/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_view.h
index 5c18d5a..2244a40a 100644
--- a/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_view.h
+++ b/chrome/browser/ui/autofill/payments/webauthn_offer_dialog_view.h
@@ -15,8 +15,10 @@
 // model of the dialog.
 class WebauthnOfferDialogView {
  public:
-  static WebauthnOfferDialogModel* CreateAndShow(
+  static WebauthnOfferDialogView* CreateAndShow(
       WebauthnOfferDialogController* controller);
+
+  virtual WebauthnOfferDialogModel* GetDialogModel() const = 0;
 };
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index 9fb35d8e..be4545a3 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -309,6 +309,11 @@
   UpdateCommandsForBookmarkEditing();
 }
 
+void BrowserCommandController::TabKeyboardFocusChangedTo(
+    base::Optional<int> index) {
+  UpdateCommandsForTabKeyboardFocus(index);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // BrowserCommandController, CommandUpdater implementation:
 
@@ -742,6 +747,15 @@
       ShowSingletonTab(browser_, GURL(kChromeUIManagementURL));
       break;
     }
+    case IDC_MUTE_TARGET_SITE:
+      MuteSiteForKeyboardFocusedTab(browser_);
+      break;
+    case IDC_PIN_TARGET_TAB:
+      PinKeyboardFocusedTab(browser_);
+      break;
+    case IDC_DUPLICATE_TARGET_TAB:
+      DuplicateKeyboardFocusedTab(browser_);
+      break;
     // Hosted App commands
     case IDC_COPY_URL:
       CopyURL(browser_);
@@ -1026,6 +1040,7 @@
   UpdateCommandsForContentRestrictionState();
   UpdateCommandsForBookmarkEditing();
   UpdateCommandsForIncognitoAvailability();
+  UpdateCommandsForTabKeyboardFocus(GetKeyboardFocusedTabIndex(browser_));
 }
 
 // static
@@ -1132,6 +1147,7 @@
   UpdateCommandsForMediaRouter();
   // Update the zoom commands when an active tab is selected.
   UpdateCommandsForZoomState();
+  UpdateCommandsForTabKeyboardFocus(GetKeyboardFocusedTabIndex(browser_));
 }
 
 void BrowserCommandController::UpdateCommandsForZoomState() {
@@ -1428,6 +1444,19 @@
                                         CanRouteMedia(browser_));
 }
 
+void BrowserCommandController::UpdateCommandsForTabKeyboardFocus(
+    base::Optional<int> target_index) {
+  command_updater_.UpdateCommandEnabled(
+      IDC_DUPLICATE_TARGET_TAB, !browser_->deprecated_is_app() &&
+                                    target_index.has_value() &&
+                                    CanDuplicateTabAt(browser_, *target_index));
+  const bool normal_window = browser_->is_type_normal();
+  command_updater_.UpdateCommandEnabled(
+      IDC_MUTE_TARGET_SITE, normal_window && target_index.has_value());
+  command_updater_.UpdateCommandEnabled(
+      IDC_PIN_TARGET_TAB, normal_window && target_index.has_value());
+}
+
 void BrowserCommandController::AddInterstitialObservers(WebContents* contents) {
   interstitial_observers_.push_back(new InterstitialObserver(this, contents));
 }
diff --git a/chrome/browser/ui/browser_command_controller.h b/chrome/browser/ui/browser_command_controller.h
index 6c47091..eb075df 100644
--- a/chrome/browser/ui/browser_command_controller.h
+++ b/chrome/browser/ui/browser_command_controller.h
@@ -62,6 +62,7 @@
   void LoadingStateChanged(bool is_loading, bool force);
   void FindBarVisibilityChanged();
   void ExtensionStateChanged();
+  void TabKeyboardFocusChangedTo(base::Optional<int> index);
 
   // Overriden from CommandUpdater:
   bool SupportsCommand(int id) const override;
@@ -189,6 +190,11 @@
   // Updates commands for Media Router.
   void UpdateCommandsForMediaRouter();
 
+  // Updates commands for tab keyboard focus state. If |target_index| is
+  // populated, it is the index of the tab with focus; if it is not populated,
+  // no tab has keyboard focus.
+  void UpdateCommandsForTabKeyboardFocus(base::Optional<int> target_index);
+
   // Add/remove observers for interstitial attachment/detachment from
   // |contents|.
   void AddInterstitialObservers(content::WebContents* contents);
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index a6065e8..9fbbe31 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -717,6 +717,12 @@
   return CanDuplicateTabAt(browser, browser->tab_strip_model()->active_index());
 }
 
+bool CanDuplicateKeyboardFocusedTab(const Browser* browser) {
+  if (!HasKeyboardFocusedTab(browser))
+    return false;
+  return CanDuplicateTabAt(browser, *GetKeyboardFocusedTabIndex(browser));
+}
+
 WebContents* DuplicateTabAt(Browser* browser, int index) {
   WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(index);
   CHECK(contents);
@@ -791,6 +797,32 @@
       TabStripModel::ContextMenuCommand::CommandToggleSiteMuted);
 }
 
+void MuteSiteForKeyboardFocusedTab(Browser* browser) {
+  if (!HasKeyboardFocusedTab(browser))
+    return;
+  browser->tab_strip_model()->ExecuteContextMenuCommand(
+      *GetKeyboardFocusedTabIndex(browser),
+      TabStripModel::ContextMenuCommand::CommandToggleSiteMuted);
+}
+
+void PinKeyboardFocusedTab(Browser* browser) {
+  if (!HasKeyboardFocusedTab(browser))
+    return;
+  browser->tab_strip_model()->ExecuteContextMenuCommand(
+      *GetKeyboardFocusedTabIndex(browser),
+      TabStripModel::ContextMenuCommand::CommandTogglePinned);
+}
+
+void DuplicateKeyboardFocusedTab(Browser* browser) {
+  if (HasKeyboardFocusedTab(browser)) {
+    DuplicateTabAt(browser, *GetKeyboardFocusedTabIndex(browser));
+  }
+}
+
+bool HasKeyboardFocusedTab(const Browser* browser) {
+  return GetKeyboardFocusedTabIndex(browser).has_value();
+}
+
 void ConvertPopupToTabbedBrowser(Browser* browser) {
   base::RecordAction(UserMetricsAction("ShowAsTab"));
   TabStripModel* tab_strip = browser->tab_strip_model();
@@ -1331,4 +1363,10 @@
 }
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
+#if !defined(TOOLKIT_VIEWS)
+base::Optional<int> GetKeyboardFocusedTabIndex(const Browser* browser) {
+  return base::nullopt;
+}
+#endif
+
 }  // namespace chrome
diff --git a/chrome/browser/ui/browser_commands.h b/chrome/browser/ui/browser_commands.h
index 6ed382da..e3e4f27 100644
--- a/chrome/browser/ui/browser_commands.h
+++ b/chrome/browser/ui/browser_commands.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "base/optional.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/browser/devtools/devtools_toggle_action.h"
@@ -103,10 +104,15 @@
         TabStripModel::UserGestureDetails(TabStripModel::GestureType::kOther));
 void DuplicateTab(Browser* browser);
 bool CanDuplicateTab(const Browser* browser);
+bool CanDuplicateKeyboardFocusedTab(const Browser* browser);
 content::WebContents* DuplicateTabAt(Browser* browser, int index);
 bool CanDuplicateTabAt(const Browser* browser, int index);
 void MuteSite(Browser* browser);
 void PinTab(Browser* browser);
+void MuteSiteForKeyboardFocusedTab(Browser* browser);
+bool HasKeyboardFocusedTab(const Browser* browser);
+void PinKeyboardFocusedTab(Browser* browser);
+void DuplicateKeyboardFocusedTab(Browser* browser);
 void ConvertPopupToTabbedBrowser(Browser* browser);
 void Exit();
 void BookmarkCurrentTabIgnoringExtensionOverrides(Browser* browser);
@@ -180,6 +186,8 @@
                                              bool force_shortcut_app);
 bool CanCreateBookmarkApp(const Browser* browser);
 
+base::Optional<int> GetKeyboardFocusedTabIndex(const Browser* browser);
+
 }  // namespace chrome
 
 #endif  // CHROME_BROWSER_UI_BROWSER_COMMANDS_H_
diff --git a/chrome/browser/ui/cocoa/main_menu_builder.mm b/chrome/browser/ui/cocoa/main_menu_builder.mm
index 4d0dc2f..2e3f951 100644
--- a/chrome/browser/ui/cocoa/main_menu_builder.mm
+++ b/chrome/browser/ui/cocoa/main_menu_builder.mm
@@ -402,8 +402,20 @@
               Item(IDS_NEXT_TAB_MAC).command_id(IDC_SELECT_NEXT_TAB),
               Item(IDS_PREV_TAB_MAC).command_id(IDC_SELECT_PREVIOUS_TAB),
               Item(IDS_DUPLICATE_TAB_MAC).command_id(IDC_DUPLICATE_TAB),
+              Item(IDS_DUPLICATE_TARGET_TAB_MAC)
+                  .command_id(IDC_DUPLICATE_TARGET_TAB)
+                  .is_alternate()
+                  .key_equivalent(@"", NSAlternateKeyMask),
               Item(IDS_MUTE_SITE_MAC).command_id(IDC_WINDOW_MUTE_SITE),
+              Item(IDS_MUTE_TARGET_SITE_MAC)
+                  .command_id(IDC_MUTE_TARGET_SITE)
+                  .is_alternate()
+                  .key_equivalent(@"", NSAlternateKeyMask),
               Item(IDS_PIN_TAB_MAC).command_id(IDC_WINDOW_PIN_TAB),
+              Item(IDS_PIN_TARGET_TAB_MAC)
+                  .command_id(IDC_PIN_TARGET_TAB)
+                  .is_alternate()
+                  .key_equivalent(@"", NSAlternateKeyMask),
               Item().is_separator(),
           })
           .Build();
diff --git a/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_browsertest.cc b/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_browsertest.cc
new file mode 100644
index 0000000..13dc3e57
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_browsertest.cc
@@ -0,0 +1,86 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/run_loop.h"
+#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_controller_impl.h"
+#include "chrome/browser/ui/autofill/payments/webauthn_offer_dialog_view.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view_impl.h"
+#include "ui/views/window/dialog_client_view.h"
+
+namespace autofill {
+
+class WebauthnOfferDialogBrowserTest : public DialogBrowserTest {
+ public:
+  WebauthnOfferDialogBrowserTest() = default;
+
+  // DialogBrowserTest:
+  void ShowUi(const std::string& name) override {
+    content::WebContents* web_contents =
+        browser()->tab_strip_model()->GetActiveWebContents();
+
+    // Do lazy initialization of WebauthnOfferDialogControllerImpl.
+    WebauthnOfferDialogControllerImpl::CreateForWebContents(web_contents);
+    DCHECK(controller());
+    controller()->ShowOfferDialog(base::DoNothing());
+  }
+
+  WebauthnOfferDialogViewImpl* GetWebauthnOfferDialog() {
+    if (!controller())
+      return nullptr;
+
+    WebauthnOfferDialogView* dialog_view = controller()->dialog_view();
+    if (!dialog_view)
+      return nullptr;
+
+    return static_cast<WebauthnOfferDialogViewImpl*>(dialog_view);
+  }
+
+  WebauthnOfferDialogControllerImpl* controller() {
+    if (!browser() || !browser()->tab_strip_model() ||
+        !browser()->tab_strip_model()->GetActiveWebContents())
+      return nullptr;
+
+    return WebauthnOfferDialogControllerImpl::FromWebContents(
+        browser()->tab_strip_model()->GetActiveWebContents());
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebauthnOfferDialogBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(WebauthnOfferDialogBrowserTest, InvokeUi_default) {
+  ShowAndVerifyUi();
+}
+
+// Ensures closing tab while dialog being visible is correctly handled.
+// RunUntilIdle() makes sure that nothing crashes after browser tab is closed.
+IN_PROC_BROWSER_TEST_F(WebauthnOfferDialogBrowserTest,
+                       CanCloseTabWhileDialogShowing) {
+  ShowUi(std::string());
+  VerifyUi();
+  browser()->tab_strip_model()->GetActiveWebContents()->Close();
+  base::RunLoop().RunUntilIdle();
+}
+
+// Ensures closing browser while dialog being visible is correctly handled.
+IN_PROC_BROWSER_TEST_F(WebauthnOfferDialogBrowserTest,
+                       CanCloseBrowserWhileDialogShowing) {
+  ShowUi(std::string());
+  VerifyUi();
+  browser()->window()->Close();
+  base::RunLoop().RunUntilIdle();
+}
+
+// Ensures dialog is closed when cancel button is clicked.
+IN_PROC_BROWSER_TEST_F(WebauthnOfferDialogBrowserTest, ClickCancelButton) {
+  ShowUi(std::string());
+  VerifyUi();
+  GetWebauthnOfferDialog()->GetDialogClientView()->CancelWindow();
+  base::RunLoop().RunUntilIdle();
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view_impl.cc b/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view_impl.cc
index e56c9d9..3f15eb52 100644
--- a/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view_impl.cc
+++ b/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view_impl.cc
@@ -34,16 +34,24 @@
 
 WebauthnOfferDialogViewImpl::~WebauthnOfferDialogViewImpl() {
   model_->RemoveObserver(this);
+  if (controller_) {
+    controller_->OnDialogClosed();
+    controller_ = nullptr;
+  }
 }
 
 // static
-WebauthnOfferDialogModel* WebauthnOfferDialogView::CreateAndShow(
+WebauthnOfferDialogView* WebauthnOfferDialogView::CreateAndShow(
     WebauthnOfferDialogController* controller) {
   WebauthnOfferDialogViewImpl* dialog =
       new WebauthnOfferDialogViewImpl(controller);
   constrained_window::ShowWebModalDialogViews(dialog,
                                               controller->GetWebContents());
-  return dialog->model();
+  return dialog;
+}
+
+WebauthnOfferDialogModel* WebauthnOfferDialogViewImpl::GetDialogModel() const {
+  return model_;
 }
 
 void WebauthnOfferDialogViewImpl::OnDialogStateChanged() {
@@ -124,14 +132,14 @@
   return false;
 }
 
-void WebauthnOfferDialogViewImpl::WindowClosing() {
+void WebauthnOfferDialogViewImpl::Hide() {
+  // Reset controller reference if the controller has been destroyed before the
+  // view being destroyed. This happens if browser window is closed when the
+  // dialog is visible.
   if (controller_) {
     controller_->OnDialogClosed();
     controller_ = nullptr;
   }
-}
-
-void WebauthnOfferDialogViewImpl::Hide() {
   GetWidget()->Close();
 }
 
diff --git a/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view_impl.h b/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view_impl.h
index 8fc7629..5a7bb5f 100644
--- a/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view_impl.h
+++ b/chrome/browser/ui/views/autofill/payments/webauthn_offer_dialog_view_impl.h
@@ -28,6 +28,9 @@
       WebauthnOfferDialogController* controller);
   ~WebauthnOfferDialogViewImpl() override;
 
+  // WebauthnOfferDialogView:
+  WebauthnOfferDialogModel* GetDialogModel() const override;
+
   // WebauthnOfferDialogModelObserver:
   void OnDialogStateChanged() override;
 
@@ -43,9 +46,7 @@
   base::string16 GetWindowTitle() const override;
   bool ShouldShowWindowTitle() const override;
   bool ShouldShowCloseButton() const override;
-  void WindowClosing() override;
 
-  WebauthnOfferDialogModel* model() { return model_; }
 
  private:
   // Closes the dialog.
diff --git a/chrome/browser/ui/views/browser_commands_views.cc b/chrome/browser/ui/views/browser_commands_views.cc
new file mode 100644
index 0000000..5a74128
--- /dev/null
+++ b/chrome/browser/ui/views/browser_commands_views.cc
@@ -0,0 +1,18 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/tabs/tab_strip.h"
+
+namespace chrome {
+
+base::Optional<int> GetKeyboardFocusedTabIndex(const Browser* browser) {
+  BrowserView* view = BrowserView::GetBrowserViewForBrowser(browser);
+  if (view && view->tabstrip())
+    return view->tabstrip()->GetFocusedTabIndex();
+  return base::nullopt;
+}
+
+}  // namespace chrome
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
index ab775e7..654c318ff 100644
--- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
+++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
@@ -32,6 +32,7 @@
 #include "ui/display/win/screen_win.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/icon_util.h"
+#include "ui/gfx/image/image_family.h"
 #include "ui/views/controls/menu/native_menu_win.h"
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 1a53315..22134474 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -455,7 +455,10 @@
   //
   // Also, tests don't always have a non-null NativeWindow backing the
   // BrowserWindow, so be sure to check for that as well.
-  if (!browser->window()->GetNativeWindow())
+  //
+  // Lastly note that this function can be called during construction of
+  // Browser, at which point browser->window() might return nullptr.
+  if (!browser->window() || !browser->window()->GetNativeWindow())
     return nullptr;
   return GetBrowserViewForNativeWindow(browser->window()->GetNativeWindow());
 }
@@ -486,6 +489,11 @@
   if (!browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP))
     return false;
 
+#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
+  if (base::FeatureList::IsEnabled(features::kWebUITabStrip))
+    return false;
+#endif  // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
+
   // Return false if the tabstrip has not yet been created (by InitViews()),
   // since callers may otherwise try to access it. Note that we can't just check
   // this alone, as the tabstrip is created unconditionally even for windows
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index 15e6ac4..d692a98 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/favicon/favicon_utils.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help.h"
@@ -393,6 +394,12 @@
     source_browser_view->TabDraggingStatusChanged(/*is_dragging=*/false);
 }
 
+void BrowserTabStripController::OnKeyboardFocusedTabChanged(
+    base::Optional<int> index) {
+  browser_view_->browser()->command_controller()->TabKeyboardFocusChangedTo(
+      index);
+}
+
 const TabGroupVisualData* BrowserTabStripController::GetVisualDataForGroup(
     TabGroupId group) const {
   return model_->GetVisualDataForGroup(group);
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
index 2937577..d6e0563 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -72,6 +72,7 @@
   void StackedLayoutMaybeChanged() override;
   void OnStartedDraggingTabs() override;
   void OnStoppedDraggingTabs() override;
+  void OnKeyboardFocusedTabChanged(base::Optional<int> index) override;
   const TabGroupVisualData* GetVisualDataForGroup(
       TabGroupId group_id) const override;
   void SetVisualDataForGroup(TabGroupId group,
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
index 1409527..77c03cda 100644
--- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
@@ -179,6 +179,9 @@
 
 void FakeBaseTabStripController::OnStoppedDraggingTabs() {}
 
+void FakeBaseTabStripController::OnKeyboardFocusedTabChanged(
+    base::Optional<int> index) {}
+
 bool FakeBaseTabStripController::IsFrameCondensed() const {
   return false;
 }
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
index 6761bbd..44bfaf19 100644
--- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
@@ -56,6 +56,7 @@
   void StackedLayoutMaybeChanged() override;
   void OnStartedDraggingTabs() override;
   void OnStoppedDraggingTabs() override;
+  void OnKeyboardFocusedTabChanged(base::Optional<int> index) override;
   const TabGroupVisualData* GetVisualDataForGroup(
       TabGroupId group_id) const override;
   void SetVisualDataForGroup(TabGroupId group,
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index caf3eb5..f073004f 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -975,6 +975,7 @@
 
   Tab* tab = new Tab(this);
   tab->set_context_menu_controller(&context_menu_controller_);
+  tab->AddObserver(this);
   AddChildViewAt(tab, view_index);
   const bool pinned = data.pinned;
   tabs_.Add(tab, model_index);
@@ -1388,6 +1389,14 @@
     CompleteAnimationAndLayout();
 }
 
+base::Optional<int> TabStrip::GetFocusedTabIndex() const {
+  for (int i = 0; i < tabs_.view_size(); ++i) {
+    if (tabs_.view_at(i)->HasFocus())
+      return i;
+  }
+  return base::nullopt;
+}
+
 const ui::ListSelectionModel& TabStrip::GetSelectionModel() const {
   return controller_->GetSelectionModel();
 }
@@ -3209,6 +3218,13 @@
 void TabStrip::OnViewFocused(views::View* observed_view) {
   if (observed_view == new_tab_button_)
     UpdateHoverCard(nullptr);
+  int index = tabs_.GetIndexOfView(observed_view);
+  if (index != -1)
+    controller_->OnKeyboardFocusedTabChanged(index);
+}
+
+void TabStrip::OnViewBlurred(views::View* observed_view) {
+  controller_->OnKeyboardFocusedTabChanged(base::nullopt);
 }
 
 void TabStrip::OnTouchUiChanged() {
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index c78603a5..d2ae1e8f 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -234,6 +234,9 @@
   // ongoing this does a layout.
   void StopAnimating(bool layout);
 
+  // Returns the index of the focused tab, if any.
+  base::Optional<int> GetFocusedTabIndex() const;
+
   // TabController:
   const ui::ListSelectionModel& GetSelectionModel() const override;
   bool SupportsMultipleSelection() override;
@@ -588,6 +591,7 @@
   // views::ViewObserver:
   void OnViewIsDeleting(views::View* observed_view) override;
   void OnViewFocused(views::View* observed_view) override;
+  void OnViewBlurred(views::View* observed_view) override;
 
   // views::WidgetObserver:
   void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h
index 1dc2b5c..81e8dc9 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h
@@ -115,6 +115,10 @@
   // from this tabstrip but the user is still dragging the tabs.
   virtual void OnStoppedDraggingTabs() = 0;
 
+  // Notifies controller that the index of the tab with keyboard focus changed
+  // to |index|.
+  virtual void OnKeyboardFocusedTabChanged(base::Optional<int> index) = 0;
+
   // Returns the TabGroupVisualData instance for the given |group|.
   virtual const TabGroupVisualData* GetVisualDataForGroup(
       TabGroupId group) const = 0;
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 9a3f688..9686cf2 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -387,22 +387,20 @@
   if (settings.FindKey(kSettingCloudPrintId))
     return PRINT_WITH_CLOUD_PRINT;
 
-  base::Optional<int> type_raw = settings.FindIntKey(kSettingPrinterType);
-  if (type_raw.has_value()) {
-    PrinterType type = static_cast<PrinterType>(type_raw.value());
-    switch (type) {
-      case kPrivetPrinter:
-        return PRINT_WITH_PRIVET;
-      case kExtensionPrinter:
-        return PRINT_WITH_EXTENSION;
-      case kPdfPrinter:
-        return PRINT_TO_PDF;
-      case kLocalPrinter:
-        break;
-      default:
-        NOTREACHED();
-        break;
-    }
+  PrinterType type = static_cast<PrinterType>(
+      settings.FindIntKey(kSettingPrinterType).value());
+  switch (type) {
+    case kPrivetPrinter:
+      return PRINT_WITH_PRIVET;
+    case kExtensionPrinter:
+      return PRINT_WITH_EXTENSION;
+    case kPdfPrinter:
+      return PRINT_TO_PDF;
+    case kLocalPrinter:
+      break;
+    default:
+      NOTREACHED();
+      break;
   }
 
   if (settings.FindBoolKey(kSettingShowSystemDialog).value_or(false))
diff --git a/chrome/browser/ui/webui/welcome/ntp_background_fetcher.cc b/chrome/browser/ui/webui/welcome/ntp_background_fetcher.cc
index 33ff488..9a5026c 100644
--- a/chrome/browser/ui/webui/welcome/ntp_background_fetcher.cc
+++ b/chrome/browser/ui/webui/welcome/ntp_background_fetcher.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/memory/ref_counted_memory.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/search/background/ntp_backgrounds.h"
diff --git a/chrome/browser/win/conflicts/inspection_results_cache.h b/chrome/browser/win/conflicts/inspection_results_cache.h
index 297491e..4c74d002 100644
--- a/chrome/browser/win/conflicts/inspection_results_cache.h
+++ b/chrome/browser/win/conflicts/inspection_results_cache.h
@@ -42,7 +42,7 @@
 };
 
 constexpr base::Feature kInspectionResultsCache{
-    "InspectionResultsCache", base::FEATURE_DISABLED_BY_DEFAULT};
+    "InspectionResultsCache", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // The InspectionResultsCache maps ModuleInfoKey to a ModuleInspectionResult.
 // The uint32_t is a time stamp that keep tracks of when the inspection result
diff --git a/chrome/browser/win/conflicts/module_database.cc b/chrome/browser/win/conflicts/module_database.cc
index 840400b..bbbf598 100644
--- a/chrome/browser/win/conflicts/module_database.cc
+++ b/chrome/browser/win/conflicts/module_database.cc
@@ -124,7 +124,7 @@
 // static
 scoped_refptr<base::SequencedTaskRunner> ModuleDatabase::GetTaskRunner() {
   static constexpr base::Feature kDistinctModuleDatabaseSequence{
-      "DistinctModuleDatabaseSequence", base::FEATURE_DISABLED_BY_DEFAULT};
+      "DistinctModuleDatabaseSequence", base::FEATURE_ENABLED_BY_DEFAULT};
 
   static base::LazySequencedTaskRunner g_ui_task_runner =
       LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index a3519c85..c0e0887 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -35,6 +35,7 @@
 buildflag_header("buildflags") {
   header = "buildflags.h"
   flags = [
+    "BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED=$builtin_cert_verifier_policy_supported",
     "ENABLE_APP_LIST=$enable_app_list",
     "ENABLE_BACKGROUND_MODE=$enable_background_mode",
     "ENABLE_BACKGROUND_CONTENTS=$enable_background_contents",
diff --git a/chrome/common/features.gni b/chrome/common/features.gni
index 0eab01b..648d427 100644
--- a/chrome/common/features.gni
+++ b/chrome/common/features.gni
@@ -21,6 +21,14 @@
 
 # Please keep features in alphabetical order.
 declare_args() {
+  # Platforms where the BuiltinCertificateVerifierEnabled enterprise policy is
+  # supported. This must must match the supported_on list of the policy in
+  # policy_templates.json and be a subset of the
+  # builtin_cert_verifier_feature_supported platforms.
+  # See crbug.com/410574.  This can be removed when the builtin verifier is
+  # unconditionally enabled on all platforms.
+  builtin_cert_verifier_policy_supported = is_chromeos || is_desktop_linux
+
   enable_app_list = is_chromeos
 
   # Enables support for background apps.
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 5ff3de2..e3fe236 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -2782,7 +2782,9 @@
 // Controlled by CACertificateManagementAllowed policy.
 const char kCACertificateManagementAllowed[] =
     "ca_certificate_management_allowed";
+#endif
 
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
 // Boolean that specifies whether the built-in certificate verifier should be
 // used. If false, Chrome will use the platform certificate verifier. If not
 // set, Chrome will choose the certificate verifier based on experiments.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 0e527a8..1d4de514 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -977,6 +977,9 @@
 #if defined(OS_CHROMEOS)
 extern const char kClientCertificateManagementAllowed[];
 extern const char kCACertificateManagementAllowed[];
+#endif
+
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
 extern const char kBuiltinCertificateVerifierEnabled[];
 #endif
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 13a6f569..3fcd37a4 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1193,7 +1193,6 @@
       "../browser/ui/autofill/payments/card_unmask_prompt_view_browsertest.cc",
       "../browser/ui/autofill/payments/card_unmask_prompt_view_tester.h",
       "../browser/ui/autofill/payments/save_card_bubble_controller_impl_browsertest.cc",
-      "../browser/ui/autofill/payments/webauthn_offer_dialog_browsertest.cc",
       "../browser/ui/bookmarks/bookmark_browsertest.cc",
       "../browser/ui/browser_browsertest.cc",
       "../browser/ui/browser_command_controller_browsertest.cc",
@@ -1850,6 +1849,7 @@
         "../browser/ui/views/autofill/payments/card_unmask_prompt_view_tester_views.h",
         "../browser/ui/views/autofill/payments/local_card_migration_browsertest.cc",
         "../browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc",
+        "../browser/ui/views/autofill/payments/webauthn_offer_dialog_browsertest.cc",
         "../browser/ui/views/bookmarks/bookmark_bubble_view_browsertest.cc",
         "../browser/ui/views/bookmarks/bookmark_editor_view_browsertest.cc",
         "../browser/ui/views/certificate_selector_dialog_browsertest.cc",
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc
index 514c239..bbd1316 100644
--- a/chrome/test/base/testing_browser_process.cc
+++ b/chrome/test/base/testing_browser_process.cc
@@ -420,11 +420,6 @@
   return resource_coordinator_parts()->tab_manager();
 }
 
-shell_integration::DefaultWebClientState
-TestingBrowserProcess::CachedDefaultWebClientState() {
-  return shell_integration::UNKNOWN_DEFAULT;
-}
-
 void TestingBrowserProcess::SetSharedURLLoaderFactory(
     scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory) {
   shared_url_loader_factory_ = shared_url_loader_factory;
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h
index 4e631b2..808be62 100644
--- a/chrome/test/base/testing_browser_process.h
+++ b/chrome/test/base/testing_browser_process.h
@@ -135,8 +135,6 @@
   resource_coordinator::TabManager* GetTabManager() override;
   resource_coordinator::ResourceCoordinatorParts* resource_coordinator_parts()
       override;
-  shell_integration::DefaultWebClientState CachedDefaultWebClientState()
-      override;
 
   // Set the local state for tests. Consumer is responsible for cleaning it up
   // afterwards (using ScopedTestingLocalState, for example).
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_websocket.js b/chrome/test/data/extensions/api_test/webrequest/test_websocket.js
index ccd942e..4a0e330 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_websocket.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_websocket.js
@@ -200,6 +200,43 @@
       testWebSocketConnection(url, true /* expectedToConnect */);
     },
 
+    // Tries to open a WebSocket connection, with a blocking handler that
+    // cancels the request. The connection will not be established.
+    function handshakeRequestCancelledWithExtraHeaders() {
+      var url = getWSTestURL(testWebSocketPort);
+      expect(
+        [  // events
+          { label: 'onBeforeRequest',
+            event: 'onBeforeRequest',
+            details: {
+              url: url,
+              type: 'websocket',
+              frameUrl: 'unknown frame URL',
+              initiator: getDomain(initiators.WEB_INITIATED)
+            },
+            retval: {cancel: true}
+          },
+          // Cancelling is considered an error.
+          { label: 'onErrorOccurred',
+            event: 'onErrorOccurred',
+            details: {
+              url: url,
+              type: 'websocket',
+              fromCache: false,
+              initiator: getDomain(initiators.WEB_INITIATED),
+              error: 'net::ERR_BLOCKED_BY_CLIENT'
+            }
+          },
+        ],
+        [  // event order
+          ['onBeforeRequest', 'onErrorOccurred']
+        ],
+        {urls: ['ws://*/*']},  // filter
+        ['blocking', 'extraHeaders']  // extraInfoSpec
+      );
+      testWebSocketConnection(url, false /* expectedToConnect */);
+    },
+
     // Tests that all the requests headers that are added by net/ are visible
     // if extraHeaders is specified.
     function testExtraRequestHeadersVisible() {
diff --git a/chrome/test/data/local_ntp/realbox_browsertest.js b/chrome/test/data/local_ntp/realbox_browsertest.js
index c18732e..6d7586c0c 100644
--- a/chrome/test/data/local_ntp/realbox_browsertest.js
+++ b/chrome/test/data/local_ntp/realbox_browsertest.js
@@ -564,10 +564,15 @@
   assertEquals(1, test.realbox.deletedLines.length);
   assertEquals(1, test.realbox.deletedLines[0]);
 
+  matchesEl.children[1].focus();
+  assertEquals(matchesEl.children[1], document.activeElement);
+
   chrome.embeddedSearch.searchBox.ondeleteautocompletematch(
       {success: true, matches: [test.realbox.getSearchMatch()]});
 
-  assertEquals(1, $(test.realbox.IDS.REALBOX_MATCHES).children.length);
+  const newMatchesEl = $(test.realbox.IDS.REALBOX_MATCHES);
+  assertEquals(1, newMatchesEl.children.length);
+  assertEquals(newMatchesEl.children[0], document.activeElement);
 };
 
 test.realbox.testRemoveIcon = function() {
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 69e49a5..b04afc4 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -938,7 +938,7 @@
   },
 
   "BuiltinCertificateVerifierEnabled": {
-    "os": ["chromeos"],
+    "os": ["chromeos", "linux"],
     "test_policy": { "BuiltinCertificateVerifierEnabled": true },
     "pref_mappings": [
       { "pref": "builtin_certificate_verifier_enabled",
@@ -3868,6 +3868,10 @@
     "pref_mappings": [{ "pref": "browser.shared_clipboard_enabled" }]
   },
 
+  "AudioSandboxEnabled": {
+    "note": "This policy is used directly through the policy service instead of through a pref."
+  },
+
   "----- Chrome OS device policies ---------------------------------------": {},
 
   "DevicePolicyRefreshRate": {
diff --git a/chrome/test/data/webui/signin/signin_browsertest.js b/chrome/test/data/webui/signin/signin_browsertest.js
index 3b7999b..90ac93e 100644
--- a/chrome/test/data/webui/signin/signin_browsertest.js
+++ b/chrome/test/data/webui/signin/signin_browsertest.js
@@ -23,11 +23,6 @@
   }
 
   /** @override */
-  testGenPreamble() {
-    GEN('  EnableUnity();');
-  }
-
-  /** @override */
   get browsePreload() {
     return 'chrome://sync-confirmation/sync_confirmation_app.html';
   }
diff --git a/chrome/test/data/webui/signin_browsertest.cc b/chrome/test/data/webui/signin_browsertest.cc
index 7c320784..508906cb 100644
--- a/chrome/test/data/webui/signin_browsertest.cc
+++ b/chrome/test/data/webui/signin_browsertest.cc
@@ -7,7 +7,9 @@
 #include "chrome/browser/signin/scoped_account_consistency.h"
 #include "components/unified_consent/scoped_unified_consent.h"
 
-SigninBrowserTest::SigninBrowserTest() {}
+SigninBrowserTest::SigninBrowserTest() {
+  EnableUnity();
+}
 
 SigninBrowserTest::~SigninBrowserTest() {}
 
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index fbca0e4..7501a8c 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -13,6 +13,7 @@
 #include "base/command_line.h"
 #include "base/files/scoped_file.h"
 #include "base/i18n/rtl.h"
+#include "base/message_loop/message_pump_type.h"
 #include "base/path_service.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -265,6 +266,8 @@
   if (!media_thread_) {
     media_thread_.reset(new base::Thread("CastMediaThread"));
     base::Thread::Options options;
+    // We need the media thread to be IO-capable to use the mixer service.
+    options.message_pump_type = base::MessagePumpType::IO;
     options.priority = base::ThreadPriority::REALTIME_AUDIO;
     CHECK(media_thread_->StartWithOptions(options));
     // Start the media_resource_tracker as soon as the media thread is created.
diff --git a/chromecast/media/audio/mixer_service/BUILD.gn b/chromecast/media/audio/mixer_service/BUILD.gn
index 3ecc884a..5407f22 100644
--- a/chromecast/media/audio/mixer_service/BUILD.gn
+++ b/chromecast/media/audio/mixer_service/BUILD.gn
@@ -68,6 +68,22 @@
   ]
 }
 
+cast_source_set("control_connection") {
+  sources = [
+    "control_connection.cc",
+    "control_connection.h",
+  ]
+
+  deps = [
+    ":common",
+    ":connection",
+    ":proto",
+    "//base",
+    "//chromecast/public",
+    "//net",
+  ]
+}
+
 cast_source_set("audio_socket_service") {
   sources = [
     "audio_socket_service.cc",
diff --git a/chromecast/media/audio/mixer_service/control_connection.cc b/chromecast/media/audio/mixer_service/control_connection.cc
new file mode 100644
index 0000000..375f5272
--- /dev/null
+++ b/chromecast/media/audio/mixer_service/control_connection.cc
@@ -0,0 +1,159 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/audio/mixer_service/control_connection.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "chromecast/media/audio/mixer_service/conversions.h"
+#include "chromecast/media/audio/mixer_service/mixer_service.pb.h"
+#include "net/socket/stream_socket.h"
+
+namespace chromecast {
+namespace media {
+namespace mixer_service {
+
+ControlConnection::ControlConnection() = default;
+
+ControlConnection::~ControlConnection() = default;
+
+void ControlConnection::Connect(ConnectedCallback callback) {
+  connect_callback_ = std::move(callback);
+  MixerConnection::Connect();
+}
+
+void ControlConnection::SetVolume(AudioContentType type,
+                                  float volume_multiplier) {
+  if (type == AudioContentType::kOther) {
+    return;
+  }
+
+  volume_[type] = volume_multiplier;
+  if (socket_) {
+    Generic message;
+    auto* volume = message.mutable_set_device_volume();
+    volume->set_content_type(ConvertContentType(type));
+    volume->set_volume_multiplier(volume_multiplier);
+    socket_->SendProto(message);
+  }
+}
+
+void ControlConnection::SetMuted(AudioContentType type, bool muted) {
+  if (type == AudioContentType::kOther) {
+    return;
+  }
+
+  muted_[type] = muted;
+  if (socket_) {
+    Generic message;
+    auto* muted = message.mutable_set_device_muted();
+    muted->set_content_type(ConvertContentType(type));
+    muted->set_muted(muted);
+    socket_->SendProto(message);
+  }
+}
+
+void ControlConnection::SetVolumeLimit(AudioContentType type,
+                                       float max_volume_multiplier) {
+  if (type == AudioContentType::kOther) {
+    return;
+  }
+
+  volume_limit_[type] = max_volume_multiplier;
+  if (socket_) {
+    Generic message;
+    auto* limit = message.mutable_set_volume_limit();
+    limit->set_content_type(ConvertContentType(type));
+    limit->set_max_volume_multiplier(max_volume_multiplier);
+    socket_->SendProto(message);
+  }
+}
+
+void ControlConnection::ConfigurePostprocessor(const std::string& name,
+                                               const void* config,
+                                               int size_bytes) {
+  if (!socket_) {
+    return;
+  }
+  Generic message;
+  auto* content = message.mutable_configure_postprocessor();
+  content->set_name(name);
+  content->set_config(static_cast<const char*>(config), size_bytes);
+  socket_->SendProto(message);
+}
+
+void ControlConnection::ReloadPostprocessors() {
+  if (!socket_) {
+    return;
+  }
+  Generic message;
+  message.mutable_reload_postprocessors();
+  socket_->SendProto(message);
+}
+
+void ControlConnection::SetStreamCountCallback(StreamCountCallback callback) {
+  stream_count_callback_ = std::move(callback);
+  if (socket_) {
+    Generic message;
+    message.mutable_request_stream_count()->set_subscribe(!callback.is_null());
+    socket_->SendProto(message);
+  }
+}
+
+void ControlConnection::OnConnected(std::unique_ptr<net::StreamSocket> socket) {
+  socket_ = std::make_unique<MixerSocket>(std::move(socket), this);
+  socket_->ReceiveMessages();
+
+  for (const auto& item : volume_limit_) {
+    Generic message;
+    auto* limit = message.mutable_set_volume_limit();
+    limit->set_content_type(ConvertContentType(item.first));
+    limit->set_max_volume_multiplier(item.second);
+    socket_->SendProto(message);
+  }
+
+  for (const auto& item : muted_) {
+    Generic message;
+    auto* muted = message.mutable_set_device_muted();
+    muted->set_content_type(ConvertContentType(item.first));
+    muted->set_muted(item.second);
+    socket_->SendProto(message);
+  }
+
+  for (const auto& item : volume_) {
+    Generic message;
+    auto* volume = message.mutable_set_device_volume();
+    volume->set_content_type(ConvertContentType(item.first));
+    volume->set_volume_multiplier(item.second);
+    socket_->SendProto(message);
+  }
+
+  if (stream_count_callback_) {
+    Generic message;
+    message.mutable_request_stream_count()->set_subscribe(true);
+    socket_->SendProto(message);
+  }
+
+  if (connect_callback_) {
+    connect_callback_.Run();
+  }
+}
+
+void ControlConnection::OnConnectionError() {
+  socket_.reset();
+  MixerConnection::Connect();
+}
+
+bool ControlConnection::HandleMetadata(const Generic& message) {
+  if (stream_count_callback_ && message.has_stream_count()) {
+    stream_count_callback_.Run(message.stream_count().primary(),
+                               message.stream_count().sfx());
+  }
+  return true;
+}
+
+}  // namespace mixer_service
+}  // namespace media
+}  // namespace chromecast
diff --git a/chromecast/media/audio/mixer_service/control_connection.h b/chromecast/media/audio/mixer_service/control_connection.h
new file mode 100644
index 0000000..850dc4f9
--- /dev/null
+++ b/chromecast/media/audio/mixer_service/control_connection.h
@@ -0,0 +1,97 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_AUDIO_MIXER_SERVICE_CONTROL_CONNECTION_H_
+#define CHROMECAST_MEDIA_AUDIO_MIXER_SERVICE_CONTROL_CONNECTION_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/macros.h"
+#include "chromecast/media/audio/mixer_service/mixer_connection.h"
+#include "chromecast/media/audio/mixer_service/mixer_socket.h"
+#include "chromecast/public/volume_control.h"
+
+namespace net {
+class StreamSocket;
+}  // namespace net
+
+namespace chromecast {
+namespace media {
+namespace mixer_service {
+
+// Mixer service connection for controlling general mixer properties, such as
+// device volume and postprocessor configuration. Not thread-safe; all usage of
+// a given instance must be on the same sequence. Must be created on an IO
+// thread.
+class ControlConnection : public MixerConnection, public MixerSocket::Delegate {
+ public:
+  using ConnectedCallback = base::RepeatingClosure;
+
+  // Callback to receive mixer stream count changes.
+  using StreamCountCallback =
+      base::RepeatingCallback<void(int primary_streams, int sfx_streams)>;
+
+  ControlConnection();
+  ~ControlConnection() override;
+
+  // Connects to the mixer. If the mixer connection is lost, this will
+  // automatically reconnect. If |callback| is nonempty, it will be called each
+  // time a connection is (re)established with the mixer. This can be used to
+  // re-send preprocessor configuration, since it is not persisted across
+  // disconnects.
+  void Connect(ConnectedCallback callback = ConnectedCallback());
+
+  // Sets volume multiplier for all streams of a given content type.
+  void SetVolume(AudioContentType type, float volume_multiplier);
+
+  // Sets mute state all streams of a given content type.
+  void SetMuted(AudioContentType type, bool muted);
+
+  // Sets the maximum effective volume multiplier for a given content type.
+  void SetVolumeLimit(AudioContentType type, float max_volume_multiplier);
+
+  // Sends arbitrary config data to a specific postprocessor. Note that the
+  // config is not persisted across disconnects, and is not saved if
+  // ConfigurePostprocessor() is called when not connected to the mixer, so
+  // use the Connect() callback to determine when to (re)send config, if needed.
+  void ConfigurePostprocessor(const std::string& name,
+                              const void* config,
+                              int size_bytes);
+
+  // Instructs the mixer to reload postprocessors based on the config file.
+  void ReloadPostprocessors();
+
+  // Sets a callback to receive mixer stream count changes. |callback| may be an
+  // empty callback to remove it.
+  void SetStreamCountCallback(StreamCountCallback callback);
+
+ private:
+  // MixerConnection implementation:
+  void OnConnected(std::unique_ptr<net::StreamSocket> socket) override;
+  void OnConnectionError() override;
+
+  // MixerSocket::Delegate implementation:
+  bool HandleMetadata(const Generic& message) override;
+
+  std::unique_ptr<MixerSocket> socket_;
+
+  ConnectedCallback connect_callback_;
+
+  base::flat_map<AudioContentType, float> volume_;
+  base::flat_map<AudioContentType, bool> muted_;
+  base::flat_map<AudioContentType, float> volume_limit_;
+
+  StreamCountCallback stream_count_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(ControlConnection);
+};
+
+}  // namespace mixer_service
+}  // namespace media
+}  // namespace chromecast
+
+#endif  // CHROMECAST_MEDIA_AUDIO_MIXER_SERVICE_CONTROL_CONNECTION_H_
diff --git a/chromecast/media/audio/mixer_service/mixer_connection.cc b/chromecast/media/audio/mixer_service/mixer_connection.cc
index f8218cd..28abbda 100644
--- a/chromecast/media/audio/mixer_service/mixer_connection.cc
+++ b/chromecast/media/audio/mixer_service/mixer_connection.cc
@@ -84,6 +84,7 @@
 
   connection_timeout_.Stop();
   if (result == net::OK) {
+    LOG_IF(INFO, !log_timeout_) << "Now connected to mixer service";
     log_connection_failure_ = true;
     log_timeout_ = true;
     OnConnected(std::move(connecting_socket_));
diff --git a/chromecast/media/audio/mixer_service/mixer_service.proto b/chromecast/media/audio/mixer_service/mixer_service.proto
index 40d2b58..ee5d191e 100644
--- a/chromecast/media/audio/mixer_service/mixer_service.proto
+++ b/chromecast/media/audio/mixer_service/mixer_service.proto
@@ -155,6 +155,17 @@
 // Instructs the mixer to reload postprocessors based on the config file.
 message ReloadPostprocessors {}
 
+// Asks the mixer to send / stop sending stream count updates.
+message RequestStreamCount {
+  optional bool subscribe = 1;
+}
+
+// Indicates how many output streams are currently being handled by the mixer.
+message StreamCount {
+  optional int32 primary = 1;
+  optional int32 sfx = 2;
+}
+
 // Indicates an error on an audio stream.
 message Error {
   enum Type {
@@ -183,5 +194,7 @@
   optional SetVolumeLimit set_volume_limit = 15;
   optional ConfigurePostprocessor configure_postprocessor = 16;
   optional ReloadPostprocessors reload_postprocessors = 17;
-  optional Error error = 18;
+  optional RequestStreamCount request_stream_count = 18;
+  optional StreamCount stream_count = 19;
+  optional Error error = 20;
 }
diff --git a/chromecast/media/audio/mixer_service/mixer_socket.cc b/chromecast/media/audio/mixer_service/mixer_socket.cc
index 50512ac..1189c13 100644
--- a/chromecast/media/audio/mixer_service/mixer_socket.cc
+++ b/chromecast/media/audio/mixer_service/mixer_socket.cc
@@ -11,6 +11,7 @@
 #include "base/big_endian.h"
 #include "base/logging.h"
 #include "chromecast/media/audio/mixer_service/constants.h"
+#include "chromecast/media/audio/mixer_service/mixer_service.pb.h"
 #include "net/base/io_buffer.h"
 #include "net/socket/stream_socket.h"
 
diff --git a/chromecast/media/audio/mixer_service/mixer_socket.h b/chromecast/media/audio/mixer_service/mixer_socket.h
index 7d370fa..3a7c9b76 100644
--- a/chromecast/media/audio/mixer_service/mixer_socket.h
+++ b/chromecast/media/audio/mixer_service/mixer_socket.h
@@ -11,9 +11,14 @@
 
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
-#include "chromecast/media/audio/mixer_service/mixer_service.pb.h"
 #include "chromecast/net/small_message_socket.h"
 
+namespace google {
+namespace protobuf {
+class MessageLite;
+}  // namespace protobuf
+}  // namespace google
+
 namespace net {
 class IOBuffer;
 class StreamSocket;
@@ -22,6 +27,7 @@
 namespace chromecast {
 namespace media {
 namespace mixer_service {
+class Generic;
 
 // Base class for sending and receiving messages to/from the mixer service.
 // Not thread-safe; all usage of a given instance must be on the same sequence.
diff --git a/chromecast/media/audio/mixer_service/output_stream_connection.cc b/chromecast/media/audio/mixer_service/output_stream_connection.cc
index e740b7a..15e7b3f5 100644
--- a/chromecast/media/audio/mixer_service/output_stream_connection.cc
+++ b/chromecast/media/audio/mixer_service/output_stream_connection.cc
@@ -154,7 +154,7 @@
 
 void OutputStreamConnection::OnConnectionError() {
   socket_.reset();
-  Connect();
+  MixerConnection::Connect();
 }
 
 bool OutputStreamConnection::HandleMetadata(const Generic& message) {
diff --git a/chromecast/media/audio/mixer_service/receiver/receiver.cc b/chromecast/media/audio/mixer_service/receiver/receiver.cc
index 53a9700..64a6365 100644
--- a/chromecast/media/audio/mixer_service/receiver/receiver.cc
+++ b/chromecast/media/audio/mixer_service/receiver/receiver.cc
@@ -61,7 +61,8 @@
                message.has_set_device_muted() ||
                message.has_set_volume_limit() ||
                message.has_configure_postprocessor() ||
-               message.has_reload_postprocessors()) {
+               message.has_reload_postprocessors() ||
+               message.has_request_stream_count()) {
       receiver_->CreateControlConnection(std::move(socket_), message);
       receiver_->RemoveInitialSocket(this);
     }
diff --git a/chromecast/media/base/audio_device_ids.cc b/chromecast/media/base/audio_device_ids.cc
index c0aeec2..856a767 100644
--- a/chromecast/media/base/audio_device_ids.cc
+++ b/chromecast/media/base/audio_device_ids.cc
@@ -12,6 +12,7 @@
 const char kAlarmAudioDeviceId[] = "assistant-alarm";
 const char kTtsAudioDeviceId[] = "assistant-tts";
 const char kBypassAudioDeviceId[] = "bypass";
+const char kNoDelayDeviceId[] = "no_delay";
 
 }  // namespace media
 }  // namespace chromecast
diff --git a/chromecast/media/base/audio_device_ids.h b/chromecast/media/base/audio_device_ids.h
index 73e0423..ca48b8b 100644
--- a/chromecast/media/base/audio_device_ids.h
+++ b/chromecast/media/base/audio_device_ids.h
@@ -15,6 +15,8 @@
 
 extern const char kAlarmAudioDeviceId[];
 
+extern const char kNoDelayDeviceId[];
+
 // TODO(kmackay|bshaya) Remove this, just use
 // ::media::AudioDeviceDescription::kCommunicationsDeviceId.
 extern const char kTtsAudioDeviceId[];
diff --git a/chromecast/media/cma/backend/BUILD.gn b/chromecast/media/cma/backend/BUILD.gn
index 7072580..83ab530 100644
--- a/chromecast/media/cma/backend/BUILD.gn
+++ b/chromecast/media/cma/backend/BUILD.gn
@@ -43,6 +43,13 @@
     "//chromecast/media/cma/base",
     "//chromecast/media/cma/decoder",
   ]
+
+  if (have_full_mixer) {
+    sources += [ "media_pipeline_backend_manager_mixer.cc" ]
+    deps += [ "//chromecast/media/audio/mixer_service:control_connection" ]
+  } else {
+    sources += [ "media_pipeline_backend_manager_no_mixer.cc" ]
+  }
 }
 
 # Target for OEM partners to override media shared library, i.e.
@@ -209,6 +216,7 @@
     ":volume_map",
     "//base",
     "//chromecast/base",
+    "//chromecast/media/audio/mixer_service:control_connection",
     "//chromecast/media/base:monotonic_clock",
     "//chromecast/media/cma/backend/mixer",
     "//chromecast/media/cma/base",
diff --git a/chromecast/media/cma/backend/desktop/cast_media_shlib_video.cc b/chromecast/media/cma/backend/desktop/cast_media_shlib_video.cc
index fbdd30ed..cf76d56 100644
--- a/chromecast/media/cma/backend/desktop/cast_media_shlib_video.cc
+++ b/chromecast/media/cma/backend/desktop/cast_media_shlib_video.cc
@@ -5,16 +5,26 @@
 #include <vector>
 #include <string>
 
+#include "base/no_destructor.h"
 #include "chromecast/public/cast_media_shlib.h"
 #include "chromecast/public/media/media_capabilities_shlib.h"
+#include "chromecast/public/video_plane.h"
 
 namespace chromecast {
 namespace media {
 
+class DesktopVideoPlane : public VideoPlane {
+ public:
+  ~DesktopVideoPlane() override = default;
+
+  void SetGeometry(const RectF& display_rect, Transform transform) override {}
+};
+
 void CastMediaShlib::Initialize(const std::vector<std::string>& argv) {}
 
 VideoPlane* CastMediaShlib::GetVideoPlane() {
-  return nullptr;
+  static base::NoDestructor<DesktopVideoPlane> g_video_plane;
+  return g_video_plane.get();
 }
 
 bool MediaCapabilitiesShlib::IsSupportedVideoConfig(VideoCodec codec,
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager.cc b/chromecast/media/cma/backend/media_pipeline_backend_manager.cc
index 2fba153..eeed7bcd 100644
--- a/chromecast/media/cma/backend/media_pipeline_backend_manager.cc
+++ b/chromecast/media/cma/backend/media_pipeline_backend_manager.cc
@@ -58,13 +58,15 @@
       buffer_delegate_(nullptr),
       weak_factory_(this) {
   DCHECK(media_task_runner_);
-  DCHECK(playing_audio_streams_count_.size() ==
-         static_cast<unsigned long>(AudioContentType::kNumTypes));
-  DCHECK(playing_noneffects_audio_streams_count_.size() ==
-         static_cast<unsigned long>(AudioContentType::kNumTypes));
+  DCHECK_EQ(playing_audio_streams_count_.size(),
+            static_cast<size_t>(AudioContentType::kNumTypes));
+  DCHECK_EQ(playing_noneffects_audio_streams_count_.size(),
+            static_cast<size_t>(AudioContentType::kNumTypes));
   for (int i = 0; i < NUM_DECODER_TYPES; ++i) {
     decoder_count_[i] = 0;
   }
+
+  RUN_ON_MEDIA_THREAD(CreateMixerConnection);
 }
 
 MediaPipelineBackendManager::~MediaPipelineBackendManager() {
@@ -124,12 +126,43 @@
     bool sfx,
     const AudioContentType type,
     int change) {
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   DCHECK(change == -1 || change == 1) << "bad count change: " << change;
 
   bool had_playing_audio_streams = (TotalPlayingAudioStreamsCount() > 0);
+  // Volume feedback sounds are only allowed when there are no non-effects
+  // audio streams playing.
+  bool prev_allow_feedback = (TotalPlayingNoneffectsAudioStreamsCount() == 0);
+
   playing_audio_streams_count_[type] += change;
   DCHECK_GE(playing_audio_streams_count_[type], 0);
 
+  if (!sfx) {
+    playing_noneffects_audio_streams_count_[type] += change;
+    DCHECK_GE(playing_noneffects_audio_streams_count_[type], 0);
+  }
+
+  HandlePlayingAudioStreamsChange(had_playing_audio_streams,
+                                  prev_allow_feedback);
+}
+
+void MediaPipelineBackendManager::OnMixerStreamCountChange(int primary_streams,
+                                                           int sfx_streams) {
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
+  bool had_playing_audio_streams = (TotalPlayingAudioStreamsCount() > 0);
+  bool prev_allow_feedback = (TotalPlayingNoneffectsAudioStreamsCount() == 0);
+
+  mixer_primary_stream_count_ = primary_streams;
+  mixer_sfx_stream_count_ = sfx_streams;
+
+  HandlePlayingAudioStreamsChange(had_playing_audio_streams,
+                                  prev_allow_feedback);
+}
+
+void MediaPipelineBackendManager::HandlePlayingAudioStreamsChange(
+    bool had_playing_audio_streams,
+    bool prev_allow_feedback) {
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   int new_playing_audio_streams = TotalPlayingAudioStreamsCount();
   if (new_playing_audio_streams == 0) {
     power_save_timer_.Start(FROM_HERE, kPowerSaveWaitTime, this,
@@ -143,17 +176,7 @@
     }
   }
 
-  if (sfx) {
-    return;
-  }
-
-  // Volume feedback sounds are only allowed when there are no non-effects
-  // audio streams playing.
-  bool prev_allow_feedback = (TotalPlayingNoneffectsAudioStreamsCount() == 0);
-  playing_noneffects_audio_streams_count_[type] += change;
-  DCHECK_GE(playing_noneffects_audio_streams_count_[type], 0);
   bool new_allow_feedback = (TotalPlayingNoneffectsAudioStreamsCount() == 0);
-
   if (new_allow_feedback != prev_allow_feedback) {
     allow_volume_feedback_observers_->Notify(
         FROM_HERE, &AllowVolumeFeedbackObserver::AllowVolumeFeedbackSounds,
@@ -166,7 +189,7 @@
   for (auto entry : playing_audio_streams_count_) {
     total += entry.second;
   }
-  return total;
+  return std::max(total, mixer_primary_stream_count_ + mixer_sfx_stream_count_);
 }
 
 int MediaPipelineBackendManager::TotalPlayingNoneffectsAudioStreamsCount() {
@@ -174,7 +197,7 @@
   for (auto entry : playing_noneffects_audio_streams_count_) {
     total += entry.second;
   }
-  return total;
+  return std::max(total, mixer_primary_stream_count_);
 }
 
 void MediaPipelineBackendManager::EnterPowerSaveMode() {
@@ -219,15 +242,6 @@
   buffer_delegate_ = buffer_delegate;
 }
 
-bool MediaPipelineBackendManager::IsPlaying(bool include_sfx,
-                                            AudioContentType type) {
-  if (include_sfx) {
-    return playing_audio_streams_count_[type];
-  } else {
-    return playing_noneffects_audio_streams_count_[type];
-  }
-}
-
 void MediaPipelineBackendManager::SetPowerSaveEnabled(bool power_save_enabled) {
   MAKE_SURE_MEDIA_THREAD(SetPowerSaveEnabled, power_save_enabled);
   power_save_enabled_ = power_save_enabled;
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager.h b/chromecast/media/cma/backend/media_pipeline_backend_manager.h
index 3f3c9ec..606a75bf 100644
--- a/chromecast/media/cma/backend/media_pipeline_backend_manager.h
+++ b/chromecast/media/cma/backend/media_pipeline_backend_manager.h
@@ -124,8 +124,6 @@
 
   BufferDelegate* buffer_delegate() const { return buffer_delegate_; }
 
-  bool IsPlaying(bool include_sfx, AudioContentType type);
-
   // If |power_save_enabled| is |false|, power save will be turned off and
   // automatic power save will be disabled until this is called with |true|.
   void SetPowerSaveEnabled(bool power_save_enabled);
@@ -133,6 +131,13 @@
  private:
   friend class ActiveMediaPipelineBackendWrapper;
 
+  class MixerConnection {
+   public:
+    virtual ~MixerConnection() = default;
+  };
+
+  void CreateMixerConnection();
+
   // Backend wrapper instances must use these APIs when allocating and releasing
   // decoder objects, so we can enforce global limit on #concurrent decoders.
   bool IncrementDecoderCount(DecoderType type);
@@ -142,6 +147,9 @@
   void UpdatePlayingAudioCount(bool sfx,
                                const AudioContentType type,
                                int change);
+  void OnMixerStreamCountChange(int primary_streams, int sfx_streams);
+  void HandlePlayingAudioStreamsChange(bool had_playing_audio_streams,
+                                       bool prev_allow_feedback);
   int TotalPlayingAudioStreamsCount();
   int TotalPlayingNoneffectsAudioStreamsCount();
 
@@ -170,6 +178,10 @@
 
   base::OneShotTimer power_save_timer_;
 
+  std::unique_ptr<MixerConnection> mixer_connection_;
+  int mixer_primary_stream_count_ = 0;
+  int mixer_sfx_stream_count_ = 0;
+
   base::WeakPtrFactory<MediaPipelineBackendManager> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaPipelineBackendManager);
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager_mixer.cc b/chromecast/media/cma/backend/media_pipeline_backend_manager_mixer.cc
new file mode 100644
index 0000000..4b8c5404
--- /dev/null
+++ b/chromecast/media/cma/backend/media_pipeline_backend_manager_mixer.cc
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "chromecast/media/audio/mixer_service/control_connection.h"
+
+namespace chromecast {
+namespace media {
+
+void MediaPipelineBackendManager::CreateMixerConnection() {
+  struct RealMixerConnection : public MixerConnection {
+    RealMixerConnection() { connection.Connect(); }
+
+    ~RealMixerConnection() override = default;
+
+    mixer_service::ControlConnection connection;
+  };
+
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
+  auto mixer = std::make_unique<RealMixerConnection>();
+  mixer->connection.SetStreamCountCallback(base::BindRepeating(
+      &MediaPipelineBackendManager::OnMixerStreamCountChange,
+      base::Unretained(this)));
+  mixer_connection_ = std::move(mixer);
+}
+
+}  // namespace media
+}  // namespace chromecast
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_manager_no_mixer.cc b/chromecast/media/cma/backend/media_pipeline_backend_manager_no_mixer.cc
new file mode 100644
index 0000000..7c0ca87
--- /dev/null
+++ b/chromecast/media/cma/backend/media_pipeline_backend_manager_no_mixer.cc
@@ -0,0 +1,15 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h"
+
+#include "base/logging.h"
+
+namespace chromecast {
+namespace media {
+
+void MediaPipelineBackendManager::CreateMixerConnection() {}
+
+}  // namespace media
+}  // namespace chromecast
diff --git a/chromecast/media/cma/backend/mixer/buffering_mixer_source.cc b/chromecast/media/cma/backend/mixer/buffering_mixer_source.cc
index 2216204..86b25d3 100644
--- a/chromecast/media/cma/backend/mixer/buffering_mixer_source.cc
+++ b/chromecast/media/cma/backend/mixer/buffering_mixer_source.cc
@@ -240,6 +240,11 @@
   return playout_channel_;
 }
 
+bool BufferingMixerSource::active() {
+  base::AutoLock lock(lock_);
+  return !paused_;
+}
+
 void BufferingMixerSource::WritePcm(scoped_refptr<DecoderBufferBase> data) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
@@ -301,13 +306,16 @@
 void BufferingMixerSource::SetPaused(bool paused) {
   LOG(INFO) << (paused ? "Pausing " : "Unpausing ") << device_id_ << " ("
             << this << ")";
-  base::AutoLock lock(lock_);
-  // Clear start timestamp, since a pause should invalidate the start timestamp
-  // anyway. The AV sync code can restart (hard correction) on resume if
-  // needed.
-  playback_start_timestamp_ = INT64_MIN;
-  mixer_rendering_delay_ = RenderingDelay();
-  paused_ = paused;
+  {
+    base::AutoLock lock(lock_);
+    // Clear start timestamp, since a pause should invalidate the start
+    // timestamp anyway. The AV sync code can restart (hard correction) on
+    // resume if needed.
+    playback_start_timestamp_ = INT64_MIN;
+    mixer_rendering_delay_ = RenderingDelay();
+    paused_ = paused;
+  }
+  mixer_->UpdateStreamCounts();
 }
 
 void BufferingMixerSource::SetVolumeMultiplier(float multiplier) {
diff --git a/chromecast/media/cma/backend/mixer/buffering_mixer_source.h b/chromecast/media/cma/backend/mixer/buffering_mixer_source.h
index 6387211..602f6177 100644
--- a/chromecast/media/cma/backend/mixer/buffering_mixer_source.h
+++ b/chromecast/media/cma/backend/mixer/buffering_mixer_source.h
@@ -141,6 +141,7 @@
   AudioContentType content_type() override;
   int desired_read_size() override;
   int playout_channel() override;
+  bool active() override;
 
   void InitializeAudioPlayback(int read_size,
                                RenderingDelay initial_rendering_delay) override;
diff --git a/chromecast/media/cma/backend/mixer/direct_mixer_source.cc b/chromecast/media/cma/backend/mixer/direct_mixer_source.cc
index 23007e3..f5e21c2 100644
--- a/chromecast/media/cma/backend/mixer/direct_mixer_source.cc
+++ b/chromecast/media/cma/backend/mixer/direct_mixer_source.cc
@@ -102,6 +102,9 @@
 int DirectMixerSource::playout_channel() {
   return playout_channel_;
 }
+bool DirectMixerSource::active() {
+  return true;
+}
 
 void DirectMixerSource::SetVolumeMultiplier(float multiplier) {
   mixer_->SetVolumeMultiplier(this, multiplier);
diff --git a/chromecast/media/cma/backend/mixer/direct_mixer_source.h b/chromecast/media/cma/backend/mixer/direct_mixer_source.h
index fd44896..704957e 100644
--- a/chromecast/media/cma/backend/mixer/direct_mixer_source.h
+++ b/chromecast/media/cma/backend/mixer/direct_mixer_source.h
@@ -57,6 +57,7 @@
   AudioContentType content_type() override;
   int desired_read_size() override;
   int playout_channel() override;
+  bool active() override;
 
   void InitializeAudioPlayback(int read_size,
                                RenderingDelay initial_rendering_delay) override;
diff --git a/chromecast/media/cma/backend/mixer/mixer_input.h b/chromecast/media/cma/backend/mixer/mixer_input.h
index 7c9d16d..928af0b 100644
--- a/chromecast/media/cma/backend/mixer/mixer_input.h
+++ b/chromecast/media/cma/backend/mixer/mixer_input.h
@@ -54,6 +54,8 @@
     virtual AudioContentType content_type() = 0;
     virtual int desired_read_size() = 0;
     virtual int playout_channel() = 0;
+    // Returns true if the source is currently providing audio to be mixed.
+    virtual bool active() = 0;
 
     // Called when the input has been added to the mixer, before any other
     // calls are made. The |read_size| is the number of frames that will be
diff --git a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
index 6850477..19a4d76 100644
--- a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
+++ b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
@@ -391,18 +391,21 @@
                             &MixerInputConnection::OnInactivityTimeout);
   }
 
-  base::AutoLock lock(lock_);
-  if (paused == paused_) {
-    return;
-  }
+  {
+    base::AutoLock lock(lock_);
+    if (paused == paused_) {
+      return;
+    }
 
-  paused_ = paused;
-  mixer_rendering_delay_ = RenderingDelay();
-  // Clear start timestamp, since a pause should invalidate the start
-  // timestamp anyway. The AV sync code can restart (hard correction) on
-  // resume if needed.
-  use_start_timestamp_ = false;
-  playback_start_timestamp_ = INT64_MIN;
+    paused_ = paused;
+    mixer_rendering_delay_ = RenderingDelay();
+    // Clear start timestamp, since a pause should invalidate the start
+    // timestamp anyway. The AV sync code can restart (hard correction) on
+    // resume if needed.
+    use_start_timestamp_ = false;
+    playback_start_timestamp_ = INT64_MIN;
+  }
+  mixer_->UpdateStreamCounts();
 }
 
 int MixerInputConnection::num_channels() {
@@ -427,6 +430,11 @@
   return playout_channel_;
 }
 
+bool MixerInputConnection::active() {
+  base::AutoLock lock(lock_);
+  return !paused_;
+}
+
 void MixerInputConnection::WritePcm(scoped_refptr<net::IOBuffer> data) {
   DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
 
diff --git a/chromecast/media/cma/backend/mixer/mixer_input_connection.h b/chromecast/media/cma/backend/mixer/mixer_input_connection.h
index 51e87bc..201a5d12 100644
--- a/chromecast/media/cma/backend/mixer/mixer_input_connection.h
+++ b/chromecast/media/cma/backend/mixer/mixer_input_connection.h
@@ -16,6 +16,7 @@
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
 #include "base/timer/timer.h"
+#include "chromecast/media/audio/mixer_service/mixer_service.pb.h"
 #include "chromecast/media/audio/mixer_service/mixer_socket.h"
 #include "chromecast/media/cma/backend/audio_fader.h"
 #include "chromecast/media/cma/backend/mixer/mixer_input.h"
@@ -95,6 +96,7 @@
   AudioContentType content_type() override;
   int desired_read_size() override;
   int playout_channel() override;
+  bool active() override;
 
   void InitializeAudioPlayback(int read_size,
                                RenderingDelay initial_rendering_delay) override;
diff --git a/chromecast/media/cma/backend/mixer/mixer_pipeline.cc b/chromecast/media/cma/backend/mixer/mixer_pipeline.cc
index 7a702e7..ff3399fe 100644
--- a/chromecast/media/cma/backend/mixer/mixer_pipeline.cc
+++ b/chromecast/media/cma/backend/mixer/mixer_pipeline.cc
@@ -25,6 +25,7 @@
   return device == ::media::AudioDeviceDescription::kDefaultDeviceId ||
          device == ::media::AudioDeviceDescription::kCommunicationsDeviceId ||
          device == kLocalAudioDeviceId || device == kAlarmAudioDeviceId ||
+         device == kNoDelayDeviceId ||
          device == kPlatformAudioDeviceId /* e.g. bluetooth and aux */ ||
          device == kTtsAudioDeviceId || device == kBypassAudioDeviceId;
 }
diff --git a/chromecast/media/cma/backend/mixer/mixer_service_receiver.cc b/chromecast/media/cma/backend/mixer/mixer_service_receiver.cc
index 65d6c68..441cfbe 100644
--- a/chromecast/media/cma/backend/mixer/mixer_service_receiver.cc
+++ b/chromecast/media/cma/backend/mixer/mixer_service_receiver.cc
@@ -4,22 +4,122 @@
 
 #include "chromecast/media/cma/backend/mixer/mixer_service_receiver.h"
 
+#include <string>
 #include <utility>
 
 #include "base/logging.h"
+#include "chromecast/media/audio/mixer_service/conversions.h"
 #include "chromecast/media/audio/mixer_service/mixer_service.pb.h"
 #include "chromecast/media/audio/mixer_service/mixer_socket.h"
 #include "chromecast/media/cma/backend/mixer/mixer_input_connection.h"
+#include "chromecast/media/cma/backend/mixer/stream_mixer.h"
 
 namespace chromecast {
 namespace media {
 
+class MixerServiceReceiver::ControlConnection
+    : public mixer_service::MixerSocket::Delegate {
+ public:
+  ControlConnection(StreamMixer* mixer,
+                    MixerServiceReceiver* receiver,
+                    std::unique_ptr<mixer_service::MixerSocket> socket)
+      : mixer_(mixer), receiver_(receiver), socket_(std::move(socket)) {
+    DCHECK(mixer_);
+    DCHECK(receiver_);
+    DCHECK(socket_);
+
+    socket_->SetDelegate(this);
+  }
+
+  ~ControlConnection() override = default;
+
+  void OnStreamCountChanged() {
+    if (!send_stream_count_) {
+      return;
+    }
+    mixer_service::Generic message;
+    auto* counts = message.mutable_stream_count();
+    counts->set_primary(receiver_->primary_stream_count_);
+    counts->set_sfx(receiver_->sfx_stream_count_);
+    socket_->SendProto(message);
+  }
+
+ private:
+  friend class MixerServiceReceiver;
+
+  // mixer_service::MixerSocket::Delegate implementation:
+  bool HandleMetadata(const mixer_service::Generic& message) override {
+    if (message.has_set_volume_limit()) {
+      mixer_->SetOutputLimit(
+          mixer_service::ConvertContentType(
+              message.set_volume_limit().content_type()),
+          message.set_volume_limit().max_volume_multiplier());
+    }
+    if (message.has_set_device_muted()) {
+      mixer_->SetMuted(mixer_service::ConvertContentType(
+                           message.set_device_muted().content_type()),
+                       message.set_device_muted().muted());
+    }
+    if (message.has_set_device_volume()) {
+      mixer_->SetVolume(mixer_service::ConvertContentType(
+                            message.set_device_volume().content_type()),
+                        message.set_device_volume().volume_multiplier());
+    }
+    if (message.has_configure_postprocessor()) {
+      mixer_->SetPostProcessorConfig(
+          message.configure_postprocessor().name(),
+          message.configure_postprocessor().config());
+    }
+    if (message.has_reload_postprocessors()) {
+      mixer_->ResetPostProcessors([](bool, const std::string&) {});
+    }
+    if (message.has_request_stream_count()) {
+      send_stream_count_ = message.request_stream_count().subscribe();
+      OnStreamCountChanged();
+    }
+
+    return true;
+  }
+
+  bool HandleAudioData(char* data, int size, int64_t timestamp) override {
+    return true;
+  }
+
+  bool HandleAudioBuffer(scoped_refptr<net::IOBuffer> buffer,
+                         char* data,
+                         int size,
+                         int64_t timestamp) override {
+    return true;
+  }
+
+  void OnConnectionError() override {
+    receiver_->RemoveControlConnection(this);
+  }
+
+  StreamMixer* const mixer_;
+  MixerServiceReceiver* const receiver_;
+  const std::unique_ptr<mixer_service::MixerSocket> socket_;
+
+  bool send_stream_count_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(ControlConnection);
+};
+
 MixerServiceReceiver::MixerServiceReceiver(StreamMixer* mixer) : mixer_(mixer) {
   DCHECK(mixer_);
 }
 
 MixerServiceReceiver::~MixerServiceReceiver() = default;
 
+void MixerServiceReceiver::OnStreamCountChanged(int primary, int sfx) {
+  primary_stream_count_ = primary;
+  sfx_stream_count_ = sfx;
+
+  for (const auto& control : control_connections_) {
+    control.second->OnStreamCountChanged();
+  }
+}
+
 void MixerServiceReceiver::CreateOutputStream(
     std::unique_ptr<mixer_service::MixerSocket> socket,
     const mixer_service::Generic& message) {
@@ -45,7 +145,15 @@
 void MixerServiceReceiver::CreateControlConnection(
     std::unique_ptr<mixer_service::MixerSocket> socket,
     const mixer_service::Generic& message) {
-  LOG(INFO) << "Unhandled control connection";
+  auto connection =
+      std::make_unique<ControlConnection>(mixer_, this, std::move(socket));
+  ControlConnection* ptr = connection.get();
+  control_connections_[ptr] = std::move(connection);
+  ptr->HandleMetadata(message);
+}
+
+void MixerServiceReceiver::RemoveControlConnection(ControlConnection* ptr) {
+  control_connections_.erase(ptr);
 }
 
 }  // namespace media
diff --git a/chromecast/media/cma/backend/mixer/mixer_service_receiver.h b/chromecast/media/cma/backend/mixer/mixer_service_receiver.h
index 239b8f58..e506804 100644
--- a/chromecast/media/cma/backend/mixer/mixer_service_receiver.h
+++ b/chromecast/media/cma/backend/mixer/mixer_service_receiver.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "chromecast/media/audio/mixer_service/receiver/receiver.h"
 
@@ -24,7 +25,12 @@
   explicit MixerServiceReceiver(StreamMixer* mixer);
   ~MixerServiceReceiver() override;
 
+  // Called by the mixer when the active stream count changes.
+  void OnStreamCountChanged(int primary, int sfx);
+
  private:
+  class ControlConnection;
+
   // mixer_service::Receiver implementation:
   void CreateOutputStream(std::unique_ptr<mixer_service::MixerSocket> socket,
                           const mixer_service::Generic& message) override;
@@ -38,8 +44,15 @@
       std::unique_ptr<mixer_service::MixerSocket> socket,
       const mixer_service::Generic& message) override;
 
+  void RemoveControlConnection(ControlConnection* ptr);
+
   StreamMixer* const mixer_;
 
+  base::flat_map<ControlConnection*, std::unique_ptr<ControlConnection>>
+      control_connections_;
+  int primary_stream_count_ = 0;
+  int sfx_stream_count_ = 0;
+
   DISALLOW_COPY_AND_ASSIGN(MixerServiceReceiver);
 };
 
diff --git a/chromecast/media/cma/backend/mixer/mock_mixer_source.h b/chromecast/media/cma/backend/mixer/mock_mixer_source.h
index ef7ed7cb..d534e03 100644
--- a/chromecast/media/cma/backend/mixer/mock_mixer_source.h
+++ b/chromecast/media/cma/backend/mixer/mock_mixer_source.h
@@ -39,6 +39,7 @@
   AudioContentType content_type() override { return content_type_; }
   int desired_read_size() override { return 1; }
   int playout_channel() override { return playout_channel_; }
+  bool active() override { return true; }
 
   MOCK_METHOD2(InitializeAudioPlayback, void(int, RenderingDelay));
   MOCK_METHOD3(FillAudioPlaybackFrames,
diff --git a/chromecast/media/cma/backend/mixer/stream_mixer.cc b/chromecast/media/cma/backend/mixer/stream_mixer.cc
index da5456b5..e6ca33a 100644
--- a/chromecast/media/cma/backend/mixer/stream_mixer.cc
+++ b/chromecast/media/cma/backend/mixer/stream_mixer.cc
@@ -594,6 +594,7 @@
   }
   inputs_.clear();
   SetCloseTimeout();
+  UpdateStreamCounts();
 }
 
 int StreamMixer::GetEffectiveChannelCount(MixerInput::Source* input_source) {
@@ -664,6 +665,7 @@
 
   inputs_[input_source] = std::move(input);
   UpdatePlayoutChannel();
+  UpdateStreamCounts();
 }
 
 void StreamMixer::RemoveInput(MixerInput::Source* input_source) {
@@ -687,6 +689,7 @@
 
   ignored_inputs_.erase(input_source);
   UpdatePlayoutChannel();
+  UpdateStreamCounts();
 
   if (inputs_.empty()) {
     SetCloseTimeout();
@@ -725,6 +728,20 @@
   mixer_pipeline_->SetPlayoutChannel(playout_channel_);
 }
 
+void StreamMixer::UpdateStreamCounts() {
+  MAKE_SURE_MIXER_THREAD(UpdateStreamCounts);
+
+  int primary = 0;
+  int sfx = 0;
+  for (const auto& it : inputs_) {
+    if (it.second->source()->active()) {
+      (it.second->primary() ? primary : sfx) += 1;
+    }
+  }
+  receiver_.Post(FROM_HERE, &MixerServiceReceiver::OnStreamCountChanged,
+                 primary, sfx);
+}
+
 MediaPipelineBackend::AudioDecoder::RenderingDelay
 StreamMixer::GetTotalRenderingDelay(FilterGroup* filter_group) {
   DCHECK(mixer_task_runner_->BelongsToCurrentThread());
@@ -941,9 +958,9 @@
   }
 }
 
-void StreamMixer::SetPostProcessorConfig(const std::string& name,
-                                         const std::string& config) {
-  MAKE_SURE_MIXER_THREAD(SetPostProcessorConfig, name, config);
+void StreamMixer::SetPostProcessorConfig(std::string name, std::string config) {
+  MAKE_SURE_MIXER_THREAD(SetPostProcessorConfig, std::move(name),
+                         std::move(config));
 
   mixer_pipeline_->SetPostProcessorConfig(name, config);
 }
diff --git a/chromecast/media/cma/backend/mixer/stream_mixer.h b/chromecast/media/cma/backend/mixer/stream_mixer.h
index d9f7d522..046148e 100644
--- a/chromecast/media/cma/backend/mixer/stream_mixer.h
+++ b/chromecast/media/cma/backend/mixer/stream_mixer.h
@@ -115,11 +115,14 @@
   void SetVolumeMultiplier(MixerInput::Source* source, float multiplier);
 
   // Sends configuration string |config| to processor |name|.
-  void SetPostProcessorConfig(const std::string& name,
-                              const std::string& config);
+  void SetPostProcessorConfig(std::string name, std::string config);
 
   void ResetPostProcessors(CastMediaShlib::ResultCallback callback);
 
+  // Updates the counts of active streams and signals any observing control
+  // connections.
+  void UpdateStreamCounts();
+
   // Test-only methods.
   StreamMixer(std::unique_ptr<MixerOutputStream> output,
               std::unique_ptr<base::Thread> mixer_thread,
diff --git a/chromecast/media/cma/backend/volume_control.cc b/chromecast/media/cma/backend/volume_control.cc
index d3189846..c59d2d2 100644
--- a/chromecast/media/cma/backend/volume_control.cc
+++ b/chromecast/media/cma/backend/volume_control.cc
@@ -28,6 +28,7 @@
 #include "base/threading/thread.h"
 #include "base/values.h"
 #include "chromecast/base/serializers.h"
+#include "chromecast/media/audio/mixer_service/control_connection.h"
 #include "chromecast/media/cma/backend/audio_buildflags.h"
 #include "chromecast/media/cma/backend/cast_audio_json.h"
 #include "chromecast/media/cma/backend/mixer/stream_mixer.h"
@@ -219,6 +220,8 @@
   void InitializeOnThread() {
     DCHECK(thread_.task_runner()->BelongsToCurrentThread());
     system_volume_control_ = SystemVolumeControl::Create(this);
+    mixer_ = std::make_unique<mixer_service::ControlConnection>();
+    mixer_->Connect();
 
     double dbfs;
     for (auto type : {AudioContentType::kMedia, AudioContentType::kAlarm,
@@ -229,9 +232,9 @@
       if (BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
         // If ALSA owns volume, our internal mixer should not apply any scaling
         // multiplier.
-        StreamMixer::Get()->SetVolume(type, 1.0f);
+        mixer_->SetVolume(type, 1.0f);
       } else {
-        StreamMixer::Get()->SetVolume(type, DbFsToScale(dbfs));
+        mixer_->SetVolume(type, DbFsToScale(dbfs));
       }
 
       // Note that mute state is not persisted across reboots.
@@ -279,8 +282,7 @@
 
     float dbfs = VolumeControl::VolumeToDbFS(level);
     if (!BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
-      StreamMixer::Get()->SetVolume(
-          type, DbFsToScale(dbfs) * volume_multipliers_[type]);
+      mixer_->SetVolume(type, DbFsToScale(dbfs) * volume_multipliers_[type]);
     }
 
     if (!from_system && type == AudioContentType::kMedia) {
@@ -306,7 +308,7 @@
     volume_multipliers_[type] = multiplier;
     float scale =
         DbFsToScale(VolumeControl::VolumeToDbFS(volumes_[type])) * multiplier;
-    StreamMixer::Get()->SetVolume(type, scale);
+    mixer_->SetVolume(type, scale);
   }
 
   void SetMutedOnThread(VolumeChangeSource source,
@@ -325,7 +327,7 @@
     }
 
     if (!BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
-      StreamMixer::Get()->SetMuted(type, muted);
+      mixer_->SetMuted(type, muted);
     }
 
     if (!from_system && type == AudioContentType::kMedia) {
@@ -350,8 +352,8 @@
       return;
     }
     limit = base::ClampToRange(limit, 0.0f, 1.0f);
-    StreamMixer::Get()->SetOutputLimit(
-        type, DbFsToScale(VolumeControl::VolumeToDbFS(limit)));
+    mixer_->SetVolumeLimit(type,
+                           DbFsToScale(VolumeControl::VolumeToDbFS(limit)));
 
     if (type == AudioContentType::kMedia) {
       system_volume_control_->SetLimit(limit);
@@ -389,6 +391,7 @@
   base::WaitableEvent initialize_complete_event_;
 
   std::unique_ptr<SystemVolumeControl> system_volume_control_;
+  std::unique_ptr<mixer_service::ControlConnection> mixer_;
 
   DISALLOW_COPY_AND_ASSIGN(VolumeControlInternal);
 };
@@ -402,6 +405,7 @@
 
 // static
 void VolumeControl::Initialize(const std::vector<std::string>& argv) {
+  StreamMixer::Get();
   GetVolumeControl();
 }
 
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 91dbfc2..f36d4d1 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-12581.0.0
\ No newline at end of file
+12583.0.0
\ No newline at end of file
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 92b7303..08e4f4f 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -59,6 +59,10 @@
 const base::Feature kCrostiniWebUIInstaller{"CrostiniWebUIInstaller",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables or disables the CryptAuth v2 DeviceSync flow.
+const base::Feature kCryptAuthV2DeviceSync{"CryptAuthV2DeviceSync",
+                                           base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables or disables the CryptAuth v2 Enrollment flow.
 const base::Feature kCryptAuthV2Enrollment{"CryptAuthV2Enrollment",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index a178a9b1..d39bb67 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -37,6 +37,8 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kCrostiniWebUIInstaller;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kCryptAuthV2DeviceSync;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kCryptAuthV2Enrollment;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kDisableOfficeEditingComponentApp;
diff --git a/chromeos/services/device_sync/cryptauth_device_syncer_impl.cc b/chromeos/services/device_sync/cryptauth_device_syncer_impl.cc
index dd24c86..9eb14d2 100644
--- a/chromeos/services/device_sync/cryptauth_device_syncer_impl.cc
+++ b/chromeos/services/device_sync/cryptauth_device_syncer_impl.cc
@@ -304,10 +304,10 @@
     if (*current_group_key == new_group_key)
       return;
 
-    PA_LOG(VERBOSE) << "Deleting old DeviceSync BetterTogether group key: "
+    PA_LOG(VERBOSE) << "Deleting old DeviceSync BetterTogether group key:\n"
                     << "public = "
                     << util::EncodeAsString(current_group_key->public_key())
-                    << ", private = "
+                    << ",\nprivate = "
                     << (current_group_key->private_key().empty()
                             ? "[empty]"
                             : "[not empty]");
@@ -316,10 +316,10 @@
         current_group_key->handle());
   }
 
-  PA_LOG(VERBOSE) << "New DeviceSync BetterTogether group key: "
+  PA_LOG(VERBOSE) << "New DeviceSync BetterTogether group key:\n"
                   << "public = "
                   << util::EncodeAsString(new_group_key.public_key())
-                  << ", private = "
+                  << ",\nprivate = "
                   << (new_group_key.private_key().empty() ? "[empty]"
                                                           : "[not empty]");
 
@@ -584,6 +584,13 @@
         id_packet_pair.first, id_packet_pair.second.device_public_key());
   }
 
+  // No device needs the group private key.
+  if (id_to_encrypting_key_map.empty()) {
+    OnShareGroupPrivateKeyFinished(
+        CryptAuthDeviceSyncResult::ResultCode::kSuccess);
+    return;
+  }
+
   const CryptAuthKey* group_key = key_registry_->GetActiveKey(
       CryptAuthKeyBundle::Name::kDeviceSyncBetterTogetherGroupKey);
   DCHECK(group_key);
diff --git a/chromeos/services/device_sync/cryptauth_device_syncer_impl_unittest.cc b/chromeos/services/device_sync/cryptauth_device_syncer_impl_unittest.cc
index 636d273..f69b359 100644
--- a/chromeos/services/device_sync/cryptauth_device_syncer_impl_unittest.cc
+++ b/chromeos/services/device_sync/cryptauth_device_syncer_impl_unittest.cc
@@ -500,6 +500,54 @@
 }
 
 TEST_F(DeviceSyncCryptAuthDeviceSyncerImplTest,
+       Success_InitialGroupKeyValid_NoDevicesNeedGroupPrivateKey) {
+  // Add the correct group key to the registry.
+  AddInitialGroupKeyToRegistry(GetGroupKey());
+
+  CallSync();
+
+  std::string encrypted_group_private_key = MakeFakeEncryptedString(
+      GetGroupKey().private_key(),
+      GetLocalDeviceForTest().device_better_together_public_key);
+
+  // Only return the local device metadata, noting that it does not need the
+  // group private key. So, there is no need to share the group private key.
+  std::vector<cryptauthv2::DeviceMetadataPacket> device_metadata_packets = {
+      ConvertTestDeviceToMetadataPacket(GetLocalDeviceForTest(),
+                                        kGroupPublicKey,
+                                        false /* need_group_private_key */)};
+  VerifyMetadataSyncerInput(&GetGroupKey());
+
+  // The initial group key is valid, so a new group key was not created.
+  FinishMetadataSyncerAttempt(
+      device_metadata_packets, base::nullopt /* new_group_key */,
+      encrypted_group_private_key, cryptauthv2::GetClientDirectiveForTest(),
+      CryptAuthDeviceSyncResult::ResultCode::kSuccess);
+
+  VerifyGroupKeyInRegistry(GetGroupKey());
+
+  base::flat_set<std::string> device_ids = {
+      GetLocalDeviceForTest().instance_id()};
+  VerifyFeatureStatusGetterInput(device_ids);
+  FinishFeatureStatusGetterAttempt(
+      device_ids, CryptAuthDeviceSyncResult::ResultCode::kSuccess);
+
+  // Even though we have the unencrypted group private key in the key registry,
+  // we decrypt the group private key from CryptAuth and check consistency.
+  RunGroupPrivateKeyDecryptor(encrypted_group_private_key, true /* succeed */);
+
+  RunDeviceMetadataDecryptor(device_metadata_packets,
+                             GetGroupKey().private_key(),
+                             {} /* device_ids_to_fail */);
+
+  VerifyDeviceSyncResult(
+      CryptAuthDeviceSyncResult(CryptAuthDeviceSyncResult::ResultCode::kSuccess,
+                                true /* device_registry_changed */,
+                                cryptauthv2::GetClientDirectiveForTest()),
+      {GetLocalDeviceForTest()});
+}
+
+TEST_F(DeviceSyncCryptAuthDeviceSyncerImplTest,
        Success_InitialGroupPublicKeyValid_NeedGroupPrivateKey) {
   // Add the correct group public key to the registry. Note that we still need
   // the group private key from CryptAuth.
diff --git a/components/about_ui/BUILD.gn b/components/about_ui/BUILD.gn
index 45fa8c84..2a7e25b 100644
--- a/components/about_ui/BUILD.gn
+++ b/components/about_ui/BUILD.gn
@@ -13,8 +13,17 @@
     "//ui/base",
     "//ui/resources",
   ]
+}
 
-  if (is_android) {
-    deps += [ "//components/about_ui/android:about_ui_jni_headers" ]
+if (is_android) {
+  static_library("about_ui_android") {
+    sources = [
+      "credit_utils_android.cc",
+    ]
+    deps = [
+      ":about_ui",
+      "//base",
+      "//components/about_ui/android:about_ui_jni_headers",
+    ]
   }
 }
diff --git a/components/about_ui/credit_utils.cc b/components/about_ui/credit_utils.cc
index eaec174..c7fe722 100644
--- a/components/about_ui/credit_utils.cc
+++ b/components/about_ui/credit_utils.cc
@@ -10,11 +10,6 @@
 #include "components/grit/components_resources.h"
 #include "ui/base/resource/resource_bundle.h"
 
-#if defined(OS_ANDROID)
-#include "base/files/file.h"
-#include "components/about_ui/android/about_ui_jni_headers/CreditUtils_jni.h"
-#endif
-
 namespace about_ui {
 
 std::string GetCredits(bool include_scripts) {
@@ -30,12 +25,4 @@
   return response;
 }
 
-#if defined(OS_ANDROID)
-static void JNI_CreditUtils_WriteCreditsHtml(JNIEnv* env, jint fd) {
-  std::string html_content = GetCredits(false);
-  base::File out_file(fd);
-  out_file.WriteAtCurrentPos(html_content.c_str(), html_content.size());
-}
-#endif
-
 }  // namespace about_ui
diff --git a/components/about_ui/credit_utils_android.cc b/components/about_ui/credit_utils_android.cc
new file mode 100644
index 0000000..ca4cf81
--- /dev/null
+++ b/components/about_ui/credit_utils_android.cc
@@ -0,0 +1,18 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/about_ui/credit_utils.h"
+
+#include "base/files/file.h"
+#include "components/about_ui/android/about_ui_jni_headers/CreditUtils_jni.h"
+
+namespace about_ui {
+
+static void JNI_CreditUtils_WriteCreditsHtml(JNIEnv* env, jint fd) {
+  std::string html_content = GetCredits(false);
+  base::File out_file(fd);
+  out_file.WriteAtCurrentPos(html_content.c_str(), html_content.size());
+}
+
+}  // namespace about_ui
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index 2492b5d..97309a9 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -361,6 +361,7 @@
     "session/arc_data_remover_unittest.cc",
     "session/arc_session_impl_unittest.cc",
     "session/arc_session_runner_unittest.cc",
+    "session/arc_vm_client_adapter_unittest.cc",
     "timer/arc_timer_bridge_unittest.cc",
     "wake_lock/arc_wake_lock_bridge_unittest.cc",
   ]
diff --git a/components/arc/session/arc_vm_client_adapter.cc b/components/arc/session/arc_vm_client_adapter.cc
index 7cb7527..ead6aeb 100644
--- a/components/arc/session/arc_vm_client_adapter.cc
+++ b/components/arc/session/arc_vm_client_adapter.cc
@@ -4,40 +4,248 @@
 
 #include "components/arc/session/arc_vm_client_adapter.h"
 
+#include <sys/statvfs.h>
+#include <time.h>
+
+#include <set>
 #include <string>
 #include <utility>
 #include <vector>
 
 #include "base/bind.h"
+#include "base/feature_list.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
+#include "base/process/launch.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/time.h"
 #include "chromeos/dbus/concierge_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
 #include "chromeos/dbus/login_manager/arc.pb.h"
 #include "chromeos/dbus/upstart/upstart_client.h"
+#include "chromeos/system/statistics_provider.h"
+#include "components/arc/arc_features.h"
 #include "components/arc/arc_util.h"
 
 namespace arc {
 namespace {
 
 constexpr const char kArcVmServerProxyJobName[] = "arcvm_2dserver_2dproxy";
+constexpr const char kBuiltinPath[] = "/opt/google/vms/android";
+constexpr const char kCrosSystemPath[] = "/usr/bin/crossystem";
+constexpr const char kDlcPath[] = "/run/imageloader/arcvm-dlc/package/root";
+constexpr const char kFstab[] = "fstab";
+constexpr const char kHomeDirectory[] = "/home";
+constexpr const char kKernel[] = "vmlinux";
+constexpr const char kRootFs[] = "system.raw.img";
+constexpr const char kVendorImage[] = "vendor.raw.img";
 
 chromeos::ConciergeClient* GetConciergeClient() {
   return chromeos::DBusThreadManager::Get()->GetConciergeClient();
 }
 
+bool IsHostRootfsWritable() {
+  struct statvfs buf;
+  if (statvfs("/", &buf) < 0) {
+    PLOG(ERROR) << "statvfs() failed";
+    return false;
+  }
+  const bool rw = !(buf.f_flag & ST_RDONLY);
+  VLOG(1) << "Host's rootfs is " << (rw ? "rw" : "ro");
+  return rw;
+}
+
+base::FilePath SelectDlcOrBuiltin(const base::FilePath& file) {
+  const base::FilePath dlc_path = base::FilePath(kDlcPath).Append(file);
+  if (base::PathExists(dlc_path)) {
+    VLOG(1) << "arcvm-dlc will be used for " << file.value();
+    return dlc_path;
+  }
+  return base::FilePath(kBuiltinPath).Append(file);
+}
+
+// TODO(pliard): Export host-side /data to the VM, and remove the function.
+vm_tools::concierge::CreateDiskImageRequest CreateArcDiskRequest(
+    const std::string& user_id_hash,
+    int64_t free_disk_bytes) {
+  DCHECK(!user_id_hash.empty());
+
+  vm_tools::concierge::CreateDiskImageRequest request;
+  request.set_cryptohome_id(user_id_hash);
+  request.set_disk_path("arcvm");
+
+  // The type of disk image to be created.
+  request.set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO);
+  request.set_storage_location(vm_tools::concierge::STORAGE_CRYPTOHOME_ROOT);
+
+  // The logical size of the new disk image, in bytes.
+  request.set_disk_size(free_disk_bytes / 2);
+
+  return request;
+}
+
+std::string GetReleaseChannel() {
+  constexpr const char kUnknown[] = "unknown";
+  const std::set<std::string> channels = {"beta",    "canary", "dev",
+                                          "dogfood", "stable", "testimage"};
+
+  std::string value;
+  if (!base::SysInfo::GetLsbReleaseValue("CHROMEOS_RELEASE_TRACK", &value)) {
+    LOG(ERROR) << "Could not load lsb-release";
+    return kUnknown;
+  }
+
+  auto pieces = base::SplitString(value, "-", base::KEEP_WHITESPACE,
+                                  base::SPLIT_WANT_ALL);
+
+  if (pieces.size() != 2 || pieces[1] != "channel") {
+    LOG(ERROR) << "Misformatted CHROMEOS_RELEASE_TRACK value in lsb-release";
+    return kUnknown;
+  }
+  if (channels.find(pieces[0]) == channels.end()) {
+    LOG(WARNING) << "Unknown ChromeOS channel: \"" << pieces[0] << "\"";
+    return kUnknown;
+  }
+
+  return pieces[0];
+}
+
+std::string MonotonicTimestamp() {
+  struct timespec ts;
+  const int ret = clock_gettime(CLOCK_BOOTTIME, &ts);
+  DPCHECK(ret == 0);
+  const int64_t time =
+      ts.tv_sec * base::Time::kNanosecondsPerSecond + ts.tv_nsec;
+  return base::NumberToString(time);
+}
+
+std::vector<std::string> GenerateKernelCmdline(
+    int32_t lcd_density,
+    const base::Optional<bool>& play_store_auto_update,
+    bool is_dev_mode,
+    bool is_host_on_vm) {
+  const std::string release_channel = GetReleaseChannel();
+  const bool stable_or_beta =
+      release_channel == "stable" || release_channel == "beta";
+
+  std::vector<std::string> result = {
+      "androidboot.hardware=bertha",
+      "androidboot.container=1",
+      // TODO(b/139480143): when ArcNativeBridgeExperiment is enabled, switch
+      // to ndk_translation.
+      "androidboot.native_bridge=libhoudini.so",
+      base::StringPrintf("androidboot.dev_mode=%d", is_dev_mode),
+      base::StringPrintf("androidboot.disable_runas=%d", !is_dev_mode),
+      base::StringPrintf("androidboot.vm=%d", is_host_on_vm),
+      // TODO(yusukes): get this from arc-setup config or equivalent.
+      "androidboot.debuggable=1",
+      base::StringPrintf("androidboot.lcd_density=%d", lcd_density),
+      base::StringPrintf(
+          "androidboot.arc_file_picker=%d",
+          base::FeatureList::IsEnabled(kFilePickerExperimentFeature)),
+      base::StringPrintf(
+          "androidboot.arc_custom_tabs=%d",
+          base::FeatureList::IsEnabled(kCustomTabsExperimentFeature) &&
+              !stable_or_beta),
+      base::StringPrintf(
+          "androidboot.arc_print_spooler=%d",
+          base::FeatureList::IsEnabled(kPrintSpoolerExperimentFeature) &&
+              !stable_or_beta),
+      "androidboot.chromeos_channel=" + release_channel,
+      "androidboot.boottime_offset=" + MonotonicTimestamp(),
+      // TODO(yusukes): remove this once arcvm supports SELinux.
+      "androidboot.selinux=permissive",
+  };
+
+  if (play_store_auto_update) {
+    result.push_back(base::StringPrintf("androidboot.play_store_auto_update=%d",
+                                        *play_store_auto_update));
+  }
+
+  // TODO(yusukes): include command line parameters from arcbootcontinue.
+  return result;
+}
+
+vm_tools::concierge::StartArcVmRequest CreateStartArcVmRequest(
+    const std::string& user_id_hash,
+    uint32_t cpus,
+    const std::string& disk_path,
+    std::vector<std::string> kernel_cmdline) {
+  vm_tools::concierge::StartArcVmRequest request;
+
+  request.set_name(kArcVmName);
+  request.set_owner_id(user_id_hash);
+
+  request.add_params("root=/dev/vda");
+  if (IsHostRootfsWritable())
+    request.add_params("rw");
+  request.add_params("init=/init");
+  for (auto& entry : kernel_cmdline)
+    request.add_params(std::move(entry));
+
+  vm_tools::concierge::VirtualMachineSpec* vm = request.mutable_vm();
+
+  vm->set_kernel(SelectDlcOrBuiltin(base::FilePath(kKernel)).value());
+
+  // Add / as /dev/vda.
+  vm->set_rootfs(SelectDlcOrBuiltin(base::FilePath(kRootFs)).value());
+
+  // Add /data as /dev/vdb.
+  vm_tools::concierge::DiskImage* disk_image = request.add_disks();
+  disk_image->set_path(disk_path);
+  disk_image->set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO);
+  disk_image->set_writable(true);
+  disk_image->set_do_mount(true);
+  // Add /vendor as /dev/vdc.
+  disk_image = request.add_disks();
+  disk_image->set_path(
+      SelectDlcOrBuiltin(base::FilePath(kVendorImage)).value());
+
+  disk_image->set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO);
+  disk_image->set_writable(false);
+  disk_image->set_do_mount(true);
+
+  // Add Android fstab.
+  request.set_fstab(SelectDlcOrBuiltin(base::FilePath(kFstab)).value());
+
+  // Add cpus.
+  request.set_cpus(cpus);
+
+  return request;
+}
+
+int GetSystemPropertyInt(const std::string& property) {
+  std::string output;
+  if (!base::GetAppOutput({kCrosSystemPath, property}, &output))
+    return -1;
+  int output_int;
+  return base::StringToInt(output, &output_int) ? output_int : -1;
+}
+
 }  // namespace
 
 class ArcVmClientAdapter : public ArcClientAdapter,
                            public chromeos::ConciergeClient::VmObserver,
                            public chromeos::ConciergeClient::Observer {
  public:
-  ArcVmClientAdapter() {
+  // Initializing |is_dev_mode_| and |is_host_on_vm_| is not always very fast.
+  // Try to initialize them in the constructor which usually runs when the
+  // system is not busy.
+  ArcVmClientAdapter()
+      : is_dev_mode_(GetSystemPropertyInt("cros_debug") == 1),
+        is_host_on_vm_(chromeos::system::StatisticsProvider::GetInstance()
+                           ->IsRunningOnVm()) {
     auto* client = GetConciergeClient();
     client->AddVmObserver(this);
     client->AddObserver(this);
@@ -86,6 +294,7 @@
     }
     base::SequencedTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback), true));
+    should_notify_observers_ = true;
   }
 
   void UpgradeArc(const UpgradeArcContainerRequest& request,
@@ -94,30 +303,17 @@
     chromeos::UpstartClient::Get()->StartJob(
         kArcVmServerProxyJobName, /*environment=*/{},
         base::BindOnce(&ArcVmClientAdapter::OnArcVmServerProxyJobStarted,
-                       weak_factory_.GetWeakPtr()));
-
-    VLOG(1) << "Starting ARCVM";
-    std::vector<std::string> env{
-        {"USER_ID_HASH=" + user_id_hash_},
-        {base::StringPrintf("ARC_LCD_DENSITY=%d", lcd_density_)},
-        {base::StringPrintf("CPUS=%u", cpus_)},
-    };
-    if (play_store_auto_update_) {
-      env.push_back(base::StringPrintf("PLAY_STORE_AUTO_UPDATE=%d",
-                                       *play_store_auto_update_));
-    }
-    chromeos::UpstartClient::Get()->StartJob("arcvm", env, std::move(callback));
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void StopArcInstance() override {
     VLOG(1) << "Stopping arcvm";
-    // TODO(yusukes): This method should eventually call ArcInstanceStopped()
-    // even when only the (yet nonexistent) 'mini' VM is running.
-    std::vector<std::string> env{{"USER_ID_HASH=" + user_id_hash_}};
-    chromeos::UpstartClient::Get()->StopJob(
-        "arcvm", env,
-        base::BindOnce(&ArcVmClientAdapter::OnArcVmJobStopped,
-                       weak_factory_.GetWeakPtr()));
+    vm_tools::concierge::StopVmRequest request;
+    request.set_name(kArcVmName);
+    request.set_owner_id(user_id_hash_);
+    GetConciergeClient()->StopVm(
+        request, base::BindOnce(&ArcVmClientAdapter::OnStopVmReply,
+                                weak_factory_.GetWeakPtr()));
   }
 
   void SetUserIdHashForProfile(const std::string& hash) override {
@@ -136,6 +332,92 @@
   void ConciergeServiceRestarted() override {}
 
  private:
+  void OnConciergeStarted(chromeos::VoidDBusMethodCallback callback,
+                          bool success) {
+    if (!success) {
+      LOG(ERROR) << "Failed to start Concierge service for arcvm";
+      std::move(callback).Run(false);
+      return;
+    }
+    VLOG(1) << "Concierge service started for arcvm.";
+
+    base::PostTaskAndReplyWithResult(
+        FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+        base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
+                       base::FilePath(kHomeDirectory)),
+        base::BindOnce(&ArcVmClientAdapter::CreateDiskImageAfterSizeCheck,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
+  void CreateDiskImageAfterSizeCheck(chromeos::VoidDBusMethodCallback callback,
+                                     int64_t free_disk_bytes) {
+    VLOG(2) << "Got free disk size: " << free_disk_bytes;
+    if (user_id_hash_.empty()) {
+      LOG(ERROR) << "User ID hash is not set";
+      std::move(callback).Run(false);
+      return;
+    }
+    // TODO(yusukes): Don't start the VM when |free_disk_bytes| is too small.
+    // TODO(pliard): Export host-side /data to the VM, and remove the call.
+    GetConciergeClient()->CreateDiskImage(
+        CreateArcDiskRequest(user_id_hash_, free_disk_bytes),
+        base::BindOnce(&ArcVmClientAdapter::OnDiskImageCreated,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
+  // TODO(pliard): Export host-side /data to the VM, and remove the first half
+  // of the function.
+  void OnDiskImageCreated(
+      chromeos::VoidDBusMethodCallback callback,
+      base::Optional<vm_tools::concierge::CreateDiskImageResponse> reply) {
+    if (!reply.has_value()) {
+      LOG(ERROR) << "Failed to create disk image. Empty response.";
+      std::move(callback).Run(false);
+      return;
+    }
+
+    const vm_tools::concierge::CreateDiskImageResponse& response =
+        reply.value();
+    if (response.status() != vm_tools::concierge::DISK_STATUS_EXISTS &&
+        response.status() != vm_tools::concierge::DISK_STATUS_CREATED) {
+      LOG(ERROR) << "Failed to create disk image: "
+                 << response.failure_reason();
+      std::move(callback).Run(false);
+      return;
+    }
+    VLOG(1) << "Disk image for arcvm ready. status=" << response.status()
+            << ", disk=" << response.disk_path();
+
+    std::vector<std::string> kernel_cmdline = GenerateKernelCmdline(
+        lcd_density_, play_store_auto_update_, is_dev_mode_, is_host_on_vm_);
+    auto start_request = CreateStartArcVmRequest(
+        user_id_hash_, cpus_, response.disk_path(), std::move(kernel_cmdline));
+    GetConciergeClient()->StartArcVm(
+        start_request,
+        base::BindOnce(&ArcVmClientAdapter::OnStartArcVmReply,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
+  void OnStartArcVmReply(
+      chromeos::VoidDBusMethodCallback callback,
+      base::Optional<vm_tools::concierge::StartVmResponse> reply) {
+    if (!reply.has_value()) {
+      LOG(ERROR) << "Failed to start arcvm. Empty response.";
+      std::move(callback).Run(false);
+      return;
+    }
+
+    const vm_tools::concierge::StartVmResponse& response = reply.value();
+    if (response.status() != vm_tools::concierge::VM_STATUS_RUNNING) {
+      LOG(ERROR) << "Failed to start arcvm: status=" << response.status()
+                 << ", reason=" << response.failure_reason();
+      std::move(callback).Run(false);
+      return;
+    }
+    VLOG(1) << "arcvm started.";
+    std::move(callback).Run(true);
+  }
+
   void OnArcInstanceStopped() {
     VLOG(1) << "ARCVM stopped. Stopping arcvm-server-proxy";
 
@@ -146,32 +428,61 @@
         base::BindOnce(&ArcVmClientAdapter::OnArcVmServerProxyJobStopped,
                        weak_factory_.GetWeakPtr()));
 
+    // If this method is called before even mini VM is started (e.g. very early
+    // vm_concierge crash), or this method is called twice (e.g. crosvm crash
+    // followed by vm_concierge crash), do nothing.
+    if (!should_notify_observers_)
+      return;
+    should_notify_observers_ = false;
+
     for (auto& observer : observer_list_)
       observer.ArcInstanceStopped();
   }
 
-  // TODO(yusukes): Remove this method when we remove arcvm.conf.
-  void OnArcVmJobStopped(bool result) {
-    if (!result)
-      LOG(ERROR) << "Failed to stop arcvm.";
+  void OnStopVmReply(
+      base::Optional<vm_tools::concierge::StopVmResponse> reply) {
+    // If the reply indicates the D-Bus call is successfully done, do nothing.
+    // Concierge call OnVmStopped() eventually.
+    if (reply.has_value() && reply.value().success())
+      return;
+
+    // We likely tried to stop mini VM which doesn't exist today. Notify
+    // observers.
+    // TODO(yusukes): Remove the fallback once we implement mini VM.
+    OnArcInstanceStopped();
   }
 
-  void OnArcVmServerProxyJobStarted(bool result) {
-    VLOG(1) << "OnArcVmServerProxyJobStarted result=" << result;
+  void OnArcVmServerProxyJobStarted(chromeos::VoidDBusMethodCallback callback,
+                                    bool result) {
+    if (!result) {
+      LOG(ERROR) << "Failed to start arcvm-server-proxy job";
+      std::move(callback).Run(false);
+      return;
+    }
+
+    VLOG(1) << "Starting Concierge service";
+    chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->StartConcierge(
+        base::BindOnce(&ArcVmClientAdapter::OnConciergeStarted,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
   }
 
   void OnArcVmServerProxyJobStopped(bool result) {
     VLOG(1) << "OnArcVmServerProxyJobStopped result=" << result;
   }
 
+  const bool is_dev_mode_;
+  // True when the *host* is running on a VM.
+  const bool is_host_on_vm_;
+
   // A hash of the primary profile user ID.
   std::string user_id_hash_;
 
   int32_t lcd_density_;
   uint32_t cpus_;
-
   base::Optional<bool> play_store_auto_update_;
 
+  bool should_notify_observers_ = false;
+
   // For callbacks.
   base::WeakPtrFactory<ArcVmClientAdapter> weak_factory_{this};
 
diff --git a/components/arc/session/arc_vm_client_adapter_unittest.cc b/components/arc/session/arc_vm_client_adapter_unittest.cc
new file mode 100644
index 0000000..1b4a38c
--- /dev/null
+++ b/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -0,0 +1,442 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/session/arc_vm_client_adapter.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/task/post_task.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
+#include "chromeos/dbus/fake_concierge_client.h"
+#include "chromeos/dbus/login_manager/arc.pb.h"
+#include "chromeos/dbus/upstart/fake_upstart_client.h"
+#include "components/arc/arc_util.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+constexpr const char kUserIdHash[] = "this_is_a_valid_user_id_hash";
+
+// A debugd client that can fail to start Concierge.
+// TODO(yusukes): Merge the feature to FakeDebugDaemonClient.
+class TestDebugDaemonClient : public chromeos::FakeDebugDaemonClient {
+ public:
+  TestDebugDaemonClient() = default;
+  ~TestDebugDaemonClient() override = default;
+
+  void StartConcierge(ConciergeCallback callback) override {
+    start_concierge_called_ = true;
+    std::move(callback).Run(start_concierge_result_);
+  }
+
+  bool start_concierge_called() const { return start_concierge_called_; }
+  void set_start_concierge_result(bool result) {
+    start_concierge_result_ = result;
+  }
+
+ private:
+  bool start_concierge_called_ = false;
+  bool start_concierge_result_ = true;
+
+  DISALLOW_COPY_AND_ASSIGN(TestDebugDaemonClient);
+};
+
+// A concierge that remembers the parameter passed to StartArcVm.
+// TODO(yusukes): Merge the feature to FakeConciergeClient.
+class TestConciergeClient : public chromeos::FakeConciergeClient {
+ public:
+  TestConciergeClient() = default;
+  ~TestConciergeClient() override = default;
+
+  void StartArcVm(
+      const vm_tools::concierge::StartArcVmRequest& request,
+      chromeos::DBusMethodCallback<vm_tools::concierge::StartVmResponse>
+          callback) override {
+    start_arc_vm_request_ = request;
+    chromeos::FakeConciergeClient::StartArcVm(request, std::move(callback));
+  }
+
+  const vm_tools::concierge::StartArcVmRequest& start_arc_vm_request() const {
+    return start_arc_vm_request_;
+  }
+
+ private:
+  vm_tools::concierge::StartArcVmRequest start_arc_vm_request_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestConciergeClient);
+};
+
+class ArcVmClientAdapterTest : public testing::Test,
+                               public ArcClientAdapter::Observer {
+ public:
+  ArcVmClientAdapterTest() {
+    // Create and set new fake clients every time to reset clients' status.
+    chromeos::DBusThreadManager::GetSetterForTesting()->SetDebugDaemonClient(
+        std::make_unique<TestDebugDaemonClient>());
+    chromeos::DBusThreadManager::GetSetterForTesting()->SetConciergeClient(
+        std::make_unique<TestConciergeClient>());
+    chromeos::UpstartClient::InitializeFake();
+  }
+
+  ~ArcVmClientAdapterTest() override {
+    chromeos::DBusThreadManager::GetSetterForTesting()->SetConciergeClient(
+        nullptr);
+    chromeos::DBusThreadManager::GetSetterForTesting()->SetDebugDaemonClient(
+        nullptr);
+  }
+
+  void SetUp() override {
+    run_loop_ = std::make_unique<base::RunLoop>();
+    adapter_ = CreateArcVmClientAdapter();
+    arc_instance_stopped_called_ = false;
+    adapter_->AddObserver(this);
+
+    // The fake client returns VM_STATUS_STARTING by default. Change it
+    // to VM_STATUS_RUNNING which is used by ARCVM.
+    vm_tools::concierge::StartVmResponse start_vm_response;
+    start_vm_response.set_status(vm_tools::concierge::VM_STATUS_RUNNING);
+    GetTestConciergeClient()->set_start_vm_response(start_vm_response);
+  }
+
+  void TearDown() override {
+    adapter_->RemoveObserver(this);
+    adapter_.reset();
+    run_loop_.reset();
+  }
+
+  // ArcClientAdapter::Observer:
+  void ArcInstanceStopped() override {
+    arc_instance_stopped_called_ = true;
+    run_loop()->Quit();
+  }
+
+  void ExpectTrueThenQuit(bool result) {
+    EXPECT_TRUE(result);
+    run_loop()->Quit();
+  }
+
+  void ExpectFalseThenQuit(bool result) {
+    EXPECT_FALSE(result);
+    run_loop()->Quit();
+  }
+
+ protected:
+  bool GetStartConciergeCalled() {
+    return GetTestDebugDaemonClient()->start_concierge_called();
+  }
+
+  void SetStartConciergeResponse(bool response) {
+    GetTestDebugDaemonClient()->set_start_concierge_result(response);
+  }
+
+  void SetValidUserIdHash() { adapter()->SetUserIdHashForProfile(kUserIdHash); }
+
+  void StartMiniArc() {
+    StartArcMiniContainerRequest req;
+    adapter()->StartMiniArc(
+        req, base::BindOnce(&ArcVmClientAdapterTest::ExpectTrueThenQuit,
+                            base::Unretained(this)));
+    run_loop()->Run();
+    RecreateRunLoop();
+  }
+
+  void UpgradeArc(bool expect_success) {
+    UpgradeArcContainerRequest req;
+    adapter()->UpgradeArc(
+        req, base::BindOnce(expect_success
+                                ? &ArcVmClientAdapterTest::ExpectTrueThenQuit
+                                : &ArcVmClientAdapterTest::ExpectFalseThenQuit,
+                            base::Unretained(this)));
+    run_loop()->Run();
+    RecreateRunLoop();
+  }
+
+  void SendVmStoppedSignal() {
+    vm_tools::concierge::VmStoppedSignal signal;
+    signal.set_name(kArcVmName);
+    auto& vm_observers = GetTestConciergeClient()->vm_observer_list();
+    for (auto& observer : vm_observers)
+      observer.OnVmStopped(signal);
+  }
+
+  void SendNameOwnerChangedSignal() {
+    auto& observers = GetTestConciergeClient()->observer_list();
+    for (auto& observer : observers)
+      observer.ConciergeServiceStopped();
+  }
+
+  void RecreateRunLoop() { run_loop_ = std::make_unique<base::RunLoop>(); }
+
+  base::RunLoop* run_loop() { return run_loop_.get(); }
+  ArcClientAdapter* adapter() { return adapter_.get(); }
+  bool arc_instance_stopped_called() const {
+    return arc_instance_stopped_called_;
+  }
+  void reset_arc_instance_stopped_called() {
+    arc_instance_stopped_called_ = false;
+  }
+  TestConciergeClient* GetTestConciergeClient() {
+    return static_cast<TestConciergeClient*>(
+        chromeos::DBusThreadManager::Get()->GetConciergeClient());
+  }
+
+ private:
+  TestDebugDaemonClient* GetTestDebugDaemonClient() {
+    return static_cast<TestDebugDaemonClient*>(
+        chromeos::DBusThreadManager::Get()->GetDebugDaemonClient());
+  }
+
+  std::unique_ptr<base::RunLoop> run_loop_;
+  std::unique_ptr<ArcClientAdapter> adapter_;
+  bool arc_instance_stopped_called_;
+
+  content::BrowserTaskEnvironment browser_task_environment_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArcVmClientAdapterTest);
+};
+
+// Tests that SetUserIdHashForProfile() doesn't crash.
+TEST_F(ArcVmClientAdapterTest, SetUserIdHashForProfile) {
+  adapter()->SetUserIdHashForProfile("deadbeef");
+}
+
+// Tests that StartMiniArc() always succeeds.
+TEST_F(ArcVmClientAdapterTest, StartMiniArc) {
+  StartMiniArc();
+  // Confirm that no VM is started. ARCVM doesn't support mini ARC yet.
+  EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
+}
+
+// Tests that StopArcInstance() eventually notifies the observer.
+TEST_F(ArcVmClientAdapterTest, StopArcInstance) {
+  StartMiniArc();
+  adapter()->StopArcInstance();
+  run_loop()->RunUntilIdle();
+  EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
+  // The callback for StopVm D-Bus reply does NOT call ArcInstanceStopped when
+  // the D-Bus call result is successful.
+  EXPECT_FALSE(arc_instance_stopped_called());
+
+  // Instead, vm_concierge explicitly notifies Chrome of the VM termination.
+  RecreateRunLoop();
+  SendVmStoppedSignal();
+  run_loop()->Run();
+  // ..and that calls ArcInstanceStopped.
+  EXPECT_TRUE(arc_instance_stopped_called());
+}
+
+// Tests that StopArcInstance() immediately notifies the observer on failure.
+TEST_F(ArcVmClientAdapterTest, StopArcInstance_Fail) {
+  StartMiniArc();
+
+  // Inject failure.
+  vm_tools::concierge::StopVmResponse response;
+  response.set_success(false);
+  GetTestConciergeClient()->set_stop_vm_response(response);
+
+  adapter()->StopArcInstance();
+  run_loop()->Run();
+  EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
+  // The callback for StopVm D-Bus reply does call ArcInstanceStopped when
+  // the D-Bus call result is NOT successful.
+  EXPECT_TRUE(arc_instance_stopped_called());
+}
+
+// Tests that UpgradeArc() handles arcvm-server-proxy startup failures properly.
+TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmProxyFailure) {
+  SetValidUserIdHash();
+  StartMiniArc();
+
+  // Inject failure to FakeUpstartClient.
+  auto* upstart_client = chromeos::FakeUpstartClient::Get();
+  upstart_client->set_start_job_result(false);
+
+  UpgradeArc(false);
+  EXPECT_FALSE(GetStartConciergeCalled());
+  EXPECT_FALSE(arc_instance_stopped_called());
+  upstart_client->set_start_job_result(true);
+
+  // Try to stop the VM. StopVm will fail in this case because
+  // no VM is running.
+  vm_tools::concierge::StopVmResponse response;
+  response.set_success(false);
+  GetTestConciergeClient()->set_stop_vm_response(response);
+  adapter()->StopArcInstance();
+  run_loop()->Run();
+  EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
+  EXPECT_TRUE(arc_instance_stopped_called());
+}
+
+// Tests that UpgradeArc() handles StartConcierge() failures properly.
+TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartConciergeFailure) {
+  SetValidUserIdHash();
+  StartMiniArc();
+  // Inject failure to StartConcierge().
+  SetStartConciergeResponse(false);
+  UpgradeArc(false);
+  EXPECT_TRUE(GetStartConciergeCalled());
+  EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
+  EXPECT_FALSE(arc_instance_stopped_called());
+
+  // Try to stop the VM. StopVm will fail in this case because
+  // no VM is running.
+  vm_tools::concierge::StopVmResponse response;
+  response.set_success(false);
+  GetTestConciergeClient()->set_stop_vm_response(response);
+  adapter()->StopArcInstance();
+  run_loop()->Run();
+  EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
+  EXPECT_TRUE(arc_instance_stopped_called());
+}
+
+// Tests that "no user ID hash" failure is handled properly.
+TEST_F(ArcVmClientAdapterTest, UpgradeArc_NoUserId) {
+  StartMiniArc();
+
+  // Don't call SetValidUserIdHash(). Note that we cannot call StartArcVm()
+  // without a valid ID.
+  UpgradeArc(false);
+  EXPECT_TRUE(GetStartConciergeCalled());
+  EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
+  EXPECT_FALSE(arc_instance_stopped_called());
+
+  // Try to stop the VM. StopVm will fail in this case because
+  // no VM is running.
+  vm_tools::concierge::StopVmResponse response;
+  response.set_success(false);
+  GetTestConciergeClient()->set_stop_vm_response(response);
+  adapter()->StopArcInstance();
+  run_loop()->Run();
+  EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
+  EXPECT_TRUE(arc_instance_stopped_called());
+}
+
+// Tests that StartArcVm() failure is handled properly.
+TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmFailure) {
+  SetValidUserIdHash();
+  StartMiniArc();
+  // Inject failure to StartArcVm().
+  vm_tools::concierge::StartVmResponse start_vm_response;
+  start_vm_response.set_status(vm_tools::concierge::VM_STATUS_UNKNOWN);
+  GetTestConciergeClient()->set_start_vm_response(start_vm_response);
+
+  UpgradeArc(false);
+  EXPECT_TRUE(GetStartConciergeCalled());
+  EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+  EXPECT_FALSE(arc_instance_stopped_called());
+
+  // Try to stop the VM. StopVm will fail in this case because
+  // no VM is running.
+  vm_tools::concierge::StopVmResponse response;
+  response.set_success(false);
+  GetTestConciergeClient()->set_stop_vm_response(response);
+  adapter()->StopArcInstance();
+  run_loop()->Run();
+  EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
+  EXPECT_TRUE(arc_instance_stopped_called());
+}
+
+// Tests that successful StartArcVm() call is handled properly.
+TEST_F(ArcVmClientAdapterTest, UpgradeArc_Success) {
+  SetValidUserIdHash();
+  StartMiniArc();
+  UpgradeArc(true);
+  EXPECT_TRUE(GetStartConciergeCalled());
+  EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+  EXPECT_FALSE(arc_instance_stopped_called());
+
+  // Try to stop the VM.
+  adapter()->StopArcInstance();
+  run_loop()->RunUntilIdle();
+  EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called());
+  EXPECT_FALSE(arc_instance_stopped_called());
+
+  RecreateRunLoop();
+  SendVmStoppedSignal();
+  run_loop()->Run();
+  EXPECT_TRUE(arc_instance_stopped_called());
+}
+
+// Tests that StartArcVm() is called with valid parameters.
+TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmParams) {
+  SetValidUserIdHash();
+  StartMiniArc();
+  UpgradeArc(true);
+  ASSERT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+
+  // Verify parameters
+  const auto& params = GetTestConciergeClient()->start_arc_vm_request();
+  EXPECT_EQ("arcvm", params.name());
+  EXPECT_EQ(kUserIdHash, params.owner_id());
+  EXPECT_LT(0u, params.cpus());
+  EXPECT_FALSE(params.vm().kernel().empty());
+  // Make sure system.raw.img is passed.
+  EXPECT_FALSE(params.vm().rootfs().empty());
+  // Make sure vendor.raw.img is passed.
+  EXPECT_LE(1, params.disks_size());
+  EXPECT_LT(0, params.params_size());
+}
+
+// Tests that crosvm crash is handled properly.
+TEST_F(ArcVmClientAdapterTest, CrosvmCrash) {
+  SetValidUserIdHash();
+  StartMiniArc();
+  UpgradeArc(true);
+  EXPECT_TRUE(GetStartConciergeCalled());
+  EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+  EXPECT_FALSE(arc_instance_stopped_called());
+
+  // Kill crosvm and verify StopArcInstance is called.
+  SendVmStoppedSignal();
+  run_loop()->Run();
+  EXPECT_TRUE(arc_instance_stopped_called());
+}
+
+// Tests that vm_concierge crash is handled properly.
+TEST_F(ArcVmClientAdapterTest, ConciergeCrash) {
+  SetValidUserIdHash();
+  StartMiniArc();
+  UpgradeArc(true);
+  EXPECT_TRUE(GetStartConciergeCalled());
+  EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+  EXPECT_FALSE(arc_instance_stopped_called());
+
+  // Kill vm_concierge and verify StopArcInstance is called.
+  SendNameOwnerChangedSignal();
+  run_loop()->Run();
+  EXPECT_TRUE(arc_instance_stopped_called());
+}
+
+// Tests the case where crosvm crashes, then vm_concierge crashes too.
+TEST_F(ArcVmClientAdapterTest, CrosvmAndConciergeCrashes) {
+  SetValidUserIdHash();
+  StartMiniArc();
+  UpgradeArc(true);
+  EXPECT_TRUE(GetStartConciergeCalled());
+  EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+  EXPECT_FALSE(arc_instance_stopped_called());
+
+  // Kill crosvm and verify StopArcInstance is called.
+  SendVmStoppedSignal();
+  run_loop()->Run();
+  EXPECT_TRUE(arc_instance_stopped_called());
+
+  // Kill vm_concierge and verify StopArcInstance is NOT called since
+  // the observer has already been called.
+  RecreateRunLoop();
+  reset_arc_instance_stopped_called();
+  SendNameOwnerChangedSignal();
+  run_loop()->RunUntilIdle();
+  EXPECT_FALSE(arc_instance_stopped_called());
+}
+
+}  // namespace
+}  // namespace arc
diff --git a/components/optimization_guide/optimization_guide_features.cc b/components/optimization_guide/optimization_guide_features.cc
index 070879b..0f13743 100644
--- a/components/optimization_guide/optimization_guide_features.cc
+++ b/components/optimization_guide/optimization_guide_features.cc
@@ -49,13 +49,17 @@
 const base::Feature kOptimizationGuideKeyedService{
     "OptimizationGuideKeyedService", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables the prediction of optimization targets.
+const base::Feature kOptimizationTargetPrediction{
+    "OptimizationTargetPrediction", base::FEATURE_DISABLED_BY_DEFAULT};
+
 size_t MaxHintsFetcherTopHostBlacklistSize() {
   // The blacklist will be limited to the most engaged hosts and will hold twice
   // (2*N) as many hosts that the HintsFetcher request hints for. The extra N
   // hosts on the blacklist are meant to cover the case that the engagement
   // scores on some of the top N host engagement scores decay and they fall out
   // of the top N.
-  return GetFieldTrialParamByFeatureAsInt(features::kOptimizationHintsFetching,
+  return GetFieldTrialParamByFeatureAsInt(kOptimizationHintsFetching,
                                           "top_host_blacklist_size_multiplier",
                                           2) *
          MaxHostsForOptimizationGuideServiceHintsFetch();
@@ -63,13 +67,13 @@
 
 size_t MaxHostsForOptimizationGuideServiceHintsFetch() {
   return GetFieldTrialParamByFeatureAsInt(
-      features::kOptimizationHintsFetching,
+      kOptimizationHintsFetching,
       "max_hosts_for_optimization_guide_service_hints_fetch", 30);
 }
 
 size_t MaxHostsForRecordingSuccessfullyCovered() {
   return GetFieldTrialParamByFeatureAsInt(
-      features::kOptimizationHintsFetching,
+      kOptimizationHintsFetching,
       "max_hosts_for_recording_successfully_covered", 200);
 }
 
@@ -78,19 +82,19 @@
   // points for a navigation from the omnibox and 1.5 points for the first
   // navigation of the day.
   return GetFieldTrialParamByFeatureAsDouble(
-      features::kOptimizationHintsFetching,
-      "min_top_host_engagement_score_threshold", 3.0);
+      kOptimizationHintsFetching, "min_top_host_engagement_score_threshold",
+      3.0);
 }
 
 base::TimeDelta StoredFetchedHintsFreshnessDuration() {
   return base::TimeDelta::FromDays(GetFieldTrialParamByFeatureAsInt(
-      features::kOptimizationHintsFetching,
+      kOptimizationHintsFetching,
       "max_store_duration_for_featured_hints_in_days", 7));
 }
 
 base::TimeDelta DurationApplyLowEngagementScoreThreshold() {
   return base::TimeDelta::FromDays(GetFieldTrialParamByFeatureAsInt(
-      features::kOptimizationHintsFetching,
+      kOptimizationHintsFetching,
       "duration_apply_low_engagement_score_threshold_in_days", 30));
 }
 
@@ -115,7 +119,7 @@
   }
 
   std::string url = base::GetFieldTrialParamValueByFeature(
-      features::kOptimizationHintsFetching, "optimization_guide_service_url");
+      kOptimizationHintsFetching, "optimization_guide_service_url");
   if (url.empty() || !GURL(url).SchemeIs(url::kHttpsScheme)) {
     if (!url.empty())
       LOG(WARNING)
@@ -128,27 +132,26 @@
 }
 
 bool IsOptimizationHintsEnabled() {
-  return base::FeatureList::IsEnabled(features::kOptimizationHints);
+  return base::FeatureList::IsEnabled(kOptimizationHints);
 }
 
 bool IsHintsFetchingEnabled() {
-  return base::FeatureList::IsEnabled(features::kOptimizationHintsFetching);
+  return base::FeatureList::IsEnabled(kOptimizationHintsFetching);
 }
 
 bool IsOptimizationGuideKeyedServiceEnabled() {
-  return base::FeatureList::IsEnabled(features::kOptimizationGuideKeyedService);
+  return base::FeatureList::IsEnabled(kOptimizationGuideKeyedService);
 }
 
 int MaxServerBloomFilterByteSize() {
-  return base::GetFieldTrialParamByFeatureAsInt(features::kOptimizationHints,
-                                                "max_bloom_filter_byte_size",
-                                                250 * 1024 /* 250KB */);
+  return base::GetFieldTrialParamByFeatureAsInt(
+      kOptimizationHints, "max_bloom_filter_byte_size", 250 * 1024 /* 250KB */);
 }
 
 base::Optional<net::EffectiveConnectionType>
 GetMaxEffectiveConnectionTypeForNavigationHintsFetch() {
   std::string param_value = base::GetFieldTrialParamValueByFeature(
-      features::kOptimizationHintsFetching,
+      kOptimizationHintsFetching,
       "max_effective_connection_type_for_navigation_hints_fetch");
 
   // Use a default value.
@@ -162,5 +165,9 @@
   return base::TimeDelta::FromHours(72);
 }
 
+bool IsOptimizationTargetPredictionEnabled() {
+  return base::FeatureList::IsEnabled(kOptimizationTargetPrediction);
+}
+
 }  // namespace features
 }  // namespace optimization_guide
diff --git a/components/optimization_guide/optimization_guide_features.h b/components/optimization_guide/optimization_guide_features.h
index a981499e..b367fd03 100644
--- a/components/optimization_guide/optimization_guide_features.h
+++ b/components/optimization_guide/optimization_guide_features.h
@@ -22,6 +22,7 @@
 constexpr char kOptimizationHintsExperimentNameParam[] = "experiment_name";
 extern const base::Feature kOptimizationHintsFetching;
 extern const base::Feature kOptimizationGuideKeyedService;
+extern const base::Feature kOptimizationTargetPrediction;
 
 // The maximum number of hosts that can be stored in the
 // |kHintsFetcherTopHostBlacklist| dictionary pref when initialized. The top
@@ -86,6 +87,9 @@
 // GetHintsFetchRefreshDuration().
 base::TimeDelta GetHintsFetchRefreshDuration();
 
+// Returns true if optimization target prediction is enabled.
+bool IsOptimizationTargetPredictionEnabled();
+
 }  // namespace features
 }  // namespace optimization_guide
 
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index aca3c59..d400c7a0 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -7237,7 +7237,7 @@
       'owners': ['file://components/policy/resources/OWNERS'],
       'type': 'main',
       'schema': { 'type': 'boolean' },
-      'supported_on': ['chrome_os:77-'],
+      'supported_on': ['chrome_os:77-', 'chrome.linux:79-'],
       'features': {
         'dynamic_refresh': False,
         'per_profile': False,
@@ -7246,11 +7246,13 @@
       'id': 575,
       'caption': '''Determines whether the built-in certificate verifier will be used to verify server certificates''',
       'tags': [],
-      'desc': '''When this setting is enabled, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will perform verification of server certificates using the built-in certificate verifier.
-      When this setting is disabled, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will perform verification of server certificates using the legacy certificate verifier provided by the platform.
-      When this setting is not set, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> the built-in or the legacy certificate verifier may be used.
+      'desc': '''When this setting is enabled, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will perform verification of server certificates using the built-in certificate verifier.
+      When this setting is disabled, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will perform verification of server certificates using the legacy certificate verifier provided by the platform.
+      When this setting is not set, the built-in or the legacy certificate verifier may be used.
 
       This policy is planned to be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 81, when support for the legacy certificate verifier on <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> is planned to be removed.
+
+      This policy is planned to be removed in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> for Linux version 83, when support for the legacy certificate verifier on Linux is planned to be removed.
       ''',
     },
     {
@@ -18345,6 +18347,27 @@
       After it is enabled by default, administrators who need more time to upgrade affected proxies may use this policy to temporarily disable this security feature. This policy will be removed after version 85.
       '''
     },
+    {
+      'name': 'AudioSandboxEnabled',
+      'owners': ['services/audio/OWNERS'],
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'supported_on': ['chrome.win:79-', 'chrome.linux:79-', 'chrome.mac:79-'],
+      'features': {
+        'dynamic_refresh': False,
+        'per_profile': False,
+      },
+      'example_value': True,
+      'id': 627,
+      'caption': '''Allow the audio sandbox to run''',
+      'tags': ['system-security'],
+      'desc': '''This policy controls the audio process sandboxed.
+      If this policy is enabled, the audio process will run sandboxed.
+      If this policy is disabled, the audio process will run unsandboxed and the WebRTC audio-processing module will run in the renderer process.
+      This leaves users open to security risks related to running the audio stack unsandboxed.
+      If this policy is not set, the default configuration for the audio sandbox will be used, which may differ per platform.
+      This policy is intended to give enterprises flexibility to disable the audio sandbox if they use security software setups that interfere with the sandbox.'''
+    }
   ],
 
   'messages': {
@@ -19165,6 +19188,6 @@
   ],
   'placeholders': [],
   'deleted_policy_ids': [412, 546, 562, 569],
-  'highest_id_currently_used': 626,
+  'highest_id_currently_used': 627,
   'highest_atomic_group_id_currently_used': 38
 }
diff --git a/components/safe_browsing/browser/safe_browsing_url_checker_impl.cc b/components/safe_browsing/browser/safe_browsing_url_checker_impl.cc
index da22ca6..52f8ba0 100644
--- a/components/safe_browsing/browser/safe_browsing_url_checker_impl.cc
+++ b/components/safe_browsing/browser/safe_browsing_url_checker_impl.cc
@@ -217,6 +217,9 @@
 
   database_manager_->CancelCheck(this);
 
+  // Any pending callbacks on this URL check should be skipped.
+  weak_factory_.InvalidateWeakPtrs();
+
   OnUrlResult(urls_[next_index_].url, safe_browsing::SB_THREAT_TYPE_SAFE,
               ThreatMetadata());
 }
diff --git a/components/search/OWNERS b/components/search/OWNERS
index e5e1133..58de8e2 100644
--- a/components/search/OWNERS
+++ b/components/search/OWNERS
@@ -1,10 +1,16 @@
+# Incoming team
 dbeam@chromium.org
+mahmadi@chromium.org
+
+# Outgoing team
 gayane@chromium.org
 kmilka@chromium.org
 kristipark@chromium.org
-mathp@chromium.org
 ramyan@chromium.org
 
+# Former team
+mathp@chromium.org
+
 # Original implementors of most of the code, but not active in Chromium anymore:
 # - jered@chromium.org
 # - samarth@chromium.org
diff --git a/content/browser/compositor/software_browser_compositor_output_surface.cc b/content/browser/compositor/software_browser_compositor_output_surface.cc
index b7938e45..68027b8f 100644
--- a/content/browser/compositor/software_browser_compositor_output_surface.cc
+++ b/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -73,9 +73,9 @@
 
   gfx::VSyncProvider* vsync_provider = software_device()->GetVSyncProvider();
   if (vsync_provider) {
-    vsync_provider->GetVSyncParameters(
-        base::Bind(&SoftwareBrowserCompositorOutputSurface::UpdateVSyncCallback,
-                   weak_factory_.GetWeakPtr()));
+    vsync_provider->GetVSyncParameters(base::BindOnce(
+        &SoftwareBrowserCompositorOutputSurface::UpdateVSyncCallback,
+        weak_factory_.GetWeakPtr()));
   }
 
   software_device()->OnSwapBuffers(base::BindOnce(
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index a0a667f..cd2aa69 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -960,81 +960,6 @@
     return observer->WaitForFinished();
   }
 
-  // Starts a download without strong validators, interrupts it, and resumes it.
-  // If |fail_content_validation| is true, download content will change during
-  // resumption.
-  void InterruptAndResumeDownloadWithoutStrongValidators(
-      bool fail_content_validation) {
-    int validation_length = 1024;
-    base::test::ScopedFeatureList scoped_feature_list;
-    std::map<std::string, std::string> params = {
-        {download::kDownloadContentValidationLengthFinchKey,
-         base::NumberToString(validation_length)}};
-    scoped_feature_list.InitAndEnableFeatureWithParameters(
-        download::features::kAllowDownloadResumptionWithoutStrongValidators,
-        params);
-    SetupErrorInjectionDownloads();
-    GURL url = TestDownloadHttpResponse::GetNextURLForDownload();
-    GURL server_url = embedded_test_server()->GetURL(url.host(), url.path());
-    TestDownloadHttpResponse::Parameters parameters =
-        TestDownloadHttpResponse::Parameters::WithSingleInterruption(
-            inject_error_callback());
-    parameters.etag.clear();
-    parameters.last_modified.clear();
-    TestDownloadHttpResponse::StartServing(parameters, server_url);
-
-    int64_t interruption_offset = parameters.injected_errors.front();
-    download::DownloadItem* download =
-        StartDownloadAndReturnItem(shell(), server_url);
-    WaitForInterrupt(download);
-
-    ASSERT_EQ(interruption_offset, download->GetReceivedBytes());
-    ASSERT_EQ(parameters.size, download->GetTotalBytes());
-
-    parameters.ClearInjectedErrors();
-    if (fail_content_validation)
-      ++parameters.pattern_generator_seed;
-    TestDownloadHttpResponse::StartServing(parameters, server_url);
-
-    // Download should complete regardless whether content changes or not.
-    download->Resume(false);
-    WaitForCompletion(download);
-
-    ASSERT_EQ(parameters.size, download->GetReceivedBytes());
-    ASSERT_EQ(parameters.size, download->GetTotalBytes());
-    ASSERT_NO_FATAL_FAILURE(ReadAndVerifyFileContents(
-        parameters.pattern_generator_seed, parameters.size,
-        download->GetTargetFilePath()));
-
-    const TestDownloadResponseHandler::CompletedRequests& requests =
-        test_response_handler()->completed_requests();
-    ASSERT_EQ(fail_content_validation ? 3u : 2u, requests.size());
-
-    // The first request only transferrs bytes up until the interruption point.
-    EXPECT_EQ(interruption_offset, requests[0]->transferred_byte_count);
-
-    // The second request is a range request.
-    std::string value;
-    ASSERT_TRUE(requests[1]->http_request.headers.find(
-                    net::HttpRequestHeaders::kIfRange) ==
-                requests[1]->http_request.headers.end());
-
-    ASSERT_TRUE(requests[1]->http_request.headers.find(
-                    net::HttpRequestHeaders::kRange) !=
-                requests[1]->http_request.headers.end());
-    EXPECT_EQ(
-        base::StringPrintf("bytes=%" PRId64 "-",
-                           interruption_offset - validation_length),
-        requests[1]->http_request.headers.at(net::HttpRequestHeaders::kRange));
-    if (fail_content_validation) {
-      // The third request is a restart request.
-      ASSERT_TRUE(requests[2]->http_request.headers.find(
-                      net::HttpRequestHeaders::kRange) ==
-                  requests[2]->http_request.headers.end());
-      EXPECT_EQ(parameters.size, requests[2]->transferred_byte_count);
-    }
-  }
-
   TestDownloadResponseHandler* test_response_handler() {
     return &test_response_handler_;
   }
@@ -1095,6 +1020,90 @@
   TestDownloadHttpResponse::InjectErrorCallback inject_error_callback_;
 };
 
+constexpr int kValidationLength = 1024;
+
+class DownloadContentTestWithoutStrongValidators : public DownloadContentTest {
+ public:
+  DownloadContentTestWithoutStrongValidators() {
+    std::map<std::string, std::string> params = {
+        {download::kDownloadContentValidationLengthFinchKey,
+         base::NumberToString(kValidationLength)}};
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        download::features::kAllowDownloadResumptionWithoutStrongValidators,
+        params);
+  }
+
+  // Starts a download without strong validators, interrupts it, and resumes it.
+  // If |fail_content_validation| is true, download content will change during
+  // resumption.
+  void InterruptAndResumeDownloadWithoutStrongValidators(
+      bool fail_content_validation) {
+    SetupErrorInjectionDownloads();
+    GURL url = TestDownloadHttpResponse::GetNextURLForDownload();
+    GURL server_url = embedded_test_server()->GetURL(url.host(), url.path());
+    TestDownloadHttpResponse::Parameters parameters =
+        TestDownloadHttpResponse::Parameters::WithSingleInterruption(
+            inject_error_callback());
+    parameters.etag.clear();
+    parameters.last_modified.clear();
+    TestDownloadHttpResponse::StartServing(parameters, server_url);
+
+    int64_t interruption_offset = parameters.injected_errors.front();
+    download::DownloadItem* download =
+        StartDownloadAndReturnItem(shell(), server_url);
+    WaitForInterrupt(download);
+
+    ASSERT_EQ(interruption_offset, download->GetReceivedBytes());
+    ASSERT_EQ(parameters.size, download->GetTotalBytes());
+
+    parameters.ClearInjectedErrors();
+    if (fail_content_validation)
+      ++parameters.pattern_generator_seed;
+    TestDownloadHttpResponse::StartServing(parameters, server_url);
+
+    // Download should complete regardless whether content changes or not.
+    download->Resume(false);
+    WaitForCompletion(download);
+
+    ASSERT_EQ(parameters.size, download->GetReceivedBytes());
+    ASSERT_EQ(parameters.size, download->GetTotalBytes());
+    ASSERT_NO_FATAL_FAILURE(ReadAndVerifyFileContents(
+        parameters.pattern_generator_seed, parameters.size,
+        download->GetTargetFilePath()));
+
+    const TestDownloadResponseHandler::CompletedRequests& requests =
+        test_response_handler()->completed_requests();
+    ASSERT_EQ(fail_content_validation ? 3u : 2u, requests.size());
+
+    // The first request only transferrs bytes up until the interruption point.
+    EXPECT_EQ(interruption_offset, requests[0]->transferred_byte_count);
+
+    // The second request is a range request.
+    std::string value;
+    ASSERT_TRUE(requests[1]->http_request.headers.find(
+                    net::HttpRequestHeaders::kIfRange) ==
+                requests[1]->http_request.headers.end());
+
+    ASSERT_TRUE(requests[1]->http_request.headers.find(
+                    net::HttpRequestHeaders::kRange) !=
+                requests[1]->http_request.headers.end());
+    EXPECT_EQ(
+        base::StringPrintf("bytes=%" PRId64 "-",
+                           interruption_offset - kValidationLength),
+        requests[1]->http_request.headers.at(net::HttpRequestHeaders::kRange));
+    if (fail_content_validation) {
+      // The third request is a restart request.
+      ASSERT_TRUE(requests[2]->http_request.headers.find(
+                      net::HttpRequestHeaders::kRange) ==
+                  requests[2]->http_request.headers.end());
+      EXPECT_EQ(parameters.size, requests[2]->transferred_byte_count);
+    }
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
 // Test fixture for parallel downloading.
 class ParallelDownloadTest : public DownloadContentTest {
  protected:
@@ -1702,13 +1711,14 @@
 }
 
 // Test resumption when strong validators are not present in the response.
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithoutStrongValidators) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTestWithoutStrongValidators,
+                       ResumeWithoutStrongValidators) {
   InterruptAndResumeDownloadWithoutStrongValidators(false);
 }
 
 // Test resumption when strong validators are not present in the response and
 // the content of the download changes.
-IN_PROC_BROWSER_TEST_F(DownloadContentTest,
+IN_PROC_BROWSER_TEST_F(DownloadContentTestWithoutStrongValidators,
                        ResumeWithoutStrongValidatorsAndFailValidation) {
   InterruptAndResumeDownloadWithoutStrongValidators(true);
 }
diff --git a/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
index 484f198..b67a40e 100644
--- a/content/browser/frame_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -1137,7 +1137,7 @@
   http_server.AddDefaultHandlers(GetTestDataFilePath());
   int post_counter = 0;
   http_server.RegisterRequestMonitor(
-      base::Bind(&PostRequestMonitor, &post_counter));
+      base::BindRepeating(&PostRequestMonitor, &post_counter));
   ASSERT_TRUE(http_server.Start());
 
   GURL url(http_server.GetURL("/session_history/form.html"));
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc
index f1895dd5..3f72dbd1 100644
--- a/content/browser/media/media_internals.cc
+++ b/content/browser/media/media_internals.cc
@@ -41,6 +41,7 @@
 #include "media/webrtc/webrtc_switches.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/service_manager/sandbox/features.h"
+#include "services/service_manager/sandbox/sandbox_type.h"
 
 #if !defined(OS_ANDROID)
 #include "media/filters/decrypting_video_decoder.h"
@@ -429,6 +430,11 @@
                                                           : "Disabled"));
   };
 
+  auto set_explicit_feature_data = [&](auto& feature, bool feature_value) {
+    audio_info_data.SetKey(feature.name,
+                           base::Value(feature_value ? "Enabled" : "Disabled"));
+  };
+
   set_feature_data(features::kAudioServiceAudioStreams);
   set_feature_data(features::kAudioServiceOutOfProcess);
 
@@ -448,8 +454,10 @@
                          base::Value(feature_value_string));
 
   set_feature_data(features::kAudioServiceLaunchOnStartup);
-  set_feature_data(service_manager::features::kAudioServiceSandbox);
-  set_feature_data(features::kWebRtcApmInAudioService);
+  set_explicit_feature_data(service_manager::features::kAudioServiceSandbox,
+                            service_manager::IsAudioSandboxEnabled());
+  set_explicit_feature_data(features::kWebRtcApmInAudioService,
+                            media::IsWebRtcApmInAudioServiceEnabled());
 
   base::string16 audio_info_update =
       SerializeUpdate("media.updateGeneralAudioInformation", &audio_info_data);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 4d5b42f..46a62c9 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3034,8 +3034,9 @@
     switches::kEnableWebGLImageChromium,
     switches::kEnableWebVR,
     switches::kFileUrlPathAlias,
-    switches::kForceDisplayColorProfile,
     switches::kForceDeviceScaleFactor,
+    switches::kForceDisableWebRtcApmInAudioService,
+    switches::kForceDisplayColorProfile,
     switches::kForceGpuMemAvailableMb,
     switches::kForceGpuRasterization,
     switches::kForceHighContrast,
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 6bf572d..406c7d8 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -404,8 +404,8 @@
 
   if (!command_line->HasSwitch(switches::kDisableNewContentRenderingTimeout)) {
     new_content_rendering_timeout_ = std::make_unique<TimeoutMonitor>(
-        base::Bind(&RenderWidgetHostImpl::ClearDisplayedGraphics,
-                   weak_factory_.GetWeakPtr()));
+        base::BindRepeating(&RenderWidgetHostImpl::ClearDisplayedGraphics,
+                            weak_factory_.GetWeakPtr()));
   }
 
   enable_viz_ = features::IsVizDisplayCompositorEnabled();
@@ -1754,12 +1754,12 @@
 }
 
 void RenderWidgetHostImpl::GetSnapshotFromBrowser(
-    const GetSnapshotFromBrowserCallback& callback,
+    GetSnapshotFromBrowserCallback callback,
     bool from_surface) {
   int snapshot_id = next_browser_snapshot_id_++;
   if (from_surface) {
     pending_surface_browser_snapshots_.insert(
-        std::make_pair(snapshot_id, callback));
+        std::make_pair(snapshot_id, std::move(callback)));
     Send(new WidgetMsg_ForceRedraw(GetRoutingID(), snapshot_id));
     return;
   }
@@ -1772,7 +1772,8 @@
     GetWakeLock()->RequestWakeLock();
 #endif
   // TODO(nzolghadr): Remove the duplication here and the if block just above.
-  pending_browser_snapshots_.insert(std::make_pair(snapshot_id, callback));
+  pending_browser_snapshots_.insert(
+      std::make_pair(snapshot_id, std::move(callback)));
   Send(new WidgetMsg_ForceRedraw(GetRoutingID(), snapshot_id));
 }
 
@@ -2884,8 +2885,8 @@
 
     ui::GrabViewSnapshotAsync(
         GetView()->GetNativeView(), snapshot_bounds,
-        base::Bind(&RenderWidgetHostImpl::OnSnapshotReceived,
-                   weak_factory_.GetWeakPtr(), snapshot_id));
+        base::BindOnce(&RenderWidgetHostImpl::OnSnapshotReceived,
+                       weak_factory_.GetWeakPtr(), snapshot_id));
   }
 }
 
@@ -2911,7 +2912,7 @@
   auto it = pending_surface_browser_snapshots_.begin();
   while (it != pending_surface_browser_snapshots_.end()) {
     if (it->first <= snapshot_id) {
-      it->second.Run(image);
+      std::move(it->second).Run(image);
       pending_surface_browser_snapshots_.erase(it++);
     } else {
       ++it;
@@ -2926,7 +2927,7 @@
   auto it = pending_browser_snapshots_.begin();
   while (it != pending_browser_snapshots_.end()) {
     if (it->first <= snapshot_id) {
-      it->second.Run(image);
+      std::move(it->second).Run(image);
       pending_browser_snapshots_.erase(it++);
     } else {
       ++it;
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 2cb77fc8..4df850f5 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -307,8 +307,8 @@
   // Returns a gfx::Image that is backed by an NSImage on MacOS or by an
   // SkBitmap otherwise. The gfx::Image may be empty if the snapshot failed.
   using GetSnapshotFromBrowserCallback =
-      base::Callback<void(const gfx::Image&)>;
-  void GetSnapshotFromBrowser(const GetSnapshotFromBrowserCallback& callback,
+      base::OnceCallback<void(const gfx::Image&)>;
+  void GetSnapshotFromBrowser(GetSnapshotFromBrowserCallback callback,
                               bool from_surface);
 
   // Sets the View of this RenderWidgetHost.
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index c8154bd..818a637 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -2335,24 +2335,26 @@
 StoragePartitionImpl::GetOriginPolicyManagerForBrowserProcess() {
   DCHECK(initialized_);
   if (!origin_policy_manager_for_browser_process_ ||
-      origin_policy_manager_for_browser_process_.encountered_error()) {
+      !origin_policy_manager_for_browser_process_.is_connected()) {
     GetNetworkContext()->GetOriginPolicyManager(
-        mojo::MakeRequest(&origin_policy_manager_for_browser_process_));
+        origin_policy_manager_for_browser_process_
+            .BindNewPipeAndPassReceiver());
   }
   return origin_policy_manager_for_browser_process_.get();
 }
 
 void StoragePartitionImpl::SetOriginPolicyManagerForBrowserProcessForTesting(
-    network::mojom::OriginPolicyManagerPtr test_origin_policy_manager) {
+    mojo::PendingRemote<network::mojom::OriginPolicyManager>
+        test_origin_policy_manager) {
   DCHECK(initialized_);
-  origin_policy_manager_for_browser_process_ =
-      std::move(test_origin_policy_manager);
+  origin_policy_manager_for_browser_process_.Bind(
+      std::move(test_origin_policy_manager));
 }
 
 void StoragePartitionImpl::
     ResetOriginPolicyManagerForBrowserProcessForTesting() {
   DCHECK(initialized_);
-  origin_policy_manager_for_browser_process_ = nullptr;
+  origin_policy_manager_for_browser_process_.reset();
 }
 
 }  // namespace content
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index c52e421..1a40b74 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -300,7 +300,8 @@
 
   // Override the origin policy manager for testing use only.
   void SetOriginPolicyManagerForBrowserProcessForTesting(
-      network::mojom::OriginPolicyManagerPtr test_origin_policy_manager);
+      mojo::PendingRemote<network::mojom::OriginPolicyManager>
+          test_origin_policy_manager);
   void ResetOriginPolicyManagerForBrowserProcessForTesting();
 
  private:
@@ -487,7 +488,7 @@
   bool is_test_url_loader_factory_for_browser_process_with_corb_ = false;
   mojo::Remote<network::mojom::CookieManager>
       cookie_manager_for_browser_process_;
-  network::mojom::OriginPolicyManagerPtr
+  mojo::Remote<network::mojom::OriginPolicyManager>
       origin_policy_manager_for_browser_process_;
 
   // See comments for site_for_service_worker().
diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
index c560a27..08618d9 100644
--- a/content/browser/utility_process_host.cc
+++ b/content/browser/utility_process_host.cc
@@ -426,6 +426,7 @@
       switches::kAudioServiceQuitTimeoutMs,
       switches::kDisableAudioOutput,
       switches::kFailAudioStreamCreation,
+      switches::kForceDisableWebRtcApmInAudioService,
       switches::kMuteAudio,
       switches::kUseFileForFakeAudioCapture,
       switches::kAgcStartupMinVolume,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 70cf3d2..e18ce79 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -134,6 +134,7 @@
 #include "content/public/common/referrer_type_converters.h"
 #include "content/public/common/result_codes.h"
 #include "content/public/common/url_utils.h"
+#include "content/public/common/use_zoom_for_dsf_policy.h"
 #include "content/public/common/web_preferences.h"
 #include "media/base/user_input_monitor.h"
 #include "net/base/url_util.h"
@@ -1668,8 +1669,25 @@
 
 void WebContentsImpl::NotifyVisibleViewportSizeChanged(
     const gfx::Size& visible_viewport_size) {
+  // This viewport size is in screen coordinates, but will be handed to blink
+  // which expects coordinates including the device scale factor when
+  // UseZoomForDSF is enabled.
+  // TODO(danakj): This scaling should be done in the renderer where emulation
+  // may override the device scale factor.
+  gfx::Size visible_viewport_size_for_blink = visible_viewport_size;
+  if (IsUseZoomForDSFEnabled()) {
+    ScreenInfo info;
+    GetMainFrame()->GetRenderWidgetHost()->GetScreenInfo(&info);
+
+    visible_viewport_size_for_blink =
+        gfx::ScaleToCeiledSize(visible_viewport_size, info.device_scale_factor);
+  }
+
+  // TODO(danakj): This should be part of VisualProperties and walk down the
+  // RenderWidget tree like other VisualProperties do, in order to set the
+  // value in each WebView holds a part of the local frame tree.
   SendPageMessage(new PageMsg_UpdatePageVisualProperties(
-      MSG_ROUTING_NONE, visible_viewport_size));
+      MSG_ROUTING_NONE, visible_viewport_size_for_blink));
 }
 
 RenderFrameHostImpl* WebContentsImpl::GetFocusedFrameFromFocusedDelegate() {
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc b/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
deleted file mode 100644
index d99eadc59..0000000
--- a/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
+++ /dev/null
@@ -1,243 +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 "third_party/blink/public/web/modules/peerconnection/media_stream_remote_video_source.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/child/child_process.h"
-#include "media/base/video_frame.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
-#include "third_party/blink/public/platform/modules/webrtc/track_observer.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
-#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_sink.h"
-#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
-#include "third_party/blink/public/web/web_heap.h"
-#include "third_party/webrtc/api/video/color_space.h"
-#include "third_party/webrtc/api/video/i420_buffer.h"
-#include "ui/gfx/color_space.h"
-
-namespace content {
-
-ACTION_P(RunClosure, closure) {
-  closure.Run();
-}
-
-class MediaStreamRemoteVideoSourceUnderTest
-    : public blink::MediaStreamRemoteVideoSource {
- public:
-  explicit MediaStreamRemoteVideoSourceUnderTest(
-      std::unique_ptr<blink::TrackObserver> observer)
-      : MediaStreamRemoteVideoSource(std::move(observer)) {}
-  using MediaStreamRemoteVideoSource::SinkInterfaceForTesting;
-  using MediaStreamRemoteVideoSource::StartSourceImpl;
-};
-
-class MediaStreamRemoteVideoSourceTest
-    : public ::testing::Test {
- public:
-  MediaStreamRemoteVideoSourceTest()
-      : task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
-        child_process_(new ChildProcess()),
-        mock_factory_(new blink::MockPeerConnectionDependencyFactory()),
-        webrtc_video_track_(blink::MockWebRtcVideoTrack::Create("test")),
-        remote_source_(nullptr),
-        number_of_successful_track_starts_(0),
-        number_of_failed_track_starts_(0) {}
-
-  void SetUp() override {
-    scoped_refptr<base::SingleThreadTaskRunner> main_thread =
-        blink::scheduler::GetSingleThreadTaskRunnerForTesting();
-
-    base::WaitableEvent waitable_event(
-        base::WaitableEvent::ResetPolicy::MANUAL,
-        base::WaitableEvent::InitialState::NOT_SIGNALED);
-
-    std::unique_ptr<blink::TrackObserver> track_observer;
-    mock_factory_->GetWebRtcSignalingThread()->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            [](scoped_refptr<base::SingleThreadTaskRunner> main_thread,
-               webrtc::MediaStreamTrackInterface* webrtc_track,
-               std::unique_ptr<blink::TrackObserver>* track_observer,
-               base::WaitableEvent* waitable_event) {
-              track_observer->reset(
-                  new blink::TrackObserver(main_thread, webrtc_track));
-              waitable_event->Signal();
-            },
-            main_thread, base::Unretained(webrtc_video_track_.get()),
-            base::Unretained(&track_observer),
-            base::Unretained(&waitable_event)));
-    waitable_event.Wait();
-
-    remote_source_ =
-        new MediaStreamRemoteVideoSourceUnderTest(std::move(track_observer));
-    webkit_source_.Initialize(blink::WebString::FromASCII("dummy_source_id"),
-                              blink::WebMediaStreamSource::kTypeVideo,
-                              blink::WebString::FromASCII("dummy_source_name"),
-                              true /* remote */);
-    webkit_source_.SetPlatformSource(base::WrapUnique(remote_source_));
-  }
-
-  void TearDown() override {
-    remote_source_->OnSourceTerminated();
-    webkit_source_.Reset();
-    blink::WebHeap::CollectAllGarbageForTesting();
-  }
-
-  MediaStreamRemoteVideoSourceUnderTest* source() {
-    return remote_source_;
-  }
-
-  blink::MediaStreamVideoTrack* CreateTrack() {
-    bool enabled = true;
-    return new blink::MediaStreamVideoTrack(
-        source(),
-        base::Bind(&MediaStreamRemoteVideoSourceTest::OnTrackStarted,
-                   base::Unretained(this)),
-        enabled);
-  }
-
-  int NumberOfSuccessConstraintsCallbacks() const {
-    return number_of_successful_track_starts_;
-  }
-
-  int NumberOfFailedConstraintsCallbacks() const {
-    return number_of_failed_track_starts_;
-  }
-
-  void StopWebRtcTrack() {
-    base::WaitableEvent waitable_event(
-        base::WaitableEvent::ResetPolicy::MANUAL,
-        base::WaitableEvent::InitialState::NOT_SIGNALED);
-    mock_factory_->GetWebRtcSignalingThread()->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            [](blink::MockWebRtcVideoTrack* video_track,
-               base::WaitableEvent* waitable_event) {
-              video_track->SetEnded();
-              waitable_event->Signal();
-            },
-            base::Unretained(static_cast<blink::MockWebRtcVideoTrack*>(
-                webrtc_video_track_.get())),
-            base::Unretained(&waitable_event)));
-    waitable_event.Wait();
-  }
-
-  const blink::WebMediaStreamSource& webkit_source() const {
-    return  webkit_source_;
-  }
-
- private:
-  void OnTrackStarted(blink::WebPlatformMediaStreamSource* source,
-                      blink::mojom::MediaStreamRequestResult result,
-                      const blink::WebString& result_name) {
-    ASSERT_EQ(source, remote_source_);
-    if (result == blink::mojom::MediaStreamRequestResult::OK)
-      ++number_of_successful_track_starts_;
-    else
-      ++number_of_failed_track_starts_;
-  }
-
-  base::test::TaskEnvironment task_environment_;
-  std::unique_ptr<ChildProcess> child_process_;
-  std::unique_ptr<blink::MockPeerConnectionDependencyFactory> mock_factory_;
-  scoped_refptr<webrtc::VideoTrackInterface> webrtc_video_track_;
-  // |remote_source_| is owned by |webkit_source_|.
-  MediaStreamRemoteVideoSourceUnderTest* remote_source_;
-  blink::WebMediaStreamSource webkit_source_;
-  int number_of_successful_track_starts_;
-  int number_of_failed_track_starts_;
-};
-
-TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) {
-  std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack());
-  EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
-
-  blink::MockMediaStreamVideoSink sink;
-  track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
-  base::RunLoop run_loop;
-  base::Closure quit_closure = run_loop.QuitClosure();
-  EXPECT_CALL(sink, OnVideoFrame())
-      .WillOnce(RunClosure(std::move(quit_closure)));
-  rtc::scoped_refptr<webrtc::I420Buffer> buffer(
-      new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240));
-
-  webrtc::I420Buffer::SetBlack(buffer);
-
-  source()->SinkInterfaceForTesting()->OnFrame(
-      webrtc::VideoFrame::Builder()
-          .set_video_frame_buffer(buffer)
-          .set_rotation(webrtc::kVideoRotation_0)
-          .set_timestamp_us(1000)
-          .build());
-  run_loop.Run();
-
-  EXPECT_EQ(1, sink.number_of_frames());
-  track->RemoveSink(&sink);
-}
-
-TEST_F(MediaStreamRemoteVideoSourceTest, RemoteTrackStop) {
-  std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack());
-
-  blink::MockMediaStreamVideoSink sink;
-  track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
-  EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateLive, sink.state());
-  EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateLive,
-            webkit_source().GetReadyState());
-  StopWebRtcTrack();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateEnded,
-            webkit_source().GetReadyState());
-  EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateEnded, sink.state());
-
-  track->RemoveSink(&sink);
-}
-
-TEST_F(MediaStreamRemoteVideoSourceTest, PreservesColorSpace) {
-  std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack());
-  blink::MockMediaStreamVideoSink sink;
-  track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
-
-  base::RunLoop run_loop;
-  EXPECT_CALL(sink, OnVideoFrame())
-      .WillOnce(RunClosure(run_loop.QuitClosure()));
-  rtc::scoped_refptr<webrtc::I420Buffer> buffer(
-      new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240));
-  webrtc::ColorSpace kColorSpace(webrtc::ColorSpace::PrimaryID::kSMPTE240M,
-                                 webrtc::ColorSpace::TransferID::kSMPTE240M,
-                                 webrtc::ColorSpace::MatrixID::kSMPTE240M,
-                                 webrtc::ColorSpace::RangeID::kLimited);
-  const webrtc::VideoFrame& input_frame =
-      webrtc::VideoFrame::Builder()
-          .set_video_frame_buffer(buffer)
-          .set_timestamp_ms(0)
-          .set_rotation(webrtc::kVideoRotation_0)
-          .set_color_space(kColorSpace)
-          .build();
-  source()->SinkInterfaceForTesting()->OnFrame(input_frame);
-  run_loop.Run();
-
-  EXPECT_EQ(1, sink.number_of_frames());
-  scoped_refptr<media::VideoFrame> output_frame = sink.last_frame();
-  EXPECT_TRUE(output_frame);
-  EXPECT_TRUE(output_frame->ColorSpace() ==
-              gfx::ColorSpace(gfx::ColorSpace::PrimaryID::SMPTE240M,
-                              gfx::ColorSpace::TransferID::SMPTE240M,
-                              gfx::ColorSpace::MatrixID::SMPTE240M,
-                              gfx::ColorSpace::RangeID::LIMITED));
-  track->RemoveSink(&sink);
-}
-
-}  // namespace content
diff --git a/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc b/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc
deleted file mode 100644
index ee46734..0000000
--- a/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc
+++ /dev/null
@@ -1,68 +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 "third_party/blink/public/web/modules/peerconnection/media_stream_video_webrtc_sink.h"
-
-#include "base/test/task_environment.h"
-#include "content/child/child_process.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_registry.h"
-#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h"
-#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
-
-namespace content {
-namespace {
-
-class MediaStreamVideoWebRtcSinkTest : public ::testing::Test {
- public:
-  MediaStreamVideoWebRtcSinkTest()
-      : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
-
-  void SetVideoTrack() {
-    registry_.Init();
-    registry_.AddVideoTrack("test video track");
-    blink::WebVector<blink::WebMediaStreamTrack> video_tracks =
-        registry_.test_stream().VideoTracks();
-    track_ = video_tracks[0];
-    // TODO(hta): Verify that track_ is valid. When constraints produce
-    // no valid format, using the track will cause a crash.
-  }
-
-  void SetVideoTrack(const base::Optional<bool>& noise_reduction) {
-    registry_.Init();
-    registry_.AddVideoTrack("test video track",
-                            blink::VideoTrackAdapterSettings(), noise_reduction,
-                            false, 0.0);
-    blink::WebVector<blink::WebMediaStreamTrack> video_tracks =
-        registry_.test_stream().VideoTracks();
-    track_ = video_tracks[0];
-    // TODO(hta): Verify that track_ is valid. When constraints produce
-    // no valid format, using the track will cause a crash.
-  }
-
- protected:
-  blink::WebMediaStreamTrack track_;
-  blink::MockPeerConnectionDependencyFactory dependency_factory_;
-
- private:
-  blink::MockMediaStreamRegistry registry_;
-  // A ChildProcess is needed to fool the Tracks and Sources into believing they
-  // are on the right threads. A TaskEnvironment must be instantiated
-  // before ChildProcess to prevent it from leaking a ThreadPool.
-  base::test::TaskEnvironment task_environment_;
-  const ChildProcess child_process_;
-};
-
-TEST_F(MediaStreamVideoWebRtcSinkTest, NoiseReductionDefaultsToNotSet) {
-  SetVideoTrack();
-  blink::MediaStreamVideoWebRtcSink my_sink(
-      track_, &dependency_factory_,
-      blink::scheduler::GetSingleThreadTaskRunnerForTesting());
-  EXPECT_TRUE(my_sink.webrtc_video_track());
-  EXPECT_FALSE(my_sink.SourceNeedsDenoisingForTesting());
-}
-
-}  // namespace
-}  // namespace content
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 63fa8c2..1749a32 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -2636,9 +2636,10 @@
     *size = view_data_.rect.size;
   } else {
     // All other cases: Report the screen size.
-    if (!render_frame_ || !render_frame_->GetLocalRootRenderWidget())
+    if (!render_frame_)
       return PP_FALSE;
-    blink::WebScreenInfo info = render_frame_->render_view()->GetScreenInfo();
+    blink::WebScreenInfo info =
+        render_frame_->GetLocalRootRenderWidget()->GetScreenInfo();
     *size = PP_MakeSize(info.rect.width, info.rect.height);
   }
   return PP_TRUE;
@@ -3221,7 +3222,8 @@
   // behavior, the width and height should probably be set to 100%, rather than
   // a fixed screen size.
 
-  blink::WebScreenInfo info = render_frame_->render_view()->GetScreenInfo();
+  blink::WebScreenInfo info =
+      render_frame_->GetLocalRootRenderWidget()->GetScreenInfo();
   screen_size_for_fullscreen_ = gfx::Size(info.rect.width, info.rect.height);
   std::string width = base::NumberToString(screen_size_for_fullscreen_.width());
   std::string height =
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 2e3518d..1c53aa8 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1474,9 +1474,10 @@
   auto* web_frame_widget =
       blink::WebFrameWidget::CreateForMainFrame(render_widget, web_frame);
 
-  render_widget->InitForMainFrame(std::move(show_callback));
-  render_view->AttachWebFrameWidget(web_frame_widget);
-
+  render_widget->InitForMainFrame(std::move(show_callback), web_frame_widget,
+                                  &params->visual_properties.screen_info);
+  // AttachWebFrameWidget() is not needed here since InitForMainFrame() received
+  // the WebFrameWidget.
   render_widget->SynchronizeVisualPropertiesFromRenderView(
       params->visual_properties);
 
@@ -1628,7 +1629,8 @@
     // create the RenderWidget if the RenderFrame owned it instead of having the
     // RenderWidget live for eternity on the RenderView (after setting up the
     // WebFrameWidget since that would be part of creating the RenderWidget).
-    render_view->ReviveUndeadMainFrameRenderWidget();
+    render_view->ReviveUndeadMainFrameRenderWidget(
+        widget_params->visual_properties.screen_info);
 
     // The RenderViewImpl and its RenderWidget already exist by the time we
     // get here (we get them from the RenderFrameProxy).
@@ -1681,7 +1683,8 @@
     // Adds a reference on RenderWidget, making it self-referencing. So it
     // will not be destroyed by scoped_refptr unless Close() has been called
     // and run.
-    render_widget->InitForChildLocalRoot(web_frame_widget);
+    render_widget->InitForChildLocalRoot(
+        web_frame_widget, widget_params->visual_properties.screen_info);
 
     render_frame->render_widget_ = render_widget.get();
     render_frame->owned_render_widget_ = std::move(render_widget);
@@ -5258,23 +5261,17 @@
   WebDocumentLoader* document_loader = frame_->GetDocumentLoader();
   WillSendRequestInternal(
       request, WebURLRequestToResourceType(request),
-      DocumentState::FromDocumentLoader(document_loader),
       GetTransitionType(document_loader, IsMainFrame(), false /* loading */));
 }
 
 void RenderFrameImpl::WillSendRequestInternal(
     blink::WebURLRequest& request,
     ResourceType resource_type,
-    DocumentState* document_state,
     ui::PageTransition transition_type) {
   if (render_view_->renderer_preferences_.enable_do_not_track)
     request.SetHttpHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader),
                                "1");
 
-  InternalDocumentStateData* internal_data =
-      InternalDocumentStateData::FromDocumentState(document_state);
-  NavigationState* navigation_state = internal_data->navigation_state();
-
   ApplyFilePathAlias(&request);
   GURL new_url;
   bool attach_same_site_cookies = false;
@@ -5338,25 +5335,6 @@
             routing_id_, request, resource_type));
   }
 
-  if (request.GetPreviewsState() == WebURLRequest::kPreviewsUnspecified) {
-    if (is_main_frame_ && !navigation_state->request_committed()) {
-      request.SetPreviewsState(static_cast<WebURLRequest::PreviewsState>(
-          navigation_state->common_params().previews_state));
-    } else {
-      WebURLRequest::PreviewsState request_previews_state =
-          static_cast<WebURLRequest::PreviewsState>(GetPreviewsState());
-
-      // The decision of whether or not to enable Client Lo-Fi is made earlier
-      // in the request lifetime, in LocalFrame::MaybeAllowImagePlaceholder(),
-      // so don't add the Client Lo-Fi bit to the request here.
-      request_previews_state &= ~(WebURLRequest::kLazyImageLoadDeferred);
-      if (request_previews_state == WebURLRequest::kPreviewsUnspecified)
-        request_previews_state = WebURLRequest::kPreviewsOff;
-
-      request.SetPreviewsState(request_previews_state);
-    }
-  }
-
   // This is an instance where we embed a copy of the routing id
   // into the data portion of the message. This can cause problems if we
   // don't register this id on the browser side, since the download manager
@@ -6968,7 +6946,6 @@
 void RenderFrameImpl::BeginNavigationInternal(
     std::unique_ptr<blink::WebNavigationInfo> info,
     bool is_history_navigation_in_new_child_frame) {
-  std::unique_ptr<DocumentState> document_state = BuildDocumentState();
   if (!frame_->WillStartNavigation(*info,
                                    is_history_navigation_in_new_child_frame))
     return;
@@ -7009,7 +6986,7 @@
   WillSendRequestInternal(
       request,
       frame_->Parent() ? ResourceType::kSubFrame : ResourceType::kMainFrame,
-      document_state.get(), transition_type);
+      transition_type);
 
   if (!info->url_request.GetExtraData())
     info->url_request.SetExtraData(std::make_unique<RequestExtraData>());
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 22e23940..1bda8aa 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -1293,13 +1293,9 @@
   bool ShouldDisplayErrorPageForFailedLoad(int error_code,
                                            const GURL& unreachable_url);
 
-  // |document_state| and |transition_type| correspond to the document which
-  // triggered this request. For main resource requests (navigations),
-  // |document_state| is a newly created one, and will be used for committing
-  // the navigation and creating the new document.
+  // |transition_type| corresponds to the document which triggered this request.
   void WillSendRequestInternal(blink::WebURLRequest& request,
                                ResourceType resource_type,
-                               DocumentState* document_state,
                                ui::PageTransition transition_type);
 
   // Returns the URL being loaded by the |frame_|'s request.
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 382d523d..385b4ca 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -516,7 +516,12 @@
         page_properties(), params->visual_properties.display_mode,
         /*is_undead=*/true, params->never_visible);
     undead_render_widget_->set_delegate(this);
-    undead_render_widget_->InitForMainFrame(std::move(show_callback));
+    // We intentionally pass in a null webwidget since it is not needed
+    // for remote frames, and we don't have one or a ScreenInfo until we have
+    // a local main frame.
+    undead_render_widget_->InitForMainFrame(std::move(show_callback),
+                                            /*web_frame_widget=*/nullptr,
+                                            /*screen_info=*/nullptr);
 
     RenderFrameProxy::CreateFrameProxy(params->proxy_routing_id, GetRoutingID(),
                                        opener_frame, MSG_ROUTING_NONE,
@@ -1490,7 +1495,8 @@
   // Adds a self-reference on the |popup_widget| so it will not be destroyed
   // when leaving scope. The WebPagePopup takes responsibility for Close()ing
   // and thus destroying the RenderWidget.
-  popup_widget->InitForPopup(std::move(opener_callback), popup_web_widget);
+  popup_widget->InitForPopup(std::move(opener_callback), popup_web_widget,
+                             render_widget->GetOriginalScreenInfo());
   // TODO(crbug.com/419087): RenderWidget has some weird logic for picking a
   // WebWidget which doesn't apply to this case. So we verify. This can go away
   // when RenderWidget::GetWebWidget() is just a simple accessor.
@@ -1543,16 +1549,10 @@
   // The previous WebFrameWidget must already be detached by
   // DetachWebFrameWidget().
   DCHECK(!render_widget_->GetWebWidget());
-
   render_widget_->SetWebWidgetInternal(frame_widget);
 
-  // Initialization for the WebFrameWidget that should only occur for the main
-  // frame, and that uses types not allowed in blink. This should maybe be
-  // passed to the creation of the WebFrameWidget or the main RenderFrame.
-  const base::CommandLine& command_line =
-      *base::CommandLine::ForCurrentProcess();
-  render_widget_->SetShowFPSCounter(
-      command_line.HasSwitch(cc::switches::kShowFPSCounter));
+  // Note that when a main frame RenderWidget is created with a main frame, then
+  // this method is not used, so other initialization should not be done here.
 }
 
 void RenderViewImpl::DetachWebFrameWidget() {
@@ -1574,7 +1574,7 @@
     // detached and replaced with a remote frame proxy. We can't close the
     // RenderWidget, and it is marked undead instead, but we do need to close
     // the WebFrameWidget and remove it from the RenderWidget.
-    render_widget_->SetIsUndead(true);
+    render_widget_->SetIsUndead();
     // The WebWidget needs to be closed even though the RenderWidget won't be
     // closed here (since it is marked undead instead).
     render_widget_->GetWebWidget()->Close();
@@ -1925,9 +1925,10 @@
   // does not change when tests override the visibility of the Page.
 }
 
-void RenderViewImpl::ReviveUndeadMainFrameRenderWidget() {
+void RenderViewImpl::ReviveUndeadMainFrameRenderWidget(
+    const ScreenInfo& screen_info) {
   render_widget_ = std::move(undead_render_widget_);
-  render_widget_->SetIsUndead(false);
+  render_widget_->SetIsRevivedFromUndead(screen_info);
 }
 
 void RenderViewImpl::OnUpdateWebPreferences(const WebPreferences& prefs) {
@@ -2047,23 +2048,16 @@
 }
 
 void RenderViewImpl::OnUpdatePageVisualProperties(
-    const gfx::Size& viewport_size) {
+    const gfx::Size& viewport_size_for_blink) {
   // TODO(https://crbug.com/998273): Handle visual_properties appropriately.
   // Using this pathway to update the visual viewport should only happen for
   // remote main frames. Local main frames will update the viewport size by
   // RenderWidget calling RenderViewImpl::ResizeVisualViewport() directly.
-  if (!main_render_frame_) {
-    // Since the viewport size comes directly from the browser, we may
-    // need to adjust it for device scale factor.
-    // TODO(wjmaclean): we should look into having the browser apply this scale
-    // before sending the viewport size.
-    gfx::Size device_scale_factor_scaled_visual_viewport_size = viewport_size;
-    if (RenderThreadImpl::current()->IsUseZoomForDSFEnabled()) {
-      device_scale_factor_scaled_visual_viewport_size = gfx::ScaleToCeiledSize(
-          viewport_size, GetScreenInfo().device_scale_factor);
-    }
-    webview()->Resize(device_scale_factor_scaled_visual_viewport_size);
-  }
+  // TODO(danakj): This should be part of VisualProperties and walk down the
+  // RenderWidget tree like other VisualProperties do, in order to set the
+  // value in each WebView holds a part of the local frame tree.
+  if (!main_render_frame_)
+    webview()->Resize(viewport_size_for_blink);
 }
 
 void RenderViewImpl::ResizeVisualViewportForWidget(
@@ -2161,43 +2155,6 @@
   }
 }
 
-blink::WebScreenInfo RenderViewImpl::GetScreenInfo() {
-  const ScreenInfo& info = page_properties()->GetScreenInfo();
-
-  blink::WebScreenInfo web_screen_info;
-  web_screen_info.device_scale_factor = info.device_scale_factor;
-  web_screen_info.color_space = info.color_space;
-  web_screen_info.depth = info.depth;
-  web_screen_info.depth_per_component = info.depth_per_component;
-  web_screen_info.is_monochrome = info.is_monochrome;
-  web_screen_info.rect = blink::WebRect(info.rect);
-  web_screen_info.available_rect = blink::WebRect(info.available_rect);
-  switch (info.orientation_type) {
-    case SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY:
-      web_screen_info.orientation_type =
-          blink::kWebScreenOrientationPortraitPrimary;
-      break;
-    case SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY:
-      web_screen_info.orientation_type =
-          blink::kWebScreenOrientationPortraitSecondary;
-      break;
-    case SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY:
-      web_screen_info.orientation_type =
-          blink::kWebScreenOrientationLandscapePrimary;
-      break;
-    case SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY:
-      web_screen_info.orientation_type =
-          blink::kWebScreenOrientationLandscapeSecondary;
-      break;
-    default:
-      web_screen_info.orientation_type = blink::kWebScreenOrientationUndefined;
-      break;
-  }
-  web_screen_info.orientation_angle = info.orientation_angle;
-
-  return web_screen_info;
-}
-
 #if defined(OS_ANDROID)
 void RenderViewImpl::SuspendVideoCaptureDevices(bool suspend) {
   if (!main_render_frame_)
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 2586007..2710fa61 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -277,7 +277,6 @@
   void PageImportanceSignalsChanged() override;
   void DidAutoResize(const blink::WebSize& newSize) override;
   void DidFocus(blink::WebLocalFrame* calling_frame) override;
-  blink::WebScreenInfo GetScreenInfo() override;
   bool CanHandleGestureEvent() override;
   bool AllowPopupsDuringPageUnload() override;
 
@@ -327,7 +326,7 @@
 
   // Instead of creating a new RenderWidget, this revives the undead
   // RenderWidget for use with a new local main frame.
-  void ReviveUndeadMainFrameRenderWidget();
+  void ReviveUndeadMainFrameRenderWidget(const ScreenInfo& screen_info);
 
  private:
   // For unit tests.
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index a6c1d3db..05b8b9f 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -505,25 +505,30 @@
 }
 
 void RenderWidget::InitForPopup(ShowCallback show_callback,
-                                blink::WebPagePopup* web_page_popup) {
+                                blink::WebPagePopup* web_page_popup,
+                                const ScreenInfo& screen_info) {
   popup_ = true;
-  Init(std::move(show_callback), web_page_popup);
+  Init(std::move(show_callback), web_page_popup, &screen_info);
 }
 
 void RenderWidget::InitForPepperFullscreen(ShowCallback show_callback,
-                                           blink::WebWidget* web_widget) {
+                                           blink::WebWidget* web_widget,
+                                           const ScreenInfo& screen_info) {
   pepper_fullscreen_ = true;
-  Init(std::move(show_callback), web_widget);
+  Init(std::move(show_callback), web_widget, &screen_info);
 }
 
-void RenderWidget::InitForMainFrame(ShowCallback show_callback) {
-  Init(std::move(show_callback), /*web_frame_widget=*/nullptr);
+void RenderWidget::InitForMainFrame(ShowCallback show_callback,
+                                    blink::WebFrameWidget* web_frame_widget,
+                                    const ScreenInfo* screen_info) {
+  Init(std::move(show_callback), web_frame_widget, screen_info);
 }
 
 void RenderWidget::InitForChildLocalRoot(
-    blink::WebFrameWidget* web_frame_widget) {
+    blink::WebFrameWidget* web_frame_widget,
+    const ScreenInfo& screen_info) {
   for_child_local_root_frame_ = true;
-  Init(base::NullCallback(), web_frame_widget);
+  Init(base::NullCallback(), web_frame_widget, &screen_info);
 }
 
 void RenderWidget::CloseForFrame(std::unique_ptr<RenderWidget> widget) {
@@ -533,50 +538,28 @@
   Close(std::move(widget));
 }
 
-void RenderWidget::Init(ShowCallback show_callback, WebWidget* web_widget) {
+void RenderWidget::Init(ShowCallback show_callback,
+                        WebWidget* web_widget,
+                        const ScreenInfo* screen_info) {
+  DCHECK_EQ(is_undead_, !web_widget);  // There is a WebWidget when not undead.
   DCHECK(!webwidget_);
   DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
 
   input_handler_ = std::make_unique<RenderWidgetInputHandler>(this, this);
 
-  LayerTreeView* layer_tree_view = InitializeLayerTreeView();
+  if (!is_undead_) {
+    InitCompositing(*screen_info);
 
-  // TODO(https://crbug.com/995981): This conditional is temporary logic to
-  // handle the case of remote main frame RenderWidgets [which shouldn't exist
-  // to begin with].
-  if (web_widget)
-    web_widget->SetAnimationHost(layer_tree_view->animation_host());
+    // If the widget is hidden, delay starting the compositor until the user
+    // shows it. Also if the RenderWidget is undead, we delay starting the
+    // compositor until we expect to use the widget, which will be signaled
+    // through reviving the undead RenderWidget.
+    if (!is_hidden_)
+      StartStopCompositor();
 
-  blink::scheduler::WebThreadScheduler* main_thread_scheduler =
-      compositor_deps_->GetWebMainThreadScheduler();
-
-  blink::scheduler::WebThreadScheduler* compositor_thread_scheduler =
-      blink::scheduler::WebThreadScheduler::CompositorThreadScheduler();
-  scoped_refptr<base::SingleThreadTaskRunner> compositor_input_task_runner;
-  // Use the compositor thread task runner unless this is a popup or other such
-  // non-frame widgets. The |compositor_thread_scheduler| can be null in tests
-  // without a compositor thread.
-  if (for_frame() && compositor_thread_scheduler) {
-    compositor_input_task_runner =
-        compositor_thread_scheduler->InputTaskRunner();
+    web_widget->SetAnimationHost(layer_tree_view_->animation_host());
   }
 
-  input_event_queue_ = base::MakeRefCounted<MainThreadEventQueue>(
-      this, main_thread_scheduler->InputTaskRunner(), main_thread_scheduler,
-      /*allow_raf_aligned_input=*/!compositor_never_visible_);
-
-  // We only use an external input handler for frame RenderWidgets because only
-  // frames use the compositor for input handling. Other kinds of RenderWidgets
-  // (e.g.  popups, plugins) must forward their input directly through
-  // RenderWidgetInputHandler into Blink.
-  bool uses_input_handler = for_frame();
-  widget_input_handler_manager_ = WidgetInputHandlerManager::Create(
-      weak_ptr_factory_.GetWeakPtr(), std::move(compositor_input_task_runner),
-      main_thread_scheduler, uses_input_handler);
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kAllowPreCommitInput))
-    widget_input_handler_manager_->AllowPreCommitInput();
-
   show_callback_ = std::move(show_callback);
 
 #if defined(OS_MACOSX)
@@ -804,58 +787,54 @@
 
   gfx::Size old_visible_viewport_size = visible_viewport_size_;
 
-  bool ignore_resize_ipc = false;
-  if (synchronous_resize_mode_for_testing_) {
+  if (delegate_ && page_properties_->ScreenMetricsEmulator()) {
+    DCHECK(!auto_resize_mode_);
+    DCHECK(!synchronous_resize_mode_for_testing_);
+
+    // TODO(danakj): Have RenderWidget grab emulated values from the emulator
+    // instead of making it call back into RenderWidget, then we can do this
+    // with a single UpdateSurfaceAndScreenInfo() call. The emulator may
+    // change the ScreenInfo and then will call back to RenderWidget. Before
+    // that we keep the current (possibly emulated) ScreenInfo.
+    UpdateSurfaceAndScreenInfo(
+        visual_properties.local_surface_id_allocation.value_or(
+            viz::LocalSurfaceIdAllocation()),
+        visual_properties.compositor_viewport_pixel_rect,
+        page_properties_->GetScreenInfo());
+
+    // This will call our SynchronizeVisualProperties() method with a
+    // different set of VisualProperties, holding emulated values. Though not
+    // all VisualProperties are modified by the metrics emulator, so it's a
+    // bit unclear to do this with the full structure. Anything it does not
+    // modify can be consumed directly here instead of in
+    // SynchronizeVisualProperties().
+    page_properties_->ScreenMetricsEmulator()->OnSynchronizeVisualProperties(
+        visual_properties.screen_info, visual_properties.new_size,
+        visual_properties.visible_viewport_size);
+  } else {
     // We can ignore browser-initialized resizing during synchronous
     // (renderer-controlled) mode, unless it is switching us to/from
     // fullsreen mode or changing the device scale factor.
-    // TODO(danakj): Does the browser actually change DSF inside a web test??
-    // TODO(danakj): Isn't the display mode check redundant with the fullscreen
-    // one?
-    if (visual_properties.is_fullscreen_granted == is_fullscreen_granted_ &&
-        visual_properties.display_mode == display_mode_ &&
-        visual_properties.screen_info.device_scale_factor ==
-            page_properties_->GetDeviceScaleFactor())
-      ignore_resize_ipc = true;
-  }
+    bool ignore_resize_ipc = synchronous_resize_mode_for_testing_;
+    if (ignore_resize_ipc) {
+      // TODO(danakj): Does the browser actually change DSF inside a web test??
+      // TODO(danakj): Isn't the display mode check redundant with the
+      // fullscreen one?
+      if (visual_properties.is_fullscreen_granted != is_fullscreen_granted_ ||
+          visual_properties.display_mode != display_mode_ ||
+          visual_properties.screen_info.device_scale_factor !=
+              page_properties_->GetDeviceScaleFactor())
+        ignore_resize_ipc = false;
+    }
 
-  // When controlling the size in the renderer, we should ignore sizes given by
-  // the browser IPC here.
-  // TODO(danakj): There are many things also being ignored that aren't the
-  // widget's size params. It works because tests that use this mode don't
-  // change those parameters, I guess. But it's more complicated then because it
-  // looks like they are related to sync resize mode. Let's move them out of
-  // this block.
-  // TODO(danakj): It would be nice if we can still use the emulator to emulate
-  // things other than the size if we are in sync resize mode - if the emulator
-  // is even used in sync resize tests. It probably isn't though, so either way
-  // it'd be good to get the emulator out of this block (maybe by overwriting
-  // some of |visual_properties| in sync resize mode instead of just
-  // skipping the emulator.
-  if (!ignore_resize_ipc) {
-    if (delegate_ && page_properties_->ScreenMetricsEmulator()) {
-      DCHECK(!auto_resize_mode_);
-      // TODO(danakj): Have RenderWidget grab emulated values from the emulator
-      // instead of making it call back into RenderWidget, then we can do this
-      // with a single UpdateSurfaceAndScreenInfo() call. The emulator may
-      // change the ScreenInfo and then will call back to RenderWidget. Before
-      // that we keep the current (possibly emulated) ScreenInfo.
-      UpdateSurfaceAndScreenInfo(
-          visual_properties.local_surface_id_allocation.value_or(
-              viz::LocalSurfaceIdAllocation()),
-          visual_properties.compositor_viewport_pixel_rect,
-          page_properties_->GetScreenInfo());
-
-      // This will call our SynchronizeVisualProperties() method with a
-      // different set of VisualProperties, holding emulated values. Though not
-      // all VisualProperties are modified by the metrics emulator, so it's a
-      // bit unclear to do this with the full structure. Anything it does not
-      // modify can be consumed directly here instead of in
-      // SynchronizeVisualProperties().
-      page_properties_->ScreenMetricsEmulator()->OnSynchronizeVisualProperties(
-          visual_properties.screen_info, visual_properties.new_size,
-          visual_properties.visible_viewport_size);
-    } else {
+    // When controlling the size in the renderer, we should ignore sizes given
+    // by the browser IPC here.
+    // TODO(danakj): There are many things also being ignored that aren't the
+    // widget's size params. It works because tests that use this mode don't
+    // change those parameters, I guess. But it's more complicated then because
+    // it looks like they are related to sync resize mode. Let's move them out
+    // of this block.
+    if (!ignore_resize_ipc) {
       gfx::Rect new_compositor_viewport_pixel_rect =
           visual_properties.compositor_viewport_pixel_rect;
       if (auto_resize_mode_) {
@@ -1940,7 +1919,8 @@
   SetPendingWindowRect(initial_rect_);
 }
 
-LayerTreeView* RenderWidget::InitializeLayerTreeView() {
+void RenderWidget::InitCompositing(const ScreenInfo& screen_info) {
+  DCHECK(!is_undead_);
   TRACE_EVENT0("blink", "RenderWidget::InitializeLayerTreeView");
 
   layer_tree_view_ = std::make_unique<LayerTreeView>(
@@ -1950,31 +1930,44 @@
       compositor_deps_->GetWebMainThreadScheduler());
   layer_tree_view_->Initialize(
       GenerateLayerTreeSettings(compositor_deps_, for_child_local_root_frame_,
-                                page_properties_->GetScreenInfo().rect.size(),
-                                page_properties_->GetDeviceScaleFactor()),
+                                screen_info.rect.size(),
+                                screen_info.device_scale_factor),
       compositor_deps_->CreateUkmRecorderFactory());
   layer_tree_host_ = layer_tree_view_->layer_tree_host();
 
-  ScreenInfo screen_info = page_properties_->GetScreenInfo();
-  // A popup widget does not get emulated. So we hand it the real screen info
-  // and adjust values it gives back into the emulated space later.
-  if (popup_) {
-    RenderWidgetScreenMetricsEmulator* emulator =
-        page_properties_->ScreenMetricsEmulator();
-    if (emulator)
-      screen_info = emulator->original_screen_info();
-  }
-
   UpdateSurfaceAndScreenInfo(local_surface_id_allocation_from_parent_,
                              CompositorViewportRect(), screen_info);
-  // If the widget is hidden, delay starting the compositor until the user shows
-  // it. Also if the RenderWidget is undead, we delay starting the compositor
-  // until we expect to use the widget, which will be signaled through
-  // reviving the undead RenderWidget.
-  if (!is_hidden_ && !is_undead_)
-    StartStopCompositor();
 
-  return layer_tree_view_.get();
+  blink::scheduler::WebThreadScheduler* main_thread_scheduler =
+      compositor_deps_->GetWebMainThreadScheduler();
+
+  blink::scheduler::WebThreadScheduler* compositor_thread_scheduler =
+      blink::scheduler::WebThreadScheduler::CompositorThreadScheduler();
+  scoped_refptr<base::SingleThreadTaskRunner> compositor_input_task_runner;
+  // Use the compositor thread task runner unless this is a popup or other such
+  // non-frame widgets. The |compositor_thread_scheduler| can be null in tests
+  // without a compositor thread.
+  if (for_frame() && compositor_thread_scheduler) {
+    compositor_input_task_runner =
+        compositor_thread_scheduler->InputTaskRunner();
+  }
+
+  input_event_queue_ = base::MakeRefCounted<MainThreadEventQueue>(
+      this, main_thread_scheduler->InputTaskRunner(), main_thread_scheduler,
+      /*allow_raf_aligned_input=*/!compositor_never_visible_);
+
+  // We only use an external input handler for frame RenderWidgets because only
+  // frames use the compositor for input handling. Other kinds of RenderWidgets
+  // (e.g.  popups, plugins) must forward their input directly through
+  // RenderWidgetInputHandler into Blink.
+  bool uses_input_handler = for_frame();
+  widget_input_handler_manager_ = WidgetInputHandlerManager::Create(
+      weak_ptr_factory_.GetWeakPtr(), std::move(compositor_input_task_runner),
+      main_thread_scheduler, uses_input_handler);
+  const base::CommandLine& command_line =
+      *base::CommandLine::ForCurrentProcess();
+  if (command_line.HasSwitch(switches::kAllowPreCommitInput))
+    widget_input_handler_manager_->AllowPreCommitInput();
 }
 
 void RenderWidget::StartStopCompositor() {
@@ -2001,9 +1994,9 @@
   }
 }
 
-void RenderWidget::SetIsUndead(bool is_undead) {
-  DCHECK_NE(is_undead, is_undead_);
-  is_undead_ = is_undead;
+void RenderWidget::SetIsUndead() {
+  DCHECK(!is_undead_);
+  is_undead_ = true;
   // If hidden, then changing undead state doesn't change anything with the
   // compositor since when hidden the compositor is always stopped.
   if (!is_hidden_)
@@ -2011,11 +2004,33 @@
 
   // Remove undead RenderWidgets from the routing map so that they cannot be
   // looked up with FromRoutingId().
-  if (is_undead) {
-    g_routing_id_widget_map.Get().erase(routing_id_);
-  } else {
-    g_routing_id_widget_map.Get().emplace(routing_id_, this);
-  }
+  g_routing_id_widget_map.Get().erase(routing_id_);
+}
+
+void RenderWidget::SetIsRevivedFromUndead(const ScreenInfo& screen_info) {
+  DCHECK(is_undead_);
+  is_undead_ = false;
+  // If started as undead, the compositor was not created yet.
+  if (!layer_tree_view_)
+    InitCompositing(screen_info);
+  // If hidden, then changing undead state doesn't change anything with the
+  // compositor since when hidden the compositor is always stopped.
+  if (!is_hidden_)
+    StartStopCompositor();
+
+  // Put revived RenderWidgets back into the routing id map so they can be
+  // looked up with FromRoutingId().
+  g_routing_id_widget_map.Get().emplace(routing_id_, this);
+
+  // Reviving from undead is like making a "new" RenderWidget, initialization
+  // that should not bleed across from the last local main frame can happen
+  // here.
+  // TODO(crbug.com/419087): This initialization can be done during
+  // InitCompositing() or when constructing the RenderWidget once there are
+  // no undead RenderWidgets.
+  const base::CommandLine& command_line =
+      *base::CommandLine::ForCurrentProcess();
+  SetShowFPSCounter(command_line.HasSwitch(cc::switches::kShowFPSCounter));
 }
 
 // static
@@ -2065,29 +2080,35 @@
     g_routing_id_widget_map.Get().erase(routing_id_);
   }
 
-  // Stop handling main thread input events immediately so we don't have them
-  // running while things are partly shut down.
-  input_event_queue_->ClearClient();
-
   // The |webwidget_| will be null when the main frame RenderWidget is undead.
   if (webwidget_)
     webwidget_->Close();
   webwidget_ = nullptr;
 
-  // The LayerTreeHost may already be in the call stack, if this RenderWidget is
-  // being destroyed during an animation callback for instance. We can not
-  // delete it here and unwind the stack back up to it, or it will crash. So we
-  // post the deletion to another task, but disconnect the LayerTreeHost (via
-  // the LayerTreeView) from the destroying RenderWidget. The LayerTreeView owns
-  // the LayerTreeHost, and is its client, so they are kept alive together for a
-  // clean call stack.
-  layer_tree_view_->Disconnect();
-  compositor_deps_->GetCleanupTaskRunner()->DeleteSoon(
-      FROM_HERE, std::move(layer_tree_view_));
-  // The |widget_input_handler_manager_| is referenced through the LayerTreeHost
-  // on the compositor thread, so must outlive the LayerTreeHost.
-  compositor_deps_->GetCleanupTaskRunner()->ReleaseSoon(
-      FROM_HERE, std::move(widget_input_handler_manager_));
+  // A RenderWidget can be created as undead and never revived, so never
+  // initialized compositing.
+  if (layer_tree_view_) {
+    // The |input_event_queue_| is refcounted and will live while an event is
+    // being handled. This drops the connection back to this RenderWidget which
+    // is being destroyed.
+    input_event_queue_->ClearClient();
+
+    // The LayerTreeHost may already be in the call stack, if this RenderWidget
+    // is being destroyed during an animation callback for instance. We can not
+    // delete it here and unwind the stack back up to it, or it will crash. So
+    // we post the deletion to another task, but disconnect the LayerTreeHost
+    // (via the LayerTreeView) from the destroying RenderWidget. The
+    // LayerTreeView owns the LayerTreeHost, and is its client, so they are kept
+    // alive together for a clean call stack.
+    layer_tree_view_->Disconnect();
+    compositor_deps_->GetCleanupTaskRunner()->DeleteSoon(
+        FROM_HERE, std::move(layer_tree_view_));
+    // The |widget_input_handler_manager_| is referenced through the
+    // LayerTreeHost on the compositor thread, so must outlive the
+    // LayerTreeHost.
+    compositor_deps_->GetCleanupTaskRunner()->ReleaseSoon(
+        FROM_HERE, std::move(widget_input_handler_manager_));
+  }
 
   // Note the ACK is a control message going to the RenderProcessHost.
   RenderThread::Get()->Send(new WidgetHostMsg_Close_ACK(routing_id()));
@@ -2153,6 +2174,43 @@
       (window_rect->y - emulator->ViewRectOrigin().y()) * emulator->scale();
 }
 
+blink::WebScreenInfo RenderWidget::GetScreenInfo() {
+  const ScreenInfo& info = page_properties_->GetScreenInfo();
+
+  blink::WebScreenInfo web_screen_info;
+  web_screen_info.device_scale_factor = info.device_scale_factor;
+  web_screen_info.color_space = info.color_space;
+  web_screen_info.depth = info.depth;
+  web_screen_info.depth_per_component = info.depth_per_component;
+  web_screen_info.is_monochrome = info.is_monochrome;
+  web_screen_info.rect = blink::WebRect(info.rect);
+  web_screen_info.available_rect = blink::WebRect(info.available_rect);
+  switch (info.orientation_type) {
+    case SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY:
+      web_screen_info.orientation_type =
+          blink::kWebScreenOrientationPortraitPrimary;
+      break;
+    case SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY:
+      web_screen_info.orientation_type =
+          blink::kWebScreenOrientationPortraitSecondary;
+      break;
+    case SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY:
+      web_screen_info.orientation_type =
+          blink::kWebScreenOrientationLandscapePrimary;
+      break;
+    case SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY:
+      web_screen_info.orientation_type =
+          blink::kWebScreenOrientationLandscapeSecondary;
+      break;
+    default:
+      web_screen_info.orientation_type = blink::kWebScreenOrientationUndefined;
+      break;
+  }
+  web_screen_info.orientation_angle = info.orientation_angle;
+
+  return web_screen_info;
+}
+
 WebRect RenderWidget::WindowRect() {
   WebRect rect;
   if (pending_window_rect_count_) {
@@ -3965,12 +4023,13 @@
 }
 
 void RenderWidget::SetWebWidgetInternal(blink::WebWidget* webwidget) {
-  // TODO(https://crbug.com/995981): This method should not need to exist, since
-  // we should be creating and destroying a RenderWidget along with the
-  // WebWidget.
-  if (webwidget)
-    webwidget->SetAnimationHost(layer_tree_view_->animation_host());
+  // Undead state is changed first, and the WebWidget is set accordingly. That
+  // means the compositor is always initialized before we get here.
+  DCHECK_EQ(is_undead_, !webwidget);
+
   webwidget_ = webwidget;
+  if (webwidget_)
+    webwidget_->SetAnimationHost(layer_tree_view_->animation_host());
 }
 
 }  // namespace content
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index be5955f0..91b535e 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -231,23 +231,27 @@
   // Initialize a new RenderWidget for a popup. The |show_callback| is called
   // when RenderWidget::Show() happens.
   void InitForPopup(ShowCallback show_callback,
-                    blink::WebPagePopup* web_page_popup);
+                    blink::WebPagePopup* web_page_popup,
+                    const ScreenInfo& screen_info);
 
   // Initialize a new RenderWidget for pepper fullscreen. The |show_callback| is
   // called when RenderWidget::Show() happens.
   void InitForPepperFullscreen(ShowCallback show_callback,
-                               blink::WebWidget* web_widget);
+                               blink::WebWidget* web_widget,
+                               const ScreenInfo& screen_info);
 
   // Initialize a new RenderWidget that will be attached to a RenderFrame (via
-  // the WebFrameWidget), for a frame that is a main frame. At the time of
-  // initialization, the WebWidget is not always available, and it will be set
-  // once the main frame is attached.
-  void InitForMainFrame(ShowCallback show_callback);
+  // the WebFrameWidget), for a frame that is a main frame. When WebFrameWidget
+  // is given, a ScreenInfo must be also.
+  void InitForMainFrame(ShowCallback show_callback,
+                        blink::WebFrameWidget* web_frame_widget,
+                        const ScreenInfo* screen_info);
 
   // Initialize a new RenderWidget that will be attached to a RenderFrame (via
   // the WebFrameWidget), for a frame that is a local root, but not the main
   // frame.
-  void InitForChildLocalRoot(blink::WebFrameWidget* web_frame_widget);
+  void InitForChildLocalRoot(blink::WebFrameWidget* web_frame_widget,
+                             const ScreenInfo& screen_info);
 
   // Sets a delegate to handle certain RenderWidget operations that need an
   // escape to the RenderView.
@@ -267,8 +271,6 @@
 
   int32_t routing_id() const { return routing_id_; }
 
-  // TODO(https://crbug.com/912193): Use CompositorDependencies on
-  // PageProperties instead.
   CompositorDependencies* compositor_deps() const { return compositor_deps_; }
 
   // This can return nullptr while the RenderWidget is closing. When for_frame()
@@ -303,7 +305,8 @@
   // otherwise act as if it is dead. Only whitelisted new IPC messages will be
   // sent, and it does no compositing. The process is free to exit when there
   // are no other non-undead RenderWidgets.
-  void SetIsUndead(bool is_undead);
+  void SetIsUndead();
+  void SetIsRevivedFromUndead(const ScreenInfo& screen_info);
 
   // A main frame RenderWidget is made undead instead of being deleted. Then
   // when a provisional frame is created, the RenderWidget is recycled and
@@ -415,6 +418,7 @@
   void AutoscrollEnd() override;
   void ClosePopupWidgetSoon() override;
   void Show(blink::WebNavigationPolicy) override;
+  blink::WebScreenInfo GetScreenInfo() override;
   blink::WebRect WindowRect() override;
   blink::WebRect ViewRect() override;
   void SetToolTipText(const blink::WebString& text,
@@ -714,13 +718,13 @@
 
   // Called by Create() functions and subclasses to finish initialization.
   // |show_callback| will be invoked once WebWidgetClient::Show() occurs, and
-  // should be null if Show() won't be triggered for this widget.
-  void Init(ShowCallback show_callback, blink::WebWidget* web_widget);
+  // should be null if Show() won't be triggered for this widget. The WebWidget
+  // and ScreenInfo are both null or both not.
+  void Init(ShowCallback show_callback,
+            blink::WebWidget* web_widget,
+            const ScreenInfo* screen_info);
 
-  // Creates the compositor, but leaves it in a stopped state, where it will
-  // not set up IPC channels or begin trying to produce frames until started
-  // via StartStopCompositor().
-  LayerTreeView* InitializeLayerTreeView();
+  void InitCompositing(const ScreenInfo& screen_info);
 
   // If appropriate, initiates the compositor to set up IPC channels and begin
   // its scheduler. Otherwise, pauses the scheduler and tears down its IPC
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc
index 36cb36d1..08978ef 100644
--- a/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -285,7 +285,8 @@
       routing_id, compositor_deps, page_properties, plugin,
       std::move(widget_receiver));
   widget->InitForPepperFullscreen(
-      std::move(show_callback), new PepperWidget(widget, local_main_frame_url));
+      std::move(show_callback), new PepperWidget(widget, local_main_frame_url),
+      page_properties->GetScreenInfo());
   return widget;
 }
 
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc
index 7e97b093..458c3ae 100644
--- a/content/renderer/render_widget_unittest.cc
+++ b/content/renderer/render_widget_unittest.cc
@@ -179,7 +179,8 @@
                      false,
                      mojo::NullReceiver()),
         always_overscroll_(false) {
-    Init(base::NullCallback(), &mock_webwidget_);
+    Init(base::NullCallback(), &mock_webwidget_,
+         &page_properties->GetScreenInfo());
 
     mock_input_handler_host_ = std::make_unique<MockWidgetInputHandlerHost>();
 
diff --git a/content/shell/test_runner/web_view_test_proxy.cc b/content/shell/test_runner/web_view_test_proxy.cc
index 1a376b9..05d3cfca 100644
--- a/content/shell/test_runner/web_view_test_proxy.cc
+++ b/content/shell/test_runner/web_view_test_proxy.cc
@@ -75,21 +75,6 @@
   RenderViewImpl::DidFocus(calling_frame);
 }
 
-blink::WebScreenInfo WebViewTestProxy::GetScreenInfo() {
-  blink::WebScreenInfo info = RenderViewImpl::GetScreenInfo();
-
-  MockScreenOrientationClient* mock_client =
-      GetTestRunner()->GetMockScreenOrientationClient();
-
-  if (!mock_client->IsDisabled()) {
-    // Override screen orientation information with mock data.
-    info.orientation_type = mock_client->CurrentOrientationType();
-    info.orientation_angle = mock_client->CurrentOrientationAngle();
-  }
-
-  return info;
-}
-
 void WebViewTestProxy::Reset() {
   // TODO(https://crbug.com/961499): There is a race condition where Reset()
   // can be called after GetWidget() has been nulled, but before this is
diff --git a/content/shell/test_runner/web_view_test_proxy.h b/content/shell/test_runner/web_view_test_proxy.h
index 54b42657..01068b7 100644
--- a/content/shell/test_runner/web_view_test_proxy.h
+++ b/content/shell/test_runner/web_view_test_proxy.h
@@ -83,7 +83,6 @@
   void PrintPage(blink::WebLocalFrame* frame) override;
   blink::WebString AcceptLanguages() override;
   void DidFocus(blink::WebLocalFrame* calling_frame) override;
-  blink::WebScreenInfo GetScreenInfo() override;
 
   // Exposed for our TestRunner harness.
   using RenderViewImpl::ApplyPageHidden;
diff --git a/content/shell/test_runner/web_widget_test_proxy.cc b/content/shell/test_runner/web_widget_test_proxy.cc
index 3db5943..a4eeaf0 100644
--- a/content/shell/test_runner/web_widget_test_proxy.cc
+++ b/content/shell/test_runner/web_widget_test_proxy.cc
@@ -120,6 +120,21 @@
   event_sender()->DoDragDrop(data, mask);
 }
 
+blink::WebScreenInfo WebWidgetTestProxy::GetScreenInfo() {
+  blink::WebScreenInfo info = RenderWidget::GetScreenInfo();
+
+  MockScreenOrientationClient* mock_client =
+      GetTestRunner()->GetMockScreenOrientationClient();
+
+  if (!mock_client->IsDisabled()) {
+    // Override screen orientation information with mock data.
+    info.orientation_type = mock_client->CurrentOrientationType();
+    info.orientation_angle = mock_client->CurrentOrientationAngle();
+  }
+
+  return info;
+}
+
 WebViewTestProxy* WebWidgetTestProxy::GetWebViewTestProxy() {
   if (delegate()) {
     // TODO(https://crbug.com/545684): Because WebViewImpl still inherits
diff --git a/content/shell/test_runner/web_widget_test_proxy.h b/content/shell/test_runner/web_widget_test_proxy.h
index 2e44b58..fdd01021 100644
--- a/content/shell/test_runner/web_widget_test_proxy.h
+++ b/content/shell/test_runner/web_widget_test_proxy.h
@@ -77,6 +77,7 @@
                      blink::WebDragOperationsMask mask,
                      const SkBitmap& drag_image,
                      const gfx::Point& image_offset) override;
+  blink::WebScreenInfo GetScreenInfo() override;
 
   // In the test runner code, it can be expected that the RenderViewImpl will
   // actually be a WebViewTestProxy as the creation of RenderView/Frame/Widget
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 7026bbd..208d98b 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1942,9 +1942,7 @@
     "../renderer/media/renderer_webaudiodevice_impl_unittest.cc",
     "../renderer/media/webrtc/fake_rtc_rtp_transceiver.cc",
     "../renderer/media/webrtc/fake_rtc_rtp_transceiver.h",
-    "../renderer/media/webrtc/media_stream_remote_video_source_unittest.cc",
     "../renderer/media/webrtc/media_stream_track_metrics_unittest.cc",
-    "../renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc",
     "../renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc",
     "../renderer/media/webrtc/peer_connection_tracker_unittest.cc",
     "../renderer/media/webrtc/rtc_peer_connection_handler_unittest.cc",
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index 326d8a6..cdf7a9a 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -279,15 +279,15 @@
 
 # Regressions in 10.12.4.
 crbug.com/705865 [ sierra intel ] conformance2/textures/misc/tex-base-level-bug.html [ Failure ]
-crbug.com/705865 [ sierra intel ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ]
+crbug.com/705865 [ sierra intel no-passthrough ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ]
 
 # Regressions in 10.13
-crbug.com/774826 [ highsierra intel-0xa2e ] deqp/functional/gles3/fbocolorbuffer/tex2d_00.html [ Failure ]
-crbug.com/774826 [ mojave intel-0xa2e ] deqp/functional/gles3/fbocolorbuffer/tex2d_00.html [ Failure ]
-crbug.com/774826 [ highsierra intel-0xa2e ] deqp/functional/gles3/fboinvalidate/format_00.html [ Failure ]
-crbug.com/774826 [ mojave intel-0xa2e ] deqp/functional/gles3/fboinvalidate/format_00.html [ Failure ]
-crbug.com/774826 [ highsierra intel-0xa2e ] deqp/functional/gles3/framebufferblit/default_framebuffer_05.html [ Failure ]
-crbug.com/774826 [ mojave intel-0xa2e ] deqp/functional/gles3/framebufferblit/default_framebuffer_05.html [ Failure ]
+crbug.com/774826 [ highsierra intel-0xa2e no-passthrough ] deqp/functional/gles3/fbocolorbuffer/tex2d_00.html [ Failure ]
+crbug.com/774826 [ mojave intel-0xa2e no-passthrough ] deqp/functional/gles3/fbocolorbuffer/tex2d_00.html [ Failure ]
+crbug.com/774826 [ highsierra intel-0xa2e no-passthrough ] deqp/functional/gles3/fboinvalidate/format_00.html [ Failure ]
+crbug.com/774826 [ mojave intel-0xa2e no-passthrough ] deqp/functional/gles3/fboinvalidate/format_00.html [ Failure ]
+crbug.com/774826 [ highsierra intel-0xa2e no-passthrough ] deqp/functional/gles3/framebufferblit/default_framebuffer_05.html [ Failure ]
+crbug.com/774826 [ mojave intel-0xa2e no-passthrough ] deqp/functional/gles3/framebufferblit/default_framebuffer_05.html [ Failure ]
 crbug.com/774827 [ highsierra nvidia-0xfe9 ] conformance2/glsl3/array-assign.html [ Failure ]
 crbug.com/774827 [ mojave nvidia-0xfe9 ] conformance2/glsl3/array-assign.html [ Failure ]
 crbug.com/774827 [ highsierra nvidia-0xfe9 ] deqp/functional/gles3/fborender/resize_03.html [ Failure ]
@@ -323,18 +323,18 @@
 crbug.com/923080 [ mac nvidia-0xfe9 ] conformance/ogles/GL/exp2/exp2_001_to_008.html [ RetryOnFailure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] conformance/programs/gl-bind-attrib-location-long-names-test.html [ Failure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] conformance/programs/gl-bind-attrib-location-test.html [ Failure ]
-crbug.com/483282 [ mac nvidia-0xfe9 ] conformance2/glsl3/loops-with-side-effects.html [ Failure ]
+crbug.com/483282 [ mac nvidia-0xfe9 no-passthrough ] conformance2/glsl3/loops-with-side-effects.html [ Failure ]
 crbug.com/981122 [ mac nvidia-0xfe9 ] conformance2/rendering/framebuffer-completeness-draw-framebuffer.html [ RetryOnFailure ]
 crbug.com/996344 [ mac nvidia-0xfe9 ] conformance2/textures/misc/tex-base-level-bug.html [ Failure ]
 crbug.com/483282 [ no-angle mac nvidia-0xfe9 ] conformance2/textures/misc/tex-input-validation.html [ Failure ]
-crbug.com/996344 [ mac nvidia-0xfe9 ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ]
+crbug.com/996344 [ mac nvidia-0xfe9 no-passthrough ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ]
 crbug.com/682834 [ mac nvidia-0xfe9 ] conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-half_float.html [ RetryOnFailure ]
 crbug.com/922517 [ mac nvidia-0xfe9 ] conformance2/textures/canvas/tex-3d-rg16f-rg-float.html [ RetryOnFailure ]
 crbug.com/784817 [ mac nvidia-0xfe9 ] conformance/glsl/bugs/init-array-with-loop.html [ Failure ]
 crbug.com/716652 [ sierra nvidia-0xfe9 ] deqp/functional/gles3/draw/random.html [ Failure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_04.html [ Failure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_07.html [ Failure ]
-crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_08.html [ Failure ]
+crbug.com/483282 [ mac nvidia-0xfe9 no-passthrough ] deqp/functional/gles3/framebufferblit/conversion_08.html [ Failure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_10.html [ Failure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_11.html [ Failure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_12.html [ Failure ]
@@ -378,7 +378,7 @@
 crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/draw/draw_elements.html [ Failure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/draw/draw_elements_instanced.html [ Failure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/draw/draw_range_elements.html [ Failure ]
-crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/fboinvalidate/format_02.html [ Failure ]
+crbug.com/483282 [ mac nvidia-0xfe9 no-passthrough ] deqp/functional/gles3/fboinvalidate/format_02.html [ Failure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/negativeshaderapi.html [ Failure ]
 crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/vertexarrays/multiple_attributes.output.html [ RetryOnFailure ]
 crbug.com/984588 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_06.html [ Failure ]
@@ -386,7 +386,7 @@
 crbug.com/984588 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_26.html [ Failure ]
 crbug.com/654187 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_28.html [ Failure ]
 crbug.com/654187 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_30.html [ Failure ]
-crbug.com/654187 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_31.html [ Failure ]
+crbug.com/654187 [ mac nvidia-0xfe9 no-passthrough ] deqp/functional/gles3/framebufferblit/conversion_31.html [ Failure ]
 crbug.com/654187 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_33.html [ Failure ]
 crbug.com/795052 [ mac nvidia-0xfe9 ] conformance2/uniforms/draw-with-uniform-blocks.html [ Failure ]
 crbug.com/911772 [ mac nvidia-0xfe9 ] conformance2/glsl3/compound-assignment-type-combination.html [ RetryOnFailure ]
@@ -397,7 +397,7 @@
 crbug.com/911772 [ mac nvidia-0xfe9 ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgb16f-rgb-half_float.html [ RetryOnFailure ]
 crbug.com/911772 [ mac nvidia-0xfe9 ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html [ RetryOnFailure ]
 crbug.com/911772 [ mac nvidia-0xfe9 ] conformance2/textures/canvas/tex-3d-r16f-red-half_float.html [ RetryOnFailure ]
-crbug.com/929398 [ mac nvidia-0xfe9 ] conformance2/glsl3/tricky-loop-conditions.html [ Failure ]
+crbug.com/929398 [ mac nvidia-0xfe9 no-passthrough ] conformance2/glsl3/tricky-loop-conditions.html [ Failure ]
 crbug.com/934556 [ mac nvidia-0xfe9 ] conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html [ RetryOnFailure ]
 crbug.com/952282 [ mac nvidia-0xfe9 ] conformance2/rendering/framebuffer-unsupported.html [ RetryOnFailure ]
 crbug.com/965209 [ mac nvidia-0xfe9 ] conformance2/samplers/multi-context-sampler-test.html [ RetryOnFailure ]
@@ -417,33 +417,33 @@
 # tests fail, they fail three times in a row, so we must mark them failing
 # rather than flaky.
 crbug.com/870856 [ mac amd ] conformance2/textures/misc/tex-base-level-bug.html [ Failure ]
-crbug.com/870856 [ mac amd ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ]
+crbug.com/870856 [ mac amd no-passthrough ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ]
 
 crbug.com/angleproject/3701 [ mac amd ] conformance2/textures/canvas/tex-2d-rg8-rg-unsigned_byte.html [ RetryOnFailure ]
 
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/array_interleaved_lines.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/array_interleaved_points.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/array_interleaved_triangles.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/array_separate_lines.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/array_separate_points.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/array_separate_triangles.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/basic_types_separate_points.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/interpolation_centroid.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/interpolation_flat.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/interpolation_smooth.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/point_size.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/position.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/random_interleaved_lines.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/random_interleaved_points.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/random_separate_lines.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/random_separate_points.html [ Failure ]
-crbug.com/483282 [ sierra amd ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/array_interleaved_lines.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/array_interleaved_points.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/array_interleaved_triangles.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/array_separate_lines.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/array_separate_points.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/array_separate_triangles.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_points.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/interpolation_centroid.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/interpolation_flat.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/interpolation_smooth.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/point_size.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/position.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_lines.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_points.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_lines.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_points.html [ Failure ]
+crbug.com/483282 [ sierra amd no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ Failure ]
 crbug.com/751254 [ mac amd ] deqp/functional/gles3/shaderindexing/mat_00.html [ RetryOnFailure ]
 crbug.com/636648 [ mac amd ] deqp/functional/gles3/shaderindexing/mat_01.html [ RetryOnFailure ]
 crbug.com/644360 [ mac amd ] deqp/functional/gles3/shaderindexing/mat_02.html [ RetryOnFailure ]
@@ -529,9 +529,59 @@
 crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ]
 crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ]
 crbug.com/658930 [ mac intel ] conformance2/textures/misc/integer-cubemap-texture-sampling.html [ Failure ]
-crbug.com/731877 [ mac intel-0xa2e ] conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html [ Failure ]
+crbug.com/731877 [ mac intel-0xa2e no-passthrough ] conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html [ Failure ]
 crbug.com/782317 [ mac intel ] conformance/rendering/rendering-stencil-large-viewport.html [ Failure ]
 
+# Mac Passthrough
+crbug.com/982294 [ mac passthrough ] conformance/glsl/bugs/sequence-operator-evaluation-order.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance/glsl/misc/shader-struct-scope.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance/glsl/misc/shader-with-short-circuiting-operators.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance/ogles/GL/build/build_177_to_178.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance/rendering/negative-one-index.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance/textures/misc/gl-teximage.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/glsl3/array-in-complex-expression.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/glsl3/loops-with-side-effects.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/glsl3/short-circuiting-in-loop-condition.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/glsl3/tricky-loop-conditions.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/misc/uninitialized-test-2.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/rendering/blitframebuffer-resolve-to-back-buffer.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/textures/misc/tex-srgb-mipmap.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/textures/misc/tex-unpack-params.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] conformance2/transform_feedback/simultaneous_binding.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/fbocolorbuffer/tex2d_00.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/fboinvalidate/format_00.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/fboinvalidate/format_02.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/framebufferblit/conversion_08.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/framebufferblit/conversion_31.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/framebufferblit/default_framebuffer_00.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/framebufferblit/default_framebuffer_05.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/integerstatequery.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/negativebufferapi.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/primitiverestart/* [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/readpixel.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/shadertexturefunction/texelfetchoffset.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/texturespecification/basic_copyteximage2d.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/texturespecification/teximage3d_pbo_params.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_params.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_points.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/interpolation_centroid.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/interpolation_flat.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/interpolation_smooth.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/point_size.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/position.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_lines.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_points.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/random_separate_lines.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/random_separate_points.html [ Failure ]
+crbug.com/982294 [ mac passthrough ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ Failure ]
 
 ####################
 # Linux failures   #
diff --git a/content/utility/utility_service_factory.cc b/content/utility/utility_service_factory.cc
index 9b0759a..0fc7abb 100644
--- a/content/utility/utility_service_factory.cc
+++ b/content/utility/utility_service_factory.cc
@@ -47,6 +47,7 @@
 #include "base/mac/mach_logging.h"
 #include "sandbox/mac/system_services.h"
 #include "services/service_manager/sandbox/features.h"
+#include "services/service_manager/sandbox/sandbox_type.h"
 #endif
 
 #if defined(OS_WIN)
@@ -199,8 +200,7 @@
 #if defined(OS_MACOSX)
   // Don't connect to launch services when running sandboxed
   // (https://crbug.com/874785).
-  if (base::FeatureList::IsEnabled(
-          service_manager::features::kAudioServiceSandbox)) {
+  if (service_manager::IsAudioSandboxEnabled()) {
     sandbox::DisableLaunchServices();
   }
 
diff --git a/device/bluetooth/bluez/bluetooth_adapter_bluez.cc b/device/bluetooth/bluez/bluetooth_adapter_bluez.cc
index 3face5a..1b68755 100644
--- a/device/bluetooth/bluez/bluetooth_adapter_bluez.cc
+++ b/device/bluetooth/bluez/bluetooth_adapter_bluez.cc
@@ -1575,12 +1575,6 @@
 
   DCHECK_EQ(NumDiscoverySessions(), 0);
 
-  if (!IsDiscovering()) {
-    std::move(callback).Run(
-        /*is_error=*/false, UMABluetoothDiscoverySessionOutcome::SUCCESS);
-    return;
-  }
-
   // Confirm that there are no more discovery sessions left.
   DCHECK_EQ(NumDiscoverySessions(), 0);
   auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
diff --git a/device/fido/fido_request_handler_base.cc b/device/fido/fido_request_handler_base.cc
index 3b4664e..42775f6 100644
--- a/device/fido/fido_request_handler_base.cc
+++ b/device/fido/fido_request_handler_base.cc
@@ -48,21 +48,22 @@
 FidoRequestHandlerBase::FidoRequestHandlerBase(
     service_manager::Connector* connector,
     FidoDiscoveryFactory* fido_discovery_factory,
-    const base::flat_set<FidoTransportProtocol>& available_transports)
-    : fido_discovery_factory_(fido_discovery_factory), connector_(connector) {
+    const base::flat_set<FidoTransportProtocol>& available_transports) {
 #if defined(OS_WIN)
-  InitDiscoveriesWin(available_transports);
+  InitDiscoveriesWin(fido_discovery_factory, connector, available_transports);
 #else
-  InitDiscoveries(available_transports);
+  InitDiscoveries(fido_discovery_factory, connector, available_transports);
 #endif  // !defined(OS_WIN)
 }
 
 void FidoRequestHandlerBase::InitDiscoveries(
+    FidoDiscoveryFactory* fido_discovery_factory,
+    service_manager::Connector* connector,
     const base::flat_set<FidoTransportProtocol>& available_transports) {
   transport_availability_info_.available_transports = available_transports;
   for (const auto transport : available_transports) {
     std::unique_ptr<FidoDiscoveryBase> discovery =
-        fido_discovery_factory_->Create(transport, connector_);
+        fido_discovery_factory->Create(transport, connector);
     if (discovery == nullptr) {
       // This can occur in tests when a ScopedVirtualU2fDevice is in effect and
       // HID transports are not configured or when caBLE discovery data isn't
@@ -107,14 +108,15 @@
 
 #if defined(OS_WIN)
 void FidoRequestHandlerBase::InitDiscoveriesWin(
+    FidoDiscoveryFactory* fido_discovery_factory,
+    service_manager::Connector* connector,
     const base::flat_set<FidoTransportProtocol>& available_transports) {
   // Try to instantiate the discovery for proxying requests to the native
   // Windows WebAuthn API; or fall back to using the regular device transport
   // discoveries if the API is unavailable.
-  auto discovery =
-      fido_discovery_factory_->MaybeCreateWinWebAuthnApiDiscovery();
+  auto discovery = fido_discovery_factory->MaybeCreateWinWebAuthnApiDiscovery();
   if (!discovery) {
-    InitDiscoveries(available_transports);
+    InitDiscoveries(fido_discovery_factory, connector, available_transports);
     return;
   }
 
@@ -142,7 +144,7 @@
         FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy};
   }
 
-  InitDiscoveries(other_transports);
+  InitDiscoveries(fido_discovery_factory, connector, other_transports);
 }
 #endif  // defined(OS_WIN)
 
diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h
index 9969d07..936ece7 100644
--- a/device/fido/fido_request_handler_base.h
+++ b/device/fido/fido_request_handler_base.h
@@ -250,15 +250,17 @@
                                        const std::string& device_id,
                                        bool is_in_pairing_mode) override;
 
-  FidoDiscoveryFactory* fido_discovery_factory_;
-
  private:
   friend class FidoRequestHandlerTest;
 
   void InitDiscoveries(
+      FidoDiscoveryFactory* fido_discovery_factory,
+      service_manager::Connector* connector,
       const base::flat_set<FidoTransportProtocol>& available_transports);
 #if defined(OS_WIN)
   void InitDiscoveriesWin(
+      FidoDiscoveryFactory* fido_discovery_factory,
+      service_manager::Connector* connector,
       const base::flat_set<FidoTransportProtocol>& available_transports);
 #endif
 
@@ -277,7 +279,6 @@
   TransportAvailabilityInfo transport_availability_info_;
   base::RepeatingClosure notify_observer_callback_;
   std::unique_ptr<BleAdapterManager> bluetooth_adapter_manager_;
-  service_manager::Connector* const connector_;
 
   base::WeakPtrFactory<FidoRequestHandlerBase> weak_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(FidoRequestHandlerBase);
diff --git a/docs/infra/cq_builders.md b/docs/infra/cq_builders.md
index 579b5a5e..0ebf866 100644
--- a/docs/infra/cq_builders.md
+++ b/docs/infra/cq_builders.md
@@ -320,7 +320,7 @@
 
 * [android-pie-arm64-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android-pie-arm64-rel) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/android-pie-arm64-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android-pie-arm64-rel))
 
-  * Experimental percentage: 10
+  * Experimental percentage: 50
 
 * [chromeos-kevin-experimental-rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/chromeos-kevin-experimental-rel) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/chromeos-kevin-experimental-rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+chromeos-kevin-experimental-rel))
 
diff --git a/extensions/browser/api/media_perception_private/media_perception_api_delegate.h b/extensions/browser/api/media_perception_private/media_perception_api_delegate.h
index 0a82196..62626120 100644
--- a/extensions/browser/api/media_perception_private/media_perception_api_delegate.h
+++ b/extensions/browser/api/media_perception_private/media_perception_api_delegate.h
@@ -26,8 +26,10 @@
  public:
   // Callback for loading a CrOS component. |mount_point| will contain a path to
   // the loaded component, if |success| is true (installation succeeded).
-  using LoadCrOSComponentCallback =
-      base::OnceCallback<void(bool success, const base::FilePath& mount_point)>;
+  using LoadCrOSComponentCallback = base::OnceCallback<void(
+      const api::media_perception_private::ComponentInstallationError
+          installation_error,
+      const base::FilePath& mount_point)>;
 
   using MediaPerceptionRequestHandler = base::RepeatingCallback<void(
       chromeos::media_perception::mojom::MediaPerceptionRequest request)>;
diff --git a/extensions/browser/api/media_perception_private/media_perception_api_manager.cc b/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
index e24a18d6..68bc3a5 100644
--- a/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
+++ b/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
@@ -194,10 +194,15 @@
 
 void MediaPerceptionAPIManager::LoadComponentCallback(
     APISetAnalyticsComponentCallback callback,
-    bool success,
+    const extensions::api::media_perception_private::ComponentInstallationError
+        installation_error,
     const base::FilePath& mount_point) {
-  if (!success) {
-    std::move(callback).Run(GetFailedToInstallComponentState());
+  if (installation_error != extensions::api::media_perception_private::
+                                COMPONENT_INSTALLATION_ERROR_NONE) {
+    extensions::api::media_perception_private::ComponentState component_state =
+        GetFailedToInstallComponentState();
+    component_state.installation_error_code = installation_error;
+    std::move(callback).Run(std::move(component_state));
     return;
   }
 
diff --git a/extensions/browser/api/media_perception_private/media_perception_api_manager.h b/extensions/browser/api/media_perception_private/media_perception_api_manager.h
index b288bd4..db7ef030 100644
--- a/extensions/browser/api/media_perception_private/media_perception_api_manager.h
+++ b/extensions/browser/api/media_perception_private/media_perception_api_manager.h
@@ -131,7 +131,8 @@
 
   // Callback with the mount point for a loaded component.
   void LoadComponentCallback(APISetAnalyticsComponentCallback callback,
-                             bool success,
+                             const extensions::api::media_perception_private::
+                                 ComponentInstallationError installation_error,
                              const base::FilePath& mount_point);
 
   bool ComponentIsLoaded();
diff --git a/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc b/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc
index 76ecfa5..a029f4f 100644
--- a/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc
+++ b/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc
@@ -36,16 +36,17 @@
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE,
           base::BindOnce(
-              std::move(load_callback), true,
+              std::move(load_callback),
+              media_perception::COMPONENT_INSTALLATION_ERROR_NONE,
               base::FilePath("/run/imageloader/rtanalytics-light/1.0")));
       return;
     }
 
-    // Firing callback with false indicates that the installation of the
-    // component failed.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
-        base::BindOnce(std::move(load_callback), false, base::FilePath()));
+        base::BindOnce(std::move(load_callback),
+                       media_perception::COMPONENT_INSTALLATION_ERROR_NOT_FOUND,
+                       base::FilePath()));
   }
 
   void BindVideoSourceProvider(
diff --git a/extensions/browser/api/web_request/web_request_proxying_websocket.cc b/extensions/browser/api/web_request/web_request_proxying_websocket.cc
index 094414e..2435e0d 100644
--- a/extensions/browser/api/web_request/web_request_proxying_websocket.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_websocket.cc
@@ -360,6 +360,11 @@
 }
 
 void WebRequestProxyingWebSocket::ContinueToStartRequest(int error_code) {
+  if (error_code != net::OK) {
+    OnError(error_code);
+    return;
+  }
+
   base::flat_set<std::string> used_header_names;
   std::vector<network::mojom::HttpHeaderPtr> additional_headers;
   for (net::HttpRequestHeaders::Iterator it(request_headers_); it.GetNext();) {
diff --git a/extensions/test/data/media_perception_private/component/runtest.js b/extensions/test/data/media_perception_private/component/runtest.js
index e77ce8d..3dc7eee 100644
--- a/extensions/test/data/media_perception_private/component/runtest.js
+++ b/extensions/test/data/media_perception_private/component/runtest.js
@@ -5,17 +5,18 @@
 function setAnalyticsComponentLight() {
   chrome.mediaPerceptionPrivate.setAnalyticsComponent({
     type: 'LIGHT',
-  }, chrome.test.callbackPass(function(component_state) {
-    chrome.test.assertEq('INSTALLED', component_state.status);
-    chrome.test.assertEq('1.0', component_state.version);
+  }, chrome.test.callbackPass(function(componentState) {
+    chrome.test.assertEq('INSTALLED', componentState.status);
+    chrome.test.assertEq('1.0', componentState.version);
   }));
 }
 
 function setAnalyticsComponentFullExpectFailure() {
   chrome.mediaPerceptionPrivate.setAnalyticsComponent({
     type: 'FULL',
-  }, chrome.test.callbackPass(function(component_state) {
-    chrome.test.assertEq('FAILED_TO_INSTALL', component_state.status);
+  }, chrome.test.callbackPass(function(componentState) {
+    chrome.test.assertEq('FAILED_TO_INSTALL', componentState.status);
+    chrome.test.assertEq('NOT_FOUND', componentState.installationErrorCode);
   }));
 }
 
@@ -29,9 +30,9 @@
 
   chrome.mediaPerceptionPrivate.setAnalyticsComponent({
     type: 'LIGHT',
-  }, chrome.test.callbackPass(function(component_state) {
-    chrome.test.assertEq('INSTALLED', component_state.status);
-    chrome.test.assertEq('1.0', component_state.version);
+  }, chrome.test.callbackPass(function(componentState) {
+    chrome.test.assertEq('INSTALLED', componentState.status);
+    chrome.test.assertEq('1.0', componentState.version);
   }));
 }
 
diff --git a/fuchsia/base/agent_impl.cc b/fuchsia/base/agent_impl.cc
index 1e1268e..a0d4ecc 100644
--- a/fuchsia/base/agent_impl.cc
+++ b/fuchsia/base/agent_impl.cc
@@ -28,6 +28,11 @@
       &ComponentStateBase::TeardownIfUnused, base::Unretained(this)));
 }
 
+void AgentImpl::ComponentStateBase::DisconnectClientsAndTeardown() {
+  agent_impl_->DeleteComponentState(component_id_);
+  // Do not touch |this|, since it is already gone.
+}
+
 void AgentImpl::ComponentStateBase::TeardownIfUnused() {
   DCHECK(agent_impl_);
 
@@ -41,7 +46,7 @@
       return;
   }
 
-  agent_impl_->DeleteComponentState(component_id_);
+  DisconnectClientsAndTeardown();
   // Do not touch |this|, since it is already gone.
 }
 
diff --git a/fuchsia/base/agent_impl.h b/fuchsia/base/agent_impl.h
index 3165076..b268b67 100644
--- a/fuchsia/base/agent_impl.h
+++ b/fuchsia/base/agent_impl.h
@@ -76,6 +76,10 @@
           &ComponentStateBase::TeardownIfUnused, base::Unretained(this)));
     }
 
+    // Requests that this instance be torn-down, regardless of whether one or
+    // more keep-alive bindings (see above) have clients.
+    void DisconnectClientsAndTeardown();
+
    private:
     friend class AgentImpl;
 
diff --git a/fuchsia/base/agent_impl_unittests.cc b/fuchsia/base/agent_impl_unittests.cc
index 12317fe..1eaa6af2 100644
--- a/fuchsia/base/agent_impl_unittests.cc
+++ b/fuchsia/base/agent_impl_unittests.cc
@@ -62,6 +62,10 @@
       : AccumulatorComponentState(component) {
     AddKeepAliveBinding(&service_binding_);
   }
+
+  void DisconnectClientsAndTeardown() {
+    AgentImpl::ComponentStateBase::DisconnectClientsAndTeardown();
+  }
 };
 
 class AgentImplTest : public ::testing::Test {
@@ -86,6 +90,10 @@
     return agent;
   }
 
+  void TeardownKeepAliveComponentState() {
+    std::move(disconnect_clients_and_teardown_).Run();
+  }
+
  protected:
   std::unique_ptr<AgentImpl::ComponentStateBase> OnComponentConnect(
       base::StringPiece component_id) {
@@ -95,7 +103,12 @@
                component_id == kAccumulatorComponentId2) {
       return std::make_unique<AccumulatorComponentState>(component_id);
     } else if (component_id == kKeepAliveComponentId) {
-      return std::make_unique<KeepAliveComponentState>(component_id);
+      auto component_state =
+          std::make_unique<KeepAliveComponentState>(component_id);
+      disconnect_clients_and_teardown_ =
+          base::BindOnce(&KeepAliveComponentState::DisconnectClientsAndTeardown,
+                         base::Unretained(component_state.get()));
+      return component_state;
     }
     return nullptr;
   }
@@ -107,6 +120,10 @@
 
   std::unique_ptr<AgentImpl> agent_impl_;
 
+  // Set only if a keep-alive component was connected, to allow the test to
+  // forcibly teardown the ComponentState for it.
+  base::OnceClosure disconnect_clients_and_teardown_;
+
   DISALLOW_COPY_AND_ASSIGN(AgentImplTest);
 };
 
@@ -251,7 +268,7 @@
   test_interface2.set_error_handler(nullptr);
 }
 
-// Verify that connections to a service registered to kee-alive the
+// Verify that connections to a service registered to keep-alive the
 // ComponentStateBase keeps it alive after the ServiceProvider is dropped.
 TEST_F(AgentImplTest, KeepAliveBinding) {
   fuchsia::modular::AgentPtr agent = CreateAgentAndConnect();
@@ -301,4 +318,36 @@
   base::RunLoop().RunUntilIdle();
 }
 
+// Verify that connections to a service registered to keep-alive the
+// ComponentStateBase is disconnected by DisconnectClientsAndTeardown.
+TEST_F(AgentImplTest, DisconnectClientsAndTeardown) {
+  fuchsia::modular::AgentPtr agent = CreateAgentAndConnect();
+
+  {
+    // Connect to the Agent and request the TestInterface.
+    fuchsia::sys::ServiceProviderPtr component_services;
+    agent->Connect(kKeepAliveComponentId, component_services.NewRequest());
+    base::fuchsia::testfidl::TestInterfacePtr test_interface;
+    component_services->ConnectToService(
+        base::fuchsia::testfidl::TestInterface::Name_,
+        test_interface.NewRequest().TakeChannel());
+
+    // The TestInterface pointer should remain valid until we call
+    // DisconnectClientsAndTeardown().
+    test_interface.set_error_handler(
+        [](zx_status_t status) { ZX_LOG_IF(ERROR, status != ZX_OK, status); });
+
+    // After disconnecting ServiceProvider, TestInterface should remain valid.
+    component_services.Unbind();
+    base::RunLoop().RunUntilIdle();
+    EXPECT_TRUE(test_interface);
+
+    // After invoking DisconnectClientsAndTeardown(), TestInterface should
+    // be disconnected.
+    TeardownKeepAliveComponentState();
+    base::RunLoop().RunUntilIdle();
+    EXPECT_FALSE(test_interface);
+  }
+}
+
 }  // namespace cr_fuchsia
diff --git a/fuchsia/engine/browser/content_directory_browsertest.cc b/fuchsia/engine/browser/content_directory_browsertest.cc
index 7437de1..7e237cd 100644
--- a/fuchsia/engine/browser/content_directory_browsertest.cc
+++ b/fuchsia/engine/browser/content_directory_browsertest.cc
@@ -3,14 +3,18 @@
 // found in the LICENSE file.
 
 #include <lib/fdio/directory.h>
+#include <lib/vfs/cpp/pseudo_dir.h>
+#include <lib/vfs/cpp/vmo_file.h>
 
 #include "fuchsia/engine/test/web_engine_browser_test.h"
 
 #include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/path_service.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/test_timeouts.h"
+#include "base/threading/thread_restrictions.h"
 #include "fuchsia/base/frame_test_util.h"
 #include "fuchsia/base/test_navigation_listener.h"
 #include "fuchsia/engine/browser/content_directory_loader_factory.h"
@@ -147,6 +151,53 @@
   navigation_listener_.RunUntilUrlAndTitleEquals(kUrl, "image fetched");
 }
 
+// Reads content sourced from VFS PseudoDirs and VmoFiles.
+IN_PROC_BROWSER_TEST_F(ContentDirectoryTest, FromVfsPseudoDir) {
+  base::ScopedAllowBlockingForTesting allow_block;
+
+  // Get the file contents and store it in a VMO.
+  std::string contents;
+  base::FilePath pkg_path;
+  base::PathService::Get(base::DIR_ASSETS, &pkg_path);
+  ASSERT_TRUE(base::ReadFileToString(
+      pkg_path.AppendASCII("fuchsia/engine/test/data/title1.html"), &contents));
+  zx::vmo contents_vmo;
+  zx_status_t status = zx::vmo::create(contents.size(), 0, &contents_vmo);
+  ASSERT_EQ(status, ZX_OK);
+  status = contents_vmo.write(contents.data(), 0, contents.size());
+  ASSERT_EQ(status, ZX_OK);
+
+  // Build up the directory structure of a VmoFile inside a PseudoDir.
+  auto vmo_file = std::make_unique<vfs::VmoFile>(
+      std::move(contents_vmo), 0, contents.size(),
+      vfs::VmoFile::WriteOption::READ_ONLY, vfs::VmoFile::Sharing::CLONE_COW);
+  vfs::PseudoDir pseudo_dir;
+  status = pseudo_dir.AddEntry("title1.html", std::move(vmo_file));
+  ASSERT_EQ(status, ZX_OK);
+
+  // Serve the PseudoDir under the "pseudo-dir" URL.
+  fuchsia::web::ContentDirectoryProvider provider;
+  provider.set_name("pseudo-dir");
+  fidl::InterfaceHandle<fuchsia::io::Directory> directory_channel;
+  pseudo_dir.Serve(
+      fuchsia::io::OPEN_FLAG_DIRECTORY | fuchsia::io::OPEN_RIGHT_READABLE,
+      directory_channel.NewRequest().TakeChannel());
+  provider.set_directory(std::move(directory_channel));
+  std::vector<fuchsia::web::ContentDirectoryProvider> providers;
+  providers.emplace_back(std::move(provider));
+  ContentDirectoryLoaderFactory::SetContentDirectoriesForTest(
+      std::move(providers));
+
+  // Access the VmoFile under the PseudoDir.
+  const GURL kUrl("fuchsia-dir://pseudo-dir/title1.html");
+  fuchsia::web::FramePtr frame = CreateFrame();
+  fuchsia::web::NavigationControllerPtr controller;
+  frame->GetNavigationController(controller.NewRequest());
+  EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+      controller.get(), fuchsia::web::LoadUrlParams(), kUrl.spec()));
+  navigation_listener_.RunUntilUrlAndTitleEquals(kUrl, "title 1");
+}
+
 // Verify that resource providers are origin-isolated.
 IN_PROC_BROWSER_TEST_F(ContentDirectoryTest, ScriptSrcCrossOriginBlocked) {
   const GURL kUrl("fuchsia-dir://testdata/cross_origin_include_script.html");
diff --git a/fuchsia/engine/browser/content_directory_loader_factory.cc b/fuchsia/engine/browser/content_directory_loader_factory.cc
index ea8fb0c..e88a03bf 100644
--- a/fuchsia/engine/browser/content_directory_loader_factory.cc
+++ b/fuchsia/engine/browser/content_directory_loader_factory.cc
@@ -335,10 +335,23 @@
     return;
   }
 
+  std::string requested_path = request.url.path();
+  if (requested_path.empty()) {
+    client->OnComplete(
+        network::URLLoaderCompletionStatus(net::ERR_INVALID_URL));
+    return;
+  }
+
+  // Not all VFS implementations handle leading slashes in the same way, so
+  // remove it for maximum compatibility.
+  // TODO(fxb/38339): Update this comment when issue is resolved.
+  if (requested_path[0] == '/')
+    requested_path = requested_path.substr(1, requested_path.size() - 1);
+
   fidl::InterfaceHandle<fuchsia::io::Node> file_handle;
-  net::Error open_result = OpenFileFromDirectory(
-      request.url.GetOrigin().host(), base::FilePath(request.url.path()),
-      file_handle.NewRequest());
+  net::Error open_result = OpenFileFromDirectory(request.url.GetOrigin().host(),
+                                                 base::FilePath(requested_path),
+                                                 file_handle.NewRequest());
   if (open_result != net::OK) {
     client->OnComplete(network::URLLoaderCompletionStatus(open_result));
     return;
@@ -351,7 +364,7 @@
   fidl::InterfaceHandle<fuchsia::io::Node> metadata_handle;
   open_result =
       OpenFileFromDirectory(request.url.GetOrigin().host(),
-                            base::FilePath(request.url.path() + "._metadata"),
+                            base::FilePath(requested_path + "._metadata"),
                             metadata_handle.NewRequest());
   if (open_result != net::OK) {
     client->OnComplete(network::URLLoaderCompletionStatus(open_result));
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index 9561d72..19141de 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -3369,6 +3369,18 @@
       "features": [
         "exit_on_context_lost"
       ]
-    }
+    },
+    {
+      "id": 314,
+      "cr_bugs": [1010338],
+      "description": "Crash on Adreno when using GL_EXT_shader_framebuffer_fetch",
+      "os": {
+        "type": "android"
+      },
+      "gl_renderer": "Adreno.*",
+      "disabled_extensions": [
+        "GL_EXT_shader_framebuffer_fetch"
+      ]
+   }
   ]
 }
diff --git a/gpu/ipc/common/gpu_memory_buffer_support.cc b/gpu/ipc/common/gpu_memory_buffer_support.cc
index b102bbb..02f52cee 100644
--- a/gpu/ipc/common/gpu_memory_buffer_support.cc
+++ b/gpu/ipc/common/gpu_memory_buffer_support.cc
@@ -110,8 +110,8 @@
   NOTREACHED();
   return false;
 #elif defined(USE_OZONE)
-  return ui::OzonePlatform::EnsureInstance()->IsNativePixmapConfigSupported(
-      format, usage);
+  return ui::OzonePlatform::GetInstance()->IsNativePixmapConfigSupported(format,
+                                                                         usage);
 #elif defined(OS_LINUX)
   return false;  // TODO(julian.isorce): Add linux support.
 #elif defined(OS_WIN)
diff --git a/gpu/vulkan/vulkan_instance.cc b/gpu/vulkan/vulkan_instance.cc
index 1f641fd..8bd39f54 100644
--- a/gpu/vulkan/vulkan_instance.cc
+++ b/gpu/vulkan/vulkan_instance.cc
@@ -269,7 +269,11 @@
     DLOG_IF(ERROR, result != VK_SUCCESS)
         << "vkEnumerateDeviceLayerProperties failed: " << result;
 
-    if (vkGetPhysicalDeviceFeatures2) {
+    // The API version of the VkInstance might be different than the supported
+    // API version of the VkPhysicalDevice, so we need to check the GPU's
+    // API version instead of just testing to see if
+    // vkGetPhysicalDeviceFeatures2 is non-null.
+    if (info.properties.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
       VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcr_converson_features =
           {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES};
       VkPhysicalDeviceProtectedMemoryFeatures protected_memory_feature = {
diff --git a/infra/config/commit-queue.cfg b/infra/config/commit-queue.cfg
index 576d65f1..4a9b36a 100644
--- a/infra/config/commit-queue.cfg
+++ b/infra/config/commit-queue.cfg
@@ -370,7 +370,7 @@
       }
       builders {
         name: "chromium/try/android-pie-arm64-rel"
-        experiment_percentage: 10
+        experiment_percentage: 50
       }
       builders {
         name: "chromium/try/chromeos-kevin-experimental-rel"
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg
index 05d7d01f..95ca7dc 100644
--- a/infra/config/cr-buildbucket.cfg
+++ b/infra/config/cr-buildbucket.cfg
@@ -375,11 +375,10 @@
   name: "celab"
   recipe {
     name: "celab"
-    # The version of CELab binaries to use for tests (cel_ctl & cel_agent).
-    properties: "celab_version:7R4C-DmIN8lwXvsToDcbG0pgyWcvJT-S-fu15NYkIdEC"
-    # This controls which tests to run (* is all tests).
+    # These control which tests to run (* is all tests, exclude Chrome tests).
     # We might create more builders for different test sets later.
     properties: "tests:*"
+    properties: "exclude:chrome_only"
   }
 }
 builder_mixins {
@@ -387,7 +386,7 @@
   mixins: "celab"
   recipe {
     properties: "pool_name:celab-chromium-ci"
-    properties_j: "pool_size:10"
+    properties_j: "pool_size:20"
   }
 }
 builder_mixins {
@@ -395,7 +394,7 @@
   mixins: "celab"
   recipe {
     properties: "pool_name:celab-chromium-try"
-    properties_j: "pool_size:10"
+    properties_j: "pool_size:20"
   }
 }
 
@@ -2545,6 +2544,10 @@
       mixins: "linux-gpu-fyi-ci-tester"
     }
     builders {
+      name: "Win10 FYI x64 SkiaRenderer GL (NVIDIA)"
+      mixins: "linux-gpu-fyi-ci-tester"
+    }
+    builders {
       name: "Win10 FYI x86 Release (NVIDIA)"
       mixins: "linux-gpu-fyi-ci-tester"
     }
@@ -3948,6 +3951,12 @@
 
     # Keep builders sorted by OS, then name.
     builders {
+      mixins: "android-try"
+      mixins: "builderless"
+      mixins: "linux-xenial"
+      name: "android-opus-kitkat-arm-rel"
+    }
+    builders {
       mixins: "android-angle-try"
       mixins: "goma-rbe-prod"
       name: "android_angle_deqp_rel_ng"
@@ -4880,6 +4889,10 @@
     }
     builders {
       mixins: "win-optional-gpu-try"
+      name: "gpu-fyi-try-win10-nvidia-skgl-64"
+    }
+    builders {
+      mixins: "win-optional-gpu-try"
       name: "gpu-try-win10-nvidia-rel"
     }
     builders {
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg
index 576d65f1..4a9b36a 100644
--- a/infra/config/generated/commit-queue.cfg
+++ b/infra/config/generated/commit-queue.cfg
@@ -370,7 +370,7 @@
       }
       builders {
         name: "chromium/try/android-pie-arm64-rel"
-        experiment_percentage: 10
+        experiment_percentage: 50
       }
       builders {
         name: "chromium/try/chromeos-kevin-experimental-rel"
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index 05d7d01f..95ca7dc 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -375,11 +375,10 @@
   name: "celab"
   recipe {
     name: "celab"
-    # The version of CELab binaries to use for tests (cel_ctl & cel_agent).
-    properties: "celab_version:7R4C-DmIN8lwXvsToDcbG0pgyWcvJT-S-fu15NYkIdEC"
-    # This controls which tests to run (* is all tests).
+    # These control which tests to run (* is all tests, exclude Chrome tests).
     # We might create more builders for different test sets later.
     properties: "tests:*"
+    properties: "exclude:chrome_only"
   }
 }
 builder_mixins {
@@ -387,7 +386,7 @@
   mixins: "celab"
   recipe {
     properties: "pool_name:celab-chromium-ci"
-    properties_j: "pool_size:10"
+    properties_j: "pool_size:20"
   }
 }
 builder_mixins {
@@ -395,7 +394,7 @@
   mixins: "celab"
   recipe {
     properties: "pool_name:celab-chromium-try"
-    properties_j: "pool_size:10"
+    properties_j: "pool_size:20"
   }
 }
 
@@ -2545,6 +2544,10 @@
       mixins: "linux-gpu-fyi-ci-tester"
     }
     builders {
+      name: "Win10 FYI x64 SkiaRenderer GL (NVIDIA)"
+      mixins: "linux-gpu-fyi-ci-tester"
+    }
+    builders {
       name: "Win10 FYI x86 Release (NVIDIA)"
       mixins: "linux-gpu-fyi-ci-tester"
     }
@@ -3948,6 +3951,12 @@
 
     # Keep builders sorted by OS, then name.
     builders {
+      mixins: "android-try"
+      mixins: "builderless"
+      mixins: "linux-xenial"
+      name: "android-opus-kitkat-arm-rel"
+    }
+    builders {
       mixins: "android-angle-try"
       mixins: "goma-rbe-prod"
       name: "android_angle_deqp_rel_ng"
@@ -4880,6 +4889,10 @@
     }
     builders {
       mixins: "win-optional-gpu-try"
+      name: "gpu-fyi-try-win10-nvidia-skgl-64"
+    }
+    builders {
+      mixins: "win-optional-gpu-try"
       name: "gpu-try-win10-nvidia-rel"
     }
     builders {
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg
index 9fcb5e6..dd06325 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -3532,6 +3532,11 @@
     short_name: "gtx"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/Win10 FYI x64 SkiaRenderer GL (NVIDIA)"
+    category: "Windows|10|x64|Nvidia"
+    short_name: "skgl"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/Win10 FYI x86 Release (NVIDIA)"
     category: "Windows|10|x86|Nvidia"
     short_name: "rel"
@@ -4123,6 +4128,9 @@
   refs: "refs/heads/master"
   manifest_name: "REVISION"
   builders {
+    name: "buildbucket/luci.chromium.try/android-opus-kitkat-arm-rel"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/android_archive_rel_ng"
   }
   builders {
@@ -4658,6 +4666,9 @@
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-win10-nvidia-rel-64"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/gpu-fyi-try-win10-nvidia-skgl-64"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/win-libfuzzer-asan-rel"
   }
   builders {
@@ -5042,6 +5053,9 @@
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-win10-nvidia-rel-64"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/gpu-fyi-try-win10-nvidia-skgl-64"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-mac-amd-dqp"
   }
   builders {
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg
index 469e7e2..a52f241 100644
--- a/infra/config/generated/luci-scheduler.cfg
+++ b/infra/config/generated/luci-scheduler.cfg
@@ -400,7 +400,6 @@
   triggers: "win-archive-dbg"
   triggers: "win-jumbo-rel"
   triggers: "win-archive-rel"
-  triggers: "win-celab-builder-rel"
   triggers: "win-pixel-builder-rel"
   triggers: "win32-arm64-rel"
   triggers: "win32-archive-dbg"
@@ -2931,6 +2930,17 @@
 }
 
 job {
+  id: "Win10 FYI x64 SkiaRenderer GL (NVIDIA)"
+  # Triggered by "GPU FYI Win x64 Builder"
+  acl_sets: "triggered-by-parent-builders"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Win10 FYI x64 SkiaRenderer GL (NVIDIA)"
+  }
+}
+
+job {
   id: "Win10 FYI x86 Release (NVIDIA)"
   # Triggered by "GPU FYI Win Builder"
   acl_sets: "triggered-by-parent-builders"
@@ -3226,6 +3236,8 @@
 job {
   id: "win-celab-builder-rel"
   acl_sets: "default"
+  # Run this every six hours
+  schedule: "0 0,6,12,18 * * *"
   buildbucket: {
     server: "cr-buildbucket.appspot.com"
     bucket: "luci.chromium.ci"
diff --git a/infra/config/luci-milo.cfg b/infra/config/luci-milo.cfg
index 9fcb5e6..dd06325 100644
--- a/infra/config/luci-milo.cfg
+++ b/infra/config/luci-milo.cfg
@@ -3532,6 +3532,11 @@
     short_name: "gtx"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/Win10 FYI x64 SkiaRenderer GL (NVIDIA)"
+    category: "Windows|10|x64|Nvidia"
+    short_name: "skgl"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/Win10 FYI x86 Release (NVIDIA)"
     category: "Windows|10|x86|Nvidia"
     short_name: "rel"
@@ -4123,6 +4128,9 @@
   refs: "refs/heads/master"
   manifest_name: "REVISION"
   builders {
+    name: "buildbucket/luci.chromium.try/android-opus-kitkat-arm-rel"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/android_archive_rel_ng"
   }
   builders {
@@ -4658,6 +4666,9 @@
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-win10-nvidia-rel-64"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/gpu-fyi-try-win10-nvidia-skgl-64"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/win-libfuzzer-asan-rel"
   }
   builders {
@@ -5042,6 +5053,9 @@
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-win10-nvidia-rel-64"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/gpu-fyi-try-win10-nvidia-skgl-64"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/gpu-fyi-try-mac-amd-dqp"
   }
   builders {
diff --git a/infra/config/luci-scheduler.cfg b/infra/config/luci-scheduler.cfg
index 469e7e2..a52f241 100644
--- a/infra/config/luci-scheduler.cfg
+++ b/infra/config/luci-scheduler.cfg
@@ -400,7 +400,6 @@
   triggers: "win-archive-dbg"
   triggers: "win-jumbo-rel"
   triggers: "win-archive-rel"
-  triggers: "win-celab-builder-rel"
   triggers: "win-pixel-builder-rel"
   triggers: "win32-arm64-rel"
   triggers: "win32-archive-dbg"
@@ -2931,6 +2930,17 @@
 }
 
 job {
+  id: "Win10 FYI x64 SkiaRenderer GL (NVIDIA)"
+  # Triggered by "GPU FYI Win x64 Builder"
+  acl_sets: "triggered-by-parent-builders"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Win10 FYI x64 SkiaRenderer GL (NVIDIA)"
+  }
+}
+
+job {
   id: "Win10 FYI x86 Release (NVIDIA)"
   # Triggered by "GPU FYI Win Builder"
   acl_sets: "triggered-by-parent-builders"
@@ -3226,6 +3236,8 @@
 job {
   id: "win-celab-builder-rel"
   acl_sets: "default"
+  # Run this every six hours
+  schedule: "0 0,6,12,18 * * *"
   buildbucket: {
     server: "cr-buildbucket.appspot.com"
     bucket: "luci.chromium.ci"
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
index 8817d8e..39d29dd 100644
--- a/ipc/ipc_mojo_bootstrap.cc
+++ b/ipc/ipc_mojo_bootstrap.cc
@@ -124,15 +124,15 @@
       : task_runner_(ipc_task_runner),
         proxy_task_runner_(proxy_task_runner),
         set_interface_id_namespace_bit_(set_interface_id_namespace_bit),
-        filters_(this),
+        dispatcher_(this),
         control_message_handler_(this),
         control_message_proxy_thunk_(this),
         control_message_proxy_(&control_message_proxy_thunk_) {
     thread_checker_.DetachFromThread();
     control_message_handler_.SetDescription(
         "IPC::mojom::Bootstrap [master] PipeControlMessageHandler");
-    filters_.Append<mojo::MessageHeaderValidator>(
-        "IPC::mojom::Bootstrap [master] MessageHeaderValidator");
+    dispatcher_.SetValidator(std::make_unique<mojo::MessageHeaderValidator>(
+        "IPC::mojom::Bootstrap [master] MessageHeaderValidator"));
 
     GetMemoryDumpProvider().AddController(this);
   }
@@ -166,7 +166,7 @@
     connector_.reset(new mojo::Connector(
         std::move(handle), mojo::Connector::SINGLE_THREADED_SEND,
         task_runner_));
-    connector_->set_incoming_receiver(&filters_);
+    connector_->set_incoming_receiver(&dispatcher_);
     connector_->set_connection_error_handler(
         base::Bind(&ChannelAssociatedGroupController::OnPipeError,
                    base::Unretained(this)));
@@ -986,7 +986,7 @@
   const bool set_interface_id_namespace_bit_;
   bool paused_ = false;
   std::unique_ptr<mojo::Connector> connector_;
-  mojo::FilterChain filters_;
+  mojo::MessageDispatcher dispatcher_;
   mojo::PipeControlMessageHandler control_message_handler_;
   ControlMessageProxyThunk control_message_proxy_thunk_;
 
diff --git a/media/fuchsia/cdm/fuchsia_cdm.cc b/media/fuchsia/cdm/fuchsia_cdm.cc
index 2b9353a..2272683 100644
--- a/media/fuchsia/cdm/fuchsia_cdm.cc
+++ b/media/fuchsia/cdm/fuchsia_cdm.cc
@@ -115,7 +115,7 @@
       base::OnceCallback<void(base::Optional<CdmPromise::Exception>)>;
 
   CdmSession(const FuchsiaCdm::SessionCallbacks* callbacks,
-             base::RepeatingClosure on_new_key)
+             FuchsiaSecureStreamDecryptor::NewKeyCB on_new_key)
       : session_callbacks_(callbacks), on_new_key_(on_new_key) {
     // License session events, e.g. license request message, key status change.
     // Fuchsia CDM service guarantees callback of functions (e.g.
@@ -184,11 +184,21 @@
   }
 
   void OnKeysChanged(std::vector<fuchsia::media::drm::KeyInfo> key_info) {
+    std::string new_key_id;
     bool has_additional_usable_key = false;
     CdmKeysInfo keys_info;
     for (const auto& info : key_info) {
       CdmKeyInformation::KeyStatus status = ToCdmKeyStatus(info.status);
       has_additional_usable_key |= (status == CdmKeyInformation::USABLE);
+      if (status == CdmKeyInformation::USABLE && new_key_id.empty()) {
+        // The |key_id| is passed to |on_new_key_| to workaround fxb/38253 in
+        // FuchsiaSecureStreamDecryptor. It needs just one valid |key_id|, so it
+        // doesn't matter if |key_info| contains more than one key.
+        // TODO(crbug.com/1012525): Remove the hack once fxb/38253 is resolved.
+        new_key_id.assign(
+            reinterpret_cast<const char*>(info.key_id.data.data()),
+            info.key_id.data.size());
+      }
       keys_info.emplace_back(new CdmKeyInformation(
           info.key_id.data.data(), info.key_id.data.size(), status, 0));
     }
@@ -197,7 +207,7 @@
         session_id_, has_additional_usable_key, std::move(keys_info));
 
     if (has_additional_usable_key)
-      on_new_key_.Run();
+      on_new_key_.Run(new_key_id);
   }
 
   void OnSessionError(zx_status_t status) {
@@ -216,7 +226,7 @@
   }
 
   const SessionCallbacks* const session_callbacks_;
-  base::RepeatingClosure on_new_key_;
+  FuchsiaSecureStreamDecryptor::NewKeyCB on_new_key_;
 
   fuchsia::media::drm::LicenseSessionPtr session_;
   std::string session_id_;
@@ -457,12 +467,12 @@
   return this;
 }
 
-void FuchsiaCdm::OnNewKey() {
+void FuchsiaCdm::OnNewKey(const std::string& key_id) {
   decryptor_.OnNewKey();
   {
     base::AutoLock auto_lock(new_key_cb_for_video_lock_);
     if (new_key_cb_for_video_)
-      new_key_cb_for_video_.Run();
+      new_key_cb_for_video_.Run(key_id);
   }
 }
 
diff --git a/media/fuchsia/cdm/fuchsia_cdm.h b/media/fuchsia/cdm/fuchsia_cdm.h
index 574a398..65fd5be 100644
--- a/media/fuchsia/cdm/fuchsia_cdm.h
+++ b/media/fuchsia/cdm/fuchsia_cdm.h
@@ -87,7 +87,8 @@
       uint32_t promise_id,
       base::Optional<CdmPromise::Exception> exception);
 
-  void OnNewKey();
+  // TODO(crbug.com/1012525): Remove |key_id| once fxb/38253 is resolved.
+  void OnNewKey(const std::string& key_id);
 
   CdmPromiseAdapter promises_;
   base::flat_map<std::string, std::unique_ptr<CdmSession>> session_map_;
@@ -98,7 +99,7 @@
   FuchsiaDecryptor decryptor_;
 
   base::Lock new_key_cb_for_video_lock_;
-  base::RepeatingClosure new_key_cb_for_video_
+  FuchsiaSecureStreamDecryptor::NewKeyCB new_key_cb_for_video_
       GUARDED_BY(new_key_cb_for_video_lock_);
 
   DISALLOW_COPY_AND_ASSIGN(FuchsiaCdm);
diff --git a/media/fuchsia/cdm/fuchsia_stream_decryptor.cc b/media/fuchsia/cdm/fuchsia_stream_decryptor.cc
index 6ecabe2..176a025 100644
--- a/media/fuchsia/cdm/fuchsia_stream_decryptor.cc
+++ b/media/fuchsia/cdm/fuchsia_stream_decryptor.cc
@@ -39,8 +39,15 @@
 
 fuchsia::media::KeyId GetKeyId(const std::string& key_id) {
   fuchsia::media::KeyId fuchsia_key_id;
-  DCHECK_EQ(key_id.size(), fuchsia_key_id.data.size());
-  std::copy(key_id.begin(), key_id.end(), fuchsia_key_id.data.begin());
+  // |key_id| may be empty when sending clear frames while we don't have
+  // Key Id yet. Send a zero |key_id| in that case.
+  // TODO(crbug.com/1012525): Remove this case once fxb/38253 is resolved.
+  if (key_id.empty()) {
+    fuchsia_key_id.data = {0};
+  } else {
+    DCHECK_EQ(key_id.size(), fuchsia::media::KEY_ID_SIZE);
+    std::copy(key_id.begin(), key_id.end(), fuchsia_key_id.data.begin());
+  }
   return fuchsia_key_id;
 }
 
@@ -65,7 +72,32 @@
   return fuchsia_pattern;
 }
 
-fuchsia::media::FormatDetails GetFormatDetails(const DecryptConfig* config) {
+// We shouldn't need to set Key ID for clear frames, but it's currently
+// required by the CDM API, see fxb/38253 . This function takes
+// |placeholder_key_id| to workaround that issue.
+// TODO(crbug.com/1012525): Remove |placeholder_key_id| once fxb/38253 is
+// resolved.
+fuchsia::media::FormatDetails GetClearFormatDetails(
+    size_t packet_size,
+    const std::string& placeholder_key_id) {
+  fuchsia::media::EncryptedFormat encrypted_format;
+  encrypted_format.set_mode(fuchsia::media::drm::ENCRYPTION_MODE_CENC)
+      .set_key_id(GetKeyId(placeholder_key_id))
+      .set_init_vector(std::vector<uint8_t>(DecryptConfig::kDecryptionKeySize));
+
+  std::vector<fuchsia::media::SubsampleEntry> subsamples(1);
+  subsamples[0].clear_bytes = packet_size;
+  subsamples[0].encrypted_bytes = 0;
+  encrypted_format.set_subsamples(subsamples);
+
+  fuchsia::media::FormatDetails format;
+  format.set_format_details_version_ordinal(0);
+  format.mutable_domain()->crypto().set_encrypted(std::move(encrypted_format));
+  return format;
+}
+
+fuchsia::media::FormatDetails GetEncryptedFormatDetails(
+    const DecryptConfig* config) {
   DCHECK(config);
 
   fuchsia::media::EncryptedFormat encrypted_format;
@@ -192,7 +224,12 @@
     return;
   }
 
-  packet.set_format(GetFormatDetails(buffer->decrypt_config()));
+  fuchsia::media::FormatDetails format =
+      (buffer->decrypt_config())
+          ? GetEncryptedFormatDetails(buffer->decrypt_config())
+          : GetClearFormatDetails(packet.size(), last_new_key_id_);
+
+  packet.set_format(std::move(format));
   processor_.Process(std::move(packet));
 }
 
@@ -457,7 +494,8 @@
   client_->OnDecryptorOutputPacket(std::move(packet));
 }
 
-base::RepeatingClosure FuchsiaSecureStreamDecryptor::GetOnNewKeyClosure() {
+FuchsiaSecureStreamDecryptor::NewKeyCB
+FuchsiaSecureStreamDecryptor::GetOnNewKeyClosure() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   return BindToCurrentLoop(base::BindRepeating(
@@ -493,9 +531,17 @@
   client_->OnDecryptorNoKey();
 }
 
-void FuchsiaSecureStreamDecryptor::OnNewKey() {
+void FuchsiaSecureStreamDecryptor::OnNewKey(const std::string& key_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
+  // Currently Widevine CDM requires a valid key_id for frames that are not
+  // encrypted, but we don't have a key_id in the beginning of the stream. To
+  // workaround this issue we save the |key_id| here and then use it for clear
+  // frames in SendInputPacket().
+  // TODO(crbug.com/1012525): Remove this hack once fxb/38253 is resolved: CDM
+  // shouldn't need |key_id| to handle clear frames.
+  last_new_key_id_ = key_id;
+
   if (!waiting_for_key_) {
     retry_on_no_key_ = true;
     return;
diff --git a/media/fuchsia/cdm/fuchsia_stream_decryptor.h b/media/fuchsia/cdm/fuchsia_stream_decryptor.h
index 60cc73d4..d0962b3 100644
--- a/media/fuchsia/cdm/fuchsia_stream_decryptor.h
+++ b/media/fuchsia/cdm/fuchsia_stream_decryptor.h
@@ -40,6 +40,9 @@
 
   SysmemBufferWriterQueue input_writer_queue_;
 
+  // Key ID for which we received the last OnNewKey() event.
+  std::string last_new_key_id_;
+
   SEQUENCE_CHECKER(sequence_checker_);
 
  private:
@@ -115,6 +118,8 @@
     virtual ~Client() = default;
   };
 
+  using NewKeyCB = base::RepeatingCallback<void(const std::string& key_id)>;
+
   FuchsiaSecureStreamDecryptor(fuchsia::media::StreamProcessorPtr processor,
                                Client* client);
   ~FuchsiaSecureStreamDecryptor() override;
@@ -136,7 +141,7 @@
   // FuchsiaClearStreamDecryptor and media::Decryptor: they report NO_KEY error
   // to the caller and expect the caller to resubmit same buffers again after
   // the key is updated.
-  base::RepeatingClosure GetOnNewKeyClosure();
+  NewKeyCB GetOnNewKeyClosure();
 
   // Drops all pending decryption requests.
   void Reset();
@@ -152,7 +157,7 @@
 
   // Callback returned by GetOnNewKeyClosure(). When waiting for a key this
   // method unpauses the stream to decrypt any pending buffers.
-  void OnNewKey();
+  void OnNewKey(const std::string& key_id);
 
   Client* const client_;
 
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index de38cb9..e92b43d 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -142,8 +142,10 @@
     {VP8PROFILE_ANY, VAProfileVP8Version0_3},
     {VP9PROFILE_PROFILE0, VAProfileVP9Profile0},
     {VP9PROFILE_PROFILE1, VAProfileVP9Profile1},
-    {VP9PROFILE_PROFILE2, VAProfileVP9Profile2},
-    {VP9PROFILE_PROFILE3, VAProfileVP9Profile3},
+    // TODO(crbug.com/1011454, crbug.com/1011469): Reenable VP9PROFILE_PROFILE2
+    // and _PROFILE3 when P010 is completely supported.
+    //{VP9PROFILE_PROFILE2, VAProfileVP9Profile2},
+    //{VP9PROFILE_PROFILE3, VAProfileVP9Profile3},
 };
 
 constexpr const char* kMesaGalliumDriverPrefix = "Mesa Gallium driver";
diff --git a/media/webrtc/webrtc_switches.cc b/media/webrtc/webrtc_switches.cc
index 8224fc1b..e19d3a4 100644
--- a/media/webrtc/webrtc_switches.cc
+++ b/media/webrtc/webrtc_switches.cc
@@ -4,6 +4,9 @@
 
 #include "media/webrtc/webrtc_switches.h"
 
+#include "base/command_line.h"
+#include "build/build_config.h"
+
 namespace switches {
 
 // Override the default minimum starting volume of the Automatic Gain Control
@@ -29,3 +32,25 @@
                                      base::FEATURE_DISABLED_BY_DEFAULT};
 
 }  // namespace features
+
+namespace switches {
+
+const char kForceDisableWebRtcApmInAudioService[] =
+    "disable-webrtc-apm-in-audio-service";
+
+}  // namespace switches
+
+namespace media {
+
+bool IsWebRtcApmInAudioServiceEnabled() {
+#if defined(OS_WIN) || defined(OS_MACOSX) || \
+    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+  return base::FeatureList::IsEnabled(features::kWebRtcApmInAudioService) &&
+         !base::CommandLine::ForCurrentProcess()->HasSwitch(
+             switches::kForceDisableWebRtcApmInAudioService);
+#else
+  return false;
+#endif
+}
+
+}  // namespace media
\ No newline at end of file
diff --git a/media/webrtc/webrtc_switches.h b/media/webrtc/webrtc_switches.h
index 0539b5b6..b527169 100644
--- a/media/webrtc/webrtc_switches.h
+++ b/media/webrtc/webrtc_switches.h
@@ -25,4 +25,15 @@
 
 }  // namespace features
 
+namespace switches {
+COMPONENT_EXPORT(MEDIA_WEBRTC)
+extern const char kForceDisableWebRtcApmInAudioService[];
+}  // namespace switches
+
+namespace media {
+
+COMPONENT_EXPORT(MEDIA_WEBRTC) bool IsWebRtcApmInAudioServiceEnabled();
+
+}  // namespace media
+
 #endif  // MEDIA_WEBRTC_WEBRTC_SWITCHES_H_
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn
index 260f30ca..d39e86a 100644
--- a/mojo/public/cpp/bindings/BUILD.gn
+++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -134,7 +134,6 @@
     "callback_helpers.h",
     "connection_error_callback.h",
     "connector.h",
-    "filter_chain.h",
     "generic_pending_receiver.cc",
     "generic_pending_receiver.h",
     "interface_endpoint_client.h",
@@ -154,11 +153,11 @@
     "lib/control_message_handler.h",
     "lib/control_message_proxy.cc",
     "lib/control_message_proxy.h",
-    "lib/filter_chain.cc",
     "lib/interface_endpoint_client.cc",
     "lib/interface_ptr_state.cc",
     "lib/interface_ptr_state.h",
     "lib/interface_serialization.h",
+    "lib/message_dispatcher.cc",
     "lib/multiplex_router.cc",
     "lib/multiplex_router.h",
     "lib/native_enum_data.h",
@@ -174,6 +173,7 @@
     "lib/sync_handle_watcher.cc",
     "lib/task_runner_helper.cc",
     "lib/task_runner_helper.h",
+    "message_dispatcher.h",
     "native_enum.h",
     "pending_associated_receiver.h",
     "pending_associated_remote.h",
diff --git a/mojo/public/cpp/bindings/associated_binding.h b/mojo/public/cpp/bindings/associated_binding.h
index 38ae6cc..daeea4f6 100644
--- a/mojo/public/cpp/bindings/associated_binding.h
+++ b/mojo/public/cpp/bindings/associated_binding.h
@@ -26,6 +26,7 @@
 
 namespace mojo {
 
+class MessageFilter;
 class MessageReceiver;
 
 // Base class used to factor out code in AssociatedBinding<T> expansions, in
@@ -35,10 +36,11 @@
   AssociatedBindingBase();
   virtual ~AssociatedBindingBase();
 
-  // Adds a message filter to be notified of each incoming message before
+  // Sets a message filter to be notified of each incoming message before
   // dispatch. If a filter returns |false| from Accept(), the message is not
-  // dispatched and the pipe is closed. Filters cannot be removed.
-  void AddFilter(std::unique_ptr<MessageReceiver> filter);
+  // dispatched and the pipe is closed. Filters cannot be removed once added
+  // and only one can be set.
+  void SetFilter(std::unique_ptr<MessageFilter> filter);
 
   // Closes the associated interface. Puts this object into a state where it can
   // be rebound.
diff --git a/mojo/public/cpp/bindings/associated_receiver.h b/mojo/public/cpp/bindings/associated_receiver.h
index 1dfaf256..10a7dd7 100644
--- a/mojo/public/cpp/bindings/associated_receiver.h
+++ b/mojo/public/cpp/bindings/associated_receiver.h
@@ -186,12 +186,13 @@
     return PendingAssociatedReceiver<Interface>(binding_.Unbind().PassHandle());
   }
 
-  // Adds a message filter to be notified of each incoming message before
+  // Sets a message filter to be notified of each incoming message before
   // dispatch. If a filter returns |false| from Accept(), the message is not
-  // dispatched and the pipe is closed. Filters cannot be removed once added.
-  void AddFilter(std::unique_ptr<MessageReceiver> filter) {
+  // dispatched and the pipe is closed. Filters cannot be removed once added
+  // and only one can be set.
+  void SetFilter(std::unique_ptr<MessageFilter> filter) {
     DCHECK(is_bound());
-    binding_.AddFilter(std::move(filter));
+    binding_.SetFilter(std::move(filter));
   }
 
   // Sends a message on the underlying message pipe and runs the current
diff --git a/mojo/public/cpp/bindings/binding.h b/mojo/public/cpp/bindings/binding.h
index d342c57..5e67f6a 100644
--- a/mojo/public/cpp/bindings/binding.h
+++ b/mojo/public/cpp/bindings/binding.h
@@ -21,7 +21,7 @@
 
 namespace mojo {
 
-class MessageReceiver;
+class MessageFilter;
 
 // Represents the binding of an interface implementation to a message pipe.
 // When the |Binding| object is destroyed, the binding between the message pipe
@@ -100,12 +100,13 @@
     internal_state_.Bind(request.internal_state(), std::move(runner));
   }
 
-  // Adds a message filter to be notified of each incoming message before
+  // Sets a message filter to be notified of each incoming message before
   // dispatch. If a filter returns |false| from Accept(), the message is not
-  // dispatched and the pipe is closed. Filters cannot be removed.
-  void AddFilter(std::unique_ptr<MessageReceiver> filter) {
+  // dispatched and the pipe is closed. Filters cannot be removed once added
+  // and only one can be set.
+  void SetFilter(std::unique_ptr<MessageFilter> filter) {
     DCHECK(is_bound());
-    internal_state_.AddFilter(std::move(filter));
+    internal_state_.SetFilter(std::move(filter));
   }
 
   // Whether there are any associated interfaces running on the pipe currently.
diff --git a/mojo/public/cpp/bindings/binding_set.h b/mojo/public/cpp/bindings/binding_set.h
index 09d8a8a50..5cbf768f 100644
--- a/mojo/public/cpp/bindings/binding_set.h
+++ b/mojo/public/cpp/bindings/binding_set.h
@@ -224,7 +224,7 @@
           binding_set_(binding_set),
           binding_id_(binding_id),
           context_(std::move(context)) {
-      binding_.AddFilter(std::make_unique<DispatchFilter>(this));
+      binding_.SetFilter(std::make_unique<DispatchFilter>(this));
       binding_.set_connection_error_with_reason_handler(
           base::BindOnce(&Entry::OnConnectionError, base::Unretained(this)));
     }
@@ -236,18 +236,20 @@
     }
 
    private:
-    class DispatchFilter : public MessageReceiver {
+    class DispatchFilter : public MessageFilter {
      public:
       explicit DispatchFilter(Entry* entry) : entry_(entry) {}
       ~DispatchFilter() override {}
 
      private:
-      // MessageReceiver:
-      bool Accept(Message* message) override {
+      // MessageFilter:
+      bool WillDispatch(Message* message) override {
         entry_->WillDispatch();
         return true;
       }
 
+      void DidDispatchOrReject(Message* message, bool accepted) override {}
+
       Entry* entry_;
 
       DISALLOW_COPY_AND_ASSIGN(DispatchFilter);
diff --git a/mojo/public/cpp/bindings/filter_chain.h b/mojo/public/cpp/bindings/filter_chain.h
deleted file mode 100644
index d87878ef..0000000
--- a/mojo/public/cpp/bindings/filter_chain.h
+++ /dev/null
@@ -1,60 +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 MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_
-#define MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_
-
-#include <utility>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "mojo/public/cpp/bindings/message.h"
-
-namespace mojo {
-
-class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) FilterChain : public MessageReceiver {
- public:
-  // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while
-  // this object is alive.
-  explicit FilterChain(MessageReceiver* sink = nullptr);
-
-  FilterChain(FilterChain&& other);
-  FilterChain& operator=(FilterChain&& other);
-  ~FilterChain() override;
-
-  template <typename FilterType, typename... Args>
-  inline void Append(Args&&... args);
-
-  void Append(std::unique_ptr<MessageReceiver> filter);
-
-  // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while
-  // this object is alive.
-  void SetSink(MessageReceiver* sink);
-
-  // MessageReceiver:
-  bool Accept(Message* message) override;
-
- private:
-  std::vector<std::unique_ptr<MessageReceiver>> filters_;
-
-  MessageReceiver* sink_;
-
-  DISALLOW_COPY_AND_ASSIGN(FilterChain);
-};
-
-template <typename FilterType, typename... Args>
-inline void FilterChain::Append(Args&&... args) {
-  Append(std::make_unique<FilterType>(std::forward<Args>(args)...));
-}
-
-template <>
-inline void FilterChain::Append<PassThroughFilter>() {
-}
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_CPP_BINDINGS_FILTER_CHAIN_H_
diff --git a/mojo/public/cpp/bindings/interface_endpoint_client.h b/mojo/public/cpp/bindings/interface_endpoint_client.h
index 363f97f..f0f1691c 100644
--- a/mojo/public/cpp/bindings/interface_endpoint_client.h
+++ b/mojo/public/cpp/bindings/interface_endpoint_client.h
@@ -27,10 +27,10 @@
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/connection_group.h"
 #include "mojo/public/cpp/bindings/disconnect_reason.h"
-#include "mojo/public/cpp/bindings/filter_chain.h"
 #include "mojo/public/cpp/bindings/lib/control_message_handler.h"
 #include "mojo/public/cpp/bindings/lib/control_message_proxy.h"
 #include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/bindings/message_dispatcher.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 
 namespace mojo {
@@ -84,9 +84,9 @@
 
   AssociatedGroup* associated_group();
 
-  // Adds a MessageReceiver which can filter a message after validation but
+  // Sets a MessageFilter which can filter a message after validation but
   // before dispatch.
-  void AddFilter(std::unique_ptr<MessageReceiver> filter);
+  void SetFilter(std::unique_ptr<MessageFilter> filter);
 
   // After this call the object is in an invalid state and shouldn't be reused.
   ScopedInterfaceEndpointHandle PassHandle();
@@ -251,7 +251,7 @@
 
   MessageReceiverWithResponderStatus* const incoming_receiver_ = nullptr;
   HandleIncomingMessageThunk thunk_{this};
-  FilterChain filters_;
+  MessageDispatcher dispatcher_;
 
   AsyncResponderMap async_responders_;
   SyncResponseMap sync_responses_;
diff --git a/mojo/public/cpp/bindings/lib/associated_binding.cc b/mojo/public/cpp/bindings/lib/associated_binding.cc
index acdaf0f..59283ac 100644
--- a/mojo/public/cpp/bindings/lib/associated_binding.cc
+++ b/mojo/public/cpp/bindings/lib/associated_binding.cc
@@ -13,9 +13,9 @@
 
 AssociatedBindingBase::~AssociatedBindingBase() {}
 
-void AssociatedBindingBase::AddFilter(std::unique_ptr<MessageReceiver> filter) {
+void AssociatedBindingBase::SetFilter(std::unique_ptr<MessageFilter> filter) {
   DCHECK(endpoint_client_);
-  endpoint_client_->AddFilter(std::move(filter));
+  endpoint_client_->SetFilter(std::move(filter));
 }
 
 void AssociatedBindingBase::Close() {
diff --git a/mojo/public/cpp/bindings/lib/binding_state.cc b/mojo/public/cpp/bindings/lib/binding_state.cc
index b82a2c4..11f948ba 100644
--- a/mojo/public/cpp/bindings/lib/binding_state.cc
+++ b/mojo/public/cpp/bindings/lib/binding_state.cc
@@ -17,9 +17,9 @@
 
 BindingStateBase::~BindingStateBase() = default;
 
-void BindingStateBase::AddFilter(std::unique_ptr<MessageReceiver> filter) {
+void BindingStateBase::SetFilter(std::unique_ptr<MessageFilter> filter) {
   DCHECK(endpoint_client_);
-  endpoint_client_->AddFilter(std::move(filter));
+  endpoint_client_->SetFilter(std::move(filter));
 }
 
 bool BindingStateBase::HasAssociatedInterfaces() const {
diff --git a/mojo/public/cpp/bindings/lib/binding_state.h b/mojo/public/cpp/bindings/lib/binding_state.h
index ced07dd..6260885d 100644
--- a/mojo/public/cpp/bindings/lib/binding_state.h
+++ b/mojo/public/cpp/bindings/lib/binding_state.h
@@ -19,7 +19,6 @@
 #include "base/sequenced_task_runner.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/connection_group.h"
-#include "mojo/public/cpp/bindings/filter_chain.h"
 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
 #include "mojo/public/cpp/bindings/interface_id.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
@@ -40,7 +39,7 @@
   BindingStateBase();
   ~BindingStateBase();
 
-  void AddFilter(std::unique_ptr<MessageReceiver> filter);
+  void SetFilter(std::unique_ptr<MessageFilter> filter);
 
   bool HasAssociatedInterfaces() const;
 
diff --git a/mojo/public/cpp/bindings/lib/filter_chain.cc b/mojo/public/cpp/bindings/lib/filter_chain.cc
deleted file mode 100644
index 5d919fe1..0000000
--- a/mojo/public/cpp/bindings/lib/filter_chain.cc
+++ /dev/null
@@ -1,47 +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 "mojo/public/cpp/bindings/filter_chain.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-
-namespace mojo {
-
-FilterChain::FilterChain(MessageReceiver* sink) : sink_(sink) {
-}
-
-FilterChain::FilterChain(FilterChain&& other) : sink_(other.sink_) {
-  other.sink_ = nullptr;
-  filters_.swap(other.filters_);
-}
-
-FilterChain& FilterChain::operator=(FilterChain&& other) {
-  std::swap(sink_, other.sink_);
-  filters_.swap(other.filters_);
-  return *this;
-}
-
-FilterChain::~FilterChain() {
-}
-
-void FilterChain::SetSink(MessageReceiver* sink) {
-  DCHECK(!sink_);
-  sink_ = sink;
-}
-
-bool FilterChain::Accept(Message* message) {
-  DCHECK(sink_);
-  for (auto& filter : filters_)
-    if (!filter->Accept(message))
-      return false;
-  return sink_->Accept(message);
-}
-
-void FilterChain::Append(std::unique_ptr<MessageReceiver> filter) {
-  filters_.emplace_back(std::move(filter));
-}
-
-}  // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
index d210a668b..4cda5fa8e 100644
--- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
+++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
@@ -153,7 +153,7 @@
     : expect_sync_requests_(expect_sync_requests),
       handle_(std::move(handle)),
       incoming_receiver_(receiver),
-      filters_(&thunk_),
+      dispatcher_(&thunk_),
       task_runner_(std::move(runner)),
       control_message_handler_(this, interface_version),
       interface_name_(interface_name) {
@@ -162,7 +162,7 @@
   // TODO(yzshen): the way to use validator (or message filter in general)
   // directly is a little awkward.
   if (payload_validator)
-    filters_.Append(std::move(payload_validator));
+    dispatcher_.SetValidator(std::move(payload_validator));
 
   if (handle_.pending_association()) {
     handle_.SetAssociationEventHandler(base::Bind(
@@ -202,9 +202,8 @@
   return std::move(handle_);
 }
 
-void InterfaceEndpointClient::AddFilter(
-    std::unique_ptr<MessageReceiver> filter) {
-  filters_.Append(std::move(filter));
+void InterfaceEndpointClient::SetFilter(std::unique_ptr<MessageFilter> filter) {
+  dispatcher_.SetFilter(std::move(filter));
 }
 
 void InterfaceEndpointClient::RaiseError() {
@@ -354,7 +353,7 @@
 
 bool InterfaceEndpointClient::HandleIncomingMessage(Message* message) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return filters_.Accept(message);
+  return dispatcher_.Accept(message);
 }
 
 void InterfaceEndpointClient::NotifyError(
diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_state.h b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
index 8cd7886..a1561c0 100644
--- a/mojo/public/cpp/bindings/lib/interface_ptr_state.h
+++ b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
@@ -24,7 +24,6 @@
 #include "base/time/time.h"
 #include "mojo/public/cpp/bindings/associated_group.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
-#include "mojo/public/cpp/bindings/filter_chain.h"
 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
 #include "mojo/public/cpp/bindings/interface_id.h"
 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
diff --git a/mojo/public/cpp/bindings/lib/message_dispatcher.cc b/mojo/public/cpp/bindings/lib/message_dispatcher.cc
new file mode 100644
index 0000000..5d48ac658
--- /dev/null
+++ b/mojo/public/cpp/bindings/lib/message_dispatcher.cc
@@ -0,0 +1,64 @@
+// 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 "mojo/public/cpp/bindings/message_dispatcher.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+
+namespace mojo {
+
+MessageDispatcher::MessageDispatcher(MessageReceiver* sink) : sink_(sink) {}
+
+MessageDispatcher::MessageDispatcher(MessageDispatcher&& other) {
+  *this = std::move(other);
+}
+
+MessageDispatcher& MessageDispatcher::operator=(MessageDispatcher&& other) {
+  std::swap(sink_, other.sink_);
+  validator_ = std::move(other.validator_);
+  filter_ = std::move(other.filter_);
+  return *this;
+}
+
+MessageDispatcher::~MessageDispatcher() {}
+
+void MessageDispatcher::SetSink(MessageReceiver* sink) {
+  DCHECK(!sink_);
+  sink_ = sink;
+}
+
+bool MessageDispatcher::Accept(Message* message) {
+  DCHECK(sink_);
+  if (validator_) {
+    if (!validator_->Accept(message))
+      return false;
+  }
+
+  if (!filter_)
+    return sink_->Accept(message);
+
+  base::WeakPtr<MessageDispatcher> weak_self = weak_factory_.GetWeakPtr();
+  if (!filter_->WillDispatch(message))
+    return false;
+  bool result = sink_->Accept(message);
+  if (!weak_self)
+    return result;
+  filter_->DidDispatchOrReject(message, result);
+  return result;
+}
+
+void MessageDispatcher::SetValidator(
+    std::unique_ptr<MessageReceiver> validator) {
+  DCHECK(!validator_);
+  validator_ = std::move(validator);
+}
+
+void MessageDispatcher::SetFilter(std::unique_ptr<MessageFilter> filter) {
+  DCHECK(!filter_);
+  filter_ = std::move(filter);
+}
+
+}  // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc
index 9da1f0a..c87cacc 100644
--- a/mojo/public/cpp/bindings/lib/multiplex_router.cc
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -317,7 +317,7 @@
     scoped_refptr<base::SequencedTaskRunner> runner)
     : set_interface_id_namespace_bit_(set_interface_id_namesapce_bit),
       task_runner_(runner),
-      filters_(this),
+      dispatcher_(this),
       connector_(std::move(message_pipe),
                  config == MULTI_INTERFACE ? Connector::MULTI_THREADED_SEND
                                            : Connector::SINGLE_THREADED_SEND,
@@ -337,7 +337,7 @@
     // on a different sequence.
     connector_.AllowWokenUpBySyncWatchOnSameThread();
   }
-  connector_.set_incoming_receiver(&filters_);
+  connector_.set_incoming_receiver(&dispatcher_);
   connector_.set_connection_error_handler(
       base::BindOnce(&MultiplexRouter::OnPipeConnectionError,
                      base::Unretained(this), false /* force_async_dispatch */));
@@ -345,7 +345,7 @@
   std::unique_ptr<MessageHeaderValidator> header_validator =
       std::make_unique<MessageHeaderValidator>();
   header_validator_ = header_validator.get();
-  filters_.Append(std::move(header_validator));
+  dispatcher_.SetValidator(std::move(header_validator));
 }
 
 MultiplexRouter::~MultiplexRouter() {
@@ -358,9 +358,9 @@
   endpoints_.clear();
 }
 
-void MultiplexRouter::AddIncomingMessageFilter(
-    std::unique_ptr<MessageReceiver> filter) {
-  filters_.Append(std::move(filter));
+void MultiplexRouter::SetIncomingMessageFilter(
+    std::unique_ptr<MessageFilter> filter) {
+  dispatcher_.SetFilter(std::move(filter));
 }
 
 void MultiplexRouter::SetMasterInterfaceName(const char* name) {
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h
index 7152453..8b31e51 100644
--- a/mojo/public/cpp/bindings/lib/multiplex_router.h
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -26,8 +26,8 @@
 #include "mojo/public/cpp/bindings/associated_group_controller.h"
 #include "mojo/public/cpp/bindings/connection_group.h"
 #include "mojo/public/cpp/bindings/connector.h"
-#include "mojo/public/cpp/bindings/filter_chain.h"
 #include "mojo/public/cpp/bindings/interface_id.h"
+#include "mojo/public/cpp/bindings/message_dispatcher.h"
 #include "mojo/public/cpp/bindings/message_header_validator.h"
 #include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
 #include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
@@ -79,9 +79,9 @@
                   bool set_interface_id_namespace_bit,
                   scoped_refptr<base::SequencedTaskRunner> runner);
 
-  // Adds a MessageReceiver which can filter a message after validation but
+  // Sets a MessageReceiver which can filter a message after validation but
   // before dispatch.
-  void AddIncomingMessageFilter(std::unique_ptr<MessageReceiver> filter);
+  void SetIncomingMessageFilter(std::unique_ptr<MessageFilter> filter);
 
   // Sets the master interface name for this router. Only used when reporting
   // message header or control message validation errors.
@@ -163,7 +163,7 @@
   }
 
   bool SimulateReceivingMessageForTesting(Message* message) {
-    return filters_.Accept(message);
+    return dispatcher_.Accept(message);
   }
 
  private:
@@ -251,10 +251,10 @@
 
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
-  // Owned by |filters_| below.
+  // Owned by |dispatcher_| below.
   MessageHeaderValidator* header_validator_ = nullptr;
 
-  FilterChain filters_;
+  MessageDispatcher dispatcher_;
   Connector connector_;
 
   SEQUENCE_CHECKER(sequence_checker_);
diff --git a/mojo/public/cpp/bindings/message.h b/mojo/public/cpp/bindings/message.h
index 1d35952..8dbb3df 100644
--- a/mojo/public/cpp/bindings/message.h
+++ b/mojo/public/cpp/bindings/message.h
@@ -297,6 +297,22 @@
   DISALLOW_COPY_AND_ASSIGN(Message);
 };
 
+class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) MessageFilter {
+ public:
+  virtual ~MessageFilter() {}
+
+  // The filter may mutate the given message.  This method is called before
+  // the message is dispatched to the associated MessageReceiver. Returns true
+  // if the message was accepted and false otherwise, indicating that the
+  // message was invalid or malformed.
+  virtual bool WillDispatch(Message* message) WARN_UNUSED_RESULT = 0;
+
+  // The filter receives notification that the message was dispatched or
+  // rejected. Since the message filter is owned by the receiver it will not be
+  // invoked if the receiver is closed during a dispatch of a message.
+  virtual void DidDispatchOrReject(Message* message, bool accepted) = 0;
+};
+
 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) MessageReceiver {
  public:
   virtual ~MessageReceiver() {}
diff --git a/mojo/public/cpp/bindings/message_dispatcher.h b/mojo/public/cpp/bindings/message_dispatcher.h
new file mode 100644
index 0000000..a279418
--- /dev/null
+++ b/mojo/public/cpp/bindings/message_dispatcher.h
@@ -0,0 +1,54 @@
+// 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 MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_DISPATCHER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_DISPATCHER_H_
+
+#include <utility>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
+#include "mojo/public/cpp/bindings/message.h"
+
+namespace mojo {
+
+class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) MessageDispatcher
+    : public MessageReceiver {
+ public:
+  // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while
+  // this object is alive.
+  explicit MessageDispatcher(MessageReceiver* sink = nullptr);
+
+  MessageDispatcher(MessageDispatcher&& other);
+  MessageDispatcher& operator=(MessageDispatcher&& other);
+  ~MessageDispatcher() override;
+
+  void SetValidator(std::unique_ptr<MessageReceiver> validator);
+  void SetFilter(std::unique_ptr<MessageFilter> filter);
+
+  // Doesn't take ownership of |sink|. Therefore |sink| has to stay alive while
+  // this object is alive.
+  void SetSink(MessageReceiver* sink);
+
+  // MessageReceiver:
+  bool Accept(Message* message) override;
+
+ private:
+  std::unique_ptr<MessageReceiver> validator_;
+  std::unique_ptr<MessageFilter> filter_;
+
+  MessageReceiver* sink_;
+
+  base::WeakPtrFactory<MessageDispatcher> weak_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(MessageDispatcher);
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BINDINGS_MESSAGE_DISPATCHER_H_
diff --git a/mojo/public/cpp/bindings/receiver.h b/mojo/public/cpp/bindings/receiver.h
index f6861eb..8bc25e09 100644
--- a/mojo/public/cpp/bindings/receiver.h
+++ b/mojo/public/cpp/bindings/receiver.h
@@ -19,7 +19,6 @@
 #include "mojo/public/cpp/bindings/lib/binding_state.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h"
-#include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 
 namespace mojo {
@@ -183,12 +182,13 @@
         internal_state_.Unbind().PassMessagePipe());
   }
 
-  // Adds a message filter to be notified of each incoming message before
+  // Sets the message filter to be notified of each incoming message before
   // dispatch. If a filter returns |false| from Accept(), the message is not
-  // dispatched and the pipe is closed. Filters cannot be removed once added.
-  void AddFilter(std::unique_ptr<MessageReceiver> filter) {
+  // dispatched and the pipe is closed. Filters cannot be removed once added
+  // and only one can be set.
+  void SetFilter(std::unique_ptr<MessageFilter> filter) {
     DCHECK(is_bound());
-    internal_state_.AddFilter(std::move(filter));
+    internal_state_.SetFilter(std::move(filter));
   }
 
   // Pause and resume message dispatch.
diff --git a/mojo/public/cpp/bindings/receiver_set.h b/mojo/public/cpp/bindings/receiver_set.h
index f312e20..71261fb 100644
--- a/mojo/public/cpp/bindings/receiver_set.h
+++ b/mojo/public/cpp/bindings/receiver_set.h
@@ -287,7 +287,7 @@
           receiver_set_(receiver_set),
           receiver_id_(receiver_id),
           context_(std::move(context)) {
-      receiver_.AddFilter(std::make_unique<DispatchFilter>(this));
+      receiver_.SetFilter(std::make_unique<DispatchFilter>(this));
       receiver_.set_disconnect_with_reason_handler(
           base::BindOnce(&Entry::OnDisconnect, base::Unretained(this)));
     }
@@ -299,18 +299,20 @@
     void FlushForTesting() { receiver_.FlushForTesting(); }
 
    private:
-    class DispatchFilter : public MessageReceiver {
+    class DispatchFilter : public MessageFilter {
      public:
       explicit DispatchFilter(Entry* entry) : entry_(entry) {}
       ~DispatchFilter() override {}
 
      private:
-      // MessageReceiver:
-      bool Accept(Message* message) override {
+      // MessageFilter:
+      bool WillDispatch(Message* message) override {
         entry_->WillDispatch();
         return true;
       }
 
+      void DidDispatchOrReject(Message* message, bool accepted) override {}
+
       Entry* entry_;
 
       DISALLOW_COPY_AND_ASSIGN(DispatchFilter);
diff --git a/mojo/public/cpp/bindings/strong_binding.h b/mojo/public/cpp/bindings/strong_binding.h
index a0fe6214..d9ebbb80 100644
--- a/mojo/public/cpp/bindings/strong_binding.h
+++ b/mojo/public/cpp/bindings/strong_binding.h
@@ -16,7 +16,6 @@
 #include "base/memory/weak_ptr.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
-#include "mojo/public/cpp/bindings/filter_chain.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
diff --git a/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc b/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc
index 928bdc3..864a9da 100644
--- a/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc
@@ -616,7 +616,7 @@
   base::OnceClosure quit_waiting_;
 };
 
-class CallbackFilter : public MessageReceiver {
+class CallbackFilter : public MessageFilter {
  public:
   explicit CallbackFilter(base::RepeatingClosure callback)
       : callback_(std::move(callback)) {}
@@ -626,12 +626,14 @@
     return std::make_unique<CallbackFilter>(std::move(callback));
   }
 
-  // MessageReceiver:
-  bool Accept(Message* message) override {
+  // MessageFilter:
+  bool WillDispatch(Message* message) override {
     callback_.Run();
     return true;
   }
 
+  void DidDispatchOrReject(Message* message, bool accepted) override {}
+
  private:
   base::RepeatingClosure callback_;
 };
@@ -655,46 +657,20 @@
   int a_status = 0;
   int b_status = 0;
 
-  ping_a_impl.receiver().AddFilter(
+  ping_a_impl.receiver().SetFilter(
       CallbackFilter::Wrap(base::BindLambdaForTesting([&] {
         EXPECT_EQ(0, a_status);
         EXPECT_EQ(0, b_status);
         a_status = 1;
       })));
 
-  ping_a_impl.receiver().AddFilter(
+  ping_b_impl.receiver().SetFilter(
       CallbackFilter::Wrap(base::BindLambdaForTesting([&] {
         EXPECT_EQ(1, a_status);
         EXPECT_EQ(0, b_status);
-        a_status = 2;
-      })));
-
-  ping_a_impl.set_ping_handler(base::BindLambdaForTesting([&] {
-    EXPECT_EQ(2, a_status);
-    EXPECT_EQ(0, b_status);
-    a_status = 3;
-  }));
-
-  ping_b_impl.receiver().AddFilter(
-      CallbackFilter::Wrap(base::BindLambdaForTesting([&] {
-        EXPECT_EQ(3, a_status);
-        EXPECT_EQ(0, b_status);
         b_status = 1;
       })));
 
-  ping_b_impl.receiver().AddFilter(
-      CallbackFilter::Wrap(base::BindLambdaForTesting([&] {
-        EXPECT_EQ(3, a_status);
-        EXPECT_EQ(1, b_status);
-        b_status = 2;
-      })));
-
-  ping_b_impl.set_ping_handler(base::BindLambdaForTesting([&] {
-    EXPECT_EQ(3, a_status);
-    EXPECT_EQ(2, b_status);
-    b_status = 3;
-  }));
-
   for (int i = 0; i < 10; ++i) {
     a_status = 0;
     b_status = 0;
@@ -705,7 +681,7 @@
       loop.Run();
     }
 
-    EXPECT_EQ(3, a_status);
+    EXPECT_EQ(1, a_status);
     EXPECT_EQ(0, b_status);
 
     {
@@ -714,8 +690,8 @@
       loop.Run();
     }
 
-    EXPECT_EQ(3, a_status);
-    EXPECT_EQ(3, b_status);
+    EXPECT_EQ(1, a_status);
+    EXPECT_EQ(1, b_status);
   }
 }
 
diff --git a/mojo/public/cpp/bindings/tests/receiver_unittest.cc b/mojo/public/cpp/bindings/tests/receiver_unittest.cc
index 5f17e27..269cb02 100644
--- a/mojo/public/cpp/bindings/tests/receiver_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/receiver_unittest.cc
@@ -338,25 +338,34 @@
   DISALLOW_COPY_AND_ASSIGN(PingServiceImpl);
 };
 
-class CallbackFilter : public MessageReceiver {
+class CallbackFilter : public MessageFilter {
  public:
-  explicit CallbackFilter(const base::RepeatingClosure& callback)
-      : callback_(callback) {}
+  explicit CallbackFilter(const base::RepeatingClosure& will_dispatch_callback,
+                          const base::RepeatingClosure& did_dispatch_callback)
+      : will_dispatch_callback_(will_dispatch_callback),
+        did_dispatch_callback_(did_dispatch_callback) {}
   ~CallbackFilter() override {}
 
   static std::unique_ptr<CallbackFilter> Wrap(
-      const base::RepeatingClosure& callback) {
-    return std::make_unique<CallbackFilter>(callback);
+      const base::RepeatingClosure& will_dispatch_callback,
+      const base::RepeatingClosure& did_dispatch_callback) {
+    return std::make_unique<CallbackFilter>(will_dispatch_callback,
+                                            did_dispatch_callback);
   }
 
-  // MessageReceiver:
-  bool Accept(Message* message) override {
-    callback_.Run();
+  // MessageFilter:
+  bool WillDispatch(Message* message) override {
+    will_dispatch_callback_.Run();
     return true;
   }
 
+  void DidDispatchOrReject(Message* message, bool accepted) override {
+    did_dispatch_callback_.Run();
+  }
+
  private:
-  const base::RepeatingClosure callback_;
+  const base::RepeatingClosure will_dispatch_callback_;
+  const base::RepeatingClosure did_dispatch_callback_;
 };
 
 // Verifies that message filters are notified in the order they were added and
@@ -368,19 +377,18 @@
                                        remote.BindNewPipeAndPassReceiver());
 
   int status = 0;
-  receiver.AddFilter(CallbackFilter::Wrap(base::BindLambdaForTesting([&] {
-    EXPECT_EQ(0, status);
-    status = 1;
-  })));
-
-  receiver.AddFilter(CallbackFilter::Wrap(base::BindLambdaForTesting([&] {
-    EXPECT_EQ(1, status);
-    status = 2;
-  })));
+  receiver.SetFilter(CallbackFilter::Wrap(base::BindLambdaForTesting([&] {
+                                            EXPECT_EQ(0, status);
+                                            status = 1;
+                                          }),
+                                          base::BindLambdaForTesting([&] {
+                                            EXPECT_EQ(2, status);
+                                            status = 3;
+                                          })));
 
   impl.set_ping_handler(base::BindLambdaForTesting([&] {
-    EXPECT_EQ(2, status);
-    status = 3;
+    EXPECT_EQ(1, status);
+    status = 2;
   }));
 
   for (int i = 0; i < 10; ++i) {
diff --git a/mojo/public/cpp/bindings/tests/validation_unittest.cc b/mojo/public/cpp/bindings/tests/validation_unittest.cc
index 1623b39..6246c4e 100644
--- a/mojo/public/cpp/bindings/tests/validation_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/validation_unittest.cc
@@ -17,9 +17,9 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "mojo/public/c/system/macros.h"
 #include "mojo/public/cpp/bindings/connector.h"
-#include "mojo/public/cpp/bindings/filter_chain.h"
 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
 #include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/bindings/message_dispatcher.h"
 #include "mojo/public/cpp/bindings/message_header_validator.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -208,6 +208,23 @@
   }
 }
 
+class TwoStepValidator : public MessageReceiver {
+ public:
+  TwoStepValidator(std::unique_ptr<MessageReceiver> first_validator,
+                   std::unique_ptr<MessageReceiver> second_validator)
+      : first_validator_(std::move(first_validator)),
+        second_validator_(std::move(second_validator)) {}
+
+  bool Accept(Message* message) override {
+    return first_validator_->Accept(message) &&
+           second_validator_->Accept(message);
+  }
+
+ private:
+  std::unique_ptr<MessageReceiver> first_validator_;
+  std::unique_ptr<MessageReceiver> second_validator_;
+};
+
 class DummyMessageReceiver : public MessageReceiver {
  public:
   bool Accept(Message* message) override {
@@ -395,18 +412,21 @@
 
 TEST_F(ValidationTest, Conformance) {
   DummyMessageReceiver dummy_receiver;
-  mojo::FilterChain validators(&dummy_receiver);
-  validators.Append<mojo::MessageHeaderValidator>();
-  validators.Append<ConformanceTestInterface::RequestValidator_>();
+  mojo::MessageDispatcher validators(&dummy_receiver);
+  validators.SetValidator(std::make_unique<TwoStepValidator>(
+      std::make_unique<mojo::MessageHeaderValidator>(),
+      std::make_unique<ConformanceTestInterface::RequestValidator_>()));
 
   RunValidationTests("conformance_", &validators);
 }
 
 TEST_F(ValidationTest, AssociatedConformace) {
   DummyMessageReceiver dummy_receiver;
-  mojo::FilterChain validators(&dummy_receiver);
-  validators.Append<mojo::MessageHeaderValidator>();
-  validators.Append<AssociatedConformanceTestInterface::RequestValidator_>();
+  mojo::MessageDispatcher validators(&dummy_receiver);
+  validators.SetValidator(std::make_unique<TwoStepValidator>(
+      std::make_unique<mojo::MessageHeaderValidator>(),
+      std::make_unique<
+          AssociatedConformanceTestInterface::RequestValidator_>()));
 
   RunValidationTests("associated_conformance_", &validators);
 }
@@ -416,19 +436,20 @@
 // detection of off-by-one errors in method ordinals.
 TEST_F(ValidationTest, BoundsCheck) {
   DummyMessageReceiver dummy_receiver;
-  mojo::FilterChain validators(&dummy_receiver);
-  validators.Append<mojo::MessageHeaderValidator>();
-  validators.Append<BoundsCheckTestInterface::RequestValidator_>();
-
+  mojo::MessageDispatcher validators(&dummy_receiver);
+  validators.SetValidator(std::make_unique<TwoStepValidator>(
+      std::make_unique<mojo::MessageHeaderValidator>(),
+      std::make_unique<BoundsCheckTestInterface::RequestValidator_>()));
   RunValidationTests("boundscheck_", &validators);
 }
 
 // This test is similar to the Conformance test but for responses.
 TEST_F(ValidationTest, ResponseConformance) {
   DummyMessageReceiver dummy_receiver;
-  mojo::FilterChain validators(&dummy_receiver);
-  validators.Append<mojo::MessageHeaderValidator>();
-  validators.Append<ConformanceTestInterface::ResponseValidator_>();
+  mojo::MessageDispatcher validators(&dummy_receiver);
+  validators.SetValidator(std::make_unique<TwoStepValidator>(
+      std::make_unique<mojo::MessageHeaderValidator>(),
+      std::make_unique<ConformanceTestInterface::ResponseValidator_>()));
 
   RunValidationTests("resp_conformance_", &validators);
 }
@@ -436,9 +457,10 @@
 // This test is similar to the BoundsCheck test but for responses.
 TEST_F(ValidationTest, ResponseBoundsCheck) {
   DummyMessageReceiver dummy_receiver;
-  mojo::FilterChain validators(&dummy_receiver);
-  validators.Append<mojo::MessageHeaderValidator>();
-  validators.Append<BoundsCheckTestInterface::ResponseValidator_>();
+  mojo::MessageDispatcher validators(&dummy_receiver);
+  validators.SetValidator(std::make_unique<TwoStepValidator>(
+      std::make_unique<mojo::MessageHeaderValidator>(),
+      std::make_unique<BoundsCheckTestInterface::ResponseValidator_>()));
 
   RunValidationTests("resp_boundscheck_", &validators);
 }
diff --git a/mojo/public/js/BUILD.gn b/mojo/public/js/BUILD.gn
index b79ba2c..c67a006 100644
--- a/mojo/public/js/BUILD.gn
+++ b/mojo/public/js/BUILD.gn
@@ -82,7 +82,7 @@
     closure_flags = strict_error_checking_closure_args + [
                       "compilation_level=ADVANCED_OPTIMIZATIONS",
                       "language_in=ECMASCRIPT_2017",
-                      "language_out=ECMASCRIPT5_STRICT",
+                      "language_out=ECMASCRIPT_2015",
                       "generate_exports",
                     ]
   }
diff --git a/mojo/public/js/bindings_lite.js b/mojo/public/js/bindings_lite.js
index e16d8db..3a8c593 100644
--- a/mojo/public/js/bindings_lite.js
+++ b/mojo/public/js/bindings_lite.js
@@ -5,8 +5,10 @@
 
 goog.provide('mojo.internal');
 
+// "self" is always defined as opposed to "this", which isn't defined in
+// modules, or "window", which isn't defined in workers.
 /** @const {!Object} */
-mojo.internal.globalScope = this;
+mojo.internal.globalScope = self;
 
 /**
  * This is effectively the same as goog.provide, but it's made available under
diff --git a/mojo/public/tools/bindings/concatenate_and_replace_closure_exports.py b/mojo/public/tools/bindings/concatenate_and_replace_closure_exports.py
index 6094a322..8571154 100755
--- a/mojo/public/tools/bindings/concatenate_and_replace_closure_exports.py
+++ b/mojo/public/tools/bindings/concatenate_and_replace_closure_exports.py
@@ -38,7 +38,7 @@
 
     module_name = match.group(1)
     if module_name == _MOJO_INTERNAL_MODULE_NAME:
-      output.write("var mojo = { internal: {} };")
+      output.write("self.mojo = { internal: {} };")
     else:
       output.write("%s('%s');\n" % (_MOJO_EXPORT_MODULE_SYMBOL, module_name))
     return
diff --git a/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc b/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc
index 5981b6d..b81f8c4 100644
--- a/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc
+++ b/mojo/public/tools/fuzzers/mojo_fuzzer_message_dump.cc
@@ -38,12 +38,12 @@
 
 /* MessageReceiver which dumps raw message bytes to disk in the provided
  * directory. */
-class MessageDumper : public mojo::MessageReceiver {
+class MessageDumper : public mojo::MessageFilter {
  public:
   explicit MessageDumper(std::string directory)
       : directory_(directory), count_(0) {}
 
-  bool Accept(mojo::Message* message) override {
+  bool WillDispatch(mojo::Message* message) override {
     base::FilePath path = directory_.Append(FILE_PATH_LITERAL("message_") +
                                             base::NumberToString(count_++) +
                                             FILE_PATH_LITERAL(".mojomsg"));
@@ -65,6 +65,8 @@
     return true;
   }
 
+  void DidDispatchOrReject(mojo::Message* message, bool accepted) override {}
+
   base::FilePath directory_;
   int count_;
 };
@@ -230,7 +232,7 @@
 
   /* Create the impl and add a MessageDumper to the filter chain. */
   env->impl = std::make_unique<FuzzImpl>(MakeRequest(&fuzz));
-  env->impl->binding_.RouterForTesting()->AddIncomingMessageFilter(
+  env->impl->binding_.RouterForTesting()->SetIncomingMessageFilter(
       std::make_unique<MessageDumper>(output_directory));
 
   /* Call methods in various ways to generate interesting messages. */
diff --git a/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/1 b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/1
new file mode 100644
index 0000000..cf1b6ff
--- /dev/null
+++ b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/1
Binary files differ
diff --git a/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/10 b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/10
new file mode 100644
index 0000000..3eb60a4
--- /dev/null
+++ b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/10
Binary files differ
diff --git a/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/2 b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/2
new file mode 100644
index 0000000..1607d95e
--- /dev/null
+++ b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/2
Binary files differ
diff --git a/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/3 b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/3
new file mode 100644
index 0000000..733f0e9b
--- /dev/null
+++ b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/3
Binary files differ
diff --git a/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/4 b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/4
new file mode 100644
index 0000000..75c585c
--- /dev/null
+++ b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/4
Binary files differ
diff --git a/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/5 b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/5
new file mode 100644
index 0000000..e7fa597
--- /dev/null
+++ b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/5
Binary files differ
diff --git a/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/6 b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/6
new file mode 100644
index 0000000..ffe7d96
--- /dev/null
+++ b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/6
Binary files differ
diff --git a/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/7 b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/7
new file mode 100644
index 0000000..05b9b3c
--- /dev/null
+++ b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/7
Binary files differ
diff --git a/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/8 b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/8
new file mode 100644
index 0000000..1a29024
--- /dev/null
+++ b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/8
Binary files differ
diff --git a/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/9 b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/9
new file mode 100644
index 0000000..e922417
--- /dev/null
+++ b/net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer/9
Binary files differ
diff --git a/net/dns/BUILD.gn b/net/dns/BUILD.gn
index 24efc2e..bbf7cf2 100644
--- a/net/dns/BUILD.gn
+++ b/net/dns/BUILD.gn
@@ -541,5 +541,7 @@
       "//net",
       "//net:net_fuzzer_test_support",
     ]
+    dict = "//net/data/fuzzer_dictionaries/net_dns_hosts_parse_fuzzer.dict"
+    seed_corpus = "//net/data/fuzzer_data/dns_parse_domain_ascii_win_fuzzer"
   }
 }
diff --git a/net/dns/dns_parse_domain_ascii_win_fuzzer.cc b/net/dns/dns_parse_domain_ascii_win_fuzzer.cc
index f1a73e4..9ae22e9 100644
--- a/net/dns/dns_parse_domain_ascii_win_fuzzer.cc
+++ b/net/dns/dns_parse_domain_ascii_win_fuzzer.cc
@@ -12,6 +12,9 @@
 #include "base/strings/string_piece.h"
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  if (size > 8 * 1024)
+    return 0;
+
   base::StringPiece16 widestr(
       reinterpret_cast<const base::StringPiece16::value_type*>(data), size / 2);
   std::string result;
diff --git a/printing/printing_context.cc b/printing/printing_context.cc
index 29d9c4e..7394019 100644
--- a/printing/printing_context.cc
+++ b/printing/printing_context.cc
@@ -97,14 +97,8 @@
     return OnError();
   }
 
-  base::Optional<int> printer_type_opt =
-      job_settings.FindIntKey(kSettingPrinterType);
-  if (!printer_type_opt.has_value()) {
-    NOTREACHED();
-    return OnError();
-  }
-
-  PrinterType printer_type = static_cast<PrinterType>(printer_type_opt.value());
+  PrinterType printer_type = static_cast<PrinterType>(
+      job_settings.FindIntKey(kSettingPrinterType).value());
   bool print_with_privet = printer_type == kPrivetPrinter;
   bool print_to_cloud = !!job_settings.FindKey(kSettingCloudPrintId);
   bool open_in_external_preview =
diff --git a/remoting/client/chromoting_client.cc b/remoting/client/chromoting_client.cc
index f1f0711..40ebba6 100644
--- a/remoting/client/chromoting_client.cc
+++ b/remoting/client/chromoting_client.cc
@@ -20,8 +20,8 @@
 #include "remoting/protocol/transport_context.h"
 #include "remoting/protocol/video_renderer.h"
 #include "remoting/protocol/webrtc_connection_to_host.h"
-#include "remoting/signaling/jid_util.h"
 #include "remoting/signaling/signaling_address.h"
+#include "remoting/signaling/signaling_id_util.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
 
 namespace remoting {
@@ -73,7 +73,7 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!session_manager_);  // Start must not be called more than once.
 
-  host_jid_ = NormalizeJid(host_jid);
+  host_jid_ = NormalizeSignalingId(host_jid);
   local_capabilities_ = capabilities;
 
   if (!protocol_config_) {
diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc
index b721380..011cbfc 100644
--- a/remoting/host/it2me/it2me_host.cc
+++ b/remoting/host/it2me/it2me_host.cc
@@ -37,8 +37,8 @@
 #include "remoting/protocol/network_settings.h"
 #include "remoting/protocol/transport_context.h"
 #include "remoting/protocol/validating_authenticator.h"
-#include "remoting/signaling/jid_util.h"
 #include "remoting/signaling/log_to_server.h"
+#include "remoting/signaling/signaling_id_util.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace remoting {
@@ -224,7 +224,7 @@
   ++failed_login_attempts_;
   if (failed_login_attempts_ == kMaxLoginAttempts) {
     DisconnectOnNetworkThread();
-  } else if (connecting_jid_ == NormalizeJid(jid)) {
+  } else if (connecting_jid_ == NormalizeSignalingId(jid)) {
     DCHECK_EQ(state_, kConnecting);
     connecting_jid_.clear();
     confirmation_dialog_proxy_.reset();
@@ -240,7 +240,7 @@
   CHECK_NE(state_, kConnected);
 
   std::string client_username;
-  if (!SplitJidResource(jid, &client_username, /*resource=*/nullptr)) {
+  if (!SplitSignalingIdResource(jid, &client_username, /*resource=*/nullptr)) {
     LOG(WARNING) << "Incorrectly formatted JID received: " << jid;
     client_username = jid;
   }
@@ -501,8 +501,8 @@
 
   // First ensure the JID we received is valid.
   std::string client_username;
-  if (!SplitJidResource(original_remote_jid, &client_username,
-                        /*resource=*/nullptr)) {
+  if (!SplitSignalingIdResource(original_remote_jid, &client_username,
+                                /*resource=*/nullptr)) {
     LOG(ERROR) << "Rejecting incoming connection from " << original_remote_jid
                << ": Invalid JID.";
     result_callback.Run(
@@ -510,7 +510,7 @@
     DisconnectOnNetworkThread();
     return;
   }
-  std::string remote_jid = NormalizeJid(original_remote_jid);
+  std::string remote_jid = NormalizeSignalingId(original_remote_jid);
 
   if (client_username.empty()) {
     LOG(ERROR) << "Invalid user name passed in: " << remote_jid;
diff --git a/remoting/host/xmpp_register_support_host_request.cc b/remoting/host/xmpp_register_support_host_request.cc
index 9fda0c5b..f10a69b 100644
--- a/remoting/host/xmpp_register_support_host_request.cc
+++ b/remoting/host/xmpp_register_support_host_request.cc
@@ -18,9 +18,9 @@
 #include "remoting/host/host_details.h"
 #include "remoting/protocol/errors.h"
 #include "remoting/signaling/iq_sender.h"
-#include "remoting/signaling/jid_util.h"
 #include "remoting/signaling/signal_strategy.h"
 #include "remoting/signaling/signaling_address.h"
+#include "remoting/signaling/signaling_id_util.h"
 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 #include "third_party/libjingle_xmpp/xmpp/constants.h"
 
@@ -152,7 +152,7 @@
   signature_tag->AddAttr(QName(kChromotingXmlNamespace, kSignatureTimeAttr),
                          time_str);
 
-  std::string message = NormalizeJid(jid) + ' ' + time_str;
+  std::string message = NormalizeSignalingId(jid) + ' ' + time_str;
   std::string signature(key_pair_->SignMessage(message));
   signature_tag->AddText(signature);
 
diff --git a/remoting/protocol/me2me_host_authenticator_factory.cc b/remoting/protocol/me2me_host_authenticator_factory.cc
index 0012752..7809f58 100644
--- a/remoting/protocol/me2me_host_authenticator_factory.cc
+++ b/remoting/protocol/me2me_host_authenticator_factory.cc
@@ -14,8 +14,8 @@
 #include "remoting/protocol/negotiating_host_authenticator.h"
 #include "remoting/protocol/rejecting_authenticator.h"
 #include "remoting/protocol/token_validator.h"
-#include "remoting/signaling/jid_util.h"
 #include "remoting/signaling/signaling_address.h"
+#include "remoting/signaling/signaling_id_util.h"
 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting {
@@ -71,8 +71,8 @@
 Me2MeHostAuthenticatorFactory::CreateAuthenticator(
     const std::string& original_local_jid,
     const std::string& original_remote_jid) {
-  std::string local_jid = NormalizeJid(original_local_jid);
-  std::string remote_jid = NormalizeJid(original_remote_jid);
+  std::string local_jid = NormalizeSignalingId(original_local_jid);
+  std::string remote_jid = NormalizeSignalingId(original_remote_jid);
 
   std::string remote_jid_prefix;
 
@@ -81,7 +81,7 @@
     // where the host owner account does not have an email associated with it.
     // In those cases, the only guarantee we have is that JIDs for the same
     // account will have the same prefix.
-    if (!SplitJidResource(local_jid, &remote_jid_prefix, nullptr)) {
+    if (!SplitSignalingIdResource(local_jid, &remote_jid_prefix, nullptr)) {
       LOG(DFATAL) << "Invalid local JID:" << local_jid;
       return base::WrapUnique(
           new RejectingAuthenticator(Authenticator::INVALID_CREDENTIALS));
@@ -125,8 +125,8 @@
   }
 
   if (!local_cert_.empty() && key_pair_.get()) {
-    std::string normalized_local_jid = NormalizeJid(local_jid);
-    std::string normalized_remote_jid = NormalizeJid(remote_jid);
+    std::string normalized_local_jid = NormalizeSignalingId(local_jid);
+    std::string normalized_remote_jid = NormalizeSignalingId(remote_jid);
 
     if (token_validator_factory_) {
       return NegotiatingHostAuthenticator::CreateWithThirdPartyAuth(
diff --git a/remoting/signaling/BUILD.gn b/remoting/signaling/BUILD.gn
index 44df316..2e0d4e0 100644
--- a/remoting/signaling/BUILD.gn
+++ b/remoting/signaling/BUILD.gn
@@ -23,8 +23,6 @@
     "ftl_signal_strategy.h",
     "iq_sender.cc",
     "iq_sender.h",
-    "jid_util.cc",
-    "jid_util.h",
     "message_reception_channel.h",
     "message_tracker.cc",
     "message_tracker.h",
@@ -40,6 +38,8 @@
     "signal_strategy.h",
     "signaling_address.cc",
     "signaling_address.h",
+    "signaling_id_util.cc",
+    "signaling_id_util.h",
     "xmpp_log_to_server.cc",
     "xmpp_log_to_server.h",
   ]
@@ -128,13 +128,13 @@
     "ftl_registration_manager_unittest.cc",
     "ftl_signal_strategy_unittest.cc",
     "iq_sender_unittest.cc",
-    "jid_util_unittest.cc",
     "message_tracker_unittest.cc",
     "push_notification_subscriber_unittest.cc",
     "remoting_log_to_server_unittest.cc",
     "server_log_entry_unittest.cc",
     "server_log_entry_unittest.h",
     "signaling_address_unittest.cc",
+    "signaling_id_util_unittest.cc",
     "xmpp_log_to_server_unittest.cc",
   ]
 
diff --git a/remoting/signaling/fake_signal_strategy.cc b/remoting/signaling/fake_signal_strategy.cc
index 658df92..00112b4 100644
--- a/remoting/signaling/fake_signal_strategy.cc
+++ b/remoting/signaling/fake_signal_strategy.cc
@@ -13,7 +13,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "remoting/signaling/jid_util.h"
+#include "remoting/signaling/signaling_id_util.h"
 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 #include "third_party/libjingle_xmpp/xmpp/constants.h"
 
diff --git a/remoting/signaling/iq_sender.cc b/remoting/signaling/iq_sender.cc
index 0e664e5..2d388b4 100644
--- a/remoting/signaling/iq_sender.cc
+++ b/remoting/signaling/iq_sender.cc
@@ -14,8 +14,8 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
-#include "remoting/signaling/jid_util.h"
 #include "remoting/signaling/signal_strategy.h"
+#include "remoting/signaling/signaling_id_util.h"
 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 #include "third_party/libjingle_xmpp/xmpp/constants.h"
 
@@ -116,7 +116,7 @@
 
   IqRequest* request = it->second;
 
-  if (NormalizeJid(request->addressee_) != NormalizeJid(from)) {
+  if (NormalizeSignalingId(request->addressee_) != NormalizeSignalingId(from)) {
     LOG(ERROR) << "Received IQ response from an invalid JID. Ignoring it."
                << " Message received from: " << from
                << " Original JID: " << request->addressee_;
diff --git a/remoting/signaling/jid_util.cc b/remoting/signaling/jid_util.cc
deleted file mode 100644
index 5e3addd..0000000
--- a/remoting/signaling/jid_util.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "remoting/signaling/jid_util.h"
-
-#include <stddef.h>
-
-#include "base/strings/string_util.h"
-
-namespace remoting {
-
-namespace {
-
-constexpr char kFtlResourcePrefix[] = "chromoting_ftl_";
-constexpr char kGmailDomain[] = "gmail.com";
-constexpr char kGooglemailDomain[] = "googlemail.com";
-
-}  // namespace
-
-std::string NormalizeJid(const std::string& jid) {
-  std::string bare_jid;
-  std::string resource;
-  if (SplitJidResource(jid, &bare_jid, &resource)) {
-    std::string normalized_bare_jid = resource.find(kFtlResourcePrefix) == 0
-                                          ? GetCanonicalEmail(bare_jid)
-                                          : base::ToLowerASCII(bare_jid);
-    return normalized_bare_jid + "/" + resource;
-  }
-  return base::ToLowerASCII(bare_jid);
-}
-
-std::string GetCanonicalEmail(std::string email) {
-  DCHECK(email.find('/') == std::string::npos)
-      << "You seemed to pass in a full JID. You should only pass in an email "
-      << "address.";
-  email = base::ToLowerASCII(email);
-  base::TrimString(email, base::kWhitespaceASCII, &email);
-
-  size_t at_index = email.find('@');
-  if (at_index == std::string::npos) {
-    LOG(ERROR) << "Unexpected email address. Character '@' is missing.";
-    return email;
-  }
-  std::string username = email.substr(0, at_index);
-  std::string domain = email.substr(at_index + 1);
-
-  if (domain == kGmailDomain || domain == kGooglemailDomain) {
-    // GMail/GoogleMail domains ignore dots, whereas other domains may not.
-    base::RemoveChars(username, ".", &username);
-    return username + '@' + kGmailDomain;
-  }
-
-  return email;
-}
-
-bool SplitJidResource(const std::string& full_jid,
-                      std::string* bare_jid,
-                      std::string* resource) {
-  size_t slash_index = full_jid.find('/');
-  if (slash_index == std::string::npos) {
-    if (bare_jid) {
-      *bare_jid = full_jid;
-    }
-    if (resource) {
-      resource->clear();
-    }
-    return false;
-  }
-
-  if (bare_jid) {
-    *bare_jid = full_jid.substr(0, slash_index);
-  }
-  if (resource) {
-    *resource = full_jid.substr(slash_index + 1);
-  }
-  return true;
-}
-
-}  // namespace remoting
diff --git a/remoting/signaling/jid_util.h b/remoting/signaling/jid_util.h
deleted file mode 100644
index 4d8a13d..0000000
--- a/remoting/signaling/jid_util.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef REMOTING_SIGNALING_JID_UTIL_H_
-#define REMOTING_SIGNALING_JID_UTIL_H_
-
-#include <string>
-
-namespace remoting {
-
-// Normalizes the |jid|. If |jid| is an FTL ID then the email part will be
-// canonicalized. Otherwise it will simply convert case-insensitive parts (node
-// and domain) to lower-case.
-std::string NormalizeJid(const std::string& jid);
-
-// Returns the canonical email for the given email. Note that this only works
-// for email address (bare JID) and does not work for full JID.
-//
-// Canonicalizes by:
-//   * changing to lowercase
-//   * removing all dots if this is a gmail.com or googlemail.com domain
-//   * normalize email domain googlemail.com to gmail.com
-std::string GetCanonicalEmail(std::string email);
-
-// Splits a JID into a bare JID and a resource suffix.  Either |full_jid|,
-// |resource|, or both may be null.  If |full_jid| is already
-// a bare JID, |resource| is set to the empty string.  Returns true if
-// |full_jid| has a resource, false if not.
-//
-// e.g. "user@domain/resource" -> "user@domain", "resource", true
-//      "user@domain"          -> "user@domain", "",         false
-bool SplitJidResource(const std::string& full_jid,
-                      std::string* bare_jid,
-                      std::string* resource);
-
-}  // namespace remoting
-
-#endif  // REMOTING_SIGNALING_JID_UTIL_H_
diff --git a/remoting/signaling/jid_util_unittest.cc b/remoting/signaling/jid_util_unittest.cc
deleted file mode 100644
index 941c85c5..0000000
--- a/remoting/signaling/jid_util_unittest.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "remoting/signaling/jid_util.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace remoting {
-
-TEST(JidUtilTest, NormalizeJid) {
-  EXPECT_EQ(NormalizeJid("USER@DOMAIN.com"), "user@domain.com");
-  EXPECT_EQ(NormalizeJid("user@domain.com"), "user@domain.com");
-  EXPECT_EQ(NormalizeJid("USER@DOMAIN.com/RESOURCE"),
-            "user@domain.com/RESOURCE");
-  EXPECT_EQ(NormalizeJid("USER@DOMAIN.com/"), "user@domain.com/");
-
-  // Jabber ID normalization
-  EXPECT_EQ("user.mixed.case@googlemail.com/RESOURCE",
-            NormalizeJid("User.Mixed.Case@GOOGLEMAIL.com/RESOURCE"));
-
-  // FTL ID normalization
-  EXPECT_EQ("user@domain.com/chromoting_ftl_abc123",
-            NormalizeJid("USER@DOMAIN.com/chromoting_ftl_abc123"));
-  EXPECT_EQ("user@domain.com/chromoting_ftl_abc123",
-            NormalizeJid("  USER@DOMAIN.com/chromoting_ftl_abc123"));
-  EXPECT_EQ("usermixedcase@gmail.com/chromoting_ftl_abc123",
-            NormalizeJid("User.Mixed.Case@GMAIL.com/chromoting_ftl_abc123"));
-  EXPECT_EQ(
-      "usermixedcase@gmail.com/chromoting_ftl_abc123",
-      NormalizeJid("User.Mixed.Case@GOOGLEMAIL.com/chromoting_ftl_abc123"));
-  EXPECT_EQ("user.mixed.case@domain.com/chromoting_ftl_abc123",
-            NormalizeJid("User.Mixed.Case@DOMAIN.com/chromoting_ftl_abc123"));
-  EXPECT_EQ("invalid.user/chromoting_ftl_abc123",
-            NormalizeJid("  Invalid.User/chromoting_ftl_abc123"));
-  EXPECT_EQ("invalid.user@/chromoting_ftl_abc123",
-            NormalizeJid("  Invalid.User@/chromoting_ftl_abc123"));
-  EXPECT_EQ("@gmail.com/chromoting_ftl_abc123",
-            NormalizeJid("@googlemail.com/chromoting_ftl_abc123"));
-}
-
-TEST(JidUtilTest, SplitJidResource) {
-  std::string bare_jid;
-  std::string resource_suffix;
-
-  EXPECT_TRUE(SplitJidResource("user@domain/resource", nullptr, nullptr));
-  EXPECT_TRUE(
-      SplitJidResource("user@domain/resource", &bare_jid, &resource_suffix));
-  EXPECT_EQ(bare_jid, "user@domain");
-  EXPECT_EQ(resource_suffix, "resource");
-
-  EXPECT_FALSE(SplitJidResource("user@domain", nullptr, nullptr));
-  EXPECT_FALSE(SplitJidResource("user@domain", &bare_jid, &resource_suffix));
-  EXPECT_EQ(bare_jid, "user@domain");
-  EXPECT_EQ(resource_suffix, "");
-}
-
-}  // namespace remoting
diff --git a/remoting/signaling/push_notification_subscriber.cc b/remoting/signaling/push_notification_subscriber.cc
index c796d14..f115206 100644
--- a/remoting/signaling/push_notification_subscriber.cc
+++ b/remoting/signaling/push_notification_subscriber.cc
@@ -9,8 +9,8 @@
 #include "base/memory/ptr_util.h"
 #include "remoting/base/logging.h"
 #include "remoting/signaling/iq_sender.h"
-#include "remoting/signaling/jid_util.h"
 #include "remoting/signaling/signaling_address.h"
+#include "remoting/signaling/signaling_id_util.h"
 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting {
@@ -56,8 +56,8 @@
           << subscription.channel << ".";
 
   std::string bare_jid;
-  SplitJidResource(signal_strategy_->GetLocalAddress().id(), &bare_jid,
-                   nullptr);
+  SplitSignalingIdResource(signal_strategy_->GetLocalAddress().id(), &bare_jid,
+                           nullptr);
 
   // Build a subscription request.
   jingle_xmpp::XmlElement* subscribe_element =
diff --git a/remoting/signaling/signaling_address.cc b/remoting/signaling/signaling_address.cc
index eda2f43..40965e1 100644
--- a/remoting/signaling/signaling_address.cc
+++ b/remoting/signaling/signaling_address.cc
@@ -10,7 +10,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "remoting/base/name_value_map.h"
-#include "remoting/signaling/jid_util.h"
+#include "remoting/signaling/signaling_id_util.h"
 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
 
 namespace remoting {
@@ -31,7 +31,7 @@
 SignalingAddress::Channel GetChannelType(std::string address) {
   std::string email;
   std::string resource;
-  bool has_resource = SplitJidResource(address, &email, &resource);
+  bool has_resource = SplitSignalingIdResource(address, &email, &resource);
   if (has_resource) {
     if (resource.find(kFtlResourcePrefix) == 0) {
       return SignalingAddress::Channel::FTL;
@@ -50,7 +50,7 @@
   switch (channel_) {
     case Channel::XMPP:
     case Channel::FTL:
-      id_ = NormalizeJid(address);
+      id_ = NormalizeSignalingId(address);
       DCHECK(!id_.empty()) << "Missing signaling ID.";
       break;
     default:
@@ -98,7 +98,7 @@
     return false;
   }
   std::string resource;
-  bool has_resource = SplitJidResource(id_, username, &resource);
+  bool has_resource = SplitSignalingIdResource(id_, username, &resource);
   DCHECK(has_resource);
   size_t ftl_resource_prefix_length = strlen(kFtlResourcePrefix);
   DCHECK_LT(ftl_resource_prefix_length, resource.length());
diff --git a/remoting/signaling/signaling_id_util.cc b/remoting/signaling/signaling_id_util.cc
new file mode 100644
index 0000000..039ff99
--- /dev/null
+++ b/remoting/signaling/signaling_id_util.cc
@@ -0,0 +1,80 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/signaling/signaling_id_util.h"
+
+#include <stddef.h>
+
+#include "base/strings/string_util.h"
+
+namespace remoting {
+
+namespace {
+
+constexpr char kFtlResourcePrefix[] = "chromoting_ftl_";
+constexpr char kGmailDomain[] = "gmail.com";
+constexpr char kGooglemailDomain[] = "googlemail.com";
+
+}  // namespace
+
+std::string NormalizeSignalingId(const std::string& id) {
+  std::string email;
+  std::string resource;
+  if (SplitSignalingIdResource(id, &email, &resource)) {
+    std::string normalized_email = resource.find(kFtlResourcePrefix) == 0
+                                       ? GetCanonicalEmail(email)
+                                       : base::ToLowerASCII(email);
+    return normalized_email + "/" + resource;
+  }
+  return base::ToLowerASCII(email);
+}
+
+std::string GetCanonicalEmail(std::string email) {
+  DCHECK(email.find('/') == std::string::npos)
+      << "You seemed to pass in a full ID. You should only pass in an email "
+      << "address.";
+  email = base::ToLowerASCII(email);
+  base::TrimString(email, base::kWhitespaceASCII, &email);
+
+  size_t at_index = email.find('@');
+  if (at_index == std::string::npos) {
+    LOG(ERROR) << "Unexpected email address. Character '@' is missing.";
+    return email;
+  }
+  std::string username = email.substr(0, at_index);
+  std::string domain = email.substr(at_index + 1);
+
+  if (domain == kGmailDomain || domain == kGooglemailDomain) {
+    // GMail/GoogleMail domains ignore dots, whereas other domains may not.
+    base::RemoveChars(username, ".", &username);
+    return username + '@' + kGmailDomain;
+  }
+
+  return email;
+}
+
+bool SplitSignalingIdResource(const std::string& full_id,
+                              std::string* email,
+                              std::string* resource) {
+  size_t slash_index = full_id.find('/');
+  if (slash_index == std::string::npos) {
+    if (email) {
+      *email = full_id;
+    }
+    if (resource) {
+      resource->clear();
+    }
+    return false;
+  }
+
+  if (email) {
+    *email = full_id.substr(0, slash_index);
+  }
+  if (resource) {
+    *resource = full_id.substr(slash_index + 1);
+  }
+  return true;
+}
+
+}  // namespace remoting
diff --git a/remoting/signaling/signaling_id_util.h b/remoting/signaling/signaling_id_util.h
new file mode 100644
index 0000000..72e9582
--- /dev/null
+++ b/remoting/signaling/signaling_id_util.h
@@ -0,0 +1,39 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_SIGNALING_SIGNALING_ID_UTIL_H_
+#define REMOTING_SIGNALING_SIGNALING_ID_UTIL_H_
+
+#include <string>
+
+namespace remoting {
+
+// Normalizes |id|. If |id| is an FTL ID then the email part will be
+// canonicalized. Otherwise it will simply convert case-insensitive parts (node
+// and domain) to lower-case.
+std::string NormalizeSignalingId(const std::string& id);
+
+// Returns the canonical email for the given email. Note that this only works
+// for email address and does not work for full signaling ID.
+//
+// Canonicalizes by:
+//   * changing to lowercase
+//   * removing all dots if this is a gmail.com or googlemail.com domain
+//   * normalize email domain googlemail.com to gmail.com
+std::string GetCanonicalEmail(std::string email);
+
+// Splits a signaling ID into a the email and a resource suffix.  Either
+// |full_id|, |resource|, or both may be null.  If |full_id| is already an email
+// address, |resource| is set to the empty string.  Returns true if |full_id|
+// has a resource, false if not.
+//
+// e.g. "user@domain/resource" -> "user@domain", "resource", true
+//      "user@domain"          -> "user@domain", "",         false
+bool SplitSignalingIdResource(const std::string& full_id,
+                              std::string* email,
+                              std::string* resource);
+
+}  // namespace remoting
+
+#endif  // REMOTING_SIGNALING_SIGNALING_ID_UTIL_H_
diff --git a/remoting/signaling/signaling_id_util_unittest.cc b/remoting/signaling/signaling_id_util_unittest.cc
new file mode 100644
index 0000000..f8779ee1
--- /dev/null
+++ b/remoting/signaling/signaling_id_util_unittest.cc
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/signaling/signaling_id_util.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace remoting {
+
+TEST(SignalingIdUtilTest, NormalizeSignalingId) {
+  EXPECT_EQ(NormalizeSignalingId("USER@DOMAIN.com"), "user@domain.com");
+  EXPECT_EQ(NormalizeSignalingId("user@domain.com"), "user@domain.com");
+  EXPECT_EQ(NormalizeSignalingId("USER@DOMAIN.com/RESOURCE"),
+            "user@domain.com/RESOURCE");
+  EXPECT_EQ(NormalizeSignalingId("USER@DOMAIN.com/"), "user@domain.com/");
+
+  // Jabber ID normalization
+  EXPECT_EQ("user.mixed.case@googlemail.com/RESOURCE",
+            NormalizeSignalingId("User.Mixed.Case@GOOGLEMAIL.com/RESOURCE"));
+
+  // FTL ID normalization
+  EXPECT_EQ("user@domain.com/chromoting_ftl_abc123",
+            NormalizeSignalingId("USER@DOMAIN.com/chromoting_ftl_abc123"));
+  EXPECT_EQ("user@domain.com/chromoting_ftl_abc123",
+            NormalizeSignalingId("  USER@DOMAIN.com/chromoting_ftl_abc123"));
+  EXPECT_EQ(
+      "usermixedcase@gmail.com/chromoting_ftl_abc123",
+      NormalizeSignalingId("User.Mixed.Case@GMAIL.com/chromoting_ftl_abc123"));
+  EXPECT_EQ("usermixedcase@gmail.com/chromoting_ftl_abc123",
+            NormalizeSignalingId(
+                "User.Mixed.Case@GOOGLEMAIL.com/chromoting_ftl_abc123"));
+  EXPECT_EQ(
+      "user.mixed.case@domain.com/chromoting_ftl_abc123",
+      NormalizeSignalingId("User.Mixed.Case@DOMAIN.com/chromoting_ftl_abc123"));
+  EXPECT_EQ("invalid.user/chromoting_ftl_abc123",
+            NormalizeSignalingId("  Invalid.User/chromoting_ftl_abc123"));
+  EXPECT_EQ("invalid.user@/chromoting_ftl_abc123",
+            NormalizeSignalingId("  Invalid.User@/chromoting_ftl_abc123"));
+  EXPECT_EQ("@gmail.com/chromoting_ftl_abc123",
+            NormalizeSignalingId("@googlemail.com/chromoting_ftl_abc123"));
+}
+
+TEST(SignalingIdUtilTest, SplitSignalingIdResource) {
+  std::string email;
+  std::string resource_suffix;
+
+  EXPECT_TRUE(
+      SplitSignalingIdResource("user@domain/resource", nullptr, nullptr));
+  EXPECT_TRUE(SplitSignalingIdResource("user@domain/resource", &email,
+                                       &resource_suffix));
+  EXPECT_EQ(email, "user@domain");
+  EXPECT_EQ(resource_suffix, "resource");
+
+  EXPECT_FALSE(SplitSignalingIdResource("user@domain", nullptr, nullptr));
+  EXPECT_FALSE(
+      SplitSignalingIdResource("user@domain", &email, &resource_suffix));
+  EXPECT_EQ(email, "user@domain");
+  EXPECT_EQ(resource_suffix, "");
+}
+
+}  // namespace remoting
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
index 060181bd..b56b294 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -243,7 +243,7 @@
   errno = 0;
   char buf[1024];
   char* cwd = getcwd(buf, sizeof(buf));
-  BPF_ASSERT_EQ(NULL, cwd);
+  BPF_ASSERT_EQ(nullptr, cwd);
   BPF_ASSERT_EQ(EPERM, errno);
 }
 
@@ -301,7 +301,7 @@
   };
 
   for (int op : ops) {
-    BPF_ASSERT_EQ(-1, syscall(__NR_futex, NULL, op, 0, NULL, NULL, 0));
+    BPF_ASSERT_EQ(-1, syscall(__NR_futex, nullptr, op, 0, nullptr, nullptr, 0));
     BPF_ASSERT_EQ(EINVAL, errno);
   }
 }
@@ -310,7 +310,7 @@
                  FutexWithRequeuePriorityInheritence,
                  DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
                  BaselinePolicy) {
-  syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI, 0, NULL, NULL, 0);
+  syscall(__NR_futex, nullptr, FUTEX_CMP_REQUEUE_PI, 0, nullptr, nullptr, 0);
   _exit(1);
 }
 
@@ -318,7 +318,8 @@
                  FutexWithRequeuePriorityInheritencePrivate,
                  DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
                  BaselinePolicy) {
-  syscall(__NR_futex, NULL, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, NULL, NULL, 0);
+  syscall(__NR_futex, nullptr, FUTEX_CMP_REQUEUE_PI_PRIVATE, 0, nullptr,
+          nullptr, 0);
   _exit(1);
 }
 
@@ -326,7 +327,7 @@
                  FutexWithUnlockPIPrivate,
                  DEATH_SEGV_MESSAGE(GetFutexErrorMessageContentForTests()),
                  BaselinePolicy) {
-  syscall(__NR_futex, NULL, FUTEX_UNLOCK_PI_PRIVATE, 0, NULL, NULL, 0);
+  syscall(__NR_futex, nullptr, FUTEX_UNLOCK_PI_PRIVATE, 0, nullptr, nullptr, 0);
   _exit(1);
 }
 #endif  // defined(LIBC_GLIBC) && !defined(OS_CHROMEOS)
@@ -390,7 +391,7 @@
 
 BPF_DEATH_TEST_C(BaselinePolicy,
                  ClockGettimeWithDisallowedClockCrashes,
-                 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+                 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
                  BaselinePolicy) {
   struct timespec ts;
   syscall(SYS_clock_gettime, CLOCK_MONOTONIC_RAW, &ts);
@@ -402,15 +403,15 @@
 
 BPF_DEATH_TEST_C(BaselinePolicy,
                  GetRandomOfDevRandomCrashes,
-                 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+                 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
                  BaselinePolicy) {
-  syscall(__NR_getrandom, NULL, 0, GRND_RANDOM);
+  syscall(__NR_getrandom, nullptr, 0, GRND_RANDOM);
 }
 
 #if !defined(__i386__)
 BPF_DEATH_TEST_C(BaselinePolicy,
                  GetSockOptWrongLevelSigsys,
-                 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+                 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
                  BaselinePolicy) {
   int fds[2];
   PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
@@ -421,7 +422,7 @@
 
 BPF_DEATH_TEST_C(BaselinePolicy,
                  GetSockOptWrongOptionSigsys,
-                 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+                 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
                  BaselinePolicy) {
   int fds[2];
   PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
@@ -432,7 +433,7 @@
 
 BPF_DEATH_TEST_C(BaselinePolicy,
                  SetSockOptWrongLevelSigsys,
-                 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+                 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
                  BaselinePolicy) {
   int fds[2];
   PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
@@ -440,10 +441,9 @@
   setsockopt(fds[0], IPPROTO_TCP, SO_PEEK_OFF, &id, sizeof(id));
 }
 
-
 BPF_DEATH_TEST_C(BaselinePolicy,
                  SetSockOptWrongOptionSigsys,
-                 DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
+                 DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
                  BaselinePolicy) {
   int fds[2];
   PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
diff --git a/services/audio/input_controller.cc b/services/audio/input_controller.cc
index ad95aa1..bcd39c5 100644
--- a/services/audio/input_controller.cc
+++ b/services/audio/input_controller.cc
@@ -96,10 +96,6 @@
 
 #if defined(AUDIO_PROCESSING_IN_AUDIO_SERVICE)
 
-bool CanRunApm() {
-  return base::FeatureList::IsEnabled(features::kWebRtcApmInAudioService);
-}
-
 bool SamplesNeedClamping(const media::AudioBus& bus) {
   const auto IsOutOfRange = [](float sample) {
     // See comment in CopySamplesWithClamping() for why the conditional is
@@ -411,7 +407,8 @@
 
 #if defined(AUDIO_PROCESSING_IN_AUDIO_SERVICE)
   if (processing_config_) {
-    if (processing_config_->settings.requires_apm() && CanRunApm()) {
+    if (processing_config_->settings.requires_apm() &&
+        media::IsWebRtcApmInAudioServiceEnabled()) {
       processing_helper_.emplace(
           params, processing_config_->settings,
           std::move(processing_config_->controls_receiver));
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 2c853cf..299ec19 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -142,10 +142,15 @@
 #include "base/android/application_status_listener.h"
 #endif
 
-#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
+#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED) || \
+    BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
 #include "net/cert/caching_cert_verifier.h"
 #include "net/cert/cert_verify_proc.h"
 #include "net/cert/cert_verify_proc_builtin.h"
+#include "net/cert/multi_threaded_cert_verifier.h"
+#endif
+
+#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
 #include "services/network/trial_comparison_cert_verifier_mojo.h"
 #endif
 
@@ -1516,7 +1521,8 @@
     cert_verifier = std::make_unique<WrappedTestingCertVerifier>();
   } else {
 #if defined(OS_ANDROID) || defined(OS_FUCHSIA) || defined(OS_CHROMEOS) || \
-    BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
+    BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED) ||                \
+    BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
     cert_net_fetcher_ = base::MakeRefCounted<net::CertNetFetcherImpl>();
 #endif
 #if defined(OS_CHROMEOS)
@@ -1539,8 +1545,9 @@
         std::move(params_->initial_additional_certificates));
     cert_verifier_with_trust_anchors_->InitializeOnIOThread(verify_proc);
     cert_verifier = base::WrapUnique(cert_verifier_with_trust_anchors_);
-#elif BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
-    if (params_->trial_comparison_cert_verifier_params) {
+#endif
+#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
+    if (!cert_verifier && params_->trial_comparison_cert_verifier_params) {
       cert_verifier = std::make_unique<net::CachingCertVerifier>(
           std::make_unique<net::CoalescingCertVerifier>(
               std::make_unique<TrialComparisonCertVerifierMojo>(
@@ -1556,6 +1563,18 @@
                       cert_net_fetcher_))));
     }
 #endif
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+    if (!cert_verifier) {
+      cert_verifier = std::make_unique<net::CachingCertVerifier>(
+          std::make_unique<net::CoalescingCertVerifier>(
+              std::make_unique<net::MultiThreadedCertVerifier>(
+                  params_->use_builtin_cert_verifier
+                      ? net::CertVerifyProc::CreateBuiltinVerifyProc(
+                            cert_net_fetcher_)
+                      : net::CertVerifyProc::CreateSystemVerifyProc(
+                            cert_net_fetcher_))));
+    }
+#endif
     if (!cert_verifier)
       cert_verifier = net::CertVerifier::CreateDefault(cert_net_fetcher_);
   }
@@ -2148,8 +2167,8 @@
 }
 
 void NetworkContext::GetOriginPolicyManager(
-    mojom::OriginPolicyManagerRequest request) {
-  origin_policy_manager_->AddBinding(std::move(request));
+    mojo::PendingReceiver<mojom::OriginPolicyManager> receiver) {
+  origin_policy_manager_->AddReceiver(std::move(receiver));
 }
 
 mojom::URLLoaderFactoryPtr
diff --git a/services/network/network_context.h b/services/network/network_context.h
index 65ccceb..0db51abc 100644
--- a/services/network/network_context.h
+++ b/services/network/network_context.h
@@ -361,7 +361,7 @@
       LookupBasicAuthCredentialsCallback callback) override;
 
   void GetOriginPolicyManager(
-      mojom::OriginPolicyManagerRequest request) override;
+      mojo::PendingReceiver<mojom::OriginPolicyManager> receiver) override;
 
   // Destroys |request| when a proxy lookup completes.
   void OnProxyLookupComplete(ProxyLookupRequest* proxy_lookup_request);
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 22e29237..cad6d73 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -5819,6 +5819,37 @@
   EXPECT_TRUE(transport_security_state->ShouldUpgradeToSSL("sub.example"));
 }
 
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+TEST_F(NetworkContextTest, UseCertVerifierBuiltin) {
+  net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+  net::test_server::RegisterDefaultHandlers(&test_server);
+  ASSERT_TRUE(test_server.Start());
+
+  // This just happens to be the only histogram that directly records which
+  // verifier was used.
+  const char kBuiltinVerifierHistogram[] =
+      "Net.CertVerifier.NameNormalizationPrivateRoots.Builtin";
+
+  for (bool builtin_verifier_enabled : {false, true}) {
+    SCOPED_TRACE(builtin_verifier_enabled);
+
+    mojom::NetworkContextParamsPtr params = CreateContextParams();
+    params->use_builtin_cert_verifier = builtin_verifier_enabled;
+    std::unique_ptr<NetworkContext> network_context =
+        CreateContextWithParams(std::move(params));
+
+    ResourceRequest request;
+    request.url = test_server.GetURL("/nocontent");
+    base::HistogramTester histogram_tester;
+    std::unique_ptr<TestURLLoaderClient> client =
+        FetchRequest(request, network_context.get());
+    EXPECT_EQ(net::OK, client->completion_status().error_code);
+    histogram_tester.ExpectTotalCount(kBuiltinVerifierHistogram,
+                                      builtin_verifier_enabled ? 1 : 0);
+  }
+}
+#endif
+
 static ResourceRequest CreateResourceRequest(const char* method,
                                              const GURL& url) {
   ResourceRequest request;
diff --git a/services/network/origin_policy/origin_policy_manager.cc b/services/network/origin_policy/origin_policy_manager.cc
index 44004ab..ce549e8b 100644
--- a/services/network/origin_policy/origin_policy_manager.cc
+++ b/services/network/origin_policy/origin_policy_manager.cc
@@ -30,9 +30,9 @@
 
 OriginPolicyManager::~OriginPolicyManager() {}
 
-void OriginPolicyManager::AddBinding(
-    mojom::OriginPolicyManagerRequest request) {
-  bindings_.AddBinding(this, std::move(request));
+void OriginPolicyManager::AddReceiver(
+    mojo::PendingReceiver<mojom::OriginPolicyManager> receiver) {
+  receivers_.Add(this, std::move(receiver));
 }
 
 void OriginPolicyManager::RetrieveOriginPolicy(
diff --git a/services/network/origin_policy/origin_policy_manager.h b/services/network/origin_policy/origin_policy_manager.h
index 1a32fb7b..2fcc7d26 100644
--- a/services/network/origin_policy/origin_policy_manager.h
+++ b/services/network/origin_policy/origin_policy_manager.h
@@ -13,7 +13,8 @@
 #include "base/component_export.h"
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/macros.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "services/network/origin_policy/origin_policy_constants.h"
 #include "services/network/origin_policy/origin_policy_header_values.h"
 #include "services/network/public/mojom/origin_policy_manager.mojom.h"
@@ -37,9 +38,9 @@
   explicit OriginPolicyManager(NetworkContext* owner_network_context);
   ~OriginPolicyManager() override;
 
-  // Bind a request to this object.  Mojo messages coming through the associated
-  // pipe will be served by this object.
-  void AddBinding(mojom::OriginPolicyManagerRequest request);
+  // Bind a receiver to this object.  Mojo messages coming through the
+  // associated pipe will be served by this object.
+  void AddReceiver(mojo::PendingReceiver<mojom::OriginPolicyManager> receiver);
 
   // mojom::OriginPolicyManager
   void RetrieveOriginPolicy(const url::Origin& origin,
@@ -65,8 +66,8 @@
                    const GURL& policy_url);
 
   // ForTesting methods
-  mojo::BindingSet<mojom::OriginPolicyManager>& GetBindingsForTesting() {
-    return bindings_;
+  mojo::ReceiverSet<mojom::OriginPolicyManager>& GetReceiversForTesting() {
+    return receivers_;
   }
 
   static OriginPolicyHeaderValues
@@ -109,12 +110,12 @@
   // Used for fetching requests
   mojom::URLLoaderFactoryPtr url_loader_factory_;
 
-  // This object's set of bindings.
+  // This object's set of receivers.
   // This MUST be below origin_policy_fetchers_ to ensure it is destroyed before
   // it. Otherwise it's possible that un-invoked OnceCallbacks owned by members
-  // of origin_policy_fetchers_ will be destroyed before the beinding they are
+  // of origin_policy_fetchers_ will be destroyed before the receiver they are
   // on is destroyed.
-  mojo::BindingSet<mojom::OriginPolicyManager> bindings_;
+  mojo::ReceiverSet<mojom::OriginPolicyManager> receivers_;
 
   DISALLOW_COPY_AND_ASSIGN(OriginPolicyManager);
 };
diff --git a/services/network/origin_policy/origin_policy_manager_unittest.cc b/services/network/origin_policy/origin_policy_manager_unittest.cc
index 3b3d9a6..77d3d9e 100644
--- a/services/network/origin_policy/origin_policy_manager_unittest.cc
+++ b/services/network/origin_policy/origin_policy_manager_unittest.cc
@@ -133,15 +133,12 @@
 };
 
 TEST_F(OriginPolicyManagerTest, AddBinding) {
-  mojom::OriginPolicyManagerPtr origin_policy_ptr;
-  mojom::OriginPolicyManagerRequest origin_policy_request(
-      mojo::MakeRequest(&origin_policy_ptr));
+  mojo::Remote<mojom::OriginPolicyManager> origin_policy_remote;
+  EXPECT_EQ(0u, manager()->GetReceiversForTesting().size());
 
-  EXPECT_EQ(0u, manager()->GetBindingsForTesting().size());
+  manager()->AddReceiver(origin_policy_remote.BindNewPipeAndPassReceiver());
 
-  manager()->AddBinding(std::move(origin_policy_request));
-
-  EXPECT_EQ(1u, manager()->GetBindingsForTesting().size());
+  EXPECT_EQ(1u, manager()->GetReceiversForTesting().size());
 }
 
 TEST_F(OriginPolicyManagerTest, ParseHeaders) {
@@ -327,14 +324,14 @@
 // response. The manager will be destroyed before the return callback is called.
 TEST_F(OriginPolicyManagerTest, DestroyWhileCallbackUninvoked) {
   {
-    mojom::OriginPolicyManagerPtr origin_policy_ptr;
+    mojo::Remote<mojom::OriginPolicyManager> origin_policy_remote;
 
     OriginPolicyManager manager(network_context());
 
-    manager.AddBinding(mojo::MakeRequest(&origin_policy_ptr));
+    manager.AddReceiver(origin_policy_remote.BindNewPipeAndPassReceiver());
 
     // This fetch will still be ongoing when the manager is destroyed.
-    origin_policy_ptr->RetrieveOriginPolicy(
+    origin_policy_remote->RetrieveOriginPolicy(
         test_server_origin(), "policy=delayed",
         base::BindOnce(&DummyRetrieveOriginPolicyCallback));
 
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn
index 6bb38ec..d524845 100644
--- a/services/network/public/mojom/BUILD.gn
+++ b/services/network/public/mojom/BUILD.gn
@@ -158,4 +158,8 @@
     enabled_features += [ "is_trial_comparison_cert_verifier_supported" ]
     sources += [ "trial_comparison_cert_verifier.mojom" ]
   }
+
+  if (builtin_cert_verifier_feature_supported) {
+    enabled_features += [ "is_builtin_cert_verifier_feature_supported" ]
+  }
 }
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index ca9fef6..4b5aa74 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -350,7 +350,7 @@
 
   // If true, the built-in cert verifier will be used. If false, the platform
   // cert verifier will be used.
-  [EnableIf=is_chromeos]
+  [EnableIf=is_builtin_cert_verifier_feature_supported]
   bool use_builtin_cert_verifier = false;
 
   // Parameters for the cert verifier comparison trial. This is a temporary
@@ -1201,5 +1201,6 @@
   ForceDomainReliabilityUploadsForTesting() => ();
 
   // Gets the OriginPolicyManager associated with this network context.
-  GetOriginPolicyManager(OriginPolicyManager& origin_policy_manager);
+  GetOriginPolicyManager(
+      pending_receiver<OriginPolicyManager> origin_policy_manager);
 };
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h
index 97de3f2..1b1b78bb 100644
--- a/services/network/test/test_network_context.h
+++ b/services/network/test/test_network_context.h
@@ -236,7 +236,7 @@
       const GURL& url,
       LookupBasicAuthCredentialsCallback callback) override {}
   void GetOriginPolicyManager(
-      mojom::OriginPolicyManagerRequest request) override {}
+      mojo::PendingReceiver<mojom::OriginPolicyManager> receiver) override {}
 };
 
 }  // namespace network
diff --git a/services/service_manager/sandbox/sandbox_type.cc b/services/service_manager/sandbox/sandbox_type.cc
index 9620166..2655d1f 100644
--- a/services/service_manager/sandbox/sandbox_type.cc
+++ b/services/service_manager/sandbox/sandbox_type.cc
@@ -25,12 +25,7 @@
           service_manager::features::kXRSandbox);
 #endif
     case SANDBOX_TYPE_AUDIO:
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
-      return !base::FeatureList::IsEnabled(
-          service_manager::features::kAudioServiceSandbox);
-#else
-      return true;
-#endif
+      return !IsAudioSandboxEnabled();
     case SANDBOX_TYPE_NETWORK:
       return !base::FeatureList::IsEnabled(
           service_manager::features::kNetworkServiceSandbox);
@@ -198,4 +193,14 @@
   return SANDBOX_TYPE_UTILITY;
 }
 
+static bool g_audio_sandbox_enabled = true;
+
+SERVICE_MANAGER_SANDBOX_EXPORT void EnableAudioSandbox(bool enable) {
+  g_audio_sandbox_enabled = enable;
+}
+
+bool IsAudioSandboxEnabled() {
+  return g_audio_sandbox_enabled;
+}
+
 }  // namespace service_manager
diff --git a/services/service_manager/sandbox/sandbox_type.h b/services/service_manager/sandbox/sandbox_type.h
index e3249ac..71f7dd5 100644
--- a/services/service_manager/sandbox/sandbox_type.h
+++ b/services/service_manager/sandbox/sandbox_type.h
@@ -93,6 +93,10 @@
 SERVICE_MANAGER_SANDBOX_EXPORT SandboxType
 UtilitySandboxTypeFromString(const std::string& sandbox_string);
 
+SERVICE_MANAGER_SANDBOX_EXPORT void EnableAudioSandbox(bool enable);
+
+SERVICE_MANAGER_SANDBOX_EXPORT bool IsAudioSandboxEnabled();
+
 }  // namespace service_manager
 
 #endif  // SERVICES_SERVICE_MANAGER_SANDBOX_SANDBOX_TYPE_H_
diff --git a/services/test/user_id/user_id_service.cc b/services/test/user_id/user_id_service.cc
index 0f56443..822bd95 100644
--- a/services/test/user_id/user_id_service.cc
+++ b/services/test/user_id/user_id_service.cc
@@ -10,7 +10,7 @@
 UserIdService::UserIdService(service_manager::mojom::ServiceRequest request)
     : service_binding_(this, std::move(request)) {
   registry_.AddInterface<mojom::UserId>(base::BindRepeating(
-      &UserIdService::BindUserIdRequest, base::Unretained(this)));
+      &UserIdService::BindUserIdReceiver, base::Unretained(this)));
 }
 
 UserIdService::~UserIdService() = default;
@@ -22,9 +22,9 @@
   registry_.BindInterface(interface_name, std::move(interface_pipe));
 }
 
-void UserIdService::BindUserIdRequest(
-    mojom::UserIdRequest request) {
-  bindings_.AddBinding(this, std::move(request));
+void UserIdService::BindUserIdReceiver(
+    mojo::PendingReceiver<mojom::UserId> receiver) {
+  receivers_.Add(this, std::move(receiver));
 }
 
 void UserIdService::GetInstanceGroup(GetInstanceGroupCallback callback) {
diff --git a/services/test/user_id/user_id_service.h b/services/test/user_id/user_id_service.h
index 0445fe99..94a56f2 100644
--- a/services/test/user_id/user_id_service.h
+++ b/services/test/user_id/user_id_service.h
@@ -5,7 +5,8 @@
 #ifndef SERVICES_USER_ID_USER_ID_SERVICE_H_
 #define SERVICES_USER_ID_USER_ID_SERVICE_H_
 
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/cpp/service_binding.h"
@@ -28,11 +29,11 @@
   // mojom::UserId:
   void GetInstanceGroup(GetInstanceGroupCallback callback) override;
 
-  void BindUserIdRequest(mojom::UserIdRequest request);
+  void BindUserIdReceiver(mojo::PendingReceiver<mojom::UserId> receiver);
 
   service_manager::ServiceBinding service_binding_;
   service_manager::BinderRegistry registry_;
-  mojo::BindingSet<mojom::UserId> bindings_;
+  mojo::ReceiverSet<mojom::UserId> receivers_;
 
   DISALLOW_COPY_AND_ASSIGN(UserIdService);
 };
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index c1d9691..1716303 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -11805,6 +11805,39 @@
           "--browser=release",
           "--passthrough",
           "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl2_conformance_gl_passthrough_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "1002:6821",
+              "os": "Mac-10.14.6",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "shards": 20
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
@@ -12394,6 +12427,38 @@
           "--browser=release",
           "--passthrough",
           "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl2_conformance_gl_passthrough_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:0a2e",
+              "os": "Mac-10.14.6"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "shards": 20
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
@@ -12998,6 +13063,39 @@
           "--browser=release",
           "--passthrough",
           "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl2_conformance_gl_passthrough_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:0fe9",
+              "os": "Mac-10.14.6",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "shards": 20
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
@@ -14224,6 +14322,43 @@
           "--browser=release",
           "--passthrough",
           "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl2_conformance_gl_passthrough_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:0a2e",
+              "os": "mac-intel-stable"
+            },
+            {
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "mac-amd-stable",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false,
+          "shards": 20
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json",
@@ -14832,6 +14967,37 @@
           "--browser=release",
           "--passthrough",
           "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl2_conformance_gl_passthrough_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:0a2e",
+              "os": "mac-intel-stable"
+            }
+          ],
+          "idempotent": false,
+          "shards": 20
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
@@ -16461,6 +16627,39 @@
           "--browser=release",
           "--passthrough",
           "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu",
+          "--webgl-conformance-version=2.0.1",
+          "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "webgl2_conformance_gl_passthrough_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "1002:6821",
+              "hidpi": "1",
+              "os": "mac-amd-stable",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false,
+          "shards": 20
+        }
+      },
+      {
+        "args": [
+          "webgl_conformance",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
           "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
           "--webgl-conformance-version=2.0.1",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
@@ -26953,6 +27152,306 @@
       }
     ]
   },
+  "Win10 FYI x64 SkiaRenderer GL (NVIDIA)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--enable-features=UseSkiaRenderer",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/skia_renderer.content_browsertests.filter"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "skia_renderer_content_browsertests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "nvidia-quadro-p400-win10-stable",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ]
+        },
+        "test": "content_browsertests"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release_x64",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "nvidia-quadro-p400-win10-stable",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false
+        }
+      },
+      {
+        "args": [
+          "depth_capture",
+          "--show-stdout",
+          "--browser=release_x64",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "depth_capture_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "nvidia-quadro-p400-win10-stable",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false
+        }
+      },
+      {
+        "args": [
+          "gpu_process",
+          "--show-stdout",
+          "--browser=release_x64",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "gpu_process_launch_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "nvidia-quadro-p400-win10-stable",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false
+        }
+      },
+      {
+        "args": [
+          "hardware_accelerated_feature",
+          "--show-stdout",
+          "--browser=release_x64",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "hardware_accelerated_feature_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "nvidia-quadro-p400-win10-stable",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false
+        }
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release_x64",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer",
+          "--dont-restore-color-profile-after-test",
+          "--build-revision",
+          "${got_revision}",
+          "--test-machine-name",
+          "${buildername}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_test",
+        "precommit_args": [
+          "--review-patch-issue",
+          "${patch_issue}",
+          "--review-patch-set",
+          "${patch_set}",
+          "--buildbucket-build-id",
+          "${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "nvidia-quadro-p400-win10-stable",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        }
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release_x64",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "nvidia-quadro-p400-win10-stable",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false
+        }
+      },
+      {
+        "args": [
+          "--num-retries=3",
+          "--additional-driver-flag=--enable-gpu-rasterization",
+          "--additional-driver-flag=--enable-features=UseSkiaRenderer",
+          "--additional-driver-flag=--use-gl=any",
+          "--additional-driver-flag=--force-gpu-rasterization",
+          "--additional-driver-flag=--enable-oop-rasterization",
+          "--additional-driver-flag=--disable-software-compositing-fallback",
+          "--additional-driver-flag=--disable-headless-mode",
+          "--no-xvfb",
+          "--fuzzy-diff",
+          "--skipped=always",
+          "--test-list=../../testing/buildbot/filters/gpu.skiarenderer_vulkan_blink_web_tests.filter",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/enable-gpu-rasterization",
+          "--additional-expectations=../../third_party/blink/web_tests/FlagExpectations/use-gl=any"
+        ],
+        "isolate_name": "blink_web_tests_exparchive",
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "skia_renderer_gl_blink_web_tests",
+        "results_handler": "layout tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "nvidia-quadro-p400-win10-stable",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release_x64",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --enable-features=UseSkiaRenderer",
+          "--dont-restore-color-profile-after-test",
+          "--build-revision",
+          "${got_revision}",
+          "--test-machine-name",
+          "${buildername}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "skia_renderer_pixel_skia_gold_test",
+        "precommit_args": [
+          "--review-patch-issue",
+          "${patch_issue}",
+          "--review-patch-set",
+          "${patch_set}",
+          "--buildbucket-build-id",
+          "${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "nvidia-quadro-p400-win10-stable",
+              "os": "Windows-10",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        }
+      }
+    ]
+  },
   "Win10 FYI x64 dEQP Release (Intel HD 630)": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index e99859c..62b2956 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -1539,43 +1539,6 @@
       {
         "args": [
           "--gtest-benchmark-name",
-          "dawn_perf_tests"
-        ],
-        "isolate_name": "dawn_perf_tests",
-        "merge": {
-          "script": "//tools/perf/process_perf_results.py"
-        },
-        "name": "dawn_perf_tests",
-        "override_compile_targets": [
-          "dawn_perf_tests"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3",
-              "os": "Ubuntu",
-              "pool": "chrome.tests.perf"
-            }
-          ],
-          "expiration": 7200,
-          "hard_timeout": 43200,
-          "ignore_task_failure": false,
-          "io_timeout": 21600,
-          "shards": 1
-        },
-        "trigger_script": {
-          "args": [
-            "--multiple-dimension-script-verbose",
-            "True"
-          ],
-          "requires_simultaneous_shard_dispatch": true,
-          "script": "//testing/trigger_scripts/perf_device_trigger.py"
-        }
-      },
-      {
-        "args": [
-          "--gtest-benchmark-name",
           "load_library_perf_tests"
         ],
         "isolate_name": "load_library_perf_tests",
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index dacfba7..a66e7ed 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -2103,6 +2103,11 @@
     "label": "//ios/testing:ocmock_support_unittests",
     "type": "raw",
   },
+  "opus_decoder_unittests": {
+    "args": [],
+    "label": "//third_party/opus:test_opus_decode",
+    "type": "raw",
+  },
   "origin_policy_parser_fuzzer": {
     "label": "//content/test/fuzzer:origin_policy_parser_fuzzer",
     "type": "fuzzer",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index d6c0fcc..610e3c5 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1722,6 +1722,9 @@
     'remove_from': [
       # Not enough capacity. https://crbug.com/946694
       'ANGLE GPU Win10 x64 Release (Intel HD 630)',
+      # Not enough capacity. https://crbug.com/982294
+      'Mac Pro FYI Release (AMD)',
+      'Mac FYI Retina Release (NVIDIA)',
     ],
   },
   'webgl2_conformance_tests': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 96b5c45..a88bf8a4 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -4594,6 +4594,13 @@
       }
     },
 
+    'opus_roll_validation_tests': {
+      'opus_decoder_unittests': {
+        # Ad-hoc binary which returns 0 on success.
+       'test': 'audio_decoder_unittests',
+      },
+    },
+
     'ozone_linux_gtests': {
       'services_unittests': {},
       'ozone_unittests': {},
@@ -5688,6 +5695,7 @@
       'gpu_telemetry_tests',
       'gpu_webgl2_conformance_telemetry_tests',
       'gpu_webgl_conformance_telemetry_tests',
+      'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
       'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
     ],
 
diff --git a/testing/buildbot/tryserver.chromium.android.json b/testing/buildbot/tryserver.chromium.android.json
index 1a12e43..a014863 100644
--- a/testing/buildbot/tryserver.chromium.android.json
+++ b/testing/buildbot/tryserver.chromium.android.json
@@ -376,6 +376,30 @@
       }
     ]
   },
+  "android-opus-kitkat-arm-rel": {
+    "isolated_scripts": [
+      {
+        "isolate_name": "opus_decoder_unittests",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "opus_decoder_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "KTU84P",
+              "device_os_type": "userdebug",
+              "device_type": "hammerhead",
+              "os": "Android"
+            }
+          ]
+        },
+        "test": "audio_decoder_unittests"
+      }
+    ]
+  },
   "android_blink_rel": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 57a263da..6c6ba6a 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -3223,7 +3223,19 @@
           'isolated_scripts': 'win_specific_xr_perf_tests',
         },
       },
-      'Win10 FYI x64 dEQP Release (Intel HD 630)': {
+      'Win10 FYI x64 SkiaRenderer GL (NVIDIA)': {
+        'browser_config': 'release_x64',
+        'os_type': 'win',
+        'mixins': [
+          'win10_nvidia_quadro_p400_stable',
+        ],
+        'test_suites': {
+          'gtest_tests': 'skia_renderer_gtests',
+          'isolated_scripts': 'gpu_blink_web_tests_skia_renderer',
+          'gpu_telemetry_tests': 'gpu_skia_renderer_non_vulkan_telemetry_tests',
+        },
+      },
+     'Win10 FYI x64 dEQP Release (Intel HD 630)': {
         'os_type': 'win',
         'mixins': [
           'win10_intel_hd_630_stable',
@@ -4408,6 +4420,16 @@
         },
         'os_type': 'android',
       },
+      'android-opus-kitkat-arm-rel': {
+        'mixins': [
+          'kitkat',
+          'hammerhead',
+        ],
+        'os_type': 'android',
+        'test_suites': {
+          'isolated_scripts': 'opus_roll_validation_tests',
+        },
+      },
       'android_blink_rel': {
         'mixins': [
           'kitkat',
diff --git a/third_party/avif/libavif b/third_party/avif/libavif
deleted file mode 160000
index 22c1ad9..0000000
--- a/third_party/avif/libavif
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 22c1ad9f706ee00c3cdd0bb71ec4b7818de2f6c3
diff --git a/third_party/blink/public/web/modules/mediastream/processed_local_audio_source.h b/third_party/blink/public/web/modules/mediastream/processed_local_audio_source.h
index 504a947..fff774f 100644
--- a/third_party/blink/public/web/modules/mediastream/processed_local_audio_source.h
+++ b/third_party/blink/public/web/modules/mediastream/processed_local_audio_source.h
@@ -26,11 +26,9 @@
 
 namespace blink {
 
-// TODO(crbug.com/704136): Move this class and method out of the Blink exposed
+// TODO(crbug.com/704136): Move this class out of the Blink exposed
 // API when all users of it have been Onion souped.
 
-BLINK_MODULES_EXPORT bool IsApmInAudioServiceEnabled();
-
 class AudioServiceAudioProcessorProxy;
 class MediaStreamAudioProcessor;
 class MediaStreamInternalFrameWrapper;
diff --git a/third_party/blink/public/web/web_view_client.h b/third_party/blink/public/web/web_view_client.h
index 75fcfac..233bd478 100644
--- a/third_party/blink/public/web/web_view_client.h
+++ b/third_party/blink/public/web/web_view_client.h
@@ -156,10 +156,6 @@
   // Called when the View acquires focus.
   virtual void DidFocus(WebLocalFrame* calling_frame) {}
 
-  // Returns information about the screen where this view's widgets are being
-  // displayed.
-  virtual WebScreenInfo GetScreenInfo() = 0;
-
   // Session history -----------------------------------------------------
 
   // Returns the number of history items before/after the current
diff --git a/third_party/blink/public/web/web_widget_client.h b/third_party/blink/public/web/web_widget_client.h
index 8842ff6..b315756 100644
--- a/third_party/blink/public/web/web_widget_client.h
+++ b/third_party/blink/public/web/web_widget_client.h
@@ -134,6 +134,10 @@
   // Called to show the widget according to the given policy.
   virtual void Show(WebNavigationPolicy) {}
 
+  // Returns information about the screen where this view's widgets are being
+  // displayed.
+  virtual WebScreenInfo GetScreenInfo() { return {}; }
+
   // Called to get/set the position of the widget's window in screen
   // coordinates. Note, the window includes any decorations such as borders,
   // scrollbars, URL bar, tab strip, etc. if they exist.
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer.cc b/third_party/blink/renderer/core/clipboard/data_transfer.cc
index b7160ec..d887455 100644
--- a/third_party/blink/renderer/core/clipboard/data_transfer.cc
+++ b/third_party/blink/renderer/core/clipboard/data_transfer.cc
@@ -67,7 +67,7 @@
   STACK_ALLOCATED();
 
  public:
-  DraggedNodeImageBuilder(const LocalFrame& local_frame, Node& node)
+  DraggedNodeImageBuilder(LocalFrame& local_frame, Node& node)
       : local_frame_(&local_frame),
         node_(&node)
 #if DCHECK_IS_ON()
@@ -148,7 +148,7 @@
   }
 
  private:
-  const Member<const LocalFrame> local_frame_;
+  const Member<LocalFrame> local_frame_;
   const Member<Node> node_;
 #if DCHECK_IS_ON()
   const uint64_t dom_tree_version_;
@@ -383,7 +383,7 @@
 // Returns a DragImage whose bitmap contains |contents|, positioned and scaled
 // in device space.
 std::unique_ptr<DragImage> DataTransfer::CreateDragImageForFrame(
-    const LocalFrame& frame,
+    LocalFrame& frame,
     float opacity,
     RespectImageOrientationEnum image_orientation,
     const FloatSize& css_size,
@@ -414,8 +414,9 @@
 
   scoped_refptr<Image> image =
       StaticBitmapImage::Create(surface->makeImageSnapshot());
+  ChromeClient& chrome_client = frame.GetPage()->GetChromeClient();
   float screen_device_scale_factor =
-      frame.GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;
+      chrome_client.GetScreenInfo(frame).device_scale_factor;
 
   return DragImage::Create(image.get(), image_orientation,
                            screen_device_scale_factor, kInterpolationDefault,
@@ -423,7 +424,7 @@
 }
 
 // static
-std::unique_ptr<DragImage> DataTransfer::NodeImage(const LocalFrame& frame,
+std::unique_ptr<DragImage> DataTransfer::NodeImage(LocalFrame& frame,
                                                    Node& node) {
   DraggedNodeImageBuilder image_node(frame, node);
   return image_node.CreateImage();
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer.h b/third_party/blink/renderer/core/clipboard/data_transfer.h
index 08ef14c..67d3be7 100644
--- a/third_party/blink/renderer/core/clipboard/data_transfer.h
+++ b/third_party/blink/renderer/core/clipboard/data_transfer.h
@@ -149,14 +149,14 @@
   // |paint_offset| is the offset from the origin of the dragged
   // object of the PaintRecordBuilder.
   static std::unique_ptr<DragImage> CreateDragImageForFrame(
-      const LocalFrame&,
+      LocalFrame&,
       float,
       RespectImageOrientationEnum,
       const FloatSize& css_size,
       const FloatPoint& paint_offset,
       PaintRecordBuilder&,
       const PropertyTreeState&);
-  static std::unique_ptr<DragImage> NodeImage(const LocalFrame&, Node&);
+  static std::unique_ptr<DragImage> NodeImage(LocalFrame&, Node&);
 
   void Trace(blink::Visitor*) override;
 
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc
index 97bc770..045d7937 100644
--- a/third_party/blink/renderer/core/css/media_values.cc
+++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -62,7 +62,7 @@
 int MediaValues::CalculateDeviceWidth(LocalFrame* frame) {
   DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
   blink::WebScreenInfo screen_info =
-      frame->GetPage()->GetChromeClient().GetScreenInfo();
+      frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
   int device_width = screen_info.rect.width;
   if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
     device_width = static_cast<int>(
@@ -74,7 +74,7 @@
 int MediaValues::CalculateDeviceHeight(LocalFrame* frame) {
   DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage());
   blink::WebScreenInfo screen_info =
-      frame->GetPage()->GetChromeClient().GetScreenInfo();
+      frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
   int device_height = screen_info.rect.height;
   if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) {
     device_height = static_cast<int>(
@@ -96,23 +96,21 @@
 int MediaValues::CalculateColorBitsPerComponent(LocalFrame* frame) {
   DCHECK(frame);
   DCHECK(frame->GetPage());
-  if (frame->GetPage()->GetChromeClient().GetScreenInfo().is_monochrome)
+  WebScreenInfo screen_info =
+      frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
+  if (screen_info.is_monochrome)
     return 0;
-  return frame->GetPage()
-      ->GetChromeClient()
-      .GetScreenInfo()
-      .depth_per_component;
+  return screen_info.depth_per_component;
 }
 
 int MediaValues::CalculateMonochromeBitsPerComponent(LocalFrame* frame) {
   DCHECK(frame);
   DCHECK(frame->GetPage());
-  if (!frame->GetPage()->GetChromeClient().GetScreenInfo().is_monochrome)
+  WebScreenInfo screen_info =
+      frame->GetPage()->GetChromeClient().GetScreenInfo(*frame);
+  if (!screen_info.is_monochrome)
     return 0;
-  return frame->GetPage()
-      ->GetChromeClient()
-      .GetScreenInfo()
-      .depth_per_component;
+  return screen_info.depth_per_component;
 }
 
 int MediaValues::CalculateDefaultFontSize(LocalFrame* frame) {
@@ -183,14 +181,17 @@
 DisplayShape MediaValues::CalculateDisplayShape(LocalFrame* frame) {
   DCHECK(frame);
   DCHECK(frame->GetPage());
-  return frame->GetPage()->GetChromeClient().GetScreenInfo().display_shape;
+  return frame->GetPage()
+      ->GetChromeClient()
+      .GetScreenInfo(*frame)
+      .display_shape;
 }
 
 ColorSpaceGamut MediaValues::CalculateColorGamut(LocalFrame* frame) {
   DCHECK(frame);
   DCHECK(frame->GetPage());
   return color_space_utilities::GetColorSpaceGamut(
-      frame->GetPage()->GetChromeClient().GetScreenInfo());
+      frame->GetPage()->GetChromeClient().GetScreenInfo(*frame));
 }
 
 PreferredColorScheme MediaValues::CalculatePreferredColorScheme(
diff --git a/third_party/blink/renderer/core/events/pointer_event_factory.cc b/third_party/blink/renderer/core/events/pointer_event_factory.cc
index 259b52e..4e80447 100644
--- a/third_party/blink/renderer/core/events/pointer_event_factory.cc
+++ b/third_party/blink/renderer/core/events/pointer_event_factory.cc
@@ -108,10 +108,9 @@
     if (dom_window && dom_window->GetFrame()) {
       LocalFrame* frame = dom_window->GetFrame();
       if (frame->GetPage()->DeviceScaleFactorDeprecated() == 1) {
-        device_scale_factor = frame->GetPage()
-                                  ->GetChromeClient()
-                                  .GetScreenInfo()
-                                  .device_scale_factor;
+        ChromeClient& chrome_client = frame->GetPage()->GetChromeClient();
+        device_scale_factor =
+            chrome_client.GetScreenInfo(*frame).device_scale_factor;
       }
     }
 
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 7b40d3c..51f7c1ad 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -1161,20 +1161,18 @@
 
 namespace {
 
-class FixedLayoutTestWebViewClient
-    : public frame_test_helpers::TestWebViewClient {
+class FixedLayoutTestWebWidgetClient
+    : public frame_test_helpers::TestWebWidgetClient {
  public:
-  FixedLayoutTestWebViewClient() = default;
-  ~FixedLayoutTestWebViewClient() override = default;
+  FixedLayoutTestWebWidgetClient() = default;
+  ~FixedLayoutTestWebWidgetClient() override = default;
 
-  // frame_test_helpers::TestWebViewClient:
+  // frame_test_helpers::TestWebWidgetClient:
   WebScreenInfo GetScreenInfo() override { return screen_info_; }
 
   WebScreenInfo screen_info_;
 };
 
-class FakeCompositingWebViewClient : public FixedLayoutTestWebViewClient {};
-
 // Helper function to set autosizing multipliers on a document.
 bool SetTextAutosizingMultiplier(Document* document, float multiplier) {
   bool multiplier_set = false;
@@ -1211,13 +1209,13 @@
 TEST_F(WebFrameTest, ChangeInFixedLayoutResetsTextAutosizingMultipliers) {
   RegisterMockedHttpURLLoad("fixed_layout.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
 
   Document* document =
       To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame())
@@ -1244,11 +1242,11 @@
   const std::string html_file = "fixed_layout.html";
   RegisterMockedHttpURLLoad(html_file);
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.InitializeAndLoad(base_url_ + html_file, nullptr, &client,
-                                    nullptr, ConfigureAndroid);
+  web_view_helper.InitializeAndLoad(base_url_ + html_file, nullptr, nullptr,
+                                    &client, ConfigureAndroid);
 
   Document* document =
       To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame())
@@ -1267,13 +1265,13 @@
   RegisterMockedHttpURLLoad("iframe_reload.html");
   RegisterMockedHttpURLLoad("visible_iframe.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "iframe_reload.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
 
   auto* main_frame =
       To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
@@ -1312,13 +1310,13 @@
 }
 
 TEST_F(WebFrameTest, ZeroHeightPositiveWidthNotIgnored) {
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 1280;
   int viewport_height = 0;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   EXPECT_EQ(viewport_width, web_view_helper.GetWebView()
@@ -1339,12 +1337,12 @@
   int viewport_width = 640;
   int viewport_height = 480;
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 2;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "no_viewport_tag.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
 
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -1365,7 +1363,7 @@
 TEST_F(WebFrameTest, FixedLayoutInitializeAtMinimumScale) {
   RegisterMockedHttpURLLoad("fixed_layout.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
@@ -1373,7 +1371,7 @@
   // Make sure we initialize to minimum scale, even if the window size
   // only becomes available after the load begins.
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "fixed_layout.html");
@@ -1408,7 +1406,7 @@
 TEST_F(WebFrameTest, WideDocumentInitializeAtMinimumScale) {
   RegisterMockedHttpURLLoad("wide_document.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
@@ -1416,7 +1414,7 @@
   // Make sure we initialize to minimum scale, even if the window size
   // only becomes available after the load begins.
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "wide_document.html");
@@ -1450,14 +1448,14 @@
 TEST_F(WebFrameTest, DelayedViewportInitialScale) {
   RegisterMockedHttpURLLoad("viewport-auto-initial-scale.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-auto-initial-scale.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -1477,14 +1475,14 @@
 TEST_F(WebFrameTest, setLoadWithOverviewModeToFalse) {
   RegisterMockedHttpURLLoad("viewport-auto-initial-scale.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-auto-initial-scale.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1498,14 +1496,14 @@
 TEST_F(WebFrameTest, SetLoadWithOverviewModeToFalseAndNoWideViewport) {
   RegisterMockedHttpURLLoad("large-div.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "large-div.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1520,14 +1518,14 @@
 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth) {
   RegisterMockedHttpURLLoad("viewport-auto-initial-scale.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-auto-initial-scale.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1551,15 +1549,15 @@
 TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale) {
   RegisterMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, &client,
-      nullptr, ConfigureAndroid);
+      base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, nullptr,
+      &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(false);
@@ -1583,14 +1581,14 @@
 TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag) {
   RegisterMockedHttpURLLoad("no_viewport_tag.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "no_viewport_tag.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(true);
@@ -1614,13 +1612,13 @@
 TEST_F(WebFrameTest, WideViewportSetsTo980WithXhtmlMp) {
   RegisterMockedHttpURLLoad("viewport/viewport-legacy-xhtmlmp.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(true);
@@ -1644,14 +1642,14 @@
 TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta) {
   RegisterMockedHttpURLLoad("viewport-height-1000.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport-height-1000.html",
-                                    nullptr, &client, nullptr,
+                                    nullptr, nullptr, &client,
                                     ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1668,14 +1666,14 @@
 TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth) {
   RegisterMockedHttpURLLoad("viewport-2x-initial-scale.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-2x-initial-scale.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-2x-initial-scale.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1698,15 +1696,15 @@
 TEST_F(WebFrameTest, PageViewportInitialScaleOverridesLoadWithOverviewMode) {
   RegisterMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, &client,
-      nullptr, ConfigureAndroid);
+      base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, nullptr,
+      &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -1718,13 +1716,13 @@
 TEST_F(WebFrameTest, setInitialPageScaleFactorPermanently) {
   RegisterMockedHttpURLLoad("fixed_layout.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   float enforced_page_scale_factor = 2.0f;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
@@ -1751,7 +1749,7 @@
        PermanentInitialPageScaleFactorOverridesLoadWithOverviewMode) {
   RegisterMockedHttpURLLoad("viewport-auto-initial-scale.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
@@ -1759,7 +1757,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-auto-initial-scale.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
   web_view_helper.GetWebView()->SetInitialPageScaleOverride(
@@ -1774,7 +1772,7 @@
        PermanentInitialPageScaleFactorOverridesPageViewportInitialScale) {
   RegisterMockedHttpURLLoad("viewport-wide-2x-initial-scale.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
@@ -1782,8 +1780,8 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, &client,
-      nullptr, ConfigureAndroid);
+      base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, nullptr,
+      &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetInitialPageScaleOverride(
       enforced_page_scale_factor);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -1805,7 +1803,7 @@
   for (size_t i = 0; i < base::size(pages); ++i)
     RegisterMockedHttpURLLoad(pages[i]);
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 400;
   int viewport_height = 300;
@@ -1814,8 +1812,8 @@
   for (size_t i = 0; i < base::size(pages); ++i) {
     for (int quirk_enabled = 0; quirk_enabled <= 1; ++quirk_enabled) {
       frame_test_helpers::WebViewHelper web_view_helper;
-      web_view_helper.InitializeAndLoad(base_url_ + pages[i], nullptr, &client,
-                                        nullptr, ConfigureAndroid);
+      web_view_helper.InitializeAndLoad(base_url_ + pages[i], nullptr, nullptr,
+                                        &client, ConfigureAndroid);
       web_view_helper.GetWebView()
           ->GetSettings()
           ->SetClobberUserAgentInitialScaleQuirk(quirk_enabled);
@@ -1834,14 +1832,14 @@
 }
 
 TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth) {
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
   float enforced_page_scale_factor = 0.5;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.InitializeAndLoad("about:blank", nullptr, &client, nullptr,
+  web_view_helper.InitializeAndLoad("about:blank", nullptr, nullptr, &client,
                                     ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1864,15 +1862,15 @@
 TEST_F(WebFrameTest, DocumentElementClientHeightWorksWithWrapContentMode) {
   RegisterMockedHttpURLLoad("0-by-0.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
 
-  web_view_helper.InitializeAndLoad(base_url_ + "0-by-0.html", nullptr, &client,
-                                    nullptr, ConfigureAndroid);
+  web_view_helper.InitializeAndLoad(base_url_ + "0-by-0.html", nullptr, nullptr,
+                                    &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetForceZeroLayoutHeight(true);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -1885,15 +1883,15 @@
 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksWithWrapContentMode) {
   RegisterMockedHttpURLLoad("0-by-0.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
 
-  web_view_helper.InitializeAndLoad(base_url_ + "0-by-0.html", nullptr, &client,
-                                    nullptr, ConfigureAndroid);
+  web_view_helper.InitializeAndLoad(base_url_ + "0-by-0.html", nullptr, nullptr,
+                                    &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetForceZeroLayoutHeight(true);
   UpdateAllLifecyclePhases(web_view_helper.GetWebView());
 
@@ -1962,7 +1960,7 @@
 TEST_F(WebFrameTest, SetForceZeroLayoutHeight) {
   RegisterMockedHttpURLLoad("200-by-300.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
@@ -1970,7 +1968,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
 
   web_view_helper.InitializeAndLoad(base_url_ + "200-by-300.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   EXPECT_LE(viewport_height, web_view_helper.GetWebView()
@@ -2019,14 +2017,14 @@
 TEST_F(WebFrameTest, ToggleViewportMetaOnOff) {
   RegisterMockedHttpURLLoad("viewport-device-width.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport-device-width.html",
-                                    nullptr, &client);
+                                    nullptr, nullptr, &client);
   WebSettings* settings = web_view_helper.GetWebView()->GetSettings();
   settings->SetViewportMetaEnabled(false);
   settings->SetViewportEnabled(true);
@@ -2057,15 +2055,15 @@
   // because the layout is only updated if either width or height is changed
   RegisterMockedHttpURLLoad("button.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
 
-  web_view_helper.InitializeAndLoad(base_url_ + "button.html", nullptr, &client,
-                                    nullptr, ConfigureAndroid);
+  web_view_helper.InitializeAndLoad(base_url_ + "button.html", nullptr, nullptr,
+                                    &client, ConfigureAndroid);
   // set view height to zero so that if the height of the view is not
   // successfully updated during later resizes touch events will fail
   // (as in not hit content included in the view)
@@ -2161,7 +2159,7 @@
   RegisterMockedHttpURLLoad("200-by-300.html");
   RegisterMockedHttpURLLoad("large-div.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
@@ -2169,7 +2167,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
 
   web_view_helper.InitializeAndLoad(base_url_ + "200-by-300.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetForceZeroLayoutHeight(true);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2187,7 +2185,7 @@
 TEST_F(WebFrameTest, SetForceZeroLayoutHeightWithWideViewportQuirk) {
   RegisterMockedHttpURLLoad("200-by-300.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
@@ -2195,7 +2193,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
 
   web_view_helper.InitializeAndLoad(base_url_ + "200-by-300.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(true);
@@ -2212,13 +2210,13 @@
 TEST_F(WebFrameTest, WideViewportQuirkClobbersHeight) {
   RegisterMockedHttpURLLoad("viewport-height-1000.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 600;
   int viewport_height = 800;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.InitializeAndLoad("about:blank", nullptr, &client, nullptr,
+  web_view_helper.InitializeAndLoad("about:blank", nullptr, nullptr, &client,
                                     ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -2240,13 +2238,13 @@
 TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling) {
   RegisterMockedHttpURLLoad("body-overflow-hidden.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client);
+  web_view_helper.Initialize(nullptr, nullptr, &client);
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "body-overflow-hidden.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -2260,13 +2258,13 @@
 TEST_F(WebFrameTest, OverflowHiddenDisablesScrollingWithSetCanHaveScrollbars) {
   RegisterMockedHttpURLLoad("body-overflow-hidden-short.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client);
+  web_view_helper.Initialize(nullptr, nullptr, &client);
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "body-overflow-hidden-short.html");
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -2285,13 +2283,13 @@
 TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk) {
   RegisterMockedHttpURLLoad("body-overflow-hidden.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client);
+  web_view_helper.Initialize(nullptr, nullptr, &client);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetIgnoreMainFrameOverflowHiddenQuirk(true);
@@ -2306,14 +2304,14 @@
 TEST_F(WebFrameTest, NonZeroValuesNoQuirk) {
   RegisterMockedHttpURLLoad("viewport-nonzero-values.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
   float expected_page_scale_factor = 0.5f;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetViewportMetaZeroValuesQuirk(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
@@ -2346,7 +2344,7 @@
 TEST_F(WebFrameTest, setPageScaleFactorDoesNotLayout) {
   RegisterMockedHttpURLLoad("fixed_layout.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   // Small viewport to ensure there are always scrollbars.
   int viewport_width = 64;
@@ -2354,7 +2352,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   unsigned prev_layout_count =
@@ -2373,14 +2371,14 @@
 TEST_F(WebFrameTest, setPageScaleFactorWithOverlayScrollbarsDoesNotLayout) {
   RegisterMockedHttpURLLoad("fixed_layout.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   unsigned prev_layout_count =
@@ -2399,14 +2397,14 @@
 TEST_F(WebFrameTest, pageScaleFactorWrittenToHistoryItem) {
   RegisterMockedHttpURLLoad("fixed_layout.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   web_view_helper.GetWebView()->SetPageScaleFactor(3);
@@ -2422,13 +2420,13 @@
 TEST_F(WebFrameTest, initialScaleWrittenToHistoryItem) {
   RegisterMockedHttpURLLoad("fixed_layout.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "fixed_layout.html");
@@ -2449,7 +2447,7 @@
 TEST_F(WebFrameTest, pageScaleFactorDoesntShrinkFrameView) {
   RegisterMockedHttpURLLoad("large-div.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   // Small viewport to ensure there are always scrollbars.
   int viewport_width = 64;
@@ -2457,7 +2455,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "large-div.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
@@ -2492,14 +2490,14 @@
 TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform) {
   RegisterMockedHttpURLLoad("fixed_layout.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   web_view_helper.GetWebView()->SetPageScaleFactor(2);
@@ -2520,7 +2518,7 @@
 TEST_F(WebFrameTest, targetDensityDpiHigh) {
   RegisterMockedHttpURLLoad("viewport-target-densitydpi-high.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   // high-dpi = 240
   float target_dpi = 240.0f;
   float device_scale_factors[] = {1.0f, 4.0f / 3.0f, 2.0f};
@@ -2534,8 +2532,8 @@
 
     frame_test_helpers::WebViewHelper web_view_helper;
     web_view_helper.InitializeAndLoad(
-        base_url_ + "viewport-target-densitydpi-high.html", nullptr, &client,
-        nullptr, ConfigureAndroid);
+        base_url_ + "viewport-target-densitydpi-high.html", nullptr, nullptr,
+        &client, ConfigureAndroid);
     web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
         true);
     web_view_helper.GetWebView()
@@ -2571,7 +2569,7 @@
 
   float device_scale_factors[] = {1.0f, 4.0f / 3.0f, 2.0f};
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   int viewport_width = 640;
   int viewport_height = 480;
 
@@ -2580,8 +2578,8 @@
 
     frame_test_helpers::WebViewHelper web_view_helper;
     web_view_helper.InitializeAndLoad(
-        base_url_ + "viewport-target-densitydpi-device.html", nullptr, &client,
-        nullptr, ConfigureAndroid);
+        base_url_ + "viewport-target-densitydpi-device.html", nullptr, nullptr,
+        &client, ConfigureAndroid);
     web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
         true);
     web_view_helper.GetWebView()
@@ -2614,7 +2612,7 @@
 
   float device_scale_factors[] = {1.0f, 4.0f / 3.0f, 2.0f};
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   int viewport_width = 640;
   int viewport_height = 480;
 
@@ -2624,7 +2622,7 @@
     frame_test_helpers::WebViewHelper web_view_helper;
     web_view_helper.InitializeAndLoad(
         base_url_ + "viewport-target-densitydpi-device-and-fixed-width.html",
-        nullptr, &client, nullptr, ConfigureAndroid);
+        nullptr, nullptr, &client, ConfigureAndroid);
     web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
         true);
     web_view_helper.GetWebView()
@@ -2654,15 +2652,15 @@
 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOne) {
   RegisterMockedHttpURLLoad("viewport-initial-scale-less-than-1.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1.33f;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-initial-scale-less-than-1.html", nullptr, &client,
-      nullptr, ConfigureAndroid);
+      base_url_ + "viewport-initial-scale-less-than-1.html", nullptr, nullptr,
+      &client, ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetSupportDeprecatedTargetDensityDPI(true);
@@ -2693,7 +2691,7 @@
   RegisterMockedHttpURLLoad(
       "viewport-initial-scale-less-than-1-device-width.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1.33f;
   int viewport_width = 640;
   int viewport_height = 480;
@@ -2701,7 +2699,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-initial-scale-less-than-1-device-width.html",
-      nullptr, &client, nullptr, ConfigureAndroid);
+      nullptr, nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetSupportDeprecatedTargetDensityDPI(true);
@@ -2734,14 +2732,14 @@
 TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride) {
   RegisterMockedHttpURLLoad("large-div.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   int viewport_width = 640;
   int viewport_height = 480;
   float enforced_page_scale_factor = 5.0f;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "large-div.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -2771,14 +2769,14 @@
 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScale) {
   RegisterMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-initial-scale-and-user-scalable-no.html", nullptr,
-      &client, nullptr, ConfigureAndroid);
+      nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetViewportMetaNonUserScalableQuirk(true);
@@ -2805,7 +2803,7 @@
        NoUserScalableQuirkIgnoresViewportScaleForNonWideViewport) {
   RegisterMockedHttpURLLoad("viewport-initial-scale-and-user-scalable-no.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1.33f;
   int viewport_width = 640;
   int viewport_height = 480;
@@ -2813,7 +2811,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-initial-scale-and-user-scalable-no.html", nullptr,
-      &client, nullptr, ConfigureAndroid);
+      nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetSupportDeprecatedTargetDensityDPI(true);
@@ -2846,14 +2844,14 @@
 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport) {
   RegisterMockedHttpURLLoad("viewport-2x-initial-scale-non-user-scalable.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-2x-initial-scale-non-user-scalable.html", nullptr,
-      &client, nullptr, ConfigureAndroid);
+      nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetViewportMetaNonUserScalableQuirk(true);
@@ -2882,13 +2880,13 @@
 TEST_F(WebFrameTest, DesktopPageCanBeZoomedInWhenWideViewportIsTurnedOff) {
   RegisterMockedHttpURLLoad("no_viewport_tag.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "no_viewport_tag.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -2905,10 +2903,10 @@
 TEST_F(WebFrameTest, AtViewportInsideAtMediaInitialViewport) {
   RegisterMockedHttpURLLoad("viewport-inside-media.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport-inside-media.html",
-                                    nullptr, &client, nullptr,
+                                    nullptr, nullptr, &client,
                                     ConfigureAndroid);
   web_view_helper.Resize(WebSize(640, 480));
 
@@ -2930,9 +2928,9 @@
 TEST_F(WebFrameTest, AtViewportAffectingAtMediaRecalcCount) {
   RegisterMockedHttpURLLoad("viewport-and-media.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(640, 480));
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "viewport-and-media.html");
@@ -2956,9 +2954,9 @@
 TEST_F(WebFrameTest, AtViewportWithViewportLengths) {
   RegisterMockedHttpURLLoad("viewport-lengths.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(800, 600));
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "viewport-lengths.html");
@@ -3108,14 +3106,14 @@
 TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars) {
   RegisterMockedHttpURLLoad("fixed_layout.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
@@ -3136,14 +3134,14 @@
 TEST_F(WebFrameTest, CanOverrideScaleLimits) {
   RegisterMockedHttpURLLoad("no_scale_for_you.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "no_scale_for_you.html",
-                                    nullptr, &client, nullptr,
+                                    nullptr, nullptr, &client,
                                     ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -3176,10 +3174,10 @@
   int view_width = 500;
   int view_height = 500;
 
-  FakeCompositingWebViewClient fake_compositing_web_view_client;
+  FixedLayoutTestWebWidgetClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &fake_compositing_web_view_client,
-                             nullptr, &ConfigureCompositingWebView);
+  web_view_helper.Initialize(nullptr, nullptr, &client,
+                             &ConfigureCompositingWebView);
 
   web_view_helper.Resize(WebSize(view_width, view_height));
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
@@ -7637,12 +7635,10 @@
 // Test verifies that layout will change a layer's scrollable attibutes
 TEST_F(WebFrameTest, overflowHiddenRewrite) {
   RegisterMockedHttpURLLoad("non-scrollable.html");
-  std::unique_ptr<FakeCompositingWebViewClient>
-      fake_compositing_web_view_client =
-          std::make_unique<FakeCompositingWebViewClient>();
+  FixedLayoutTestWebWidgetClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, fake_compositing_web_view_client.get(),
-                             nullptr, &ConfigureCompositingWebView);
+  web_view_helper.Initialize(nullptr, nullptr, &client,
+                             &ConfigureCompositingWebView);
 
   web_view_helper.Resize(WebSize(100, 100));
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
@@ -7773,11 +7769,11 @@
 }
 
 TEST_F(WebFrameTest, FrameViewScrollAccountsForBrowserControls) {
-  FakeCompositingWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   RegisterMockedHttpURLLoad("long_scroll.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "long_scroll.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
 
   WebViewImpl* web_view = web_view_helper.GetWebView();
   LocalFrameView* frame_view = web_view_helper.LocalMainFrame()->GetFrameView();
@@ -7864,14 +7860,14 @@
 TEST_F(WebFrameTest, MaximumScrollPositionCanBeNegative) {
   RegisterMockedHttpURLLoad("rtl-overview-mode.html");
 
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.device_scale_factor = 1;
   int viewport_width = 640;
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "rtl-overview-mode.html",
-                                    nullptr, &client, nullptr,
+                                    nullptr, nullptr, &client,
                                     ConfigureAndroid);
   web_view_helper.GetWebView()->SetInitialPageScaleOverride(-1);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
@@ -7887,7 +7883,7 @@
 }
 
 TEST_F(WebFrameTest, FullscreenLayerSize) {
-  FakeCompositingWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   RegisterMockedHttpURLLoad("fullscreen_div.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   int viewport_width = 640;
@@ -7895,7 +7891,7 @@
   client.screen_info_.rect.width = viewport_width;
   client.screen_info_.rect.height = viewport_height;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "fullscreen_div.html", nullptr, &client, nullptr,
+      base_url_ + "fullscreen_div.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   UpdateAllLifecyclePhases(web_view_impl);
@@ -7928,13 +7924,13 @@
 }
 
 TEST_F(WebFrameTest, FullscreenLayerNonScrollable) {
-  FakeCompositingWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   RegisterMockedHttpURLLoad("fullscreen_div.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   int viewport_width = 640;
   int viewport_height = 480;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "fullscreen_div.html", nullptr, &client, nullptr,
+      base_url_ + "fullscreen_div.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   UpdateAllLifecyclePhases(web_view_impl);
@@ -7988,13 +7984,13 @@
 }
 
 TEST_F(WebFrameTest, FullscreenMainFrame) {
-  FakeCompositingWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   RegisterMockedHttpURLLoad("fullscreen_div.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   int viewport_width = 640;
   int viewport_height = 480;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "fullscreen_div.html", nullptr, &client, nullptr,
+      base_url_ + "fullscreen_div.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   UpdateAllLifecyclePhases(web_view_impl);
@@ -8042,12 +8038,12 @@
 }
 
 TEST_F(WebFrameTest, FullscreenSubframe) {
-  FakeCompositingWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   RegisterMockedHttpURLLoad("fullscreen_iframe.html");
   RegisterMockedHttpURLLoad("fullscreen_div.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "fullscreen_iframe.html", nullptr, &client, nullptr,
+      base_url_ + "fullscreen_iframe.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   int viewport_width = 640;
   int viewport_height = 480;
@@ -8132,11 +8128,11 @@
 }
 
 TEST_F(WebFrameTest, FullscreenWithTinyViewport) {
-  FakeCompositingWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   RegisterMockedHttpURLLoad("viewport-tiny.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-tiny.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-tiny.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   int viewport_width = 384;
   int viewport_height = 640;
@@ -8177,11 +8173,11 @@
 }
 
 TEST_F(WebFrameTest, FullscreenResizeWithTinyViewport) {
-  FakeCompositingWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   RegisterMockedHttpURLLoad("viewport-tiny.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-tiny.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-tiny.html", nullptr, nullptr, &client,
       ConfigureAndroid);
   int viewport_width = 384;
   int viewport_height = 640;
@@ -8236,12 +8232,12 @@
   WebSize screen_size_minus_status_bars(598, 359);
   WebSize screen_size(640, 384);
 
-  FakeCompositingWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   RegisterMockedHttpURLLoad("fullscreen_restore_scale_factor.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "fullscreen_restore_scale_factor.html", nullptr, &client,
-      nullptr, &ConfigureAndroid);
+      base_url_ + "fullscreen_restore_scale_factor.html", nullptr, nullptr,
+      &client, &ConfigureAndroid);
   client.screen_info_.rect.width =
       screen_size_minus_status_bars_minus_url_bar.width;
   client.screen_info_.rect.height =
@@ -9867,10 +9863,10 @@
 
 TEST_F(WebFrameTest, ResizeInvalidatesDeviceMediaQueries) {
   RegisterMockedHttpURLLoad("device_media_queries.html");
-  FixedLayoutTestWebViewClient client;
+  FixedLayoutTestWebWidgetClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "device_media_queries.html",
-                                    nullptr, &client, nullptr,
+                                    nullptr, nullptr, &client,
                                     ConfigureAndroid);
   auto* frame =
       To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
@@ -9920,7 +9916,7 @@
     RegisterMockedHttpURLLoad("device_emulation.html");
     client_.screen_info_.device_scale_factor = 1;
     web_view_helper_.InitializeAndLoad(base_url_ + "device_emulation.html",
-                                       nullptr, &client_);
+                                       nullptr, nullptr, &client_);
   }
 
   void TestResize(const WebSize size, const String& expected_size) {
@@ -9944,7 +9940,7 @@
     return callback_helper.StringValue();
   }
 
-  FixedLayoutTestWebViewClient client_;
+  FixedLayoutTestWebWidgetClient client_;
   frame_test_helpers::WebViewHelper web_view_helper_;
 };
 
@@ -13000,13 +12996,15 @@
 
 TEST_F(WebFrameTest, MediaQueriesInLocalFrameInsideRemote) {
   frame_test_helpers::WebViewHelper helper;
-  FixedLayoutTestWebViewClient client;
+  helper.InitializeRemote();
+
+  FixedLayoutTestWebWidgetClient client;
   client.screen_info_.is_monochrome = false;
   client.screen_info_.depth_per_component = 8;
-  helper.InitializeRemote(nullptr, nullptr, &client);
 
-  WebLocalFrameImpl* local_frame =
-      frame_test_helpers::CreateLocalChild(*helper.RemoteMainFrame());
+  WebLocalFrameImpl* local_frame = frame_test_helpers::CreateLocalChild(
+      *helper.RemoteMainFrame(), WebString(), WebFrameOwnerProperties(),
+      nullptr, nullptr, &client);
 
   ASSERT_TRUE(local_frame->GetFrame());
   MediaValues* media_values =
diff --git a/third_party/blink/renderer/core/exported/web_layer_test.cc b/third_party/blink/renderer/core/exported/web_layer_test.cc
index 2209eea..d022944 100644
--- a/third_party/blink/renderer/core/exported/web_layer_test.cc
+++ b/third_party/blink/renderer/core/exported/web_layer_test.cc
@@ -947,7 +947,10 @@
   // both layers.
   outer_element->setAttribute(html_names::kStyleAttr, "width: 200px;");
   UpdateAllLifecyclePhases();
-  EXPECT_TRUE(outer_element_layer->subtree_property_changed());
+  // The overflow clip does not affect |outer_element_layer|, so
+  // subtree_property_changed should be false for it. It does affect
+  // |inner_element_layer| though.
+  EXPECT_FALSE(outer_element_layer->subtree_property_changed());
   EXPECT_TRUE(inner_element_layer->subtree_property_changed());
 
   // After a frame the |subtree_property_changed| value should be reset.
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
index 109534f..6ba87e7 100644
--- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -151,8 +151,9 @@
         timeline->GetAnimationTimeline());
   }
 
-  WebScreenInfo GetScreenInfo() const override {
-    return popup_->web_view_->Client()->GetScreenInfo();
+  WebScreenInfo GetScreenInfo(LocalFrame&) const override {
+    // LocalFrame is ignored since there is only 1 frame in a popup.
+    return popup_->WidgetClient()->GetScreenInfo();
   }
 
   WebViewImpl* GetWebView() const override { return popup_->web_view_; }
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index 50f3553..47eb0f69 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -370,6 +370,9 @@
   // the case by this point).
   web_view_->DidAttachLocalMainFrame();
 
+  web_view_->SetDeviceScaleFactor(
+      test_web_widget_client_->GetScreenInfo().device_scale_factor);
+
   // Set an initial size for subframes.
   if (frame->Parent())
     frame->FrameWidget()->Resize(WebSize());
@@ -497,8 +500,6 @@
             .GetAllowUniversalAccessFromFileURLs());
   }
 
-  web_view_->SetDeviceScaleFactor(
-      test_web_view_client_->GetScreenInfo().device_scale_factor);
   web_view_->SetDefaultPageScaleLimits(1, 4);
 }
 
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index 71ae84f..9b89b5e 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -292,7 +292,6 @@
   // WebViewClient overrides.
   bool CanHandleGestureEvent() override { return true; }
   bool CanUpdateLayout() override { return true; }
-  blink::WebScreenInfo GetScreenInfo() override { return {}; }
   WebView* CreateView(WebLocalFrame* opener,
                       const WebURLRequest&,
                       const WebWindowFeatures&,
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index a9a895a..e910319 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -454,14 +454,12 @@
 int LocalDOMWindow::orientation() const {
   DCHECK(RuntimeEnabledFeatures::OrientationEventEnabled());
 
-  if (!GetFrame() || !GetFrame()->GetPage())
+  LocalFrame* frame = GetFrame();
+  if (!frame)
     return 0;
 
-  int orientation = GetFrame()
-                        ->GetPage()
-                        ->GetChromeClient()
-                        .GetScreenInfo()
-                        .orientation_angle;
+  ChromeClient& chrome_client = frame->GetChromeClient();
+  int orientation = chrome_client.GetScreenInfo(*frame).orientation_angle;
   // For backward compatibility, we want to return a value in the range of
   // [-90; 180] instead of [0; 360[ because window.orientation used to behave
   // like that in WebKit (this is a WebKit proprietary API).
@@ -796,7 +794,7 @@
   if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
     return static_cast<int>(
         lroundf(chrome_client.RootWindowRect(*frame).Height() *
-                chrome_client.GetScreenInfo().device_scale_factor));
+                chrome_client.GetScreenInfo(*frame).device_scale_factor));
   }
   return chrome_client.RootWindowRect(*frame).Height();
 }
@@ -814,7 +812,7 @@
   if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
     return static_cast<int>(
         lroundf(chrome_client.RootWindowRect(*frame).Width() *
-                chrome_client.GetScreenInfo().device_scale_factor));
+                chrome_client.GetScreenInfo(*frame).device_scale_factor));
   }
   return chrome_client.RootWindowRect(*frame).Width();
 }
@@ -874,7 +872,7 @@
   if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
     return static_cast<int>(
         lroundf(chrome_client.RootWindowRect(*frame).X() *
-                chrome_client.GetScreenInfo().device_scale_factor));
+                chrome_client.GetScreenInfo(*frame).device_scale_factor));
   }
   return chrome_client.RootWindowRect(*frame).X();
 }
@@ -892,7 +890,7 @@
   if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
     return static_cast<int>(
         lroundf(chrome_client.RootWindowRect(*frame).Y() *
-                chrome_client.GetScreenInfo().device_scale_factor));
+                chrome_client.GetScreenInfo(*frame).device_scale_factor));
   }
   return chrome_client.RootWindowRect(*frame).Y();
 }
diff --git a/third_party/blink/renderer/core/frame/screen.cc b/third_party/blink/renderer/core/frame/screen.cc
index f31ab99..5d9629c 100644
--- a/third_party/blink/renderer/core/frame/screen.cc
+++ b/third_party/blink/renderer/core/frame/screen.cc
@@ -38,106 +38,106 @@
 
 namespace blink {
 
+namespace {
+
+WebScreenInfo GetScreenInfo(LocalFrame& frame) {
+  return frame.GetChromeClient().GetScreenInfo(frame);
+}
+
+}  // namespace
+
 Screen::Screen(LocalFrame* frame) : DOMWindowClient(frame) {}
 
 int Screen::height() const {
-  if (!GetFrame())
+  LocalFrame* frame = GetFrame();
+  if (!frame)
     return 0;
-  Page* page = GetFrame()->GetPage();
-  if (!page)
-    return 0;
+  Page* page = frame->GetPage();
   if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
-    WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+    WebScreenInfo screen_info = GetScreenInfo(*frame);
     return static_cast<int>(
         lroundf(screen_info.rect.height * screen_info.device_scale_factor));
   }
-  return page->GetChromeClient().GetScreenInfo().rect.height;
+  return GetScreenInfo(*frame).rect.height;
 }
 
 int Screen::width() const {
-  if (!GetFrame())
+  LocalFrame* frame = GetFrame();
+  if (!frame)
     return 0;
-  Page* page = GetFrame()->GetPage();
-  if (!page)
-    return 0;
+  Page* page = frame->GetPage();
   if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
-    WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+    WebScreenInfo screen_info = GetScreenInfo(*frame);
     return static_cast<int>(
         lroundf(screen_info.rect.width * screen_info.device_scale_factor));
   }
-  return page->GetChromeClient().GetScreenInfo().rect.width;
+  return GetScreenInfo(*frame).rect.width;
 }
 
 unsigned Screen::colorDepth() const {
-  if (!GetFrame() || !GetFrame()->GetPage())
+  LocalFrame* frame = GetFrame();
+  if (!frame)
     return 0;
-  return static_cast<unsigned>(
-      GetFrame()->GetPage()->GetChromeClient().GetScreenInfo().depth);
+  return static_cast<unsigned>(GetScreenInfo(*frame).depth);
 }
 
 unsigned Screen::pixelDepth() const {
-  if (!GetFrame())
+  LocalFrame* frame = GetFrame();
+  if (!frame)
     return 0;
-  return static_cast<unsigned>(
-      GetFrame()->GetPage()->GetChromeClient().GetScreenInfo().depth);
+  return static_cast<unsigned>(GetScreenInfo(*frame).depth);
 }
 
 int Screen::availLeft() const {
-  if (!GetFrame())
+  LocalFrame* frame = GetFrame();
+  if (!frame)
     return 0;
-  Page* page = GetFrame()->GetPage();
-  if (!page)
-    return 0;
+  Page* page = frame->GetPage();
   if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
-    WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+    WebScreenInfo screen_info = GetScreenInfo(*frame);
     return static_cast<int>(lroundf(screen_info.available_rect.x *
                                     screen_info.device_scale_factor));
   }
-  return static_cast<int>(
-      page->GetChromeClient().GetScreenInfo().available_rect.x);
+  return static_cast<int>(GetScreenInfo(*frame).available_rect.x);
 }
 
 int Screen::availTop() const {
-  if (!GetFrame())
+  LocalFrame* frame = GetFrame();
+  if (!frame)
     return 0;
-  Page* page = GetFrame()->GetPage();
-  if (!page)
-    return 0;
+  Page* page = frame->GetPage();
   if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
-    WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+    WebScreenInfo screen_info = GetScreenInfo(*frame);
     return static_cast<int>(lroundf(screen_info.available_rect.y *
                                     screen_info.device_scale_factor));
   }
-  return static_cast<int>(
-      page->GetChromeClient().GetScreenInfo().available_rect.y);
+  return static_cast<int>(GetScreenInfo(*frame).available_rect.y);
 }
 
 int Screen::availHeight() const {
-  if (!GetFrame())
+  LocalFrame* frame = GetFrame();
+  if (!frame)
     return 0;
-  Page* page = GetFrame()->GetPage();
-  if (!page)
-    return 0;
+  Page* page = frame->GetPage();
   if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
-    WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+    WebScreenInfo screen_info = GetScreenInfo(*frame);
     return static_cast<int>(lroundf(screen_info.available_rect.height *
                                     screen_info.device_scale_factor));
   }
-  return page->GetChromeClient().GetScreenInfo().available_rect.height;
+  return GetScreenInfo(*frame).available_rect.height;
 }
 
 int Screen::availWidth() const {
-  if (!GetFrame())
+  LocalFrame* frame = GetFrame();
+  if (!frame)
     return 0;
-  Page* page = GetFrame()->GetPage();
-  if (!page)
-    return 0;
+  Page* page = frame->GetPage();
   if (page->GetSettings().GetReportScreenSizeInPhysicalPixelsQuirk()) {
-    WebScreenInfo screen_info = page->GetChromeClient().GetScreenInfo();
+    WebScreenInfo screen_info = GetScreenInfo(*frame);
     return static_cast<int>(lroundf(screen_info.available_rect.width *
                                     screen_info.device_scale_factor));
   }
-  return page->GetChromeClient().GetScreenInfo().available_rect.width;
+  return GetScreenInfo(*frame).available_rect.width;
 }
 
 void Screen::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc
index 9daab70..cc6e9c1 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -4192,10 +4192,10 @@
 }
 
 gfx::ColorSpace HTMLMediaElement::TargetColorSpace() {
-  const LocalFrame* frame = GetDocument().GetFrame();
+  LocalFrame* frame = GetDocument().GetFrame();
   if (!frame)
     return gfx::ColorSpace();
-  return frame->GetPage()->GetChromeClient().GetScreenInfo().color_space;
+  return frame->GetPage()->GetChromeClient().GetScreenInfo(*frame).color_space;
 }
 
 bool HTMLMediaElement::WasAutoplayInitiated() {
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.cc b/third_party/blink/renderer/core/input/mouse_event_manager.cc
index 005e1f7..79575861 100644
--- a/third_party/blink/renderer/core/input/mouse_event_manager.cc
+++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -78,10 +78,9 @@
     if (dom_window && dom_window->GetFrame()) {
       LocalFrame* frame = dom_window->GetFrame();
       if (frame->GetPage()->DeviceScaleFactorDeprecated() == 1) {
-        device_scale_factor = frame->GetPage()
-                                  ->GetChromeClient()
-                                  .GetScreenInfo()
-                                  .device_scale_factor;
+        ChromeClient& chrome_client = frame->GetChromeClient();
+        device_scale_factor =
+            chrome_client.GetScreenInfo(*frame).device_scale_factor;
       }
     }
     // movementX/Y is type int for now, so we need to truncated the coordinates
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc
index 30ebb63..f15be07 100644
--- a/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -331,11 +331,10 @@
   // to date DSF when layout happens, we plumb this through to the FontCache, so
   // that we can correctly retrieve RenderStyleForStrike from out of
   // process. crbug.com/845468
-  FontCache::SetDeviceScaleFactor(GetFrameView()
-                                      ->GetFrame()
-                                      .GetChromeClient()
-                                      .GetScreenInfo()
-                                      .device_scale_factor);
+  LocalFrame& frame = GetFrameView()->GetFrame();
+  ChromeClient& chrome_client = frame.GetChromeClient();
+  FontCache::SetDeviceScaleFactor(
+      chrome_client.GetScreenInfo(frame).device_scale_factor);
 #endif
 
   LayoutBlockFlow::UpdateLayout();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc
index a3d0a90..7f919d2 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc
@@ -111,7 +111,7 @@
   builder.SetPercentageResolutionSize(size);
   builder.SetTextDirection(direction);
   builder.SetIsShrinkToFit(shrink_to_fit);
-  builder.SetFragmentainerSpaceAtBfcStart(fragmentainer_space_available);
+  builder.SetFragmentainerBlockSize(fragmentainer_space_available);
   builder.SetFragmentationType(block_fragmentation);
   return builder.ToConstraintSpace();
 }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index 1a32600..764cf34 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -1966,13 +1966,15 @@
 
 LayoutUnit NGBlockLayoutAlgorithm::FragmentainerSpaceAvailable() const {
   DCHECK(container_builder_.BfcBlockOffset());
-  return ConstraintSpace().FragmentainerSpaceAtBfcStart() -
+  return FragmentainerSpaceAtBfcStart(ConstraintSpace()) -
          *container_builder_.BfcBlockOffset();
 }
 
 bool NGBlockLayoutAlgorithm::IsFragmentainerOutOfSpace(
     LayoutUnit block_offset) const {
-  if (!ConstraintSpace().HasBlockFragmentation())
+  if (did_break_before_child_)
+    return true;
+  if (!ConstraintSpace().HasKnownFragmentainerBlockSize())
     return false;
   if (!container_builder_.BfcBlockOffset().has_value())
     return false;
@@ -1980,33 +1982,6 @@
 }
 
 bool NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
-  LayoutUnit consumed_block_size =
-      BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit();
-  LayoutUnit block_size =
-      ComputeBlockSizeForFragment(ConstraintSpace(), Style(), border_padding_,
-                                  consumed_block_size + intrinsic_block_size_);
-
-  block_size -= consumed_block_size;
-  DCHECK_GE(block_size, LayoutUnit())
-      << "Adding and subtracting the consumed_block_size shouldn't leave the "
-         "block_size for this fragment smaller than zero.";
-
-  LayoutUnit space_left = FragmentainerSpaceAvailable();
-
-  if (space_left <= LayoutUnit()) {
-    // The amount of space available may be zero, or even negative, if the
-    // border-start edge of this block starts exactly at, or even after the
-    // fragmentainer boundary. We're going to need a break before this block,
-    // because no part of it fits in the current fragmentainer. Due to margin
-    // collapsing with children, this situation is something that we cannot
-    // always detect prior to layout. The fragment produced by this algorithm is
-    // going to be thrown away. The parent layout algorithm will eventually
-    // detect that there's no room for a fragment for this node, and drop the
-    // fragment on the floor. Therefore it doesn't matter how we set up the
-    // container builder, so just return.
-    return true;
-  }
-
   if (Node().ChildrenInline() && !early_break_) {
     if (container_builder_.DidBreak() || first_overflowing_line_) {
       if (first_overflowing_line_ &&
@@ -2036,8 +2011,38 @@
     }
   }
 
-  FinishFragmentation(&container_builder_, block_size, intrinsic_block_size_,
-                      consumed_block_size, space_left);
+  if (!ConstraintSpace().HasKnownFragmentainerBlockSize())
+    return true;
+
+  LayoutUnit consumed_block_size =
+      BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit();
+  LayoutUnit block_size =
+      ComputeBlockSizeForFragment(ConstraintSpace(), Style(), border_padding_,
+                                  consumed_block_size + intrinsic_block_size_);
+
+  block_size -= consumed_block_size;
+  DCHECK_GE(block_size, LayoutUnit())
+      << "Adding and subtracting the consumed_block_size shouldn't leave the "
+         "block_size for this fragment smaller than zero.";
+
+  LayoutUnit space_left = FragmentainerSpaceAvailable();
+
+  if (space_left <= LayoutUnit()) {
+    // The amount of space available may be zero, or even negative, if the
+    // border-start edge of this block starts exactly at, or even after the
+    // fragmentainer boundary. We're going to need a break before this block,
+    // because no part of it fits in the current fragmentainer. Due to margin
+    // collapsing with children, this situation is something that we cannot
+    // always detect prior to layout. The fragment produced by this algorithm is
+    // going to be thrown away. The parent layout algorithm will eventually
+    // detect that there's no room for a fragment for this node, and drop the
+    // fragment on the floor. Therefore it doesn't matter how we set up the
+    // container builder, so just return.
+    return true;
+  }
+
+  FinishFragmentation(ConstraintSpace(), block_size, intrinsic_block_size_,
+                      consumed_block_size, space_left, &container_builder_);
 
   return true;
 }
@@ -2086,6 +2091,11 @@
     appeal_before = kBreakAppealLastResort;
   }
 
+  // We only care about soft breaks if we have a fragmentainer block-size.
+  // During column balancing this may be unknown.
+  if (!ConstraintSpace().HasKnownFragmentainerBlockSize())
+    return kContinueWithoutBreaking;
+
   const auto& physical_fragment = layout_result.PhysicalFragment();
   if (IsA<NGBlockBreakToken>(physical_fragment.BreakToken())) {
     // The block child broke inside. We now need to decide whether to keep that
@@ -2253,10 +2263,17 @@
     NGBreakAppeal appeal,
     bool is_forced_break,
     NGPreviousInflowPosition* previous_inflow_position) {
-  // The remaining part of the fragmentainer (the unusable space for child
-  // content, due to the break) should still be occupied by this container.
-  previous_inflow_position->logical_block_offset =
-      FragmentainerSpaceAvailable();
+  did_break_before_child_ = true;
+
+  if (ConstraintSpace().HasKnownFragmentainerBlockSize()) {
+    // The remaining part of the fragmentainer (the unusable space for child
+    // content, due to the break) should still be occupied by this container.
+    previous_inflow_position->logical_block_offset =
+        FragmentainerSpaceAvailable();
+  }
+
+  DCHECK(is_forced_break || ConstraintSpace().HasKnownFragmentainerBlockSize());
+
   // This will drop the fragment (if any) on the floor and retry at the start of
   // the next fragmentainer.
   container_builder_.AddBreakBeforeChild(child, appeal, is_forced_break);
@@ -2265,6 +2282,15 @@
 void NGBlockLayoutAlgorithm::PropagateSpaceShortage(
     const NGLayoutResult& layout_result,
     LayoutUnit block_offset) {
+  // There's no shortage to report in the initial column balancing pass, since
+  // we haven't even calculated a tentative column block-size yet.
+  if (ConstraintSpace().IsInitialColumnBalancingPass())
+    return;
+
+  // Only multicol cares about space shortage.
+  if (ConstraintSpace().BlockFragmentationType() != kFragmentColumn)
+    return;
+
   LayoutUnit space_shortage;
   if (layout_result.MinimalSpaceShortage() == LayoutUnit::Max()) {
     // Calculate space shortage: Figure out how much more space would have been
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
index 5058b3d5..9b1b9d5 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
@@ -425,6 +425,8 @@
   // A or B breakpoint (between block-level siblings or line box siblings).
   bool has_processed_first_child_ = false;
 
+  bool did_break_before_child_ = false;
+
   NGExclusionSpace exclusion_space_;
 
   // When set, this will specify where to break before or inside.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
index 7466d4b..9ff6544 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -105,8 +105,21 @@
   used_column_count_ =
       ResolveUsedColumnCount(content_box_size_.inline_size, Style());
 
-  if (ConstraintSpace().HasBlockFragmentation())
+  // If we know the block-size of the fragmentainers in an outer fragmentation
+  // context (if any), our columns may be constrained by that, meaning that we
+  // may have to fragment earlier than what we would have otherwise, and, if
+  // that's the case, that we may also not create overflowing columns (in the
+  // inline axis), but rather finish the row and resume in the next row in the
+  // next outer fragmentainer. Note that it is possible to be nested inside a
+  // fragmentation context that doesn't know the block-size of its
+  // fragmentainers. This would be in the first layout pass of an outer multicol
+  // container, before any tentative column block-size has been calculated.
+  is_constrained_by_outer_fragmentation_context_ =
+      ConstraintSpace().HasKnownFragmentainerBlockSize();
+
+  if (is_constrained_by_outer_fragmentation_context_)
     container_builder_.SetHasBlockFragmentation();
+
   container_builder_.SetIsBlockFragmentationContextRoot();
 
   // Omit leading border+padding+scrollbar for all fragments but the first.
@@ -134,12 +147,13 @@
     block_size = border_box_size.block_size - previously_consumed_block_size;
   }
 
-  if (ConstraintSpace().HasBlockFragmentation()) {
+  if (is_constrained_by_outer_fragmentation_context_) {
     // In addition to establishing one, we're nested inside another
     // fragmentation context.
-    FinishFragmentation(&container_builder_, block_size, intrinsic_block_size_,
+    FinishFragmentation(ConstraintSpace(), block_size, intrinsic_block_size_,
                         previously_consumed_block_size,
-                        ConstraintSpace().FragmentainerSpaceAtBfcStart());
+                        FragmentainerSpaceAtBfcStart(ConstraintSpace()),
+                        &container_builder_);
   } else {
     container_builder_.SetBlockSize(block_size);
     container_builder_.SetIntrinsicBlockSize(intrinsic_block_size_);
@@ -306,7 +320,7 @@
   // If block-size is non-auto, subtract the space for content we've consumed in
   // previous fragments. This is necessary when we're nested inside another
   // fragmentation context.
-  if (ConstraintSpace().HasBlockFragmentation() &&
+  if (is_constrained_by_outer_fragmentation_context_ &&
       column_size.block_size != kIndefiniteSize) {
     if (const auto* token = BreakToken())
       column_size.block_size -= token->ConsumedBlockSize();
@@ -323,7 +337,7 @@
   // contexts, not just by a block-size specified on this multicol container.
   bool balance_columns = Style().GetColumnFill() == EColumnFill::kBalance ||
                          (column_size.block_size == kIndefiniteSize &&
-                          !ConstraintSpace().HasBlockFragmentation());
+                          !is_constrained_by_outer_fragmentation_context_);
 
   if (balance_columns) {
     column_size.block_size =
@@ -331,9 +345,9 @@
   }
 
   bool needs_more_fragments_in_outer = false;
-  if (ConstraintSpace().HasBlockFragmentation()) {
+  if (is_constrained_by_outer_fragmentation_context_) {
     LayoutUnit available_outer_space =
-        ConstraintSpace().FragmentainerSpaceAtBfcStart() - column_block_offset;
+        FragmentainerSpaceAtBfcStart(ConstraintSpace()) - column_block_offset;
 
     // TODO(mstensho): This should never be negative, or even zero. Turn into a
     // DCHECK when the underlying problem is fixed.
@@ -726,7 +740,6 @@
 
   space_builder.SetFragmentationType(kFragmentColumn);
   space_builder.SetFragmentainerBlockSize(column_block_size);
-  space_builder.SetFragmentainerSpaceAtBfcStart(column_block_size);
   space_builder.SetIsAnonymous(true);
   space_builder.SetIsInColumnBfc();
   if (balance_columns)
@@ -747,11 +760,6 @@
   NGConstraintSpaceBuilder space_builder(
       ConstraintSpace(), Style().GetWritingMode(), /* is_new_fc */ true);
   space_builder.SetFragmentationType(kFragmentColumn);
-  // TODO(mstensho): It would be better to use kIndefiniteSize here, rather than
-  // LayoutUnit::Max(), but the fragmentation machinery currently gets confused
-  // by such a value.
-  space_builder.SetFragmentainerBlockSize(LayoutUnit::Max());
-  space_builder.SetFragmentainerSpaceAtBfcStart(LayoutUnit::Max());
   space_builder.SetAvailableSize({column_size.inline_size, kIndefiniteSize});
   space_builder.SetPercentageResolutionSize(column_size);
   space_builder.SetIsAnonymous(true);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
index 06a3ad1..7f558dde 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
@@ -72,6 +72,7 @@
   LayoutUnit column_inline_size_;
   LayoutUnit column_inline_progression_;
   LayoutUnit intrinsic_block_size_;
+  bool is_constrained_by_outer_fragmentation_context_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
index 0bf44052..3e71299 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -3042,6 +3042,77 @@
   EXPECT_EQ(expectation, dump);
 }
 
+TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingLinesForcedBreak3) {
+  // We have 7+5 lines and 3 columns. There's a forced break after 7 lines, then
+  // 5 more lines. There will be another implicit break among the first 7 lines,
+  // while the columns will have to fit 5 lines, because of the 5 lines after
+  // the forced break. The first column will have 5 lines. The second one will
+  // have 2. The third one (after the break) will have 5. The lines are wrapped
+  // inside a block child of the multicol container.
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #parent {
+        columns: 3;
+        column-gap: 10px;
+        width: 320px;
+        line-height: 20px;
+        orphans: 1;
+        widows: 1;
+      }
+    </style>
+    <div id="container">
+      <div id="parent">
+        <div style="width:66px;">
+          <br><br><br><br><br><br><br>
+          <div style="width:99px; break-before:column;"></div>
+          <br><br><br><br><br>
+        </div>
+      </div>
+    </div>
+  )HTML");
+
+  String dump = DumpFragmentTree(GetElementById("container"));
+  String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
+  offset:unplaced size:1000x100
+    offset:0,0 size:320x100
+      offset:0,0 size:100x100
+        offset:0,0 size:66x100
+          offset:0,0 size:66x100
+            offset:0,0 size:0x20
+              offset:0,9 size:0x1
+            offset:0,20 size:0x20
+              offset:0,9 size:0x1
+            offset:0,40 size:0x20
+              offset:0,9 size:0x1
+            offset:0,60 size:0x20
+              offset:0,9 size:0x1
+            offset:0,80 size:0x20
+              offset:0,9 size:0x1
+      offset:110,0 size:100x100
+        offset:0,0 size:66x100
+          offset:0,0 size:66x40
+            offset:0,0 size:0x20
+              offset:0,9 size:0x1
+            offset:0,20 size:0x20
+              offset:0,9 size:0x1
+      offset:220,0 size:100x100
+        offset:0,0 size:66x100
+          offset:0,0 size:99x0
+          offset:0,0 size:66x100
+            offset:0,0 size:0x20
+              offset:0,9 size:0x1
+            offset:0,20 size:0x20
+              offset:0,9 size:0x1
+            offset:0,40 size:0x20
+              offset:0,9 size:0x1
+            offset:0,60 size:0x20
+              offset:0,9 size:0x1
+            offset:0,80 size:0x20
+              offset:0,9 size:0x1
+)DUMP";
+  EXPECT_EQ(expectation, dump);
+}
+
 TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingLinesAvoidBreakInside) {
   // We have 6 lines and 3 columns. If we make the columns tall enough to hold 2
   // lines each, it should all fit. But then there's a block with 3 lines and
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
index 1b59daf..207b169 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
@@ -255,14 +255,34 @@
                          : kIndefiniteSize;
   }
 
-  // Return the block space that was available in the current fragmentainer at
-  // the start of the current block formatting context. Note that if the start
-  // of the current block formatting context is in a previous fragmentainer, the
-  // size of the current fragmentainer is returned instead.
-  LayoutUnit FragmentainerSpaceAtBfcStart() const {
+  // Return true if we're column-balancing, and are in the initial pass where
+  // we're calculating the initial minimal column block-size.
+  bool IsInitialColumnBalancingPass() const {
+    return BlockFragmentationType() == kFragmentColumn &&
+           FragmentainerBlockSize() == kIndefiniteSize;
+  }
+
+  // Return true if we're block-fragmented and know our fragmentainer
+  // block-size.
+  bool HasKnownFragmentainerBlockSize() const {
+    if (!HasBlockFragmentation() || IsInitialColumnBalancingPass())
+      return false;
+    // The only case where we allow an unknown fragmentainer block-size is if
+    // we're in the initial column balancing pass.
+    DCHECK(FragmentainerBlockSize() != kIndefiniteSize);
+    return true;
+  }
+
+  // Return the block-offset from the block-start of the fragmentainer
+  // relative to the block-start of the current block formatting context in
+  // the current fragmentainer. Note that if the current block formatting
+  // context starts in a previous fragmentainer, we'll return the block-offset
+  // relative to the current fragmentainer.
+  LayoutUnit FragmentainerOffsetAtBfc() const {
     DCHECK(HasBlockFragmentation());
-    return HasRareData() ? rare_data_->fragmentainer_space_at_bfc_start
-                         : kIndefiniteSize;
+    if (HasRareData())
+      return rare_data_->fragmentainer_offset_at_bfc;
+    return LayoutUnit();
   }
 
   // Whether the current constraint space is for the newly established
@@ -579,8 +599,7 @@
               other.replaced_percentage_resolution_block_size),
           bfc_offset(other.bfc_offset),
           fragmentainer_block_size(other.fragmentainer_block_size),
-          fragmentainer_space_at_bfc_start(
-              other.fragmentainer_space_at_bfc_start),
+          fragmentainer_offset_at_bfc(other.fragmentainer_offset_at_bfc),
           data_union_type(other.data_union_type),
           block_direction_fragmentation_type(
               other.block_direction_fragmentation_type),
@@ -635,7 +654,7 @@
     NGBfcOffset bfc_offset;
 
     LayoutUnit fragmentainer_block_size = kIndefiniteSize;
-    LayoutUnit fragmentainer_space_at_bfc_start = kIndefiniteSize;
+    LayoutUnit fragmentainer_offset_at_bfc;
 
     unsigned data_union_type : 2;
     unsigned block_direction_fragmentation_type : 2;
@@ -645,8 +664,7 @@
 
     bool MaySkipLayout(const RareData& other) const {
       if (fragmentainer_block_size != other.fragmentainer_block_size ||
-          fragmentainer_space_at_bfc_start !=
-              other.fragmentainer_space_at_bfc_start ||
+          fragmentainer_offset_at_bfc != other.fragmentainer_offset_at_bfc ||
           data_union_type != other.data_union_type ||
           block_direction_fragmentation_type !=
               other.block_direction_fragmentation_type ||
@@ -671,7 +689,7 @@
     // Must be kept in sync with members checked within |MaySkipLayout|.
     bool IsInitialForMaySkipLayout() const {
       if (fragmentainer_block_size != kIndefiniteSize ||
-          fragmentainer_space_at_bfc_start != kIndefiniteSize ||
+          fragmentainer_offset_at_bfc ||
           block_direction_fragmentation_type != kFragmentNone ||
           is_inside_balanced_columns || is_in_column_bfc ||
           early_break_appeal != kBreakAppealLastResort)
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
index c96f13ec..dea3f89 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
@@ -114,13 +114,13 @@
       space_.EnsureRareData()->fragmentainer_block_size = size;
   }
 
-  void SetFragmentainerSpaceAtBfcStart(LayoutUnit space) {
+  void SetFragmentainerOffsetAtBfc(LayoutUnit offset) {
 #if DCHECK_IS_ON()
-    DCHECK(!is_fragmentainer_space_at_bfc_start_set_);
-    is_fragmentainer_space_at_bfc_start_set_ = true;
+    DCHECK(!is_fragmentainer_offset_at_bfc_set_);
+    is_fragmentainer_offset_at_bfc_set_ = true;
 #endif
-    if (space != kIndefiniteSize)
-      space_.EnsureRareData()->fragmentainer_space_at_bfc_start = space;
+    if (offset != LayoutUnit())
+      space_.EnsureRareData()->fragmentainer_offset_at_bfc = offset;
   }
 
   void SetTextDirection(TextDirection direction) {
@@ -347,7 +347,7 @@
   bool is_available_size_set_ = false;
   bool is_percentage_resolution_size_set_ = false;
   bool is_fragmentainer_block_size_set_ = false;
-  bool is_fragmentainer_space_at_bfc_start_set_ = false;
+  bool is_fragmentainer_offset_at_bfc_set_ = false;
   bool is_block_direction_fragmentation_type_set_ = false;
   bool is_margin_strut_set_ = false;
   bool is_optimistic_bfc_block_offset_set_ = false;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
index 0fd132e..31af104 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -144,22 +144,21 @@
                         bool is_new_fc) {
   DCHECK(parent_space.HasBlockFragmentation());
 
-  LayoutUnit space_available =
-      parent_space.FragmentainerSpaceAtBfcStart() - new_bfc_block_offset;
-
   builder->SetFragmentainerBlockSize(parent_space.FragmentainerBlockSize());
-  builder->SetFragmentainerSpaceAtBfcStart(space_available);
+  new_bfc_block_offset += parent_space.FragmentainerOffsetAtBfc();
+  builder->SetFragmentainerOffsetAtBfc(new_bfc_block_offset);
   builder->SetFragmentationType(parent_space.BlockFragmentationType());
 
   if (parent_space.IsInColumnBfc() && !is_new_fc)
     builder->SetIsInColumnBfc();
 }
 
-void FinishFragmentation(NGBoxFragmentBuilder* builder,
+void FinishFragmentation(const NGConstraintSpace& space,
                          LayoutUnit block_size,
                          LayoutUnit intrinsic_block_size,
                          LayoutUnit previously_consumed_block_size,
-                         LayoutUnit space_left) {
+                         LayoutUnit space_left,
+                         NGBoxFragmentBuilder* builder) {
   if (builder->DidBreak()) {
     // One of our children broke. Even if we fit within the remaining space, we
     // need to prepare a break token.
@@ -177,7 +176,9 @@
     builder->SetBreakAppeal(kBreakAppealPerfect);
     builder->SetBlockSize(space_left);
     builder->SetIntrinsicBlockSize(space_left);
-    builder->PropagateSpaceShortage(block_size - space_left);
+    if (space.BlockFragmentationType() == kFragmentColumn &&
+        !space.IsInitialColumnBalancingPass())
+      builder->PropagateSpaceShortage(block_size - space_left);
     return;
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
index 259b10e..c170ff3 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
@@ -7,6 +7,7 @@
 
 #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h"
 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
@@ -14,7 +15,6 @@
 namespace blink {
 
 class NGBoxFragmentBuilder;
-class NGConstraintSpace;
 class NGLayoutResult;
 
 // Join two adjacent break values specified on break-before and/or break-
@@ -56,6 +56,15 @@
                                          NGBlockNode child,
                                          const NGLayoutResult&);
 
+// Return the block space that was available in the current fragmentainer at the
+// start of the current block formatting context. Note that if the start of the
+// current block formatting context is in a previous fragmentainer, the size of
+// the current fragmentainer is returned instead.
+inline LayoutUnit FragmentainerSpaceAtBfcStart(const NGConstraintSpace& space) {
+  DCHECK(space.HasKnownFragmentainerBlockSize());
+  return space.FragmentainerBlockSize() - space.FragmentainerOffsetAtBfc();
+}
+
 // Set up a child's constraint space builder for block fragmentation. The child
 // participates in the same fragmentation context as parent_space. If the child
 // establishes a new formatting context, new_bfc_block_offset must be set to the
@@ -68,11 +77,12 @@
                         bool is_new_fc);
 
 // Write fragmentation information to the fragment builder after layout.
-void FinishFragmentation(NGBoxFragmentBuilder*,
+void FinishFragmentation(const NGConstraintSpace&,
                          LayoutUnit block_size,
                          LayoutUnit intrinsic_block_size,
                          LayoutUnit previously_consumed_block_size,
-                         LayoutUnit space_left);
+                         LayoutUnit space_left,
+                         NGBoxFragmentBuilder*);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
index b630a5ab..21ab11c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
@@ -103,7 +103,6 @@
   // TODO(mstensho): Handle auto block size.
   space_builder.SetFragmentationType(kFragmentPage);
   space_builder.SetFragmentainerBlockSize(page_size.block_size);
-  space_builder.SetFragmentainerSpaceAtBfcStart(page_size.block_size);
   space_builder.SetIsAnonymous(true);
 
   return space_builder.ToConstraintSpace();
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index d3097bd1..ec31d7f 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -180,7 +180,9 @@
   float WindowToViewportScalar(LocalFrame*, const float s) const override {
     return s;
   }
-  WebScreenInfo GetScreenInfo() const override { return WebScreenInfo(); }
+  WebScreenInfo GetScreenInfo(LocalFrame&) const override {
+    return WebScreenInfo();
+  }
   void ContentsSizeChanged(LocalFrame*, const IntSize&) const override {}
 
   void ShowMouseOverURL(const HitTestResult&) override {}
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 0139af4..753155f 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -429,6 +429,18 @@
   if (document_loader->ForceFetchCacheMode())
     request.SetCacheMode(*document_loader->ForceFetchCacheMode());
 
+  if (request.GetPreviewsState() == WebURLRequest::kPreviewsUnspecified) {
+    WebURLRequest::PreviewsState request_previews_state =
+        document_loader->GetPreviewsState();
+    // The decision of whether or not to enable Client Lo-Fi is made earlier
+    // in the request lifetime, in LocalFrame::MaybeAllowImagePlaceholder(),
+    // so don't add the Client Lo-Fi bit to the request here.
+    request_previews_state &= ~(WebURLRequest::kLazyImageLoadDeferred);
+    if (request_previews_state == WebURLRequest::kPreviewsUnspecified)
+      request_previews_state = WebURLRequest::kPreviewsOff;
+    request.SetPreviewsState(request_previews_state);
+  }
+
   GetLocalFrameClient()->DispatchWillSendRequest(request);
   FrameScheduler* frame_scheduler = GetFrame()->GetFrameScheduler();
   if (!for_redirect && frame_scheduler) {
diff --git a/third_party/blink/renderer/core/page/chrome_client.cc b/third_party/blink/renderer/core/page/chrome_client.cc
index ee6869a..212a909 100644
--- a/third_party/blink/renderer/core/page/chrome_client.cc
+++ b/third_party/blink/renderer/core/page/chrome_client.cc
@@ -50,7 +50,7 @@
 
 void ChromeClient::SetWindowRectWithAdjustment(const IntRect& pending_rect,
                                                LocalFrame& frame) {
-  IntRect screen = GetScreenInfo().available_rect;
+  IntRect screen = GetScreenInfo(frame).available_rect;
   IntRect window = pending_rect;
 
   IntSize minimum_size = MinimumWindowSize();
diff --git a/third_party/blink/renderer/core/page/chrome_client.h b/third_party/blink/renderer/core/page/chrome_client.h
index aff7c9a..c4c72923 100644
--- a/third_party/blink/renderer/core/page/chrome_client.h
+++ b/third_party/blink/renderer/core/page/chrome_client.h
@@ -259,7 +259,7 @@
 
   virtual WebViewImpl* GetWebView() const = 0;
 
-  virtual WebScreenInfo GetScreenInfo() const = 0;
+  virtual WebScreenInfo GetScreenInfo(LocalFrame& frame) const = 0;
   virtual void SetCursor(const Cursor&, LocalFrame* local_root) = 0;
 
   virtual void SetCursorOverridden(bool) = 0;
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc
index f5cc527..08ace3f 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -493,10 +493,11 @@
   return viewport_rect.width;
 }
 
-WebScreenInfo ChromeClientImpl::GetScreenInfo() const {
-  if (!web_view_->Client())
-    return {};
-  return web_view_->Client()->GetScreenInfo();
+WebScreenInfo ChromeClientImpl::GetScreenInfo(LocalFrame& frame) const {
+  WebWidgetClient* client =
+      WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget()->Client();
+  DCHECK(client);
+  return client->GetScreenInfo();
 }
 
 void ChromeClientImpl::OverrideVisibleRectForMainFrame(
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.h b/third_party/blink/renderer/core/page/chrome_client_impl.h
index f1784f0..ed65582 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.h
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.h
@@ -126,7 +126,7 @@
                            const LocalFrameView*) const override;
   float WindowToViewportScalar(const float) const override;
   float WindowToViewportScalar(LocalFrame*, const float) const override;
-  WebScreenInfo GetScreenInfo() const override;
+  WebScreenInfo GetScreenInfo(LocalFrame&) const override;
   void OverrideVisibleRectForMainFrame(LocalFrame& frame,
                                        IntRect* paint_rect) const override;
   float InputEventsScaleForEmulation() const override;
diff --git a/third_party/blink/renderer/core/page/drag_controller.cc b/third_party/blink/renderer/core/page/drag_controller.cc
index 9cd4d60..85275af 100644
--- a/third_party/blink/renderer/core/page/drag_controller.cc
+++ b/third_party/blink/renderer/core/page/drag_controller.cc
@@ -1147,7 +1147,7 @@
 
 // static
 std::unique_ptr<DragImage> DragController::DragImageForSelection(
-    const LocalFrame& frame,
+    LocalFrame& frame,
     float opacity) {
   if (!frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated().IsRange())
     return nullptr;
@@ -1244,7 +1244,7 @@
                                  src->GetPage()->GetVisualViewport().Scale());
 
       float screen_device_scale_factor =
-          src->GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;
+          src->GetChromeClient().GetScreenInfo(*src).device_scale_factor;
       // Pass the selected image size in DIP becasue dragImageForImage clips the
       // image in DIP.  The coordinates of the locations are in Viewport
       // coordinates, and they're converted in the Blink client.
@@ -1281,7 +1281,7 @@
     if (!drag_image) {
       DCHECK(src->GetPage());
       float screen_device_scale_factor =
-          src->GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;
+          src->GetChromeClient().GetScreenInfo(*src).device_scale_factor;
       drag_image = DragImageForLink(link_url, hit_test_result.TextContent(),
                                     screen_device_scale_factor);
       drag_location = DragLocationForLink(drag_image.get(), mouse_dragged_point,
@@ -1328,7 +1328,7 @@
   if (image) {
     float resolution_scale = image->ResolutionScale();
     float device_scale_factor =
-        page_->GetChromeClient().GetScreenInfo().device_scale_factor;
+        frame->GetChromeClient().GetScreenInfo(*frame).device_scale_factor;
     if (device_scale_factor != resolution_scale) {
       DCHECK_GT(resolution_scale, 0);
       float scale = device_scale_factor / resolution_scale;
diff --git a/third_party/blink/renderer/core/page/drag_controller.h b/third_party/blink/renderer/core/page/drag_controller.h
index 626b42cd..daeed24 100644
--- a/third_party/blink/renderer/core/page/drag_controller.h
+++ b/third_party/blink/renderer/core/page/drag_controller.h
@@ -84,8 +84,7 @@
 
   DragState& GetDragState();
 
-  static std::unique_ptr<DragImage> DragImageForSelection(const LocalFrame&,
-                                                          float);
+  static std::unique_ptr<DragImage> DragImageForSelection(LocalFrame&, float);
 
   // Return the selection bounds in absolute coordinates for the frame, clipped
   // to the visual viewport.
diff --git a/third_party/blink/renderer/core/page/touch_adjustment.cc b/third_party/blink/renderer/core/page/touch_adjustment.cc
index dfd2d50..bd943ba 100644
--- a/third_party/blink/renderer/core/page/touch_adjustment.cc
+++ b/third_party/blink/renderer/core/page/touch_adjustment.cc
@@ -518,10 +518,11 @@
       subtargets, touch_adjustment::HybridDistanceFunction);
 }
 
-LayoutSize GetHitTestRectForAdjustment(const LocalFrame& frame,
+LayoutSize GetHitTestRectForAdjustment(LocalFrame& frame,
                                        const LayoutSize& touch_area) {
+  ChromeClient& chrome_client = frame.GetChromeClient();
   float device_scale_factor =
-      frame.GetPage()->GetChromeClient().GetScreenInfo().device_scale_factor;
+      chrome_client.GetScreenInfo(frame).device_scale_factor;
   // Check if zoom-for-dsf is enabled. If not, touch_area is in dip, so we don't
   // need to convert max_size_in_dip to physical pixel.
   if (frame.GetPage()->DeviceScaleFactorDeprecated() != 1)
diff --git a/third_party/blink/renderer/core/page/touch_adjustment.h b/third_party/blink/renderer/core/page/touch_adjustment.h
index 8b85a88..6134ac9 100644
--- a/third_party/blink/renderer/core/page/touch_adjustment.h
+++ b/third_party/blink/renderer/core/page/touch_adjustment.h
@@ -49,8 +49,7 @@
 // touch_area is in root frame coordinates, which is in physical pixel when
 // zoom-for-dsf is enabled, otherwise in dip (when page scale is 1).
 CORE_EXPORT LayoutSize
-GetHitTestRectForAdjustment(const LocalFrame& frame,
-                            const LayoutSize& touch_area);
+GetHitTestRectForAdjustment(LocalFrame& frame, const LayoutSize& touch_area);
 
 struct TouchAdjustmentResult {
   uint32_t unique_event_id;
diff --git a/third_party/blink/renderer/core/page/touch_adjustment_test.cc b/third_party/blink/renderer/core/page/touch_adjustment_test.cc
index 47ca38f..ff53ce8 100644
--- a/third_party/blink/renderer/core/page/touch_adjustment_test.cc
+++ b/third_party/blink/renderer/core/page/touch_adjustment_test.cc
@@ -12,15 +12,17 @@
 
 namespace {
 
-class MockChromeClient : public RenderingTestChromeClient {
+class FakeChromeClient : public RenderingTestChromeClient {
  public:
-  MockChromeClient() = default;
+  FakeChromeClient() = default;
 
   void SetDeviceScaleFactor(float device_scale_factor) {
     screen_info_.device_scale_factor = device_scale_factor;
   }
 
-  WebScreenInfo GetScreenInfo() const override { return screen_info_; }
+  WebScreenInfo GetScreenInfo(LocalFrame&) const override {
+    return screen_info_;
+  }
 
  private:
   WebScreenInfo screen_info_;
@@ -32,11 +34,11 @@
  protected:
   TouchAdjustmentTest()
       : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()),
-        chrome_client_(MakeGarbageCollected<MockChromeClient>()) {}
+        chrome_client_(MakeGarbageCollected<FakeChromeClient>()) {}
 
   LocalFrame& GetFrame() const { return *GetDocument().GetFrame(); }
 
-  MockChromeClient& GetChromeClient() const override { return *chrome_client_; }
+  FakeChromeClient& GetChromeClient() const override { return *chrome_client_; }
 
   void SetZoomAndScale(float device_scale_factor,
                        float browser_zoom_factor,
@@ -53,7 +55,7 @@
   const LayoutSize min_touch_area_dip_unscaled = LayoutSize(20, 20);
 
  private:
-  Persistent<MockChromeClient> chrome_client_;
+  Persistent<FakeChromeClient> chrome_client_;
 
   float device_scale_factor_;
   float page_scale_factor_;
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
index d361d785a..fc15680d 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -245,7 +245,6 @@
                           owning_layer_.GetSquashingDisallowedReasons());
 
   graphics_layer_->SetHitTestable(true);
-  UpdateTransform(GetLayoutObject().StyleRef());
 }
 
 void CompositedLayerMapping::DestroyGraphicsLayers() {
@@ -260,22 +259,6 @@
   scrolling_contents_layer_ = nullptr;
 }
 
-void CompositedLayerMapping::UpdateTransform(const ComputedStyle& style) {
-  // FIXME: This could use m_owningLayer.transform(), but that currently has
-  // transform-origin baked into it, and we don't want that.
-  TransformationMatrix t;
-  if (owning_layer_.HasTransformRelatedProperty()) {
-    style.ApplyTransform(
-        t, LayoutSize(ToLayoutBox(GetLayoutObject()).PixelSnappedSize()),
-        ComputedStyle::kExcludeTransformOrigin,
-        ComputedStyle::kIncludeMotionPath,
-        ComputedStyle::kIncludeIndependentTransformProperties);
-    MakeMatrixRenderable(t, Compositor()->HasAcceleratedCompositing());
-  }
-
-  graphics_layer_->SetTransform(t);
-}
-
 void CompositedLayerMapping::UpdateBackgroundPaintsOntoScrollingContentsLayer(
     bool& invalidate_graphics_layer,
     bool& invalidate_scrolling_contents_layer) {
@@ -811,11 +794,6 @@
   DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
             DocumentLifecycle::kInCompositingUpdate);
 
-  // Set transform property, if it is not animating. We have to do this here
-  // because the transform is affected by the layer dimensions.
-  if (!GetLayoutObject().StyleRef().IsRunningTransformAnimationOnCompositor())
-    UpdateTransform(GetLayoutObject().StyleRef());
-
   IntRect local_compositing_bounds;
   IntRect relative_compositing_bounds;
   PhysicalOffset offset_from_composited_ancestor;
@@ -843,8 +821,6 @@
       layers_needing_paint_invalidation);
 
   UpdateMaskLayerGeometry();
-  UpdateTransformGeometry(snapped_offset_from_composited_ancestor,
-                          relative_compositing_bounds);
   // TODO(yigu): Currently the decoration layer uses the same contentSize
   // as the foreground layer. There are scenarios where the sizes could be
   // different so the decoration layer size should be calculated separately.
@@ -1013,37 +989,6 @@
       graphics_layer_->OffsetFromLayoutObject());
 }
 
-void CompositedLayerMapping::UpdateTransformGeometry(
-    const IntPoint& snapped_offset_from_composited_ancestor,
-    const IntRect& relative_compositing_bounds) {
-  if (owning_layer_.HasTransformRelatedProperty()) {
-    const LayoutRect border_box =
-        ToLayoutBox(GetLayoutObject()).BorderBoxRect();
-
-    // Get layout bounds in the coords of compositingContainer to match
-    // relativeCompositingBounds.
-    IntRect layer_bounds = PixelSnappedIntRect(
-        PhysicalRect(owning_layer_.SubpixelAccumulation(), border_box.Size()));
-    layer_bounds.MoveBy(snapped_offset_from_composited_ancestor);
-
-    // Update properties that depend on layer dimensions
-    FloatPoint3D transform_origin =
-        ComputeTransformOrigin(IntRect(IntPoint(), layer_bounds.Size()));
-
-    // |transformOrigin| is in the local space of this layer.
-    // layerBounds - relativeCompositingBounds converts to the space of the
-    // compositing bounds relative to the composited ancestor. This does not
-    // apply to the z direction, since the page is 2D.
-    FloatPoint3D composited_transform_origin(
-        layer_bounds.X() - relative_compositing_bounds.X() +
-            transform_origin.X(),
-        layer_bounds.Y() - relative_compositing_bounds.Y() +
-            transform_origin.Y(),
-        transform_origin.Z());
-    graphics_layer_->SetTransformOrigin(composited_transform_origin);
-  }
-}
-
 void CompositedLayerMapping::UpdateScrollingLayerGeometry(
     const IntRect& local_compositing_bounds) {
   if (!scrolling_layer_)
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
index d3be8cd..40e89258 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
@@ -323,9 +323,6 @@
       IntPoint graphics_layer_parent_location);
   void UpdateChildTransformLayerGeometry();
   void UpdateMaskLayerGeometry();
-  void UpdateTransformGeometry(
-      const IntPoint& snapped_offset_from_composited_ancestor,
-      const IntRect& relative_compositing_bounds);
   void UpdateForegroundLayerGeometry();
   void UpdateDecorationOutlineLayerGeometry(
       const IntSize& relative_compositing_bounds_size);
diff --git a/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc b/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
index 41ee0bd..3808d616 100644
--- a/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
+++ b/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
@@ -32,18 +32,6 @@
   return FloatPoint();
 }
 
-// For kOutputAsLayerTree only.
-void AddTransformJSONProperties(const GraphicsLayer* layer, JSONObject& json) {
-  const TransformationMatrix& transform = layer->Transform();
-  if (!transform.IsIdentity())
-    json.SetArray("transform", TransformAsJSONArray(transform));
-
-  if (!transform.IsIdentityOrTranslation()) {
-    json.SetArray("origin",
-                  PointAsJSONArray(FloatPoint3D(layer->TransformOrigin())));
-  }
-}
-
 std::unique_ptr<JSONObject> GraphicsLayerAsJSON(
     const GraphicsLayer* layer,
     LayerTreeFlags flags,
@@ -92,9 +80,6 @@
                     Color(layer->BackgroundColor()).NameForLayoutTreeAsText());
   }
 
-  if (flags & kOutputAsLayerTree)
-    AddTransformJSONProperties(layer, *json);
-
   FloatPoint scroll_position(ScrollPosition(*layer));
   if (scroll_position != FloatPoint())
     json->SetArray("scrollPosition", PointAsJSONArray(scroll_position));
diff --git a/third_party/blink/renderer/core/svg/animation/smil_time.h b/third_party/blink/renderer/core/svg/animation/smil_time.h
index e24cb72..d317626c 100644
--- a/third_party/blink/renderer/core/svg/animation/smil_time.h
+++ b/third_party/blink/renderer/core/svg/animation/smil_time.h
@@ -70,10 +70,10 @@
     return base::TimeDelta::FromMicroseconds(1);
   }
   static constexpr SMILTime FromSecondsD(double seconds) {
-    return base::TimeDelta::FromSecondsD(seconds);
+    return std::min(SMILTime(base::TimeDelta::FromSecondsD(seconds)), Latest());
   }
   static constexpr SMILTime FromMicroseconds(int64_t us) {
-    return base::TimeDelta::FromMicroseconds(us);
+    return std::min(SMILTime(base::TimeDelta::FromMicroseconds(us)), Latest());
   }
 
   // Used for computing progress. Don't use for anything else.
diff --git a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
index f903048..aee2de6c 100644
--- a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
+++ b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
@@ -321,10 +321,7 @@
     result = parse.ToDouble(&ok);
   if (!ok)
     return SMILTime::Unresolved();
-  SMILTime offset_value = SMILTime::FromSecondsD(result);
-  if (!offset_value.IsFinite())
-    return SMILTime::Unresolved();
-  return offset_value;
+  return SMILTime::FromSecondsD(result);
 }
 
 SMILTime SVGSMILElement::ParseClockValue(const String& data) {
@@ -361,10 +358,7 @@
 
   if (!ok)
     return SMILTime::Unresolved();
-  SMILTime clock_value = SMILTime::FromSecondsD(result);
-  if (!clock_value.IsFinite())
-    return SMILTime::Unresolved();
-  return clock_value;
+  return SMILTime::FromSecondsD(result);
 }
 
 bool SVGSMILElement::ParseCondition(const String& value,
diff --git a/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityNodeView.js b/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityNodeView.js
index 6c2d58f7..26862da 100644
--- a/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityNodeView.js
+++ b/third_party/blink/renderer/devtools/front_end/accessibility/AccessibilityNodeView.js
@@ -18,6 +18,7 @@
 
     this.element.classList.add('accessibility-computed');
     this.registerRequiredCSS('accessibility/accessibilityNode.css');
+    this._treeOutline.setFocusable(true);
   }
 
   /**
@@ -94,6 +95,11 @@
     for (const property of /** @type {!Array.<!Protocol.Accessibility.AXProperty>} */ (axNode.properties())) {
       addProperty(property);
     }
+
+    const firstNode = treeOutline.firstChild();
+    if (firstNode) {
+      firstNode.select(/* omitFocus= */ true, /* selectedByUser= */ false);
+    }
   }
 
   /**
@@ -280,7 +286,6 @@
 
     this._property = property;
     this.toggleOnClick = true;
-    this.selectable = false;
 
     this.listItemElement.classList.add('property');
   }
@@ -314,7 +319,6 @@
   constructor(source, axNode) {
     super(axNode);
     this._source = source;
-    this.selectable = false;
   }
 
   /**
@@ -479,7 +483,7 @@
 
     this._value = value;
     this._axRelatedNodeElement = new Accessibility.AXRelatedNodeElement(node, value);
-    this.selectable = false;
+    this.selectable = true;
   }
 
   /**
@@ -496,6 +500,14 @@
           Protocol.Accessibility.AXValueType.ComputedString, this._value.text));
     }
   }
+
+  /**
+   * @override
+   */
+  onenter() {
+    this._axRelatedNodeElement.revealNode();
+    return true;
+  }
 };
 
 /**
@@ -535,6 +547,13 @@
 
     return element;
   }
+
+  /**
+   * Attempts to cause the node referred to by the related node to be selected in the tree.
+   */
+  revealNode() {
+    this._deferredNode.resolvePromise().then(node => Common.Revealer.reveal(node));
+  }
 };
 
 /**
diff --git a/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js b/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js
index 18f0729..32acbdb 100644
--- a/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js
+++ b/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js
@@ -317,6 +317,7 @@
     for (let i = 0; i < palette.colors.length; i++) {
       const animationDelay = animate ? i * 100 / palette.colors.length : 0;
       const colorElement = this._createPaletteColor(palette.colors[i], palette.colorNames[i], animationDelay);
+      colorElement.tabIndex = -1;
       colorElement.addEventListener(
           'mousedown',
           this._paletteColorSelected.bind(this, palette.colors[i], palette.colorNames[i], palette.matchUserFormat));
@@ -627,6 +628,8 @@
     palette.colors.push(this.colorString());
     this._customPaletteSetting.set(palette);
     this._showPalette(this._customPaletteSetting.get(), false);
+    const colorElements = this._paletteContainer.querySelectorAll('.spectrum-palette-color');
+    colorElements[colorElements.length - 1].focus();
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/color_picker/spectrum.css b/third_party/blink/renderer/devtools/front_end/color_picker/spectrum.css
index 3373b42..59978d1 100644
--- a/third_party/blink/renderer/devtools/front_end/color_picker/spectrum.css
+++ b/third_party/blink/renderer/devtools/front_end/color_picker/spectrum.css
@@ -424,6 +424,11 @@
     border-color: transparent;
 }
 
+.spectrum-palette-color:not(.has-material-shades):focus {
+  border: 1px solid var(--accent-color-hover);
+  transform: scale(1.4);
+}
+
 .spectrum-palette > .spectrum-palette-color:not(.empty-color):not(.has-material-shades):hover,
 .palette-color-shades > .spectrum-palette-color:not(.empty-color):hover {
     transform: scale(1.15);
diff --git a/third_party/blink/renderer/devtools/front_end/elements/PropertiesWidget.js b/third_party/blink/renderer/devtools/front_end/elements/PropertiesWidget.js
index b6c3e4e..186227f 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/PropertiesWidget.js
+++ b/third_party/blink/renderer/devtools/front_end/elements/PropertiesWidget.js
@@ -43,6 +43,16 @@
         SDK.DOMModel, SDK.DOMModel.Events.ChildNodeCountUpdated, this._onNodeChange, this);
     UI.context.addFlavorChangeListener(SDK.DOMNode, this._setNode, this);
     this._node = UI.context.flavor(SDK.DOMNode);
+
+    this._treeOutline = new ObjectUI.ObjectPropertiesSectionsTreeOutline({readOnly: true});
+    this._treeOutline.setShowSelectionOnKeyboardFocus(/* show */ true, /* preventTabOrder */ false);
+    this._expandController = new ObjectUI.ObjectPropertiesSectionsTreeExpandController(this._treeOutline);
+    this.contentElement.appendChild(this._treeOutline.element);
+
+    this._treeOutline.addEventListener(UI.TreeOutline.Events.ElementExpanded, () => {
+      Host.userMetrics.actionTaken(Host.UserMetrics.Action.DOMPropertiesExpanded);
+    });
+
     this.update();
   }
 
@@ -67,7 +77,6 @@
 
     if (!this._node) {
       this.contentElement.removeChildren();
-      this.sections = [];
       return;
     }
 
@@ -92,15 +101,9 @@
     }
 
     const properties = propertiesResult.properties;
-    const expanded = [];
-    const sections = this.sections || [];
-    for (let i = 0; i < sections.length; ++i) {
-      expanded.push(sections[i].expanded);
-    }
+    this._treeOutline.removeChildren();
 
-    this.contentElement.removeChildren();
-    this.sections = [];
-
+    let selected = false;
     // Get array of property user-friendly names.
     for (let i = 0; i < properties.length; ++i) {
       if (!parseInt(properties[i].name, 10)) {
@@ -109,14 +112,13 @@
       const property = properties[i].value;
       let title = property.description;
       title = title.replace(/Prototype$/, '');
-      const section = new ObjectUI.ObjectPropertiesSection(property, title);
-      section.element.classList.add('properties-widget-section');
-      this.sections.push(section);
-      this.contentElement.appendChild(section.element);
-      if (expanded[this.sections.length - 1]) {
-        section.expand();
+
+      const section = this._createSectionTreeElement(property, title);
+      this._treeOutline.appendChild(section);
+      if (!selected) {
+        section.select(/* omitFocus= */ true, /* selectedByUser= */ false);
+        selected = true;
       }
-      section.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._propertyExpanded, this);
     }
 
     /**
@@ -136,13 +138,19 @@
   }
 
   /**
-   * @param {!Common.Event} event
+   * @param {!SDK.RemoteObject} property
+   * @param {string} title
+   * @returns {!ObjectUI.ObjectPropertiesSection.RootElement}
    */
-  _propertyExpanded(event) {
-    Host.userMetrics.actionTaken(Host.UserMetrics.Action.DOMPropertiesExpanded);
-    for (const section of this.sections) {
-      section.removeEventListener(UI.TreeOutline.Events.ElementExpanded, this._propertyExpanded, this);
-    }
+  _createSectionTreeElement(property, title) {
+    const titleElement = createElementWithClass('span', 'tree-element-title');
+    titleElement.textContent = title;
+
+    const section = new ObjectUI.ObjectPropertiesSection.RootElement(property);
+    section.title = titleElement;
+    this._expandController.watchSection(title, section);
+
+    return section;
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
index 37758fe..a5d90213 100644
--- a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
+++ b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
@@ -468,13 +468,22 @@
 ObjectUI.ObjectPropertiesSection._arrayLoadThreshold = 100;
 /** @const */
 ObjectUI.ObjectPropertiesSection._maxRenderableStringLength = 10000;
+/**
+ * @typedef {{
+ *   readOnly: (boolean|undefined),
+ * }}
+ */
+ObjectUI.ObjectPropertiesSectionsTreeOutlineOptions;
 
 ObjectUI.ObjectPropertiesSectionsTreeOutline = class extends UI.TreeOutlineInShadow {
-  constructor() {
+  /**
+   * @param {?ObjectUI.ObjectPropertiesSectionsTreeOutlineOptions=} options
+   */
+  constructor(options) {
     super();
     this.registerRequiredCSS('object_ui/objectValue.css');
     this.registerRequiredCSS('object_ui/objectPropertiesSection.css');
-    this._editable = true;
+    this._editable = !(options && options.readOnly);
     this.contentElement.classList.add('source-code');
     this.contentElement.classList.add('object-properties-section');
     this.hideOverflow();
diff --git a/third_party/blink/renderer/devtools/front_end/perf_ui/OverviewGrid.js b/third_party/blink/renderer/devtools/front_end/perf_ui/OverviewGrid.js
index d59e668d..a9e224f 100644
--- a/third_party/blink/renderer/devtools/front_end/perf_ui/OverviewGrid.js
+++ b/third_party/blink/renderer/devtools/front_end/perf_ui/OverviewGrid.js
@@ -138,6 +138,8 @@
 
 PerfUI.OverviewGrid.ResizerOffset = 3.5;  // half pixel because offset values are not rounded but ceiled
 
+PerfUI.OverviewGrid.OffsetFromWindowEnds = 10;
+
 /**
  * @unrestricted
  */
@@ -172,11 +174,23 @@
         this._rightResizeElement, this._resizerElementStartDragging.bind(this),
         this._rightResizeElementDragging.bind(this), null, 'ew-resize');
 
+    this._leftResizeElement.tabIndex = 0;
+    this._leftResizeElement.addEventListener('keydown', event => this._handleKeyboardResizing(event, false));
+
+    this._rightResizeElement.tabIndex = 0;
+    this._rightResizeElement.addEventListener('keydown', event => this._handleKeyboardResizing(event, true));
+    this._rightResizeElement.addEventListener('focus', this._onRightResizeElementFocused.bind(this));
+
     this._leftCurtainElement = parentElement.createChild('div', 'window-curtain-left');
     this._rightCurtainElement = parentElement.createChild('div', 'window-curtain-right');
     this.reset();
   }
 
+  _onRightResizeElementFocused() {
+    // To prevent browser focus from scrolling the element into view and shifting the contents of the strip
+    this._parentElement.scrollLeft = 0;
+  }
+
   reset() {
     this.windowLeft = 0.0;
     this.windowRight = 1.0;
@@ -228,6 +242,50 @@
 
   /**
    * @param {!Event} event
+   * @param {boolean=} moveRightResizer
+   */
+  _handleKeyboardResizing(event, moveRightResizer) {
+    let increment = false;
+    if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
+      if (event.key === 'ArrowRight') {
+        increment = true;
+      }
+      const newPos = this._getNewResizerPosition(event.target.offsetLeft, increment, event.ctrlKey);
+      if (moveRightResizer) {
+        this._resizeWindowRight(newPos);
+      } else {
+        this._resizeWindowLeft(newPos);
+      }
+      event.consume(true);
+    }
+  }
+
+  /**
+   * @param {number} offset
+   * @param {boolean=} increment
+   * @param {boolean=} ctrlPressed
+   * @return {number}
+   */
+  _getNewResizerPosition(offset, increment, ctrlPressed) {
+    let newPos;
+    // We shift by 10px if the ctrlKey is pressed and 2 otherwise.  1px shifts result in noOp due to rounding in _updateCurtains
+    let pixelsToShift = ctrlPressed ? 10 : 2;
+    pixelsToShift = increment ? pixelsToShift : -Math.abs(pixelsToShift);
+    const offsetLeft = offset + PerfUI.OverviewGrid.ResizerOffset;
+    newPos = offsetLeft + pixelsToShift;
+    if (increment && newPos < PerfUI.OverviewGrid.OffsetFromWindowEnds) {
+      // When incrementing, snap to the window offset value (10px) if the new position is between 0px and 10px
+      newPos = PerfUI.OverviewGrid.OffsetFromWindowEnds;
+    } else if (!increment && newPos > this._parentElement.clientWidth - PerfUI.OverviewGrid.OffsetFromWindowEnds) {
+      // When decrementing, snap to the window offset value (10px) from the rightmost side if the new position is within 10px from the end.
+      newPos = this._parentElement.clientWidth - PerfUI.OverviewGrid.OffsetFromWindowEnds;
+    }
+
+    return newPos;
+  }
+
+  /**
+   * @param {!Event} event
    * @return {boolean}
    */
   _startWindowSelectorDragging(event) {
@@ -306,7 +364,7 @@
    */
   _resizeWindowLeft(start) {
     // Glue to edge.
-    if (start < 10) {
+    if (start < PerfUI.OverviewGrid.OffsetFromWindowEnds) {
       start = 0;
     } else if (start > this._rightResizeElement.offsetLeft - 4) {
       start = this._rightResizeElement.offsetLeft - 4;
@@ -319,7 +377,7 @@
    */
   _resizeWindowRight(end) {
     // Glue to edge.
-    if (end > this._parentElement.clientWidth - 10) {
+    if (end > this._parentElement.clientWidth - PerfUI.OverviewGrid.OffsetFromWindowEnds) {
       end = this._parentElement.clientWidth;
     } else if (end < this._leftResizeElement.offsetLeft + PerfUI.OverviewGrid.MinSelectableSize) {
       end = this._leftResizeElement.offsetLeft + PerfUI.OverviewGrid.MinSelectableSize;
@@ -347,13 +405,16 @@
     let right = this.windowRight;
     const width = right - left;
 
-    // We allow actual time window to be arbitrarily small but don't want the UI window to be too small.
-    const widthInPixels = width * this._parentElement.clientWidth;
-    const minWidthInPixels = PerfUI.OverviewGrid.MinSelectableSize / 2;
-    if (widthInPixels < minWidthInPixels) {
-      const factor = minWidthInPixels / widthInPixels;
-      left = ((this.windowRight + this.windowLeft) - width * factor) / 2;
-      right = ((this.windowRight + this.windowLeft) + width * factor) / 2;
+    // OverviewGrids that are instantiated before the parentElement is shown will have a parent element client width of 0 which throws off the 'factor' calculation
+    if (this._parentElement.clientWidth !== 0) {
+      // We allow actual time window to be arbitrarily small but don't want the UI window to be too small.
+      const widthInPixels = width * this._parentElement.clientWidth;
+      const minWidthInPixels = PerfUI.OverviewGrid.MinSelectableSize / 2;
+      if (widthInPixels < minWidthInPixels) {
+        const factor = minWidthInPixels / widthInPixels;
+        left = ((this.windowRight + this.windowLeft) - width * factor) / 2;
+        right = ((this.windowRight + this.windowLeft) + width * factor) / 2;
+      }
     }
     this._leftResizeElement.style.left = (100 * left).toFixed(2) + '%';
     this._rightResizeElement.style.left = (100 * right).toFixed(2) + '%';
diff --git a/third_party/blink/renderer/devtools/front_end/perf_ui/overviewGrid.css b/third_party/blink/renderer/devtools/front_end/perf_ui/overviewGrid.css
index fd09baf..3cb840c 100644
--- a/third_party/blink/renderer/devtools/front_end/perf_ui/overviewGrid.css
+++ b/third_party/blink/renderer/devtools/front_end/perf_ui/overviewGrid.css
@@ -24,6 +24,10 @@
     z-index: 500;
 }
 
+.overview-grid-window-resizer[data-keyboard-focus="true"]:focus {
+    background-color: var(--active-control-bg-color);
+}
+
 .overview-grid-cursor-area {
     position: absolute;
     left: 0;
diff --git a/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js b/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
index 3da09be9..b27b0540 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
+++ b/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
@@ -493,6 +493,7 @@
     super(createElementWithClass('button', 'toolbar-button'));
     this.element.addEventListener('click', this._clicked.bind(this), false);
     this.element.addEventListener('mousedown', this._mouseDown.bind(this), false);
+    this.element.addEventListener('keydown', this._keydown.bind(this), false);
 
     this._glyphElement = UI.Icon.create('', 'toolbar-glyph hidden');
     this.element.appendChild(this._glyphElement);
@@ -568,6 +569,16 @@
   /**
    * @param {!Event} event
    */
+  _keydown(event) {
+    if (!this._enabled)
+      return;
+    this.dispatchEventToListeners(UI.ToolbarButton.Events.KeyDown, event);
+    event.consume();
+  }
+
+  /**
+   * @param {!Event} event
+   */
   _mouseDown(event) {
     if (!this._enabled) {
       return;
@@ -578,6 +589,7 @@
 
 ToolbarButton.Events = {
   Click: Symbol('Click'),
+  KeyDown: Symbol('KeyDown'),
   MouseDown: Symbol('MouseDown')
 };
 
diff --git a/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css b/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css
index df31c93..5f07efe 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css
+++ b/third_party/blink/renderer/devtools/front_end/ui/inspectorStyle.css
@@ -36,6 +36,7 @@
     --accent-color: #1a73e8;
     --accent-fg-color: #1a73e8;
     --accent-color-hover: #3b86e8;
+    --active-control-bg-color: #5a5a5a;
     --focus-bg-color: hsl(214, 40%, 92%);
     --toolbar-bg-color: #f3f3f3;
     --toolbar-hover-bg-color: #eaeaea;
@@ -57,6 +58,7 @@
     --accent-color: #0e639c;
     --accent-fg-color: #cccccc;
     --accent-color-hover: rgb(17, 119, 187);
+    --active-control-bg-color: #cdcdcd;
     --focus-bg-color: hsl(214, 19%, 27%);
     --toolbar-bg-color: #333333;
     --toolbar-hover-bg-color: #202020;
diff --git a/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextSelector.js b/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextSelector.js
index 2ae61c0..047b4457 100644
--- a/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextSelector.js
+++ b/third_party/blink/renderer/devtools/front_end/web_audio/AudioContextSelector.js
@@ -61,8 +61,7 @@
     const changedContext = /** @type {!Protocol.WebAudio.BaseAudioContext} */ (event.data);
     const contextIndex = this._items.findIndex(context => context.contextId === changedContext.contextId);
     if (contextIndex > -1) {
-      this._items.remove(contextIndex);
-      this._items.insert(contextIndex, changedContext);
+      this._items.replace(contextIndex, changedContext);
 
       // If the changed context is currently selected by user. Re-select it
       // because the actual element is replaced with a new one.
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 0044f51..cc7b5c2 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -381,6 +381,8 @@
     "peerconnection/adapters/quic_packet_transport_adapter_test.cc",
     "peerconnection/byte_buffer_queue_test.cc",
     "peerconnection/call_setup_state_tracker_unittest.cc",
+    "peerconnection/media_stream_remote_video_source_test.cc",
+    "peerconnection/media_stream_video_webrtc_sink_test.cc",
     "peerconnection/rtc_data_channel_test.cc",
     "peerconnection/rtc_ice_transport_test.cc",
     "peerconnection/rtc_ice_transport_test.h",
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection.cc b/third_party/blink/renderer/modules/accessibility/ax_selection.cc
index b7166cb..02efbea 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_selection.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_selection.cc
@@ -156,6 +156,9 @@
       *ax_text_control, static_cast<int>(text_control.selectionEnd()),
       extent_affinity);
 
+  if (!ax_base.IsValid() || !ax_extent.IsValid())
+    return {};
+
   AXSelection::Builder selection_builder;
   selection_builder.SetBase(ax_base).SetExtent(ax_extent);
   return selection_builder.Build();
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc
index e691c1b..45a2ca0 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc
@@ -62,10 +62,10 @@
 
 namespace {
 
-class MockChromeClientForImpl : public EmptyChromeClient {
+class FakeChromeClient : public EmptyChromeClient {
  public:
-  // EmptyChromeClient overrides:
-  WebScreenInfo GetScreenInfo() const override {
+  // ChromeClient overrides.
+  WebScreenInfo GetScreenInfo(LocalFrame&) const override {
     WebScreenInfo screen_info;
     screen_info.orientation_type = kWebScreenOrientationLandscapePrimary;
     return screen_info;
@@ -171,7 +171,7 @@
   void InitializePage() {
     Page::PageClients clients;
     FillWithEmptyClients(clients);
-    clients.chrome_client = MakeGarbageCollected<MockChromeClientForImpl>();
+    clients.chrome_client = MakeGarbageCollected<FakeChromeClient>();
     SetupPageWithClients(&clients,
                          MakeGarbageCollected<StubLocalFrameClientForImpl>());
 
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
index a3ad5315..f2b7505 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
@@ -293,11 +293,12 @@
   // consistency. Use WebScreenOrientationLockLandscape as a fallback value.
   // TODO(mlamouri): we could improve this by having direct access to
   // `window.screen.orientation.type`.
-  Frame* frame = GetDocument().GetFrame();
+  LocalFrame* frame = GetDocument().GetFrame();
   if (!frame)
     return kWebScreenOrientationLockLandscape;
 
-  switch (frame->GetChromeClient().GetScreenInfo().orientation_type) {
+  ChromeClient& chrome_client = frame->GetChromeClient();
+  switch (chrome_client.GetScreenInfo(*frame).orientation_type) {
     case kWebScreenOrientationPortraitPrimary:
     case kWebScreenOrientationPortraitSecondary:
       return kWebScreenOrientationLockPortrait;
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
index 4e5c0360..42327ab4 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
@@ -131,7 +131,7 @@
         WTF::Bind(DidExitFullscreen, WrapPersistent(frame.GetDocument())));
   }
 
-  MOCK_CONST_METHOD0(GetScreenInfo, WebScreenInfo());
+  MOCK_CONST_METHOD1(GetScreenInfo, WebScreenInfo(LocalFrame&));
 
   MockScreenOrientation& ScreenOrientationClient() {
     return mock_screen_orientation_;
@@ -373,7 +373,7 @@
                     screen_info.rect, screen_info.orientation_angle));
 
     testing::Mock::VerifyAndClearExpectations(&ChromeClient());
-    EXPECT_CALL(ChromeClient(), GetScreenInfo())
+    EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
         .Times(AtLeast(1))
         .WillRepeatedly(Return(screen_info));
 
@@ -589,31 +589,31 @@
   // 100x100 has more subtilities, it depends on the current screen orientation.
   WebScreenInfo screen_info;
   screen_info.orientation_type = kWebScreenOrientationUndefined;
-  EXPECT_CALL(ChromeClient(), GetScreenInfo())
+  EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
       .Times(1)
       .WillOnce(Return(screen_info));
   EXPECT_EQ(kWebScreenOrientationLockLandscape, ComputeOrientationLock());
 
   screen_info.orientation_type = kWebScreenOrientationPortraitPrimary;
-  EXPECT_CALL(ChromeClient(), GetScreenInfo())
+  EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
       .Times(1)
       .WillOnce(Return(screen_info));
   EXPECT_EQ(kWebScreenOrientationLockPortrait, ComputeOrientationLock());
 
   screen_info.orientation_type = kWebScreenOrientationPortraitPrimary;
-  EXPECT_CALL(ChromeClient(), GetScreenInfo())
+  EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
       .Times(1)
       .WillOnce(Return(screen_info));
   EXPECT_EQ(kWebScreenOrientationLockPortrait, ComputeOrientationLock());
 
   screen_info.orientation_type = kWebScreenOrientationLandscapePrimary;
-  EXPECT_CALL(ChromeClient(), GetScreenInfo())
+  EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
       .Times(1)
       .WillOnce(Return(screen_info));
   EXPECT_EQ(kWebScreenOrientationLockLandscape, ComputeOrientationLock());
 
   screen_info.orientation_type = kWebScreenOrientationLandscapeSecondary;
-  EXPECT_CALL(ChromeClient(), GetScreenInfo())
+  EXPECT_CALL(ChromeClient(), GetScreenInfo(_))
       .Times(1)
       .WillOnce(Return(screen_info));
   EXPECT_EQ(kWebScreenOrientationLockLandscape, ComputeOrientationLock());
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
index bb12a4a..6188026 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate.cc
@@ -270,11 +270,11 @@
 
 MediaControlsRotateToFullscreenDelegate::SimpleOrientation
 MediaControlsRotateToFullscreenDelegate::ComputeScreenOrientation() const {
-  Frame* frame = video_element_->GetDocument().GetFrame();
+  LocalFrame* frame = video_element_->GetDocument().GetFrame();
   if (!frame)
     return SimpleOrientation::kUnknown;
 
-  switch (frame->GetChromeClient().GetScreenInfo().orientation_type) {
+  switch (frame->GetChromeClient().GetScreenInfo(*frame).orientation_type) {
     case kWebScreenOrientationPortraitPrimary:
     case kWebScreenOrientationPortraitSecondary:
       return SimpleOrientation::kPortrait;
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc
index cfe9298..1db7eaaa 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc
@@ -34,6 +34,7 @@
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
+using testing::_;
 using testing::AtLeast;
 using testing::Return;
 
@@ -72,7 +73,7 @@
     Fullscreen::DidExitFullscreen(*frame.GetDocument());
   }
 
-  MOCK_CONST_METHOD0(GetScreenInfo, WebScreenInfo());
+  MOCK_CONST_METHOD1(GetScreenInfo, WebScreenInfo(LocalFrame&));
 };
 
 class StubLocalFrameClient : public EmptyLocalFrameClient {
@@ -191,7 +192,7 @@
   // Set initial screen orientation (called by `Attach` during `AppendChild`).
   WebScreenInfo screen_info;
   screen_info.orientation_type = initial_screen_orientation;
-  EXPECT_CALL(GetChromeClient(), GetScreenInfo())
+  EXPECT_CALL(GetChromeClient(), GetScreenInfo(_))
       .Times(AtLeast(1))
       .WillRepeatedly(Return(screen_info));
 
@@ -232,7 +233,7 @@
   WebScreenInfo screen_info;
   screen_info.orientation_type = new_screen_orientation;
   testing::Mock::VerifyAndClearExpectations(&GetChromeClient());
-  EXPECT_CALL(GetChromeClient(), GetScreenInfo())
+  EXPECT_CALL(GetChromeClient(), GetScreenInfo(_))
       .Times(AtLeast(1))
       .WillRepeatedly(Return(screen_info));
   DispatchEvent(GetWindow(), event_type_names::kOrientationchange);
diff --git a/third_party/blink/renderer/modules/mediastream/BUILD.gn b/third_party/blink/renderer/modules/mediastream/BUILD.gn
index f33987b..dbc9feb 100644
--- a/third_party/blink/renderer/modules/mediastream/BUILD.gn
+++ b/third_party/blink/renderer/modules/mediastream/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/jumbo.gni")
+import("//media/webrtc/audio_processing.gni")
 import("//third_party/blink/renderer/modules/modules.gni")
 
 blink_modules_sources("mediastream") {
@@ -89,6 +90,7 @@
   ]
   deps = [
     "//media/capture/mojom:image_capture_blink",
+    "//media/webrtc",
   ]
 }
 
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc
index f2884c5..1a2a3bd 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.cc
@@ -16,6 +16,7 @@
 #include "media/audio/audio_features.h"
 #include "media/base/audio_parameters.h"
 #include "media/base/limits.h"
+#include "media/webrtc/webrtc_switches.h"
 #include "third_party/blink/public/common/mediastream/media_stream_controls.h"
 #include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_processor_options.h"
 #include "third_party/blink/public/platform/modules/mediastream/media_stream_audio_source.h"
@@ -1011,7 +1012,7 @@
     }
     if (is_reconfiguration_allowed || source_info.type() == SourceType::kNone ||
         source_info.type() == SourceType::kApmProcessed) {
-      if (IsApmInAudioServiceEnabled()) {
+      if (media::IsWebRtcApmInAudioServiceEnabled()) {
         processing_based_containers_.push_back(
             ProcessingBasedContainer::CreateRemoteApmProcessedContainer(
                 source_info, is_device_capture, device_parameters_,
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio_test.cc
index a1028f4..e062b237 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio_test.cc
@@ -1899,7 +1899,7 @@
   constraint_factory_.basic().echo_cancellation.SetExact(true);
   result = SelectSettings();
 
-  if (IsApmInAudioServiceEnabled() && GetParam())
+  if (media::IsWebRtcApmInAudioServiceEnabled() && GetParam())
     EXPECT_FALSE(result.HasValue());
   else
     EXPECT_TRUE(result.HasValue());
@@ -1916,7 +1916,7 @@
   constraint_factory_.basic().echo_cancellation.SetExact(true);
   result = SelectSettings();
 
-  if (IsApmInAudioServiceEnabled() && GetParam())
+  if (media::IsWebRtcApmInAudioServiceEnabled() && GetParam())
     EXPECT_TRUE(result.HasValue());
   else
     EXPECT_FALSE(result.HasValue());
diff --git a/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.cc b/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.cc
index 740459b..2dfc830 100644
--- a/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.cc
+++ b/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.cc
@@ -84,14 +84,6 @@
 }
 }  // namespace
 
-bool IsApmInAudioServiceEnabled() {
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
-  return base::FeatureList::IsEnabled(features::kWebRtcApmInAudioService);
-#else
-  return false;
-#endif
-}
-
 ProcessedLocalAudioSource::ProcessedLocalAudioSource(
     WebLocalFrame* web_frame,
     const blink::MediaStreamDevice& device,
@@ -268,7 +260,7 @@
   DCHECK(params.IsValid());
   media::AudioSourceParameters source_params(device().session_id());
   const bool use_remote_apm =
-      IsApmInAudioServiceEnabled() &&
+      media::IsWebRtcApmInAudioServiceEnabled() &&
       MediaStreamAudioProcessor::WouldModifyAudio(audio_processing_properties_);
   if (use_remote_apm) {
     audio_processor_proxy_ =
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
index 2434c36..054e30c 100644
--- a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
+++ b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
@@ -951,7 +951,8 @@
   gfx::Size screen_size(blink::kDefaultScreenCastWidth,
                         blink::kDefaultScreenCastHeight);
   if (frame_) {  // Can be null in tests.
-    blink::WebScreenInfo info = frame_->GetChromeClient().GetScreenInfo();
+    blink::WebScreenInfo info =
+        frame_->GetChromeClient().GetScreenInfo(*frame_);
     screen_size = gfx::Size(info.rect.width, info.rect.height);
   }
   return screen_size;
diff --git a/third_party/blink/renderer/modules/peerconnection/DEPS b/third_party/blink/renderer/modules/peerconnection/DEPS
index f206842..31dc9c7 100644
--- a/third_party/blink/renderer/modules/peerconnection/DEPS
+++ b/third_party/blink/renderer/modules/peerconnection/DEPS
@@ -23,5 +23,6 @@
 specific_include_rules = {
     ".*test\.cc" : [
         "+base/run_loop.h",
+        "+ui/gfx/color_space.h",
     ],
 }
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
new file mode 100644
index 0000000..38c1327
--- /dev/null
+++ b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
@@ -0,0 +1,234 @@
+// 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 "third_party/blink/public/web/modules/peerconnection/media_stream_remote_video_source.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "media/base/video_frame.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h"
+#include "third_party/blink/public/platform/modules/webrtc/track_observer.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_video_sink.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/public/web/web_heap.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/webrtc/api/video/color_space.h"
+#include "third_party/webrtc/api/video/i420_buffer.h"
+#include "ui/gfx/color_space.h"
+
+namespace blink {
+
+ACTION_P(RunClosure, closure) {
+  closure.Run();
+}
+
+class MediaStreamRemoteVideoSourceUnderTest
+    : public blink::MediaStreamRemoteVideoSource {
+ public:
+  explicit MediaStreamRemoteVideoSourceUnderTest(
+      std::unique_ptr<blink::TrackObserver> observer)
+      : MediaStreamRemoteVideoSource(std::move(observer)) {}
+  using MediaStreamRemoteVideoSource::SinkInterfaceForTesting;
+  using MediaStreamRemoteVideoSource::StartSourceImpl;
+};
+
+class MediaStreamRemoteVideoSourceTest : public ::testing::Test {
+ public:
+  MediaStreamRemoteVideoSourceTest()
+      : mock_factory_(new blink::MockPeerConnectionDependencyFactory()),
+        webrtc_video_track_(blink::MockWebRtcVideoTrack::Create("test")),
+        remote_source_(nullptr),
+        number_of_successful_track_starts_(0),
+        number_of_failed_track_starts_(0) {}
+
+  void SetUp() override {
+    scoped_refptr<base::SingleThreadTaskRunner> main_thread =
+        blink::scheduler::GetSingleThreadTaskRunnerForTesting();
+
+    base::WaitableEvent waitable_event(
+        base::WaitableEvent::ResetPolicy::MANUAL,
+        base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+    std::unique_ptr<blink::TrackObserver> track_observer;
+    mock_factory_->GetWebRtcSignalingThread()->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            [](scoped_refptr<base::SingleThreadTaskRunner> main_thread,
+               webrtc::MediaStreamTrackInterface* webrtc_track,
+               std::unique_ptr<blink::TrackObserver>* track_observer,
+               base::WaitableEvent* waitable_event) {
+              track_observer->reset(
+                  new blink::TrackObserver(main_thread, webrtc_track));
+              waitable_event->Signal();
+            },
+            main_thread, base::Unretained(webrtc_video_track_.get()),
+            base::Unretained(&track_observer),
+            base::Unretained(&waitable_event)));
+    waitable_event.Wait();
+
+    remote_source_ =
+        new MediaStreamRemoteVideoSourceUnderTest(std::move(track_observer));
+    web_source_.Initialize(blink::WebString::FromASCII("dummy_source_id"),
+                           blink::WebMediaStreamSource::kTypeVideo,
+                           blink::WebString::FromASCII("dummy_source_name"),
+                           true /* remote */);
+    web_source_.SetPlatformSource(base::WrapUnique(remote_source_));
+  }
+
+  void TearDown() override {
+    remote_source_->OnSourceTerminated();
+    web_source_.Reset();
+    blink::WebHeap::CollectAllGarbageForTesting();
+  }
+
+  MediaStreamRemoteVideoSourceUnderTest* source() { return remote_source_; }
+
+  blink::MediaStreamVideoTrack* CreateTrack() {
+    bool enabled = true;
+    return new blink::MediaStreamVideoTrack(
+        source(),
+        base::Bind(&MediaStreamRemoteVideoSourceTest::OnTrackStarted,
+                   base::Unretained(this)),
+        enabled);
+  }
+
+  int NumberOfSuccessConstraintsCallbacks() const {
+    return number_of_successful_track_starts_;
+  }
+
+  int NumberOfFailedConstraintsCallbacks() const {
+    return number_of_failed_track_starts_;
+  }
+
+  void StopWebRtcTrack() {
+    base::WaitableEvent waitable_event(
+        base::WaitableEvent::ResetPolicy::MANUAL,
+        base::WaitableEvent::InitialState::NOT_SIGNALED);
+    mock_factory_->GetWebRtcSignalingThread()->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            [](blink::MockWebRtcVideoTrack* video_track,
+               base::WaitableEvent* waitable_event) {
+              video_track->SetEnded();
+              waitable_event->Signal();
+            },
+            base::Unretained(static_cast<blink::MockWebRtcVideoTrack*>(
+                webrtc_video_track_.get())),
+            base::Unretained(&waitable_event)));
+    waitable_event.Wait();
+  }
+
+  const blink::WebMediaStreamSource& webkit_source() const {
+    return web_source_;
+  }
+
+ private:
+  void OnTrackStarted(blink::WebPlatformMediaStreamSource* source,
+                      blink::mojom::MediaStreamRequestResult result,
+                      const blink::WebString& result_name) {
+    ASSERT_EQ(source, remote_source_);
+    if (result == blink::mojom::MediaStreamRequestResult::OK)
+      ++number_of_successful_track_starts_;
+    else
+      ++number_of_failed_track_starts_;
+  }
+
+  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+  std::unique_ptr<blink::MockPeerConnectionDependencyFactory> mock_factory_;
+  scoped_refptr<webrtc::VideoTrackInterface> webrtc_video_track_;
+  // |remote_source_| is owned by |web_source_|.
+  MediaStreamRemoteVideoSourceUnderTest* remote_source_;
+  blink::WebMediaStreamSource web_source_;
+  int number_of_successful_track_starts_;
+  int number_of_failed_track_starts_;
+};
+
+TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) {
+  std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack());
+  EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
+
+  blink::MockMediaStreamVideoSink sink;
+  track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
+  base::RunLoop run_loop;
+  base::Closure quit_closure = run_loop.QuitClosure();
+  EXPECT_CALL(sink, OnVideoFrame())
+      .WillOnce(RunClosure(std::move(quit_closure)));
+  rtc::scoped_refptr<webrtc::I420Buffer> buffer(
+      new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240));
+
+  webrtc::I420Buffer::SetBlack(buffer);
+
+  source()->SinkInterfaceForTesting()->OnFrame(
+      webrtc::VideoFrame::Builder()
+          .set_video_frame_buffer(buffer)
+          .set_rotation(webrtc::kVideoRotation_0)
+          .set_timestamp_us(1000)
+          .build());
+  run_loop.Run();
+
+  EXPECT_EQ(1, sink.number_of_frames());
+  track->RemoveSink(&sink);
+}
+
+TEST_F(MediaStreamRemoteVideoSourceTest, RemoteTrackStop) {
+  std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack());
+
+  blink::MockMediaStreamVideoSink sink;
+  track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
+  EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateLive, sink.state());
+  EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateLive,
+            webkit_source().GetReadyState());
+  StopWebRtcTrack();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateEnded,
+            webkit_source().GetReadyState());
+  EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateEnded, sink.state());
+
+  track->RemoveSink(&sink);
+}
+
+TEST_F(MediaStreamRemoteVideoSourceTest, PreservesColorSpace) {
+  std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack());
+  blink::MockMediaStreamVideoSink sink;
+  track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
+
+  base::RunLoop run_loop;
+  EXPECT_CALL(sink, OnVideoFrame())
+      .WillOnce(RunClosure(run_loop.QuitClosure()));
+  rtc::scoped_refptr<webrtc::I420Buffer> buffer(
+      new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240));
+  webrtc::ColorSpace kColorSpace(webrtc::ColorSpace::PrimaryID::kSMPTE240M,
+                                 webrtc::ColorSpace::TransferID::kSMPTE240M,
+                                 webrtc::ColorSpace::MatrixID::kSMPTE240M,
+                                 webrtc::ColorSpace::RangeID::kLimited);
+  const webrtc::VideoFrame& input_frame =
+      webrtc::VideoFrame::Builder()
+          .set_video_frame_buffer(buffer)
+          .set_timestamp_ms(0)
+          .set_rotation(webrtc::kVideoRotation_0)
+          .set_color_space(kColorSpace)
+          .build();
+  source()->SinkInterfaceForTesting()->OnFrame(input_frame);
+  run_loop.Run();
+
+  EXPECT_EQ(1, sink.number_of_frames());
+  scoped_refptr<media::VideoFrame> output_frame = sink.last_frame();
+  EXPECT_TRUE(output_frame);
+  EXPECT_TRUE(output_frame->ColorSpace() ==
+              gfx::ColorSpace(gfx::ColorSpace::PrimaryID::SMPTE240M,
+                              gfx::ColorSpace::TransferID::SMPTE240M,
+                              gfx::ColorSpace::MatrixID::SMPTE240M,
+                              gfx::ColorSpace::RangeID::LIMITED));
+  track->RemoveSink(&sink);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc
new file mode 100644
index 0000000..9e3d3bdf
--- /dev/null
+++ b/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink_test.cc
@@ -0,0 +1,59 @@
+// 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 "third_party/blink/public/web/modules/peerconnection/media_stream_video_webrtc_sink.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/public/web/modules/mediastream/mock_media_stream_registry.h"
+#include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h"
+#include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+
+namespace blink {
+
+class MediaStreamVideoWebRtcSinkTest : public ::testing::Test {
+ public:
+  void SetVideoTrack() {
+    registry_.Init();
+    registry_.AddVideoTrack("test video track");
+    blink::WebVector<blink::WebMediaStreamTrack> video_tracks =
+        registry_.test_stream().VideoTracks();
+    track_ = video_tracks[0];
+    // TODO(hta): Verify that track_ is valid. When constraints produce
+    // no valid format, using the track will cause a crash.
+  }
+
+  void SetVideoTrack(const base::Optional<bool>& noise_reduction) {
+    registry_.Init();
+    registry_.AddVideoTrack("test video track",
+                            blink::VideoTrackAdapterSettings(), noise_reduction,
+                            false, 0.0);
+    blink::WebVector<blink::WebMediaStreamTrack> video_tracks =
+        registry_.test_stream().VideoTracks();
+    track_ = video_tracks[0];
+    // TODO(hta): Verify that track_ is valid. When constraints produce
+    // no valid format, using the track will cause a crash.
+  }
+
+ protected:
+  blink::WebMediaStreamTrack track_;
+  blink::MockPeerConnectionDependencyFactory dependency_factory_;
+
+ private:
+  ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+
+  blink::MockMediaStreamRegistry registry_;
+};
+
+TEST_F(MediaStreamVideoWebRtcSinkTest, NoiseReductionDefaultsToNotSet) {
+  SetVideoTrack();
+  blink::MediaStreamVideoWebRtcSink my_sink(
+      track_, &dependency_factory_,
+      blink::scheduler::GetSingleThreadTaskRunnerForTesting());
+  EXPECT_TRUE(my_sink.webrtc_video_track());
+  EXPECT_FALSE(my_sink.SourceNeedsDenoisingForTesting());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_impl.cc b/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_impl.cc
index eecfa9c..e2a7884 100644
--- a/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_impl.cc
+++ b/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_impl.cc
@@ -87,13 +87,14 @@
   DCHECK(orientation_);
   DCHECK(GetPage());
   ChromeClient& chrome_client = GetPage()->GetChromeClient();
-  WebScreenInfo screen_info = chrome_client.GetScreenInfo();
+  WebScreenInfo screen_info = chrome_client.GetScreenInfo(*GetFrame());
   WebScreenOrientationType orientation_type = screen_info.orientation_type;
   if (orientation_type == kWebScreenOrientationUndefined) {
     // The embedder could not provide us with an orientation, deduce it
     // ourselves.
-    orientation_type = ComputeOrientation(chrome_client.GetScreenInfo().rect,
-                                          screen_info.orientation_angle);
+    orientation_type =
+        ComputeOrientation(chrome_client.GetScreenInfo(*GetFrame()).rect,
+                           screen_info.orientation_angle);
   }
   DCHECK(orientation_type != kWebScreenOrientationUndefined);
 
@@ -122,7 +123,7 @@
   // The orientation type and angle are tied in a way that if the angle has
   // changed, the type must have changed.
   uint16_t current_angle =
-      GetPage()->GetChromeClient().GetScreenInfo().orientation_angle;
+      GetPage()->GetChromeClient().GetScreenInfo(*GetFrame()).orientation_angle;
 
   // FIXME: sendOrientationChangeEvent() currently send an event all the
   // children of the frame, so it should only be called on the frame on
diff --git a/third_party/blink/renderer/modules/sensor/sensor_proxy.cc b/third_party/blink/renderer/modules/sensor/sensor_proxy.cc
index e32c2c7..f57bd59 100644
--- a/third_party/blink/renderer/modules/sensor/sensor_proxy.cc
+++ b/third_party/blink/renderer/modules/sensor/sensor_proxy.cc
@@ -65,14 +65,14 @@
 
 namespace {
 
-uint16_t GetScreenOrientationAngleForPage(Page* page) {
+uint16_t GetScreenOrientationAngle(LocalFrame& frame) {
   if (WebTestSupport::IsRunningWebTest()) {
     // Simulate that the device is turned 90 degrees on the right.
     // 'orientation_angle' must be 270 as per
     // https://w3c.github.io/screen-orientation/#dfn-update-the-orientation-information.
     return 270;
   }
-  return page->GetChromeClient().GetScreenInfo().orientation_angle;
+  return frame.GetChromeClient().GetScreenInfo(frame).orientation_angle;
 }
 
 }  // namespace
@@ -83,7 +83,9 @@
     if (remapped_reading_.timestamp() != reading_.timestamp()) {
       remapped_reading_ = reading_;
       SensorReadingRemapper::RemapToScreenCoords(
-          type_, GetScreenOrientationAngleForPage(GetPage()),
+          type_,
+          GetScreenOrientationAngle(
+              *provider_->GetSupplementable()->GetFrame()),
           &remapped_reading_);
     }
     return remapped_reading_;
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc b/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
index 8421304b..f3c6a8a 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
+++ b/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
@@ -25,6 +25,12 @@
 
 namespace blink {
 
+// Disabling this will cause parkable strings to never be compressed.
+// This is useful for headless mode + virtual time. Since virtual time advances
+// quickly, strings may be parked too eagerly in that mode.
+const base::Feature kCompressParkableStrings{"CompressParkableStrings",
+                                             base::FEATURE_ENABLED_BY_DEFAULT};
+
 struct ParkableStringManager::Statistics {
   size_t original_size;
   size_t uncompressed_size;
@@ -38,11 +44,18 @@
 
 namespace {
 
+bool CompressionEnabled() {
+  return base::FeatureList::IsEnabled(kCompressParkableStrings);
+}
+
 class OnPurgeMemoryListener : public GarbageCollected<OnPurgeMemoryListener>,
                               public MemoryPressureListener {
   USING_GARBAGE_COLLECTED_MIXIN(OnPurgeMemoryListener);
 
   void OnPurgeMemory() override {
+    if (!CompressionEnabled()) {
+      return;
+    }
     ParkableStringManager::Instance().PurgeMemory();
   }
 };
@@ -147,7 +160,8 @@
   // Don't attempt to park strings smaller than this size.
   static constexpr unsigned int kSizeThreshold = 10000;
   // TODO(lizeb): Consider parking non-main thread strings.
-  return string.length() > kSizeThreshold && IsMainThread();
+  return string.length() > kSizeThreshold && IsMainThread() &&
+         CompressionEnabled();
 }
 
 scoped_refptr<ParkableStringImpl> ParkableStringManager::Add(
@@ -254,6 +268,7 @@
 
 void ParkableStringManager::ParkAll(ParkableStringImpl::ParkingMode mode) {
   DCHECK(IsMainThread());
+  DCHECK(CompressionEnabled());
 
   size_t total_size = 0;
   for (ParkableStringImpl* str : parked_strings_)
@@ -305,6 +320,8 @@
 }
 
 void ParkableStringManager::AgeStringsAndPark() {
+  DCHECK(CompressionEnabled());
+
   TRACE_EVENT0("blink", "ParkableStringManager::AgeStringsAndPark");
   has_pending_aging_task_ = false;
 
@@ -331,6 +348,9 @@
 }
 
 void ParkableStringManager::ScheduleAgingTaskIfNeeded() {
+  if (!CompressionEnabled())
+    return;
+
   if (has_pending_aging_task_)
     return;
 
@@ -346,6 +366,7 @@
 
 void ParkableStringManager::PurgeMemory() {
   DCHECK(IsMainThread());
+  DCHECK(CompressionEnabled());
 
   ParkAll(ParkableStringImpl::ParkingMode::kAlways);
   // Critical memory pressure: drop compressed data for strings that we cannot
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string_manager.h b/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
index 1333ed75..5aefb098 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
+++ b/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_PARKABLE_STRING_MANAGER_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_PARKABLE_STRING_MANAGER_H_
 
+#include "base/feature_list.h"
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/time/time.h"
@@ -21,6 +22,8 @@
 
 class ParkableString;
 
+PLATFORM_EXPORT extern const base::Feature kCompressParkableStrings;
+
 class PLATFORM_EXPORT ParkableStringManagerDumpProvider
     : public base::trace_event::MemoryDumpProvider {
   USING_FAST_MALLOC(ParkableStringManagerDumpProvider);
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string_test.cc b/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
index 545633f..970245a 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
+++ b/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
@@ -8,6 +8,7 @@
 
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/timer/elapsed_timer.h"
@@ -59,7 +60,9 @@
   }
 
   void WaitForAging() {
-    EXPECT_GT(task_environment_.GetPendingMainThreadTaskCount(), 0u);
+    if (base::FeatureList::IsEnabled(kCompressParkableStrings)) {
+      EXPECT_GT(task_environment_.GetPendingMainThreadTaskCount(), 0u);
+    }
     task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(
         ParkableStringManager::kAgingIntervalInSeconds));
   }
@@ -673,6 +676,18 @@
   EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(savings))));
 }
 
+TEST_F(ParkableStringTest, CompressionDisabled) {
+  base::test::ScopedFeatureList features;
+  features.InitAndDisableFeature(kCompressParkableStrings);
+
+  ParkableString parkable(MakeLargeString().ReleaseImpl());
+  WaitForDelayedParking();
+  EXPECT_FALSE(parkable.Impl()->is_parked());
+
+  MemoryPressureListenerRegistry::Instance().OnPurgeMemory();
+  EXPECT_FALSE(parkable.Impl()->is_parked());
+}
+
 TEST_F(ParkableStringTest, Aging) {
   ParkableString parkable(MakeLargeString().ReleaseImpl());
   EXPECT_TRUE(parkable.Impl()->is_young_for_testing());
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index a2b64cd..f34488cb 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -1129,7 +1129,7 @@
     const EffectPaintPropertyNode& effect) {
   if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
     return PropertyTreeManager::DirectlyUpdateCompositedOpacityValue(
-        property_trees, effect);
+        property_trees, *root_layer_->layer_tree_host(), effect);
   }
   return false;
 }
@@ -1138,7 +1138,7 @@
     const TransformPaintPropertyNode& transform) {
   if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
     return PropertyTreeManager::DirectlyUpdateScrollOffsetTransform(
-        property_trees, transform);
+        property_trees, *root_layer_->layer_tree_host(), transform);
   }
   return false;
 }
@@ -1146,8 +1146,8 @@
 bool PaintArtifactCompositor::DirectlyUpdateTransform(
     const TransformPaintPropertyNode& transform) {
   if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
-    return PropertyTreeManager::DirectlyUpdateTransform(property_trees,
-                                                        transform);
+    return PropertyTreeManager::DirectlyUpdateTransform(
+        property_trees, *root_layer_->layer_tree_host(), transform);
   }
   return false;
 }
@@ -1155,8 +1155,8 @@
 bool PaintArtifactCompositor::DirectlyUpdatePageScaleTransform(
     const TransformPaintPropertyNode& transform) {
   if (auto* property_trees = GetPropertyTreesForDirectUpdate()) {
-    return PropertyTreeManager::DirectlyUpdatePageScaleTransform(property_trees,
-                                                                 transform);
+    return PropertyTreeManager::DirectlyUpdatePageScaleTransform(
+        property_trees, *root_layer_->layer_tree_host(), transform);
   }
   return false;
 }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
index 41a73f4..94e6d59 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -114,6 +114,7 @@
 
 bool PropertyTreeManager::DirectlyUpdateCompositedOpacityValue(
     cc::PropertyTrees* property_trees,
+    cc::LayerTreeHost& host,
     const EffectPaintPropertyNode& effect) {
   auto* cc_effect = property_trees->effect_tree.Node(
       effect.CcNodeId(property_trees->sequence_number));
@@ -128,11 +129,13 @@
   cc_effect->opacity = effect.Opacity();
   cc_effect->effect_changed = true;
   property_trees->effect_tree.set_needs_update(true);
+  host.SetNeedsCommit();
   return true;
 }
 
 bool PropertyTreeManager::DirectlyUpdateScrollOffsetTransform(
     cc::PropertyTrees* property_trees,
+    cc::LayerTreeHost& host,
     const TransformPaintPropertyNode& transform) {
   auto* scroll_node = transform.ScrollNode();
   // Only handle scroll adjustments.
@@ -158,11 +161,13 @@
   cc_transform->transform_changed = true;
   property_trees->transform_tree.set_needs_update(true);
   property_trees->scroll_tree.set_needs_update(true);
+  host.SetNeedsCommit();
   return true;
 }
 
 bool PropertyTreeManager::DirectlyUpdateTransform(
     cc::PropertyTrees* property_trees,
+    cc::LayerTreeHost& host,
     const TransformPaintPropertyNode& transform) {
   // If we have a ScrollNode, we should be using
   // DirectlyUpdateScrollOffsetTransform().
@@ -182,11 +187,13 @@
 
   cc_transform->transform_changed = true;
   property_trees->transform_tree.set_needs_update(true);
+  host.SetNeedsCommit();
   return true;
 }
 
 bool PropertyTreeManager::DirectlyUpdatePageScaleTransform(
     cc::PropertyTrees* property_trees,
+    cc::LayerTreeHost& host,
     const TransformPaintPropertyNode& transform) {
   DCHECK(!transform.ScrollNode());
 
@@ -200,6 +207,7 @@
                                   cc_transform);
   cc_transform->transform_changed = true;
   property_trees->transform_tree.set_needs_update(true);
+  host.SetNeedsCommit();
   return true;
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
index 0031fa2..09b99c7 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
+++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
@@ -17,6 +17,7 @@
 class ClipTree;
 class EffectTree;
 class Layer;
+class LayerTreeHost;
 class PropertyTrees;
 class ScrollTree;
 class TransformTree;
@@ -119,14 +120,18 @@
 
   static bool DirectlyUpdateCompositedOpacityValue(
       cc::PropertyTrees*,
+      cc::LayerTreeHost&,
       const EffectPaintPropertyNode&);
   static bool DirectlyUpdateScrollOffsetTransform(
       cc::PropertyTrees*,
+      cc::LayerTreeHost&,
       const TransformPaintPropertyNode&);
   static bool DirectlyUpdateTransform(cc::PropertyTrees*,
+                                      cc::LayerTreeHost&,
                                       const TransformPaintPropertyNode&);
   static bool DirectlyUpdatePageScaleTransform(
       cc::PropertyTrees*,
+      cc::LayerTreeHost&,
       const TransformPaintPropertyNode&);
 
  private:
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index 903bfa1..7c861b2 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -585,19 +585,6 @@
   // Note that we don't resize m_contentsLayer. It's up the caller to do that.
 }
 
-void GraphicsLayer::SetTransform(const TransformationMatrix& transform) {
-  transform_ = transform;
-  CcLayer()->SetTransform(TransformationMatrix::ToTransform(transform));
-}
-
-void GraphicsLayer::SetTransformOrigin(const gfx::Point3F& transform_origin) {
-  CcLayer()->SetTransformOrigin(transform_origin);
-}
-
-const gfx::Point3F& GraphicsLayer::TransformOrigin() const {
-  return CcLayer()->transform_origin();
-}
-
 
 bool GraphicsLayer::MasksToBounds() const {
   return CcLayer()->masks_to_bounds();
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h
index 82162e5..64b5b2f 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -124,16 +124,10 @@
   const gfx::PointF& GetPosition() const;
   void SetPosition(const gfx::PointF&);
 
-  const gfx::Point3F& TransformOrigin() const;
-  void SetTransformOrigin(const gfx::Point3F&);
-
   // The size of the layer.
   const gfx::Size& Size() const;
   void SetSize(const gfx::Size&);
 
-  const TransformationMatrix& Transform() const { return transform_; }
-  void SetTransform(const TransformationMatrix&);
-
   void SetRenderingContext(int id);
 
   bool MasksToBounds() const;
diff --git a/third_party/blink/web_tests/SmokeTests b/third_party/blink/web_tests/SmokeTests
index fadbf5a..f0575713 100644
--- a/third_party/blink/web_tests/SmokeTests
+++ b/third_party/blink/web_tests/SmokeTests
@@ -811,6 +811,7 @@
 http/tests/linkHeader/link-header-no-crash-space-invalid.php
 http/tests/loading/remove-child-triggers-parser.html
 http/tests/local/formdata/send-form-data-with-null-string.html
+http/tests/mojo/shared-buffer.html
 http/tests/plugins/navigator-plugins-in-cross-origin-frame.html
 http/tests/pointer-lock/iframe-sandboxed.html
 http/tests/preload/avoid_delaying_onload_link_preload.html
@@ -839,7 +840,6 @@
 media/video-error-does-not-exist.html
 media/W3C/video/preload/preload_reflects_none.html
 mhtml/mhtml_in_iframe.html
-mojo/shared-buffer.html
 navigator_language/navigator_language.html
 netinfo/type-change-no-listener.html
 paint/float/float-text-clip.html
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 90e981d8..9cea30b 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -844,242 +844,7 @@
 crbug.com/591099 [ Mac10.11 ] virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] fast/dynamic/outerHTML-doc.html [ Failure ]
 #crbug.com/591099 [ Mac ] fast/events/before-unload-return-value-from-listener.html [ Crash Timeout ]
-crbug.com/591099 [ Mac10.13 ] css3/selectors3/html/css3-modsel-80.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] editing/selection/5232159.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] css2.1/t040302-c61-phys-len-00-b.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] css2.1/t1205-c561-list-displ-00-b.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] css2.1/t1202-counter-08-b.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] css2.1/t0805-c5522-brdr-02-e.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/basic-inputs.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/button/button-inner-block-reuse.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/formmove2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/indeterminate.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/input-appearance-height.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/search/search-vertical-alignment.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/select/option-script.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/select/select-align.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/select/select-disabled-appearance.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/suggestion-picker/date-suggestion-picker-appearance.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-locale-hebrew.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-rtl.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/targeted-frame-submission.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/text/textfield-focus-ring.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/textarea/basic-textareas-quirks.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/forms/validation-bubble-appearance-rtl-ui.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/inline-block/baseline-vertical.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/inline/002.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/inline/br-text-decoration.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/inline/inline-box-background-long-image.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/invalid/010.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/invalid/021.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/invalid/missing-dt-end-tag.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/invalid/nestedh3s.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/lists/003-vertical.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/lists/003.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/lists/007-vertical.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/lists/007.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/multicol/composited-inner-multicol.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/multicol/composited-layer-multiple-fragments-translated.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/overflow/overflow-auto-table.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/overflow/table-overflow-float.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/parser/fonts.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/parser/xhtml-alternate-entities.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/replaced/max-width-percent.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/replaced/selection-rect-transform.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/replaced/table-replaced-element.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/selectors/020.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/selectors/040.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/selectors/042.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/selectors/066.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/selectors/078b.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/selectors/lang-inheritance.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/selectors/lang-vs-xml-lang.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/040-vertical.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/100-percent-cell-width.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_border-table-cell-collapsed-border.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_border-table-cell.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_border-table-column-collapsed-border.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_border-table-column-group-collapsed-border.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_border-table-column.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_fixed-bg-table.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_layers-show-collapsed-border.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_layers-show.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_position-table-row-group-collapsed-border.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_position-table-row-group.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_simple-table-cell.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_simple-table-collapsed-border.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_simple-table-column-collapsed-border.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/backgr_simple-table.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/form-with-table-style.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/insert-row-before-form.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/prepend-in-anonymous-table.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/rowspan-paint-order-vertical.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/split-table-section-before-anonymous-block-3.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/tbody-background-image-repeat-x.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/tbody-background-image.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/table/unused-percent-heights.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/basic/007.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/basic/012.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/basic/generic-family-changes.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/capitalize-empty-generated-string.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/color-emoji.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/ellipsis-in-absolute-block.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/ellipsis-in-justified-text.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/ellipsis-mixed-text-in-ltr-flow-underline.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/ellipsis-mixed-text-in-rtl-flow-underline.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/ellipsis-platform-font-change.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/ellipsis-with-list-marker-in-ltr-flow.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/ellipsis-with-list-marker-in-rtl-flow.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/font-features/caps-native-synthesis.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/font-stretch-variant.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/font-stretch.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/font-weight.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/international/alef-connected.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/international/bidi-AN-after-empty-run.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/international/bidi-LDB-2-CSS.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/international/bidi-innertext.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/international/bidi-linebreak-001.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/international/bidi-linebreak-003.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/international/bold-bengali.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/international/danda-space.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/international/shape-across-elements.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/justify-ideograph-vertical.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/midword-break-before-surrogate-pair.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/place-mixed-ellipsis-in-inline-blocks-align-center-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/place-mixed-ellipsis-in-inline-blocks-align-left-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/place-mixed-ellipsis-in-inline-blocks-align-right-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/place-mixed-ellipsis-in-inline-blocks.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/place-rtl-ellipsis-in-inline-blocks-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/place-rtl-ellipsis-in-inline-blocks-align-center.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/place-rtl-ellipsis-in-inline-blocks-align-left.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/selection/complex-text-rtl-selection-repaint.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/selection/selection-hard-linebreak.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/selection/selection-rect-line-height-too-big.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/vertical-rl-rtl-linebreak.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/wbr-in-pre-crash.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/whitespace/pre-wrap-last-char.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/text/whitespace/pre-wrap-line-test.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/writing-mode/border-image-vertical-lr.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/writing-mode/border-radius-clipping-vertical-lr.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/writing-mode/broken-ideograph-small-caps.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] fast/writing-mode/broken-ideographic-font.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] html/details_summary/details-marker-style.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] html/details_summary/details-writing-mode.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] ietestcenter/css3/text/textshadow-003.htm [ Failure ]
-crbug.com/591099 [ Mac10.13 ] ietestcenter/css3/text/textshadow-010.htm [ Failure ]
-crbug.com/591099 [ Mac10.13 ] images/exif-orientation-image-document.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] images/imagemap-circle-focus-ring.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] images/imagemap-focus-ring.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] images/imagemap-overflowing-polygon-focus-ring.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] media/video-colorspace-yuv420.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] virtual/audio-service/media/video-colorspace-yuv420.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] media/video-empty-source.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] virtual/audio-service/media/video-empty-source.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] plugins/embed-attributes-style.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] svg/custom/clone-element-with-animated-svg-properties.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] svg/custom/svg-fonts-in-html.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] svg/custom/text-match-highlight.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] svg/custom/transformed-text-pattern.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] svg/dom/SVGLocatable-getCTM-svg-root.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] svg/dom/SVGStringList-basics.xhtml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] svg/hixie/rendering-model/004.xhtml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] svg/wicd/test-rightsizing-a.xhtml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug106158-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug10633.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug1188.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug11944.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug1302.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug157890.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug17130-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug23235.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug2479-1.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug2479-3.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug2509.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug2684.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug2981-1.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug38916.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug3977.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug43039.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug4576.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug46368-1.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug46623-1.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug4849-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug5188.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug55694.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug57828-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug5838.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug6404.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug650.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug69382-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug7112-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug7342.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug80762-1.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug88035-2.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/bugs/bug8950.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/core/col_span.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/body_tfoot.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/body_thead.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/col_span.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/colgroup_span.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/colgroup_valign_baseline.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/table_row_align_center.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/table_rules_all.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/table_rules_groups.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tables_cellpadding.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tables_cellpadding_pct.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tables_style.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tbody_align_char.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tbody_char.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tbody_valign_bottom.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tbody_valign_middle.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/td_valign_top.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tfoot_char.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tfoot_valign_baseline.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tfoot_valign_bottom.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/thead_align_char.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/thead_valign_baseline.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/thead_valign_bottom.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/thead_valign_middle.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tr_bgcolor_white.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/tr_bgcolor_white_rgb.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_col_valign_middle.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_colgroup_valign_bottom.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_colgroup_valign_middle.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_table_border.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_table_style.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_tbody_align_char.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_tbody_valign_baseline.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_tbody_valign_middle.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_td_align_center.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_td_valign_top.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_tfoot_align_char.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_tfoot_style.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_tfoot_valign_baseline.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/marvin/x_th_width.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla/other/test6.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla_expected_failures/bugs/bug10140.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla_expected_failures/bugs/bug1725.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla_expected_failures/bugs/bug17826.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla_expected_failures/bugs/bug72393.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla_expected_failures/bugs/bug89315.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla_expected_failures/bugs/bug91057.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla_expected_failures/marvin/backgr_fixed-bg.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] tables/mozilla_expected_failures/marvin/x_colgroup_width_px.xml [ Failure ]
-crbug.com/591099 [ Mac10.13 ] transforms/3d/general/perspective-units.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] transforms/diamond.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] virtual/exotic-color-space/images/exif-orientation-css.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] virtual/gpu-rasterization/images/exif-orientation.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] virtual/gpu-rasterization/images/image-map-anchor-children.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] virtual/gpu-rasterization/images/imagemap-focus-ring-zoom.html [ Failure ]
-crbug.com/591099 [ Mac10.13 ] virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring.html [ Failure ]
-#crbug.com/591099 [ Mac ] virtual/mouseevent_fractional/fast/events/before-unload-return-value-from-listener.html [ Crash Timeout ]
-crbug.com/591099 [ Mac10.13 ] virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ]
 
 #crbug.com/974725 [ Win7 ] fast/events/before-unload-return-value-from-listener.html [ Pass Crash ]
 
@@ -2951,6 +2716,12 @@
 crbug.com/1012627 [ Win7 ] external/wpt/css/css-text/line-breaking/line-breaking-021.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Linux ] external/wpt/webxr/events_referenceSpace_reset.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.10 ] external/wpt/webxr/events_referenceSpace_reset.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.12 ] external/wpt/webxr/events_referenceSpace_reset.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.13 ] external/wpt/webxr/events_referenceSpace_reset.https.html [ Timeout ]
+crbug.com/626703 [ Retina ] external/wpt/webxr/events_referenceSpace_reset.https.html [ Timeout ]
+crbug.com/626703 [ Win ] external/wpt/webxr/events_referenceSpace_reset.https.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/clear-site-data/storage.https.html [ Timeout ]
 crbug.com/626703 [ Mac ] external/wpt/clear-site-data/storage.https.html [ Timeout ]
 crbug.com/626703 [ Win ] external/wpt/clear-site-data/storage.https.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index 5f02d3e..5a3c806 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -114627,6 +114627,18 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-input-element/range-setattribute-value.html": [
+    [
+     "html/semantics/forms/the-input-element/range-setattribute-value.html",
+     [
+      [
+       "/html/semantics/forms/the-input-element/range-setattribute-value-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "html/semantics/forms/the-textarea-element/multiline-placeholder-cr.html": [
     [
      "html/semantics/forms/the-textarea-element/multiline-placeholder-cr.html",
@@ -160264,6 +160276,9 @@
    "html/semantics/forms/the-input-element/range-intrinsic-size-ref.html": [
     []
    ],
+   "html/semantics/forms/the-input-element/range-setattribute-value-ref.html": [
+    []
+   ],
    "html/semantics/forms/the-input-element/resources/image-submit-click.html": [
     []
    ],
@@ -185400,6 +185415,134 @@
      {}
     ]
    ],
+   "IndexedDB/blob-contenttype.any.js": [
+    [
+     "IndexedDB/blob-contenttype.any.html",
+     {
+      "script_metadata": [
+       [
+        "title",
+        "Blob Content Type"
+       ],
+       [
+        "script",
+        "support.js"
+       ]
+      ]
+     }
+    ],
+    [
+     "IndexedDB/blob-contenttype.any.worker.html",
+     {
+      "script_metadata": [
+       [
+        "title",
+        "Blob Content Type"
+       ],
+       [
+        "script",
+        "support.js"
+       ]
+      ]
+     }
+    ]
+   ],
+   "IndexedDB/blob-delete-objectstore-db.any.js": [
+    [
+     "IndexedDB/blob-delete-objectstore-db.any.html",
+     {
+      "script_metadata": [
+       [
+        "title",
+        "Blob Delete Object Store"
+       ],
+       [
+        "script",
+        "support.js"
+       ]
+      ]
+     }
+    ],
+    [
+     "IndexedDB/blob-delete-objectstore-db.any.worker.html",
+     {
+      "script_metadata": [
+       [
+        "title",
+        "Blob Delete Object Store"
+       ],
+       [
+        "script",
+        "support.js"
+       ]
+      ]
+     }
+    ]
+   ],
+   "IndexedDB/blob-valid-after-deletion.any.js": [
+    [
+     "IndexedDB/blob-valid-after-deletion.any.html",
+     {
+      "script_metadata": [
+       [
+        "title",
+        "Blob Valid After Deletion"
+       ],
+       [
+        "script",
+        "support.js"
+       ]
+      ]
+     }
+    ],
+    [
+     "IndexedDB/blob-valid-after-deletion.any.worker.html",
+     {
+      "script_metadata": [
+       [
+        "title",
+        "Blob Valid After Deletion"
+       ],
+       [
+        "script",
+        "support.js"
+       ]
+      ]
+     }
+    ]
+   ],
+   "IndexedDB/blob-valid-before-commit.any.js": [
+    [
+     "IndexedDB/blob-valid-before-commit.any.html",
+     {
+      "script_metadata": [
+       [
+        "title",
+        "Blob Valid Before Commit"
+       ],
+       [
+        "script",
+        "support.js"
+       ]
+      ]
+     }
+    ],
+    [
+     "IndexedDB/blob-valid-before-commit.any.worker.html",
+     {
+      "script_metadata": [
+       [
+        "title",
+        "Blob Valid Before Commit"
+       ],
+       [
+        "script",
+        "support.js"
+       ]
+      ]
+     }
+    ]
+   ],
    "IndexedDB/clone-before-keypath-eval.html": [
     [
      "IndexedDB/clone-before-keypath-eval.html",
@@ -273009,6 +273152,12 @@
      {}
     ]
    ],
+   "portals/portals-api.html": [
+    [
+     "portals/portals-api.html",
+     {}
+    ]
+   ],
    "portals/portals-cross-origin-load.sub.html": [
     [
      "portals/portals-cross-origin-load.sub.html",
@@ -273053,6 +273202,12 @@
      {}
     ]
    ],
+   "portals/portals-no-frame-crash.html": [
+    [
+     "portals/portals-no-frame-crash.html",
+     {}
+    ]
+   ],
    "portals/portals-post-message.sub.html": [
     [
      "portals/portals-post-message.sub.html",
@@ -334448,6 +334603,22 @@
    "c16c0a4e010f9805796cd93f9cbd1f141e6c91e5",
    "testharness"
   ],
+  "IndexedDB/blob-contenttype.any.js": [
+   "6faa0ad4f3eecfa2a1a2ef2df60d175b3b61a699",
+   "testharness"
+  ],
+  "IndexedDB/blob-delete-objectstore-db.any.js": [
+   "61d7bad914e96a9063c97e3a14844aa8c30079e4",
+   "testharness"
+  ],
+  "IndexedDB/blob-valid-after-deletion.any.js": [
+   "7c7825cb421e2f1e2aacb9838db594ff16e8f30a",
+   "testharness"
+  ],
+  "IndexedDB/blob-valid-before-commit.any.js": [
+   "0803c9ea69c1e187bab2e6f0afe76a403973b645",
+   "testharness"
+  ],
   "IndexedDB/clone-before-keypath-eval.html": [
    "bf67c5d6d732f6dfcf7687d9b12f3d313eb61707",
    "testharness"
@@ -392269,7 +392440,7 @@
    "testharness"
   ],
   "css/css-sizing/animation/width-interpolation.html": [
-   "16b67c5ed66b769359e24df7c17f9d7baf0a46e9",
+   "d165c994b5de6fe1561498aa04c075196357f5f6",
    "testharness"
   ],
   "css/css-sizing/aspect-ratio-affects-container-width-when-height-changes.html": [
@@ -454664,6 +454835,14 @@
    "c45a180063f963e2c738a81148e67b69dfb68ad8",
    "reftest"
   ],
+  "html/semantics/forms/the-input-element/range-setattribute-value-ref.html": [
+   "71a44cdf2fad8c0657821c7c23af77296bdfea2f",
+   "support"
+  ],
+  "html/semantics/forms/the-input-element/range-setattribute-value.html": [
+   "3a03a5b6fe0a94bd294e5273fdd384e4e055904d",
+   "reftest"
+  ],
   "html/semantics/forms/the-input-element/range.html": [
    "209ce25306e02986238ae26fb6fdf38b0a26a500",
    "testharness"
@@ -462089,7 +462268,7 @@
    "support"
   ],
   "interfaces/webrtc.idl": [
-   "b8657386f9cea8e0587ebca3ab92b0eb76a70cc8",
+   "2989db5453f5333c8e04e6d237f4142aa9fa85f8",
    "support"
   ],
   "interfaces/webusb.idl": [
@@ -476976,6 +477155,10 @@
    "70545458b4609ac6f1993834da09bcebee65c118",
    "testharness"
   ],
+  "portals/portals-api.html": [
+   "79d2d526bdb752fb307e2136a84a7a56b15fed9d",
+   "testharness"
+  ],
   "portals/portals-cross-origin-load.sub.html": [
    "e19a225de046ba01a1232fb0cb456b6a706f583a",
    "testharness"
@@ -477004,6 +477187,10 @@
    "9d8d09be9b104b7fa0c58f58c5b19d641db6c0eb",
    "testharness"
   ],
+  "portals/portals-no-frame-crash.html": [
+   "c87afa38c29bf98344c9d01039ed6bf9af1d5d96",
+   "testharness"
+  ],
   "portals/portals-post-message.sub.html": [
    "b37e8afa6db05218d8e128ce1bc352ed1f892273",
    "testharness"
@@ -504549,7 +504736,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/android_webview.py": [
-   "168b7dec37c63c6917adcc0afc98dacb43966184",
+   "fdf53f7d6ab91620866915110fea41606739ae32",
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/base.py": [
@@ -512389,7 +512576,7 @@
    "support"
   ],
   "webdriver/tests/new_session/conftest.py": [
-   "bf974ab1c000a1d733664637faf9b39e7303d556",
+   "d67fdba449dea79fb5113b39f795d874a53ffc40",
    "support"
   ],
   "webdriver/tests/new_session/create_alwaysMatch.py": [
@@ -514149,7 +514336,7 @@
    "testharness"
   ],
   "webrtc/idlharness.https.window-expected.txt": [
-   "4a3962ded4ed6bdc2cc48e0b3b6fab33ccaa8ffc",
+   "8d12f132e2f7717e99c51a0cbfd9c6b4948b0a39",
    "support"
   ],
   "webrtc/idlharness.https.window.js": [
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/visufx/animation/visibility-interpolation.html b/third_party/blink/web_tests/external/wpt/css/CSS2/visufx/animation/visibility-interpolation.html
deleted file mode 100644
index 683b393a..0000000
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/visufx/animation/visibility-interpolation.html
+++ /dev/null
@@ -1,70 +0,0 @@
-<!DOCTYPE html>
-<meta charset="UTF-8">
-<title>visibility interpolation</title>
-<link rel="help" href="https://www.w3.org/TR/CSS2/visufx.html#visibility">
-<meta name="assert" content="visibility supports">
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/css/support/interpolation-testcommon.js"></script>
-
-<body>
-<script>
-test_interpolation({
-  property: 'visibility',
-  from: 'visible',
-  to: 'visible'
-}, [
-  {at: -1, expect: 'visible'},
-  {at: 0, expect: 'visible'},
-  {at: 0.5, expect: 'visible'},
-  {at: 1, expect: 'visible'},
-  {at: 1.5, expect: 'visible'},
-]);
-
-test_interpolation({
-  property: 'visibility',
-  from: 'visible',
-  to: 'hidden'
-}, [
-  {at: -1, expect: 'visible'},
-  {at: 0, expect: 'visible'},
-  {at: 0.1, expect: 'visible'},
-  {at: 0.9, expect: 'visible'},
-  {at: 1, expect: 'hidden'},
-  {at: 1.5, expect: 'hidden'},
-]);
-
-test_interpolation({
-  property: 'visibility',
-  from: 'hidden',
-  to: 'visible'
-}, [
-  {at: -1, expect: 'hidden'},
-  {at: 0, expect: 'hidden'},
-  {at: 0.1, expect: 'visible'},
-  {at: 0.9, expect: 'visible'},
-  {at: 1, expect: 'visible'},
-  {at: 1.5, expect: 'visible'},
-]);
-
-test_interpolation({
-  property: 'visibility',
-  from: 'collapse',
-  to: 'visible'
-}, [
-  {at: -1, expect: 'collapse'},
-  {at: 0, expect: 'collapse'},
-  {at: 0.1, expect: 'visible'},
-  {at: 0.9, expect: 'visible'},
-  {at: 1, expect: 'visible'},
-  {at: 1.5, expect: 'visible'},
-]);
-
-test_no_interpolation({
-  property: 'visibility',
-  from: 'collapse',
-  to: 'hidden'
-});
-</script>
-</body>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl b/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl
index b865738..2989db5 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl
@@ -233,7 +233,8 @@
 [Exposed=Window]
 interface RTCPeerConnectionIceErrorEvent : Event {
   constructor(DOMString type, RTCPeerConnectionIceErrorEventInit eventInitDict);
-  readonly attribute DOMString hostCandidate;
+  readonly attribute DOMString? address;
+  readonly attribute unsigned short? port;
   readonly attribute DOMString url;
   readonly attribute unsigned short errorCode;
   readonly attribute USVString errorText;
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py
index b7b08bb..fdf53f7 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py
@@ -54,6 +54,8 @@
     capabilities["goog:chromeOptions"]["androidPackage"] = \
         "org.chromium.webview_shell"
     capabilities["goog:chromeOptions"]["androidActivity"] = ".WebPlatformTestsActivity"
+    if 'device_serial' in kwargs:
+        capabilities["goog:chromeOptions"]["androidDeviceSerial"] = kwargs['device_serial']
 
     # Workaround: driver.quit() cannot quit SystemWebViewShell.
     executor_kwargs["pause_after_test"] = False
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/new_session/conftest.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/new_session/conftest.py
index bf974ab..d67fdba 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/new_session/conftest.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/new_session/conftest.py
@@ -25,6 +25,19 @@
     return add_browser_capabilities
 
 
+@pytest.fixture(name="configuration")
+def fixture_configuration(configuration):
+  """Remove "acceptInsecureCerts" from capabilities if it exists.
+
+  Some browser configurations add acceptInsecureCerts capability by default.
+  Remove it during new_session tests to avoid interference.
+  """
+
+  if "acceptInsecureCerts" in configuration["capabilities"]:
+    configuration = dict(configuration)
+    del configuration["capabilities"]["acceptInsecureCerts"]
+  return configuration
+
 @pytest.fixture(name="new_session")
 def fixture_new_session(request, configuration, current_session):
     """Start a new session for tests which themselves test creating new sessions.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt
index 4a3962de..8d12f132 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 514 tests; 475 PASS, 39 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 516 tests; 473 PASS, 43 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS idl_test validation
 PASS Test driver for asyncInitCertificate
@@ -206,13 +206,15 @@
 PASS RTCPeerConnectionIceErrorEvent interface: existence and properties of interface prototype object
 PASS RTCPeerConnectionIceErrorEvent interface: existence and properties of interface prototype object's "constructor" property
 PASS RTCPeerConnectionIceErrorEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCPeerConnectionIceErrorEvent interface: attribute hostCandidate
+FAIL RTCPeerConnectionIceErrorEvent interface: attribute address assert_true: The prototype object must have a property "address" expected true got false
+FAIL RTCPeerConnectionIceErrorEvent interface: attribute port assert_true: The prototype object must have a property "port" expected true got false
 PASS RTCPeerConnectionIceErrorEvent interface: attribute url
 PASS RTCPeerConnectionIceErrorEvent interface: attribute errorCode
 PASS RTCPeerConnectionIceErrorEvent interface: attribute errorText
 PASS RTCPeerConnectionIceErrorEvent must be primary interface of new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 });
 PASS Stringification of new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 });
-PASS RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "hostCandidate" with the proper type
+FAIL RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "address" with the proper type assert_inherits: property "address" not found in prototype chain
+FAIL RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "port" with the proper type assert_inherits: property "port" not found in prototype chain
 PASS RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "url" with the proper type
 PASS RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "errorCode" with the proper type
 PASS RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "errorText" with the proper type
diff --git a/third_party/blink/web_tests/fast/replaced/table-replaced-element-expected.txt b/third_party/blink/web_tests/fast/replaced/table-replaced-element-expected.txt
index 8b072d5..46faf40 100644
--- a/third_party/blink/web_tests/fast/replaced/table-replaced-element-expected.txt
+++ b/third_party/blink/web_tests/fast/replaced/table-replaced-element-expected.txt
@@ -2,7 +2,7 @@
 
 This tests that the contents of a table do not overflow when the table contains an image with percentage height. For this test to pass, the blue rectangle should be entirely within the table border and/or you should see a 'PASS' message below.
 
-Height of table: 306
+Height of table: 290
 Height of table contents: 280
 PASS: Table contents do not overflow outside of table border.
 
diff --git a/third_party/blink/web_tests/fast/text/international/shape-across-elements-expected.txt b/third_party/blink/web_tests/fast/text/international/shape-across-elements-expected.txt
index df204ba..2dafceb 100644
--- a/third_party/blink/web_tests/fast/text/international/shape-across-elements-expected.txt
+++ b/third_party/blink/web_tests/fast/text/international/shape-across-elements-expected.txt
@@ -1,5 +1,5 @@
-FAIL Width of isolated word should match width of word with markup.
-FAIL Width of partial glyph in ligature should not match width of isolated glyph.
+PASS Width of isolated word does match width of word with markup.
+PASS Width of partial glyph in ligature does not match width of isolated glyph.
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/devtools/webaudio/audio-context-selector-test-expected.txt b/third_party/blink/web_tests/http/tests/devtools/webaudio/audio-context-selector-test-expected.txt
index 1444f4e1..40243f6 100644
--- a/third_party/blink/web_tests/http/tests/devtools/webaudio/audio-context-selector-test-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/webaudio/audio-context-selector-test-expected.txt
@@ -62,7 +62,6 @@
 
 Running: testOnListItemReplacedCalled
 _onListItemReplaced called with contexts (items) count: 1
-_onListItemReplaced called with contexts (items) count: 0
 _onListItemReplaced called with contexts (items) count: 1
 
 Number of contexts (items): 1
diff --git a/third_party/blink/web_tests/http/tests/mojo/associated_binding.html b/third_party/blink/web_tests/http/tests/mojo/associated_binding.html
new file mode 100644
index 0000000..3977a5a7
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/associated_binding.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.js"></script>
+<script>
+'use strict';
+
+function SenderImpl(callback) {
+  this.callback = callback;
+}
+
+SenderImpl.prototype.echo = function(value) {
+  return Promise.resolve({value: value});
+};
+
+SenderImpl.prototype.send = function(value) {
+  if (this.callback) {
+    this.callback(value);
+  }
+};
+
+var IntegerSenderImpl = SenderImpl;
+
+function IntegerSenderConnectionImpl() {
+  this.integerSenderBindings = new mojo.AssociatedBindingSet(
+      mojo.test.IntegerSender);
+}
+
+IntegerSenderConnectionImpl.prototype.getSender = function(
+    integerSenderRequest) {
+  this.integerSenderBindings.addBinding(new IntegerSenderImpl(),
+      integerSenderRequest);
+};
+
+promise_test(async () => {
+  var integerSenderConnection = new mojo.test.IntegerSenderConnectionPtr();
+  var integerSenderConnectionImpl = new IntegerSenderConnectionImpl();
+  var integerSenderConnectionBinding = new mojo.Binding(
+      mojo.test.IntegerSenderConnection,
+      integerSenderConnectionImpl,
+      mojo.makeRequest(integerSenderConnection));
+
+  // AssociatedInterfaceRequest for integerSender.
+  var integerSenderPtrInfo0 = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest0 = mojo.makeRequest(integerSenderPtrInfo0);
+  var integerSender0 = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo0);
+
+  var integerSenderPtrInfo1 = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest1 = mojo.makeRequest(integerSenderPtrInfo1);
+  var integerSender1 = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo1);
+
+  integerSenderConnection.getSender(integerSenderRequest0);
+  integerSenderConnection.getSender(integerSenderRequest1);
+
+  // Master Binding close triggers connection error handler on
+  // interface endpoint clients for all associated endpoints.
+  var connectionErrorHandler0 = new Promise((resolve, reject) => {
+    integerSender0.ptr.setConnectionErrorHandler(() => {
+      resolve();
+    });
+  });
+
+  var connectionErrorHandler1 = new Promise((resolve, reject) => {
+    integerSender1.ptr.setConnectionErrorHandler(() => {
+      resolve();
+    });
+  });
+
+  setTimeout(integerSenderConnectionBinding.close.bind(
+      integerSenderConnectionBinding), 0);
+  await Promise.all([connectionErrorHandler0, connectionErrorHandler1]);
+}, 'all endpoints connectionErrorHandler called on master binding close');
+
+promise_test(async () => {
+  var integerSenderConnection = new mojo.test.IntegerSenderConnectionPtr();
+  var integerSenderConnectionImpl = new IntegerSenderConnectionImpl();
+  var integerSenderConnectionBinding = new mojo.Binding(
+      mojo.test.IntegerSenderConnection,
+      integerSenderConnectionImpl,
+      mojo.makeRequest(integerSenderConnection));
+
+  var integerSenders = [];
+  for (var i = 0; i < 3; i++) {
+    // AssociatedInterfaceRequest for integerSender.
+    var integerSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
+    var integerSenderRequest = mojo.makeRequest(integerSenderPtrInfo);
+    var integerSender =
+        new mojo.test.IntegerSenderAssociatedPtr(integerSenderPtrInfo);
+    integerSenderConnection.getSender(integerSenderRequest);
+
+    // Wait for integerSenderConnection getSender message to be received by
+    // integerSenderConnection's binding side and all integerSender binding
+    // to be created.
+    assert_equals((await integerSender.echo(3)).value, 3);
+    integerSenders.push(integerSender);
+  }
+
+  await new Promise((resolve, reject) => {
+    integerSenderConnectionImpl.integerSenderBindings
+        .setConnectionErrorHandler(() => {resolve();});
+    integerSenders[0].ptr.reset();
+  });
+
+  await new Promise((resolve, reject) => {
+    integerSenderConnectionImpl.integerSenderBindings
+        .setConnectionErrorHandler(function({customReason, description}) {
+      assert_equals(customReason, 32);
+      assert_equals(description, 'goodbye');
+      resolve();
+    });
+    integerSenders[1].ptr.resetWithReason({customReason: 32,
+        description: 'goodbye'});
+  });
+
+  // integerSender2's binding should still exist.
+  assert_equals((await integerSenders[2].echo(11)).value, 11);
+
+  integerSenderConnectionImpl.integerSenderBindings.closeAllBindings();
+  assert_true(integerSenderConnectionImpl.integerSenderBindings.isEmpty());
+}, 'associated binding set');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/associated_interface_ptr.html b/third_party/blink/web_tests/http/tests/mojo/associated_interface_ptr.html
new file mode 100644
index 0000000..50e56be
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/associated_interface_ptr.html
@@ -0,0 +1,345 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.js"></script>
+<script>
+'use strict';
+
+function SenderImpl(callback) {
+  this.callback = callback;
+}
+
+SenderImpl.prototype.echo = function(value) {
+  return Promise.resolve({value: value});
+};
+
+SenderImpl.prototype.send = function(value) {
+  if (this.callback) {
+    this.callback(value);
+  }
+};
+
+var IntegerSenderImpl = SenderImpl;
+var StringSenderImpl = SenderImpl;
+
+function IntegerSenderConnectionImpl() {
+  this.integerSenderBinding_ = null;
+}
+
+IntegerSenderConnectionImpl.prototype.getSender = function(
+    integerSenderRequest) {
+  this.integerSenderBinding_ = new mojo.AssociatedBinding(
+      mojo.test.IntegerSender, new IntegerSenderImpl(), integerSenderRequest);
+};
+
+IntegerSenderConnectionImpl.prototype.asyncGetSender = function() {
+  var integerSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest = mojo.makeRequest(integerSenderPtrInfo);
+  this.getSender(integerSenderRequest);
+  return Promise.resolve({sender: integerSenderPtrInfo});
+};
+
+function IntegerSenderConnectionAtBothEndsImpl() {
+  this.integerSender_ = null;
+}
+
+IntegerSenderConnectionAtBothEndsImpl.prototype.getSender =
+    IntegerSenderConnectionImpl.prototype.getSender;
+
+IntegerSenderConnectionAtBothEndsImpl.prototype.setSender = function(
+    integerSenderPtrInfo) {
+  this.integerSender_ = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo);
+  return this.integerSender_.echo(456);
+};
+
+function IntegerSenderConnectionImplWithConnectionError() {
+  this.integerSenderBinding_ = null;
+}
+
+IntegerSenderConnectionImplWithConnectionError.prototype.getSender =
+    function(integerSenderRequest) {
+  this.integerSenderBinding_ = new mojo.AssociatedBinding(
+      mojo.test.IntegerSender, new IntegerSenderImpl(), integerSenderRequest);
+  this.integerSenderBinding_.closeWithReason(
+      {customReason: 42, description: 'hey'});
+};
+
+function SenderConnectionBindLaterImpl({getIntegerSenderCallback,
+    getStringSenderCallback} = {}) {
+  this.getIntegerSenderCallback = getIntegerSenderCallback;
+  this.getStringSenderCallback = getStringSenderCallback;
+  this.integerSenderBinding_ = null;
+  this.stringSenderBinding_ = null;
+}
+
+SenderConnectionBindLaterImpl.prototype.getIntegerSender =
+    function(integerSenderRequest) {
+  setTimeout(() => {
+    this.integerSenderBinding_ = new mojo.AssociatedBinding(
+        mojo.test.IntegerSender,
+        new IntegerSenderImpl(this.getIntegerSenderCallback),
+        integerSenderRequest);
+  }, 0);
+};
+
+SenderConnectionBindLaterImpl.prototype.getStringSender =
+    function(stringSenderRequest) {
+  this.stringSenderBinding_ = new mojo.AssociatedBinding(
+      mojo.test.StringSender,
+      new StringSenderImpl(this.getStringSenderCallback),
+      stringSenderRequest);
+};
+
+function SenderConnectionImpl({getIntegerSenderCallback,
+    getStringSenderCallback} = {}) {
+  this.getIntegerSenderCallback = getIntegerSenderCallback;
+  this.getStringSenderCallback = getStringSenderCallback;
+  this.integerSenderBinding_ = null;
+  this.stringSenderBinding_ = null;
+}
+
+SenderConnectionImpl.prototype.getIntegerSender =
+    function(integerSenderRequest) {
+  this.integerSenderBinding_ = new mojo.AssociatedBinding(
+      mojo.test.IntegerSender,
+      new IntegerSenderImpl(this.getIntegerSenderCallback),
+      integerSenderRequest);
+};
+
+SenderConnectionImpl.prototype.getStringSender =
+    function(stringSenderRequest) {
+  this.stringSenderBinding_ = new mojo.AssociatedBinding(
+      mojo.test.StringSender,
+      new StringSenderImpl(this.getStringSenderCallback),
+      stringSenderRequest);
+};
+
+promise_test(async () => {
+  var integerSenderConnection = new
+      mojo.test.IntegerSenderConnectionPtr();
+  var integerSenderConnectionBinding = new mojo.Binding(
+      mojo.test.IntegerSenderConnection,
+      new IntegerSenderConnectionImpl(),
+      mojo.makeRequest(integerSenderConnection));
+
+  // Sending AssociatedInterfaceRequest.
+  var integerSenderPtrInfo0 = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest0 = mojo.makeRequest(integerSenderPtrInfo0);
+
+  var integerSender0 = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo0);
+
+  integerSenderConnection.getSender(integerSenderRequest0);
+  assert_equals((await integerSender0.echo(123)).value, 123);
+
+  // Recieving AssociatedInterfacePtrInfo.
+  var integerSenderPtrInfo1 =
+      (await integerSenderConnection.asyncGetSender()).sender;
+  var integerSender1 = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo1);
+  assert_equals((await integerSender1.echo(456)).value, 456);
+}, 'pass associated interfaces');
+
+// Bind to the same pipe two associated interfaces, whose implementation
+// lives at different ends. Test that the two don't interfere.
+promise_test(async () => {
+  var integerSenderConnectionAtBothEnds = new
+      mojo.test.IntegerSenderConnectionAtBothEndsPtr();
+  var integerSenderConnectionAtBothEndsBinding = new mojo.Binding(
+      mojo.test.IntegerSenderConnectionAtBothEnds,
+      new IntegerSenderConnectionAtBothEndsImpl(),
+      mojo.makeRequest(integerSenderConnectionAtBothEnds));
+
+  // Associated Interface whose Binding Impl lives on the other side.
+  // Sending AssociatedInterfaceRequest.
+  var integerSenderPtrInfo0 = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest0 = mojo.makeRequest(integerSenderPtrInfo0);
+
+  var integerSender0 = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo0);
+
+  integerSenderConnectionAtBothEnds.getSender(integerSenderRequest0);
+  assert_equals((await integerSender0.echo(123)).value, 123);
+
+  // Associated Interface whose Binding Impl lives on this side.
+  // Sending AssociatedInterfacePtrInfo.
+  var integerSenderPtrInfo1 = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest1 = mojo.makeRequest(integerSenderPtrInfo1);
+
+  var integerSenderBinding = new mojo.AssociatedBinding(
+      mojo.test.IntegerSender, new IntegerSenderImpl(),
+      integerSenderRequest1);
+
+  assert_equals((await integerSenderConnectionAtBothEnds.setSender(
+      integerSenderPtrInfo1)).value, 456);
+}, 'associated interfaces on both ends');
+
+promise_test(async () => {
+  var integerSenderConnection = new mojo.test.IntegerSenderConnectionPtr();
+  var integerSenderConnectionBinding = new mojo.Binding(
+      mojo.test.IntegerSenderConnection,
+      new IntegerSenderConnectionImplWithConnectionError(),
+      mojo.makeRequest(integerSenderConnection));
+
+  // Sending AssociatedInterfaceRequest.
+  var integerSenderPtrInfo0 = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest0 = mojo.makeRequest(integerSenderPtrInfo0);
+
+  var integerSender0 = new mojo.test.IntegerSenderAssociatedPtr(
+          integerSenderPtrInfo0);
+
+  integerSenderConnection.getSender(integerSenderRequest0);
+  await new Promise((resolve, reject) => {
+    integerSender0.ptr.setConnectionErrorHandler(function({customReason,
+        description}) {
+      assert_equals(customReason, 42);
+      assert_equals(description, 'hey');
+      resolve();
+    });
+  });
+}, 'connection error with reason');
+
+// Test that AssociatedInterfacePtr is notified with connection error when
+// the interface hasn't associated with a message pipe and the peer is
+// closed.
+promise_test(async () => {
+  var integerSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest = mojo.makeRequest(integerSenderPtrInfo);
+
+  var integerSender = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo);
+
+  await new Promise((resolve, reject) => {
+    integerSender.ptr.setConnectionErrorHandler(function({customReason,
+        description}) {
+      assert_equals(customReason, 42);
+      assert_equals(description, 'hey');
+      resolve();
+    });
+    integerSenderRequest.resetWithReason({customReason: 42,
+        description: 'hey'})
+  });
+}, 'pending AssociatedInterfacePtr connection error with reason');
+
+promise_test(async () => {
+  var integerSenderConnection = new mojo.test.IntegerSenderConnectionPtr();
+  var integerSenderConnectionBinding = new mojo.Binding(
+      mojo.test.IntegerSenderConnection, new IntegerSenderConnectionImpl(),
+      mojo.makeRequest(integerSenderConnection));
+
+  // Sending AssociatedInterfaceRequest.
+  var integerSenderPtrInfo0 = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest0 = mojo.makeRequest(integerSenderPtrInfo0);
+  var integerSender0 = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo0);
+  integerSenderConnection.getSender(integerSenderRequest0);
+
+  // Recieving AssociatedInterfacePtrInfo.
+  var integerSenderPtrInfo1 =
+      (await integerSenderConnection.asyncGetSender()).sender;
+  var integerSender1 = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo1);
+
+  // Master InterfacePtrController reset triggers connection error handler on
+  // interface endpoint clients for all associated endpoints.
+  var connectionErrorHandler0 = new Promise((resolve, reject) => {
+    integerSender0.ptr.setConnectionErrorHandler(() => {
+      resolve();
+    });
+  });
+
+  var connectionErrorHandler1 = new Promise((resolve, reject) => {
+    integerSender1.ptr.setConnectionErrorHandler(() => {
+      resolve();
+    });
+  });
+
+  setTimeout(integerSenderConnection.ptr.reset.bind(
+      integerSenderConnection.ptr), 0);
+  await Promise.all([connectionErrorHandler0, connectionErrorHandler1]);
+}, 'all endpoints connectionErrorHandler called on master interface reset');
+
+// Cache the current message and pause processing incoming messages if
+// endpoint does not have client attached yet to ensure fifo message arrival.
+promise_test(async () => {
+  var senderConnection = new mojo.test.SenderConnectionPtr();
+  var senderConnectionBindLaterImpl = new SenderConnectionBindLaterImpl();
+  var senderConnectionBinding = new mojo.Binding(
+      mojo.test.SenderConnection, senderConnectionBindLaterImpl,
+      mojo.makeRequest(senderConnection));
+
+  // AssociatedInterfaceRequest for stringSender.
+  var stringSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
+  var stringSenderRequest = mojo.makeRequest(stringSenderPtrInfo);
+  var stringSender = new mojo.test.StringSenderAssociatedPtr(
+      stringSenderPtrInfo);
+
+  // AssociatedInterfaceRequest for integerSender.
+  var integerSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest = mojo.makeRequest(integerSenderPtrInfo);
+  var integerSender = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo);
+
+  var value = await new Promise(function(resolve, reject) {
+    senderConnectionBindLaterImpl.getIntegerSenderCallback = resolve;
+    senderConnectionBindLaterImpl.getStringSenderCallback= reject;
+    senderConnection.getStringSender(stringSenderRequest);
+    senderConnection.getIntegerSender(integerSenderRequest);
+    // Test FIFO arrival order of message.
+    integerSender.send(456); // This message should arrive first.
+    stringSender.send('goodbye');
+  });
+
+  assert_equals(value, 456);
+}, 'fifo order should be preserved for messages');
+
+promise_test(async () => {
+  var senderConnection = new mojo.test.SenderConnectionPtr();
+  var senderConnectionImpl = new SenderConnectionImpl();
+  var senderConnectionBinding = new mojo.Binding(
+      mojo.test.SenderConnection, senderConnectionImpl,
+      mojo.makeRequest(senderConnection));
+
+  // AssociatedInterfaceRequest for stringSender.
+  var stringSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
+  var stringSenderRequest = mojo.makeRequest(stringSenderPtrInfo);
+  var stringSender = new mojo.test.StringSenderAssociatedPtr(
+      stringSenderPtrInfo);
+
+  // AssociatedInterfaceRequest for integerSender.
+  var integerSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
+  var integerSenderRequest = mojo.makeRequest(integerSenderPtrInfo);
+  var integerSender = new mojo.test.IntegerSenderAssociatedPtr(
+      integerSenderPtrInfo);
+
+  var value = await new Promise(function(resolve, reject) {
+    senderConnectionImpl.getIntegerSenderCallback = reject;
+    senderConnectionImpl.getStringSenderCallback= resolve;
+    senderConnection.getStringSender(stringSenderRequest);
+    senderConnection.getIntegerSender(integerSenderRequest);
+
+    // Wait for integerSenderBinding to be created.
+    integerSender.echo(100).then(function(result) {
+      assert_equals(result.value, 100);
+
+      // This causes this endpoint handle's endpoint client to be detached.
+      var handle = senderConnectionImpl.integerSenderBinding_.
+          interfaceEndpointClient_.passHandle();
+
+      // Cache message. Connector will pause processing incoming messages.
+      integerSender.send(456);
+      stringSender.send('goodbye');
+
+      // Closing the target endpoint handle of the cached message will cause
+      // the cached message to be discarded and the connector to resume
+      // processing incoming messages.
+      setTimeout(handle.reset.bind(handle), 0);
+    });
+  });
+
+  assert_equals(value, 'goodbye');
+}, 'discard cached message if target endpoint closed');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/bind-intercepted-interface-in-worker.html b/third_party/blink/web_tests/http/tests/mojo/bind-intercepted-interface-in-worker.html
new file mode 100644
index 0000000..867ea337
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/bind-intercepted-interface-in-worker.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict';
+
+let worker = new Worker('./resources/bind-intercepted-interface-in-worker.js');
+fetch_tests_from_worker(worker);
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/bind-interface.html b/third_party/blink/web_tests/http/tests/mojo/bind-interface.html
new file mode 100644
index 0000000..378b3aaf
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/bind-interface.html
@@ -0,0 +1,151 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/content/test/data/mojo_web_test_helper_test.mojom.js"></script>
+<script src="resources/helpers.js"></script>
+<script>
+
+promise_test(() => {
+  let helper = new content.mojom.MojoWebTestHelperPtr;
+  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
+                     mojo.makeRequest(helper).handle);
+
+  const kTestMessage = "hello world.";
+  const kExpectedReply = ".dlrow olleh";
+  return helper.reverse(kTestMessage).then(reply => {
+    assert_equals(reply.reversed, kExpectedReply);
+  });
+}, "can bind interfaces");
+
+promise_test(() => {
+  let helperImpl = new TestHelperImpl;
+  let interceptor =
+      new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
+  interceptor.oninterfacerequest = e => {
+    helperImpl.bindRequest(e.handle);
+  };
+  interceptor.start();
+
+  let helper = new content.mojom.MojoWebTestHelperPtr;
+  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
+                     mojo.makeRequest(helper).handle);
+  interceptor.stop();
+
+  return helper.reverse("doesn't matter").then(reply => {
+    assert_equals(reply.reversed, kTestReply);
+  });
+}, "can intercept calls to bindInterface");
+
+promise_test(async () => {
+  // Intercept this interface at "context" scope to check that it is being
+  // requested at "process" scope.
+  let helperImpl = new TestHelperImpl;
+  let interceptor =
+      new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
+  interceptor.oninterfacerequest = e => {
+    helperImpl.bindRequest(e.handle);
+  };
+  interceptor.start();
+
+  let helper = new content.mojom.MojoWebTestHelperPtr;
+  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
+                     mojo.makeRequest(helper).handle,
+                     "process");
+
+  const kTestMessage = "hello world.";
+  const kExpectedReply = ".dlrow olleh";
+  await helper.reverse(kTestMessage).then(reply => {
+    assert_equals(reply.reversed, kExpectedReply);
+  });
+
+  interceptor.stop();
+}, "can request interfaces at process scope");
+
+promise_test(() => {
+  let helperImpl = new TestHelperImpl;
+  let interceptor = new MojoInterfaceInterceptor(
+      content.mojom.MojoWebTestHelper.name, "process");
+  interceptor.oninterfacerequest = e => {
+    helperImpl.bindRequest(e.handle);
+  };
+  interceptor.start();
+
+  let helper = new content.mojom.MojoWebTestHelperPtr;
+  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
+                     mojo.makeRequest(helper).handle,
+                     "process");
+  interceptor.stop();
+
+  return helper.reverse("doesn't matter").then(reply => {
+    assert_equals(reply.reversed, kTestReply);
+  });
+}, "can intercept interfaces at process scope");
+
+test(() => {
+  let a = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
+  let b = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
+  a.oninterfacerequest = () => {};
+  b.oninterfacerequest = () => {};
+  a.start();
+  assert_throws('InvalidModificationError', () => { b.start(); });
+  a.stop();
+}, "interface interceptors are mutually exclusive");
+
+test(() => {
+  let a = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name,
+                                       "process");
+  let b = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name,
+                                       "process");
+  a.oninterfacerequest = () => {};
+  b.oninterfacerequest = () => {};
+  a.start();
+  assert_throws('InvalidModificationError', () => { b.start(); });
+  a.stop();
+}, "process scope interface interceptors are mutually exclusive");
+
+promise_test(async t => {
+  // First check that the interceptor can be started and intercepts requests.
+  let interceptor =
+      new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
+  let promise = new Promise(resolve => {
+    interceptor.oninterfacerequest = e => {
+      resolve(e.handle);
+    };
+  });
+  interceptor.start();
+
+  let pipe = Mojo.createMessagePipe();
+  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name, pipe.handle0);
+  let interceptedHandle = await promise;
+  assert_true(interceptedHandle instanceof MojoHandle);
+  interceptedHandle.close();
+  pipe.handle1.close();
+
+  // Stop the interceptor and make another request.
+  interceptor.stop();
+
+  let helper = new content.mojom.MojoWebTestHelperPtr;
+  interceptor.oninterfacerequest = t.step_func(() => {
+    assert_unreached("unexpected 'interfacerequest' event after stop");
+  });
+  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
+                     mojo.makeRequest(helper).handle);
+
+  // Enusre that the interface is functioning, i.e. the request definitely was
+  // not intercepted.
+  await helper.reverse("abc").then(reply => {
+    assert_equals(reply.reversed, "cba");
+  });
+  pipe.handle1.close();
+
+  // And ensure that we can start a new interceptor for the same interface since
+  // the previous one was stopped.
+  interceptor =
+      new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
+  interceptor.oninterfacerequest = e => {};
+  interceptor.start();
+  interceptor.stop();
+}, "interceptors cancel properly");
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/binding.html b/third_party/blink/web_tests/http/tests/mojo/binding.html
new file mode 100644
index 0000000..18129f6
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/binding.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/math_calculator.mojom.js"></script>
+<script>
+'use strict';
+
+function CalculatorImpl() {
+  this.total = 0;
+}
+
+CalculatorImpl.prototype.clear = function() {
+  this.total = 0;
+  return Promise.resolve({value: this.total});
+};
+
+CalculatorImpl.prototype.add = function(value) {
+  this.total += value;
+  return Promise.resolve({value: this.total});
+};
+
+CalculatorImpl.prototype.multiply = function(value) {
+  this.total *= value;
+  return Promise.resolve({value: this.total});
+};
+
+test(() => {
+  var binding = new mojo.Binding(math.Calculator, new CalculatorImpl());
+  assert_false(binding.isBound());
+
+  var calc = new math.CalculatorPtr();
+  var request = mojo.makeRequest(calc);
+  binding.bind(request);
+  assert_true(binding.isBound());
+
+  binding.close();
+  assert_false(binding.isBound());
+}, 'is bound');
+
+promise_test(async () => {
+  var calc1 = new math.CalculatorPtr();
+  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
+                                     mojo.makeRequest(calc1));
+  assert_equals((await calc1.add(2)).value, 2);
+
+  var calc2 = new math.CalculatorPtr();
+  calcBinding.bind(mojo.makeRequest(calc2));
+  assert_equals((await calc2.add(2)).value, 4);
+}, 'reusable');
+
+promise_test(async () => {
+  var calc = new math.CalculatorPtr();
+  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
+                                     mojo.makeRequest(calc));
+
+  await new Promise((resolve, reject) => {
+    calcBinding.setConnectionErrorHandler(() => { resolve(); });
+    calc.ptr.reset();
+  });
+}, 'connection error');
+
+promise_test(async () => {
+  var calc = new math.CalculatorPtr();
+  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
+                                     mojo.makeRequest(calc));
+
+  await new Promise((resolve, reject) => {
+    calcBinding.setConnectionErrorHandler(({customReason, description}) => {
+      assert_equals(customReason, 32);
+      assert_equals(description, 'goodbye');
+      resolve();
+    });
+    calc.ptr.resetWithReason({customReason: 32, description: 'goodbye'});
+  });
+}, 'connection error with reason');
+
+promise_test(async () => {
+  var calc = new math.CalculatorPtr();
+  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
+                                     mojo.makeRequest(calc));
+  assert_equals((await calc.add(2)).value, 2);
+
+  var interfaceRequest = calcBinding.unbind();
+  assert_false(calcBinding.isBound());
+
+  var newCalcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
+                                        interfaceRequest);
+  assert_equals((await calc.add(2)).value, 2);
+}, 'unbind');
+
+promise_test(async () => {
+  var calc1 = new math.CalculatorPtr();
+  var calc2 = new math.CalculatorPtr();
+  var calcImpl = new CalculatorImpl();
+
+  var bindingSet = new mojo.BindingSet(math.Calculator);
+  assert_true(bindingSet.isEmpty());
+
+  bindingSet.addBinding(calcImpl, mojo.makeRequest(calc1));
+  bindingSet.addBinding(calcImpl, mojo.makeRequest(calc2));
+  assert_false(bindingSet.isEmpty());
+
+  assert_equals((await calc1.add(3)).value, 3);
+  assert_equals((await calc2.add(4)).value, 7);
+
+  await new Promise((resolve, reject) => {
+    bindingSet.setConnectionErrorHandler(() => { resolve(); });
+    calc1.ptr.reset();
+  });
+
+  assert_equals((await calc2.add(5)).value, 12);
+
+  bindingSet.closeAllBindings();
+  assert_true(bindingSet.isEmpty());
+}, 'binding set');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/bindings-lite-modules.html b/third_party/blink/web_tests/http/tests/mojo/bindings-lite-modules.html
new file mode 100644
index 0000000..45a811b4
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/bindings-lite-modules.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script type="module">
+import '/gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js';
+import '/gen/content/test/data/lite_js_test.mojom-lite.js';
+import './bindings-lite-tests.js';
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/bindings-lite-old-names.html b/third_party/blink/web_tests/http/tests/mojo/bindings-lite-old-names.html
new file mode 100644
index 0000000..205ce28
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/bindings-lite-old-names.html
@@ -0,0 +1,209 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script>
+<script src="/gen/content/test/data/lite_js_old_names_test.mojom-lite.js"></script>
+<script>
+'use strict';
+
+const kTestMessage = 'hello there';
+const kTestNumbers = [0, 1, 1, 2, 3, 5, 8, 13, 21];
+
+class TargetImpl {
+  constructor() {
+    this.numPokes = 0;
+    this.target = new liteJsOldNamesTest.mojom.TestMessageTarget(this);
+  }
+
+  poke() { this.numPokes++; }
+  ping() { return Promise.resolve(); }
+  repeat(message, numbers) { return {message: message, numbers: numbers}; }
+  flatten(values) {}
+  flattenUnions(unions) {}
+  requestSubinterface(request, client) {}
+}
+
+promise_test(() => {
+  let impl = new TargetImpl;
+  let proxy = impl.target.$.createProxy();
+  proxy.poke();
+  return proxy.ping().then(() => {
+    assert_equals(impl.numPokes, 1);
+  });
+}, 'messages with replies return Promises that resolve on reply received');
+
+promise_test(() => {
+  let impl = new TargetImpl;
+  let proxy = impl.target.$.createProxy();
+  return proxy.repeat(kTestMessage, kTestNumbers)
+              .then(reply => {
+                assert_equals(reply.message, kTestMessage);
+                assert_array_equals(reply.numbers, kTestNumbers);
+              });
+}, 'implementations can reply with multiple reply arguments');
+
+promise_test(async (t) => {
+  const impl = new TargetImpl;
+  const proxy = impl.target.$.createProxy();
+
+  await proxy.ping();
+  proxy.$.close();
+
+  await promise_rejects(t, new Error(), proxy.ping());
+}, 'after the pipe is closed all future calls should fail');
+
+promise_test(async (t) => {
+  const impl = new TargetImpl;
+  const proxy = impl.target.$.createProxy();
+
+  // None of these promises should successfully resolve because we are
+  // immediately closing the pipe.
+  const promises = []
+  for (let i = 0; i < 10; i++) {
+    promises.push(proxy.ping());
+  }
+
+  proxy.$.close();
+
+  for (const promise of promises) {
+    await promise_rejects(t, new Error(), promise);
+  }
+}, 'closing the pipe drops any pending messages');
+
+promise_test(() => {
+  let impl = new TargetImpl;
+
+  // Intercept any browser-bound request for TestMessageTarget and bind it
+  // instead to the local |impl| object.
+  let interceptor = new MojoInterfaceInterceptor(
+    liteJsOldNamesTest.mojom.TestMessageTarget.$interfaceName);
+  interceptor.oninterfacerequest = e => {
+    impl.target.$.bindHandle(e.handle);
+  }
+  interceptor.start();
+
+  let proxy = liteJsOldNamesTest.mojom.TestMessageTarget.getProxy();
+  proxy.poke();
+
+  return proxy.ping().then(() => {
+    assert_equals(impl.numPokes, 1);
+  });
+}, 'getProxy() attempts to send requests to the frame host');
+
+promise_test(() => {
+  let router = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
+  let proxy = router.$.createProxy();
+  return new Promise(resolve => {
+    router.poke.addListener(resolve);
+    proxy.poke();
+  });
+}, 'basic generated CallbackRouter behavior works as intended');
+
+promise_test(() => {
+  let router = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
+  let proxy = router.$.createProxy();
+  let numPokes = 0;
+  router.poke.addListener(() => ++numPokes);
+  router.ping.addListener(() => Promise.resolve());
+  proxy.poke();
+  return proxy.ping().then(() => assert_equals(numPokes, 1));
+}, 'CallbackRouter listeners can reply to messages');
+
+promise_test(() => {
+  let router = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
+  let proxy = router.$.createProxy();
+  router.repeat.addListener(
+    (message, numbers) => ({message: message, numbers: numbers}));
+  return proxy.repeat(kTestMessage, kTestNumbers)
+              .then(reply => {
+                assert_equals(reply.message, kTestMessage);
+                assert_array_equals(reply.numbers, kTestNumbers);
+              });
+}, 'CallbackRouter listeners can reply with multiple reply arguments');
+
+promise_test(() => {
+  let targetRouter = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
+  let targetProxy = targetRouter.$.createProxy();
+  let subinterfaceRouter = new liteJsOldNamesTest.mojom.SubinterfaceCallbackRouter;
+  targetRouter.requestSubinterface.addListener((request, client) => {
+    let values = [];
+    subinterfaceRouter.$.bindHandle(request.handle);
+    subinterfaceRouter.push.addListener(value => values.push(value));
+    subinterfaceRouter.flush.addListener(() => {
+      client.didFlush(values);
+      values = [];
+    });
+  });
+
+  let clientRouter = new liteJsOldNamesTest.mojom.SubinterfaceClientCallbackRouter;
+  let subinterfaceProxy = new liteJsOldNamesTest.mojom.SubinterfaceProxy;
+  targetProxy.requestSubinterface(
+    subinterfaceProxy.$.createRequest(), clientRouter.$.createProxy());
+  return new Promise(resolve => {
+    clientRouter.didFlush.addListener(values => {
+      assert_array_equals(values, kTestNumbers);
+      resolve();
+    });
+
+    kTestNumbers.forEach(n => subinterfaceProxy.push(n));
+    subinterfaceProxy.flush();
+  });
+}, 'can send and receive interface requests and proxies');
+
+promise_test(() => {
+  const targetRouter = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
+  const targetProxy = targetRouter.$.createProxy();
+  targetRouter.flatten.addListener(values => ({values: values.map(v => v.x)}));
+  return targetProxy.flatten([{x: 1}, {x: 2}, {x: 3}]).then(reply => {
+    assert_array_equals(reply.values, [1, 2, 3]);
+  });
+}, 'regression test for complex array serialization');
+
+promise_test(() => {
+  const targetRouter = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
+  const targetProxy = targetRouter.$.createProxy();
+  targetRouter.flattenUnions.addListener(unions => {
+    return {x: unions.filter(u => u.x !== undefined).map(u => u.x),
+            s: unions.filter(u => u.s !== undefined).map(u => u.s.x)};
+  });
+
+  return targetProxy.flattenUnions(
+    [{x: 1}, {x: 2}, {s: {x: 3}}, {s: {x: 4}}, {x: 5}, {s: {x: 6}}])
+                    .then(reply => {
+                      assert_array_equals(reply.x, [1, 2, 5]);
+                      assert_array_equals(reply.s, [3, 4, 6]);
+                    });
+}, 'can serialize and deserialize unions');
+
+promise_test(() => {
+  let impl = new TargetImpl;
+  let proxy = impl.target.$.createProxy();
+
+  // Poke a bunch of times. These should never race with the assertion below,
+  // because the |flushForTesting| request/response is ordered against other
+  // messages on |proxy|.
+  const kNumPokes = 100;
+  for (let i = 0; i < kNumPokes; ++i)
+    proxy.poke();
+  return proxy.$.flushForTesting().then(() => {
+    assert_equals(impl.numPokes, kNumPokes);
+  });
+}, 'can use generated flushForTesting API for synchronization in tests');
+
+promise_test(async(t) => {
+  const impl = new TargetImpl;
+  const proxy = impl.target.$.createProxy();
+  const disconnectPromise = new Promise(resolve => impl.target.onConnectionError.addListener(resolve));
+  proxy.$.close();
+  return disconnectPromise;
+}, 'InterfaceTarget connection error handler runs when set on an Interface object');
+
+promise_test(() => {
+  const router = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
+  const proxy = router.$.createProxy();
+  const disconnectPromise = new Promise(resolve => router.onConnectionError.addListener(resolve));
+  proxy.$.close();
+  return disconnectPromise;
+}, 'InterfaceTarget connection error handler runs when set on an InterfaceCallbackRouter object');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/bindings-lite-sw.https.html b/third_party/blink/web_tests/http/tests/mojo/bindings-lite-sw.https.html
new file mode 100644
index 0000000..71cd4d0
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/bindings-lite-sw.https.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<script src = "/resources/testharness.js"></script>
+<script src = "/resources/testharnessreport.js"></script>
+<script src = "/serviceworker/resources/test-helpers.js"></script>
+<script>
+service_worker_test('./bindings-lite-sw.js');
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/bindings-lite-sw.js b/third_party/blink/web_tests/http/tests/mojo/bindings-lite-sw.js
new file mode 100644
index 0000000..943a2a5
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/bindings-lite-sw.js
@@ -0,0 +1,5 @@
+'use strict';
+importScripts('/resources/testharness.js');
+importScripts('/gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js');
+importScripts('/gen/content/test/data/lite_js_test.mojom-lite.js');
+importScripts('./bindings-lite-tests.js');
diff --git a/third_party/blink/web_tests/http/tests/mojo/bindings-lite-tests.js b/third_party/blink/web_tests/http/tests/mojo/bindings-lite-tests.js
new file mode 100644
index 0000000..cce7f4c
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/bindings-lite-tests.js
@@ -0,0 +1,213 @@
+'use strict';
+
+// These tests can be imported as a module or added as a script to tests lite
+// bindings.
+
+const kTestMessage = 'hello there';
+const kTestNumbers = [0, 1, 1, 2, 3, 5, 8, 13, 21];
+
+class TargetImpl {
+  constructor() {
+    this.numPokes = 0;
+    this.target = new liteJsTest.mojom.TestMessageTargetReceiver(this);
+  }
+
+  poke() { this.numPokes++; }
+  ping() { return Promise.resolve(); }
+  repeat(message, numbers) { return {message: message, numbers: numbers}; }
+  echo(nested) { return Promise.resolve({nested: nested}); }
+  flatten(values) {}
+  flattenUnions(unions) {}
+  requestSubinterface(request, client) {}
+}
+
+promise_test(() => {
+  let impl = new TargetImpl;
+  let remote = impl.target.$.bindNewPipeAndPassRemote();
+  remote.poke();
+  return remote.ping().then(() => {
+    assert_equals(impl.numPokes, 1);
+  });
+}, 'messages with replies return Promises that resolve on reply received');
+
+promise_test(() => {
+  let impl = new TargetImpl;
+  let remote = impl.target.$.bindNewPipeAndPassRemote();
+  return remote.repeat(kTestMessage, kTestNumbers)
+               .then(reply => {
+                 assert_equals(reply.message, kTestMessage);
+                 assert_array_equals(reply.numbers, kTestNumbers);
+               });
+}, 'implementations can reply with multiple reply arguments');
+
+promise_test(() => {
+  let impl = new TargetImpl;
+  let remote = impl.target.$.bindNewPipeAndPassRemote();
+  const enumValue = liteJsTest.mojom.TestMessageTarget_NestedEnum.kFoo;
+  return remote.echo(enumValue)
+               .then(({nested}) => assert_equals(nested, enumValue));
+}, 'nested enums are usable as arguments and responses.');
+
+promise_test(async (t) => {
+  const impl = new TargetImpl;
+  const remote = impl.target.$.bindNewPipeAndPassRemote();
+
+  await remote.ping();
+  remote.$.close();
+
+  await promise_rejects(t, new Error(), remote.ping());
+}, 'after the pipe is closed all future calls should fail');
+
+promise_test(async (t) => {
+  const impl = new TargetImpl;
+  const remote = impl.target.$.bindNewPipeAndPassRemote();
+
+  // None of these promises should successfully resolve because we are
+  // immediately closing the pipe.
+  const promises = []
+  for (let i = 0; i < 10; i++) {
+    promises.push(remote.ping());
+  }
+
+  remote.$.close();
+
+  for (const promise of promises) {
+    await promise_rejects(t, new Error(), promise);
+  }
+}, 'closing the pipe drops any pending messages');
+
+promise_test(() => {
+  let impl = new TargetImpl;
+
+  // Intercept any browser-bound request for TestMessageTarget and bind it
+  // instead to the local |impl| object.
+  let interceptor = new MojoInterfaceInterceptor(
+    liteJsTest.mojom.TestMessageTarget.$interfaceName);
+  interceptor.oninterfacerequest = e => {
+    impl.target.$.bindHandle(e.handle);
+  }
+  interceptor.start();
+
+  let remote = liteJsTest.mojom.TestMessageTarget.getRemote();
+  remote.poke();
+  return remote.ping().then(() => {
+    assert_equals(impl.numPokes, 1);
+  });
+}, 'getRemote() attempts to send requests to the frame host');
+
+promise_test(() => {
+  let router = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
+  let remote = router.$.bindNewPipeAndPassRemote();
+  return new Promise(resolve => {
+    router.poke.addListener(resolve);
+    remote.poke();
+  });
+}, 'basic generated CallbackRouter behavior works as intended');
+
+promise_test(() => {
+  let router = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
+  let remote = router.$.bindNewPipeAndPassRemote();
+  let numPokes = 0;
+  router.poke.addListener(() => ++numPokes);
+  router.ping.addListener(() => Promise.resolve());
+  remote.poke();
+  return remote.ping().then(() => assert_equals(numPokes, 1));
+}, 'CallbackRouter listeners can reply to messages');
+
+promise_test(() => {
+  let router = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
+  let remote = router.$.bindNewPipeAndPassRemote();
+  router.repeat.addListener(
+    (message, numbers) => ({message: message, numbers: numbers}));
+  return remote.repeat(kTestMessage, kTestNumbers)
+               .then(reply => {
+                 assert_equals(reply.message, kTestMessage);
+                 assert_array_equals(reply.numbers, kTestNumbers);
+               });
+}, 'CallbackRouter listeners can reply with multiple reply arguments');
+
+promise_test(() => {
+  let targetRouter = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
+  let targetRemote = targetRouter.$.bindNewPipeAndPassRemote();
+  let subinterfaceRouter = new liteJsTest.mojom.SubinterfaceCallbackRouter;
+  targetRouter.requestSubinterface.addListener((request, client) => {
+    let values = [];
+    subinterfaceRouter.$.bindHandle(request.handle);
+    subinterfaceRouter.push.addListener(value => values.push(value));
+    subinterfaceRouter.flush.addListener(() => {
+      client.didFlush(values);
+      values = [];
+    });
+  });
+
+  let clientRouter = new liteJsTest.mojom.SubinterfaceClientCallbackRouter;
+  let subinterfaceRemote = new liteJsTest.mojom.SubinterfaceRemote;
+  targetRemote.requestSubinterface(
+    subinterfaceRemote.$.bindNewPipeAndPassReceiver(),
+    clientRouter.$.bindNewPipeAndPassRemote());
+  return new Promise(resolve => {
+    clientRouter.didFlush.addListener(values => {
+      assert_array_equals(values, kTestNumbers);
+      resolve();
+    });
+
+    kTestNumbers.forEach(n => subinterfaceRemote.push(n));
+    subinterfaceRemote.flush();
+  });
+}, 'can send and receive interface requests and proxies');
+
+promise_test(() => {
+  const targetRouter = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
+  const targetRemote = targetRouter.$.bindNewPipeAndPassRemote();
+  targetRouter.flatten.addListener(values => ({values: values.map(v => v.x)}));
+  return targetRemote.flatten([{x: 1}, {x: 2}, {x: 3}]).then(reply => {
+    assert_array_equals(reply.values, [1, 2, 3]);
+  });
+}, 'regression test for complex array serialization');
+
+promise_test(() => {
+  const targetRouter = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
+  const targetRemote = targetRouter.$.bindNewPipeAndPassRemote();
+  targetRouter.flattenUnions.addListener(unions => {
+    return {x: unions.filter(u => u.x !== undefined).map(u => u.x),
+            s: unions.filter(u => u.s !== undefined).map(u => u.s.x)};
+  });
+
+  return targetRemote.flattenUnions(
+    [{x: 1}, {x: 2}, {s: {x: 3}}, {s: {x: 4}}, {x: 5}, {s: {x: 6}}])
+                     .then(reply => {
+                       assert_array_equals(reply.x, [1, 2, 5]);
+                       assert_array_equals(reply.s, [3, 4, 6]);
+                     });
+}, 'can serialize and deserialize unions');
+
+promise_test(() => {
+  let impl = new TargetImpl;
+  let remote = impl.target.$.bindNewPipeAndPassRemote();
+
+  // Poke a bunch of times. These should never race with the assertion below,
+  // because the |flushForTesting| request/response is ordered against other
+  // messages on |remote|.
+  const kNumPokes = 100;
+  for (let i = 0; i < kNumPokes; ++i)
+    remote.poke();
+  return remote.$.flushForTesting().then(() => {
+    assert_equals(impl.numPokes, kNumPokes);
+  });
+}, 'can use generated flushForTesting API for synchronization in tests');
+
+promise_test(async(t) => {
+  const impl = new TargetImpl;
+  const remote = impl.target.$.bindNewPipeAndPassRemote();
+  const disconnectPromise = new Promise(resolve => impl.target.onConnectionError.addListener(resolve));
+  remote.$.close();
+  return disconnectPromise;
+}, 'InterfaceTarget connection error handler runs when set on an Interface object');
+
+promise_test(() => {
+  const router = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
+  const remote = router.$.bindNewPipeAndPassRemote();
+  const disconnectPromise = new Promise(resolve => router.onConnectionError.addListener(resolve));
+  remote.$.close();
+  return disconnectPromise;
+}, 'InterfaceTarget connection error handler runs when set on an InterfaceCallbackRouter object');
diff --git a/third_party/blink/web_tests/http/tests/mojo/bindings-lite.html b/third_party/blink/web_tests/http/tests/mojo/bindings-lite.html
new file mode 100644
index 0000000..1fd0c183
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/bindings-lite.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script>
+<script src="/gen/content/test/data/lite_js_test.mojom-lite.js"></script>
+<script src="./bindings-lite-tests.js"></script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/codec.html b/third_party/blink/web_tests/http/tests/mojo/codec.html
new file mode 100644
index 0000000..4398ce2
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/codec.html
@@ -0,0 +1,319 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/js-test-resources/testharness-helpers.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/test_structs.mojom.js"></script>
+<script>
+'use strict';
+
+test(() => {
+  var bar = new sample.Bar();
+  bar.alpha = 1;
+  bar.beta = 2;
+  bar.gamma = 3;
+  bar.type = 0x08070605;
+  bar.extraProperty = "banana";
+
+  var messageName = 42;
+  var payloadSize = sample.Bar.encodedSize;
+
+  var builder = new mojo.internal.MessageV0Builder(messageName, payloadSize);
+  builder.encodeStruct(sample.Bar, bar);
+
+  var message = builder.finish();
+
+  var expectedMemory = new Uint8Array([
+    24, 0, 0, 0,
+     0, 0, 0, 0,
+     0, 0, 0, 0,
+    42, 0, 0, 0,
+     0, 0, 0, 0,
+     0, 0, 0, 0,
+
+    16, 0, 0, 0,
+     0, 0, 0, 0,
+
+     1, 2, 3, 0,
+     5, 6, 7, 8,
+  ]);
+
+  var actualMemory = new Uint8Array(message.buffer.arrayBuffer);
+  assert_weak_equals(actualMemory, expectedMemory);
+
+  var reader = new mojo.internal.MessageReader(message);
+
+  assert_equals(reader.payloadSize, payloadSize);
+  assert_equals(reader.messageName, messageName);
+
+  var bar2 = reader.decodeStruct(sample.Bar);
+
+  assert_equals(bar2.alpha, bar.alpha);
+  assert_equals(bar2.beta, bar.beta);
+  assert_equals(bar2.gamma, bar.gamma);
+  assert_false("extraProperty" in bar2);
+}, 'bar');
+
+test(() => {
+  var foo = new sample.Foo();
+  foo.x = 0x212B4D5;
+  foo.y = 0x16E93;
+  foo.a = 1;
+  foo.b = 0;
+  foo.c = 3; // This will get truncated to one bit.
+  foo.bar = new sample.Bar();
+  foo.bar.alpha = 91;
+  foo.bar.beta = 82;
+  foo.bar.gamma = 73;
+  foo.data = [
+    4, 5, 6, 7, 8,
+  ];
+  foo.extraBars = [
+    new sample.Bar(), new sample.Bar(), new sample.Bar(),
+  ];
+  for (var i = 0; i < foo.extraBars.length; ++i) {
+    foo.extraBars[i].alpha = 1 * i;
+    foo.extraBars[i].beta = 2 * i;
+    foo.extraBars[i].gamma = 3 * i;
+  }
+  foo.name = "I am a banana";
+  // This is supposed to be a handle, but we fake it with an integer.
+  foo.source = 23423782;
+  foo.arrayOfArrayOfBools = [
+    [true], [false, true]
+  ];
+  foo.arrayOfBools = [
+    true, false, true, false, true, false, true, true
+  ];
+
+
+  var messageName = 31;
+  var payloadSize = 304;
+
+  var builder = new mojo.internal.MessageV0Builder(messageName, payloadSize);
+  builder.encodeStruct(sample.Foo, foo);
+
+  var message = builder.finish();
+
+  var expectedMemory = new Uint8Array([
+    /*  0: */   24,    0,    0,    0,    0,    0,    0,    0,
+    /*  8: */    0,    0,    0,    0,   31,    0,    0,    0,
+    /* 16: */    0,    0,    0,    0,    0,    0,    0,    0,
+    /* 24: */   96,    0,    0,    0,    0,    0,    0,    0,
+    /* 32: */ 0xD5, 0xB4, 0x12, 0x02, 0x93, 0x6E, 0x01,    0,
+    /* 40: */    5,    0,    0,    0,    0,    0,    0,    0,
+    /* 48: */   72,    0,    0,    0,    0,    0,    0,    0,
+  ]);
+  // TODO(abarth): Test more of the message's raw memory.
+  var actualMemory = new Uint8Array(message.buffer.arrayBuffer,
+                                    0, expectedMemory.length);
+  assert_weak_equals(actualMemory, expectedMemory);
+
+  var expectedHandles = [
+    23423782,
+  ];
+
+  assert_weak_equals(message.handles, expectedHandles);
+
+  var reader = new mojo.internal.MessageReader(message);
+
+  assert_equals(reader.payloadSize, payloadSize);
+  assert_equals(reader.messageName, messageName);
+
+  var foo2 = reader.decodeStruct(sample.Foo);
+
+  assert_equals(foo2.x, foo.x);
+  assert_equals(foo2.y, foo.y);
+
+  assert_equals(foo2.a, foo.a & 1 ? true : false);
+  assert_equals(foo2.b, foo.b & 1 ? true : false);
+  assert_equals(foo2.c, foo.c & 1 ? true : false);
+
+  assert_weak_equals(foo2.bar, foo.bar);
+  assert_weak_equals(foo2.data, foo.data);
+
+  assert_weak_equals(foo2.extraBars, foo.extraBars);
+  assert_equals(foo2.name, foo.name);
+  assert_equals(foo2.source, foo.source);
+
+  assert_weak_equals(foo2.arrayOfBools, foo.arrayOfBools);
+}, 'foo');
+
+
+// Verify that the references to the imported Rect type in test_structs.mojom
+// are generated correctly.
+test(() => {
+
+  function createRect(x, y, width, height) {
+    var r = new mojo.test.Rect();
+    r.x = x;
+    r.y = y;
+    r.width = width;
+    r.height = height;
+    return r;
+  }
+
+  var r = new mojo.test.NamedRegion();
+  r.name = "rectangle";
+  r.rects = new Array(createRect(1, 2, 3, 4), createRect(10, 20, 30, 40));
+
+  var builder = new mojo.internal.MessageV0Builder(
+      1, mojo.test.NamedRegion.encodedSize);
+  builder.encodeStruct(mojo.test.NamedRegion, r);
+  var reader = new mojo.internal.MessageReader(builder.finish());
+  var result = reader.decodeStruct(mojo.test.NamedRegion);
+
+  assert_equals(result.name, "rectangle");
+  assert_weak_equals(result.rects[0], createRect(1, 2, 3, 4));
+  assert_weak_equals(result.rects[1], createRect(10, 20, 30, 40));
+}, 'named region');
+
+// Verify that a single boolean field in a struct is correctly decoded to
+// boolean type.
+test(() => {
+  var singleBool = new mojo.test.SingleBoolStruct();
+  singleBool.value = true;
+
+  var builder = new mojo.internal.MessageV0Builder(
+      1, mojo.test.SingleBoolStruct.encodedSize);
+  builder.encodeStruct(mojo.test.SingleBoolStruct, singleBool);
+  var reader = new mojo.internal.MessageReader(builder.finish());
+  var result = reader.decodeStruct(mojo.test.SingleBoolStruct);
+
+  assert_true(result.value);
+}, 'single boolean struct');
+
+test(() => {
+  function encodeDecode(cls, input, expectedResult, encodedSize) {
+    var messageName = 42;
+    var payloadSize = encodedSize || cls.encodedSize;
+
+    var builder = new mojo.internal.MessageV0Builder(messageName, payloadSize);
+    builder.encodeStruct(cls, input)
+    var message = builder.finish();
+
+    var reader = new mojo.internal.MessageReader(message);
+    assert_equals(reader.payloadSize, payloadSize);
+    assert_equals(reader.messageName, messageName);
+    var result = reader.decodeStruct(cls);
+    assert_equals(result, expectedResult);
+  }
+  encodeDecode(mojo.internal.String, "banana", "banana", 24);
+  encodeDecode(mojo.internal.NullableString, null, null, 8);
+  encodeDecode(mojo.internal.Int8, -1, -1);
+  encodeDecode(mojo.internal.Int8, 0xff, -1);
+  encodeDecode(mojo.internal.Int16, -1, -1);
+  encodeDecode(mojo.internal.Int16, 0xff, 0xff);
+  encodeDecode(mojo.internal.Int16, 0xffff, -1);
+  encodeDecode(mojo.internal.Int32, -1, -1);
+  encodeDecode(mojo.internal.Int32, 0xffff, 0xffff);
+  encodeDecode(mojo.internal.Int32, 0xffffffff, -1);
+  encodeDecode(mojo.internal.Float, 1.0, 1.0);
+  encodeDecode(mojo.internal.Double, 1.0, 1.0);
+}, 'types');
+
+test(() => {
+  var aligned = [
+    0, // 0
+    8, // 1
+    8, // 2
+    8, // 3
+    8, // 4
+    8, // 5
+    8, // 6
+    8, // 7
+    8, // 8
+    16, // 9
+    16, // 10
+    16, // 11
+    16, // 12
+    16, // 13
+    16, // 14
+    16, // 15
+    16, // 16
+    24, // 17
+    24, // 18
+    24, // 19
+    24, // 20
+  ];
+  for (var i = 0; i < aligned.length; ++i)
+    assert_equals(mojo.internal.align(i), aligned[i]);
+
+}, 'align');
+
+test(() => {
+  var str = "B\u03ba\u1f79";  // some UCS-2 codepoints
+  var messageName = 42;
+  var payloadSize = 24;
+
+  var builder = new mojo.internal.MessageV0Builder(messageName, payloadSize);
+  var encoder = builder.createEncoder(8);
+  encoder.encodeStringPointer(str);
+  var message = builder.finish();
+  var expectedMemory = new Uint8Array([
+    /*  0: */   24,    0,    0,    0,    0,    0,    0,    0,
+    /*  8: */    0,    0,    0,    0,   42,    0,    0,    0,
+    /* 16: */    0,    0,    0,    0,    0,    0,    0,    0,
+    /* 24: */    8,    0,    0,    0,    0,    0,    0,    0,
+    /* 32: */   14,    0,    0,    0,    6,    0,    0,    0,
+    /* 40: */ 0x42, 0xCE, 0xBA, 0xE1, 0xBD, 0xB9,    0,    0,
+  ]);
+  var actualMemory = new Uint8Array(message.buffer.arrayBuffer);
+  assert_weak_equals(actualMemory, expectedMemory);
+
+  var reader = new mojo.internal.MessageReader(message);
+  assert_equals(reader.payloadSize, payloadSize);
+  assert_equals(reader.messageName, messageName);
+  var str2 = reader.decoder.decodeStringPointer();
+  assert_equals(str2, str);
+}, 'utf8');
+
+test(() => {
+  var str = "Hello world ".repeat(100000);
+  var messageName = 42;
+  var payloadSize = 1200000;
+
+  var builder = new mojo.internal.MessageV0Builder(messageName, payloadSize);;
+  var encoder = builder.createEncoder(1200000);
+  encoder.encodeStringPointer(str);
+  var message = builder.finish();
+
+  var reader = new mojo.internal.MessageReader(message);
+  var str2 = reader.decoder.decodeStringPointer();
+  assert_equals(str2, str);
+}, 'very long utf8');
+
+test(() => {
+  var encoder = new mojo.internal.MessageV0Builder(42, 24).createEncoder(8);
+  function DummyClass() {};
+  var testCases = [
+    // method, args, invalid examples, valid examples
+    [encoder.encodeArrayPointer, [DummyClass], [75],
+        [[], null, undefined, new Uint8Array([])]],
+    [encoder.encodeStringPointer, [], [75, new String("foo")],
+        ["", "bar", null, undefined]],
+    [encoder.encodeMapPointer, [DummyClass, DummyClass], [75],
+        [new Map(), null, undefined]],
+  ];
+
+  testCases.forEach(function(test) {
+    var method = test[0];
+    var baseArgs = test[1];
+    var invalidExamples = test[2];
+    var validExamples = test[3];
+
+    var encoder = new mojo.internal.MessageV0Builder(42, 24).createEncoder(8);
+    invalidExamples.forEach(function(invalid) {
+      assert_throws(new Error, function() {
+        method.apply(encoder, baseArgs.concat(invalid));
+      });
+    });
+
+    validExamples.forEach(function(valid) {
+      var encoder = new mojo.internal.MessageV0Builder(42, 24).createEncoder(8);
+      method.apply(encoder, baseArgs.concat(valid));
+    });
+  });
+}, 'typed pointer validation');
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/connection.html b/third_party/blink/web_tests/http/tests/mojo/connection.html
new file mode 100644
index 0000000..17ea1dc
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/connection.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.js"></script>
+<script>
+'use strict';
+
+promise_test(async () => {
+  function ServiceImpl() {
+  }
+
+  ServiceImpl.prototype.frobinate = function(foo, baz, port) {
+    assert_equals(foo.name, "Example name");
+    assert_equals(baz, sample.Service.BazOptions.REGULAR);
+    assert_true(port.ptr.isBound());
+    port.ptr.reset();
+
+    return Promise.resolve({result: 42});
+  };
+
+  var service = new sample.ServicePtr();
+  var serviceBinding = new mojo.Binding(
+      sample.Service, new ServiceImpl(), mojo.makeRequest(service));
+  var sourcePipe = Mojo.createMessagePipe();
+  var port = new sample.PortPtr();
+  var portRequest = mojo.makeRequest(port);
+
+  var foo = new sample.Foo();
+  foo.bar = new sample.Bar();
+  foo.name = "Example name";
+  foo.source = sourcePipe.handle0;
+
+  assert_equals((await service.frobinate(
+      foo, sample.Service.BazOptions.REGULAR, port)).result, 42);
+
+  service.ptr.reset();
+  serviceBinding.close();
+
+  // sourcePipe.handle1 hasn't been closed yet.
+  sourcePipe.handle1.close();
+
+  // portRequest.handle hasn't been closed yet.
+  portRequest.handle.close();
+}, 'client server');
+
+promise_test(async () => {
+  var service = new sample.ServicePtr();
+  // Discard the interface request.
+  var interfaceRequest = mojo.makeRequest(service);
+  interfaceRequest.close();
+
+  try {
+    await service.frobinate(null, sample.Service.BazOptions.REGULAR, null);
+    assert_unreached();
+  } catch (e) {
+    assert_not_equals(e, null);
+  }
+}, 'write to closed pipe');
+
+promise_test(async () => {
+  function ProviderImpl() {
+  }
+
+  ProviderImpl.prototype.echoString = function(a) {
+    return Promise.resolve({a: a});
+  };
+
+  ProviderImpl.prototype.echoStrings = function(a, b) {
+    return Promise.resolve({a: a, b: b});
+  };
+
+  var provider = new sample.ProviderPtr();
+  var providerBinding = new mojo.Binding(
+      sample.Provider, new ProviderImpl(), mojo.makeRequest(provider));
+  assert_equals((await provider.echoString("hello")).a, "hello");
+  var response = await provider.echoStrings("hello", "world");
+  assert_equals(response.a, "hello");
+  assert_equals(response.b, "world");
+}, 'request response');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/data-pipe.html b/third_party/blink/web_tests/http/tests/mojo/data-pipe.html
new file mode 100644
index 0000000..93f26c4
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/data-pipe.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<title>Mojo data pipe tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+let kElementNumBytes = 1;
+let kCapacityNumBytes = 64;
+
+function createDataPipe() {
+  return Mojo.createDataPipe({
+      elementNumBytes: kElementNumBytes,
+      capacityNumBytes: kCapacityNumBytes
+  });
+};
+
+test(() => {
+  let {result, producer, consumer} = createDataPipe();
+  assert_equals(result, Mojo.RESULT_OK);
+  assert_true(producer instanceof MojoHandle);
+  assert_true(consumer instanceof MojoHandle);
+}, "Create data pipe");
+
+test(() => {
+  assert_equals(Mojo.createDataPipe({}).result, Mojo.RESULT_INVALID_ARGUMENT);
+  assert_equals(Mojo.createDataPipe({elementNumBytes: kElementNumBytes}).result,
+                Mojo.RESULT_INVALID_ARGUMENT);
+  assert_equals(
+      Mojo.createDataPipe({capacityNumBytes: kCapacityNumBytes}).result,
+      Mojo.RESULT_INVALID_ARGUMENT);
+})
+
+test(() => {
+  let {producer, consumer} = createDataPipe();
+  let data = new Uint8Array(kCapacityNumBytes);
+
+  let {result, numBytes} = producer.writeData(data);
+  assert_equals(result, Mojo.RESULT_OK);
+  assert_equals(numBytes, data.length);
+}, "Write data");
+
+test(() => {
+  let {producer, consumer} = createDataPipe();
+  let data = new Uint8Array(kCapacityNumBytes + 1);
+
+  let {result, numBytes} = producer.writeData(data, {allOrNone: true});
+  assert_equals(result, Mojo.RESULT_OUT_OF_RANGE);
+  assert_equals(numBytes, 0);
+}, "Write data all or none");
+
+async_test((test) => {
+  let {producer, consumer} = createDataPipe();
+  let data = new Uint8Array(kCapacityNumBytes);
+
+  consumer.watch({readable: true}, test.step_func_done((result) => {
+    var {result, numBytes} = consumer.queryData();
+    assert_equals(result, Mojo.RESULT_OK);
+    assert_equals(numBytes, data.length);
+  }));
+  producer.writeData(data);
+}, "Query data");
+
+async_test((test) => {
+  let {producer, consumer} = createDataPipe();
+  let data = new Uint8Array(kCapacityNumBytes);
+  for (let i = 0; i < data.length; ++i)
+    data[i] = i;
+
+  consumer.watch({readable: true}, test.step_func_done((result) => {
+    var kDiscardNumBytes = data.length / 2;
+
+    var {result, numBytes} = consumer.discardData(kDiscardNumBytes);
+    assert_equals(result, Mojo.RESULT_OK);
+    assert_equals(numBytes, kDiscardNumBytes);
+
+    var {result, numBytes} = consumer.queryData();
+    assert_equals(result, Mojo.RESULT_OK);
+    assert_equals(numBytes, kDiscardNumBytes);
+
+    var buffer = new Uint8Array(kDiscardNumBytes);
+    var {result, numBytes} = consumer.readData(buffer);
+    assert_equals(result, Mojo.RESULT_OK);
+    assert_equals(numBytes, kDiscardNumBytes);
+    assert_array_equals(buffer, data.slice(kDiscardNumBytes));
+  }));
+  producer.writeData(data);
+}, "Discard data");
+
+async_test((test) => {
+  let {producer, consumer} = createDataPipe();
+  let data = new Uint8Array(kCapacityNumBytes);
+
+  consumer.watch({readable: true}, test.step_func_done((result) => {
+    var {result, numBytes} = consumer.discardData(data.length + 1, {allOrNone: true});
+    assert_equals(result, Mojo.RESULT_OUT_OF_RANGE);
+    assert_equals(numBytes, 0);
+  }));
+  producer.writeData(data);
+}, "Discard data all or none");
+
+async_test((test) => {
+  let {producer, consumer} = createDataPipe();
+  let data = new Uint8Array(kCapacityNumBytes);
+  for (let i = 0; i < data.length; ++i)
+    data[i] = i;
+
+  consumer.watch({readable: true}, test.step_func_done((result) => {
+    var buffer = new Uint8Array(data.length);
+    var {result, numBytes} = consumer.readData(buffer);
+    assert_equals(result, Mojo.RESULT_OK);
+    assert_equals(numBytes, data.length);
+    assert_array_equals(buffer, data);
+
+    var {result, numBytes} = consumer.queryData();
+    assert_equals(result, Mojo.RESULT_OK);
+    assert_equals(numBytes, 0);
+  }));
+  producer.writeData(data);
+}, "Read data");
+
+async_test((test) => {
+  let {producer, consumer} = createDataPipe();
+  let data = new Uint8Array(kCapacityNumBytes);
+
+  consumer.watch({readable: true}, test.step_func_done((result) => {
+    var buffer = new Uint8Array(data.length + 1);
+    var {result, numBytes} = consumer.readData(buffer, {allOrNone: true});
+    assert_equals(result, Mojo.RESULT_OUT_OF_RANGE);
+    assert_equals(numBytes, 0);
+  }));
+  producer.writeData(data);
+}, "Read data all or none");
+
+async_test((test) => {
+  let {producer, consumer} = createDataPipe();
+  let data = new Uint8Array(kCapacityNumBytes);
+  for (let i = 0; i < data.length; ++i)
+    data[i] = i;
+
+  consumer.watch({readable: true}, test.step_func_done((result) => {
+    var buffer = new Uint8Array(data.length);
+    var {result, numBytes} = consumer.readData(buffer, {peek: true});
+    assert_equals(result, Mojo.RESULT_OK);
+    assert_equals(numBytes, data.length);
+    assert_array_equals(buffer, data);
+
+    var {result, numBytes} = consumer.queryData();
+    assert_equals(result, Mojo.RESULT_OK);
+    assert_equals(numBytes, data.length);
+  }));
+  producer.writeData(data);
+}, "Peek data");
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/detached-frame.html b/third_party/blink/web_tests/http/tests/mojo/detached-frame.html
new file mode 100644
index 0000000..5b015ef
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/detached-frame.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/content/test/data/mojo_web_test_helper_test.mojom.js"></script>
+<body>
+<script>
+
+function frameLoaded(frame) {
+  return new Promise(resolve => {
+    let eventHandler = e => {
+      frame.removeEventListener('load', eventHandler);
+      resolve();
+    };
+    frame.addEventListener('load', eventHandler);
+  });
+}
+
+promise_test(async () => {
+  let frame = document.createElement("iframe");
+  let promise = frameLoaded(frame);
+  document.body.appendChild(frame);
+  await promise;
+
+  // Save a reference to the Mojo object from the child frame so that we can
+  // make calls to it after the context has been destroyed.
+  let frameMojo = frame.contentWindow.Mojo;
+  document.body.removeChild(frame);
+
+  let helper = new content.mojom.MojoWebTestHelperPtr;
+  frameMojo.bindInterface(content.mojom.MojoWebTestHelper.name,
+                          mojo.makeRequest(helper).handle);
+
+  try {
+    let reply = await helper.reverse("hello world.");
+    assert_unreached();
+  } catch (e) {
+    // Connection failure expected.
+  }
+}, "Mojo object is safe to use after its frame has been detached");
+
+promise_test(async () => {
+  let frame = document.createElement("iframe");
+  let promise = frameLoaded(frame);
+  document.body.appendChild(frame);
+  await promise;
+
+  // Save a reference to the MojoInterfaceInterceptor constructor from the child
+  // frame so that we can be used after the context has been destroyed.
+  let frameMojoInterfaceInterceptor =
+      frame.contentWindow.MojoInterfaceInterceptor;
+  document.body.removeChild(frame);
+
+  let interceptor = new frameMojoInterfaceInterceptor(
+      content.mojom.MojoWebTestHelper.name);
+  try {
+    interceptor.start();
+    assert_unreached();
+  } catch (e) {
+    // Failure expected.
+  }
+}, "MojoInterfaceInterceptor constructor is safe to use after its frame has been detached");
+
+promise_test(async () => {
+  let frame = document.createElement("iframe");
+  let promise = frameLoaded(frame);
+  document.body.appendChild(frame);
+  await promise;
+
+  // Create the interceptor while the frame is attached so that it is associated
+  // with the frame's execution context.
+  let interceptor = new frame.contentWindow.MojoInterfaceInterceptor(
+      content.mojom.MojoWebTestHelper.name);
+  document.body.removeChild(frame);
+
+  try {
+    interceptor.start();
+    assert_unreached();
+  } catch (e) {
+    // Failure expected.
+  }
+}, "MojoInterfaceInterceptor can't be started after its frame has been detached");
+
+promise_test(async () => {
+  let frame = document.createElement("iframe");
+  let promise = frameLoaded(frame);
+  document.body.appendChild(frame);
+  await promise;
+
+  // Create the interceptor and start it while the frame is attached.
+  let interceptor = new frame.contentWindow.MojoInterfaceInterceptor(
+      content.mojom.MojoWebTestHelper.name);
+  interceptor.start();
+  document.body.removeChild(frame);
+
+  // stop() will succeed because it is implicitly called when the execution
+  // context is destroyed.
+  interceptor.stop();
+}, "MojoInterfaceInterceptor is stopped on frame destruction");
+
+</script>
+</body>
diff --git a/third_party/blink/web_tests/http/tests/mojo/document-interface-broker-override.html b/third_party/blink/web_tests/http/tests/mojo/document-interface-broker-override.html
new file mode 100644
index 0000000..930f4a2
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/document-interface-broker-override.html
@@ -0,0 +1,43 @@
+<body>
+<script src="/js-test-resources/document-interface-broker-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script>
+<script src="/gen/mojo/public/mojom/base/unguessable_token.mojom-lite.js"></script>
+<script src="/gen/url/mojom/url.mojom-lite.js"></script>
+<script src="/gen/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom-lite.js"></script>
+<script src="/gen/third_party/blink/public/mojom/frame/document_interface_broker.mojom-lite.js"></script>
+<script>
+'use strict';
+
+promise_test(async t => {
+  // Create a test implementation of FrameHostTestInterface
+  const frameHostTestImpl = new blink.mojom.FrameHostTestInterfaceCallbackRouter;
+  frameHostTestImpl.getName.addListener(() => ({ name: 'TestFrameHostTestImpl' }));
+
+  const broker = new blink.mojom.DocumentInterfaceBrokerRemote(
+      Mojo.getDocumentInterfaceBrokerHandle());
+
+  const testInterfaceBeforeOverride = new blink.mojom.FrameHostTestInterfaceRemote;
+  broker.getFrameHostTestInterface(testInterfaceBeforeOverride.$.bindNewPipeAndPassReceiver());
+
+  setDocumentInterfaceBrokerOverrides({ getFrameHostTestInterface: request => {
+    frameHostTestImpl.$.bindHandle(request.handle);
+  }});
+
+  const testInterfaceAfterOverride = new blink.mojom.FrameHostTestInterfaceRemote;
+  broker.getFrameHostTestInterface(testInterfaceAfterOverride.$.bindNewPipeAndPassReceiver());
+
+  // Verify that RenderFrameHostImpl's implementation gets called without an override
+  let reply = await testInterfaceBeforeOverride.getName();
+  assert_equals(reply.name, 'RenderFrameHostImpl');
+
+  // Verify that the test implementation gets called after the override
+  reply = await testInterfaceAfterOverride.getName();
+  assert_equals(reply.name, 'TestFrameHostTestImpl');
+},
+'Appropriate DocumentInterfaceBroker implementations are called before and after overriding');
+
+</script>
+ </body>
+ </html>
diff --git a/third_party/blink/web_tests/http/tests/mojo/interface_ptr.html b/third_party/blink/web_tests/http/tests/mojo/interface_ptr.html
new file mode 100644
index 0000000..92043a3
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/interface_ptr.html
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/math_calculator.mojom.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.js"></script>
+<script>
+'use strict';
+
+function CalculatorImpl() {
+  this.total = 0;
+}
+
+CalculatorImpl.prototype.clear = function() {
+  this.total = 0;
+  return Promise.resolve({value: this.total});
+};
+
+CalculatorImpl.prototype.add = function(value) {
+  this.total += value;
+  return Promise.resolve({value: this.total});
+};
+
+CalculatorImpl.prototype.multiply = function(value) {
+  this.total *= value;
+  return Promise.resolve({value: this.total});
+};
+
+function IntegerAccessorImpl() {
+  this.integer = 0;
+}
+
+IntegerAccessorImpl.prototype.getInteger = function() {
+  return Promise.resolve({data: this.integer});
+};
+
+IntegerAccessorImpl.prototype.setInteger = function(value) {
+  this.integer = value;
+};
+
+test(() => {
+  var calc = new math.CalculatorPtr();
+  assert_false(calc.ptr.isBound());
+
+  var request = mojo.makeRequest(calc);
+  assert_true(calc.ptr.isBound());
+
+  calc.ptr.reset();
+  assert_false(calc.ptr.isBound());
+}, 'is bound');
+
+promise_test(async () => {
+  var calc = new math.CalculatorPtr();
+  var calcBinding = new mojo.Binding(
+      math.Calculator, new CalculatorImpl(), mojo.makeRequest(calc));
+
+  assert_equals((await calc.add(2)).value, 2);
+  assert_equals((await calc.multiply(5)).value, 10);
+  assert_equals((await calc.clear()).value, 0);
+}, 'end to end');
+
+promise_test(async () => {
+  var calc = new math.CalculatorPtr();
+  var calcImpl1 = new CalculatorImpl();
+  var calcBinding1 = new mojo.Binding(math.Calculator, calcImpl1,
+                                      mojo.makeRequest(calc));
+  var calcImpl2 = new CalculatorImpl();
+  var calcBinding2 = new mojo.Binding(math.Calculator, calcImpl2);
+
+  assert_equals((await calc.add(2)).value, 2);
+  calcBinding2.bind(mojo.makeRequest(calc));
+  assert_equals((await calc.add(2)).value, 2);
+  assert_equals(calcImpl1.total, 2);
+  assert_equals(calcImpl2.total, 2);
+}, 'reusable');
+
+promise_test(async () => {
+  var calc = new math.CalculatorPtr();
+  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
+                                     mojo.makeRequest(calc));
+
+  await new Promise((resolve, reject) => {
+    calc.ptr.setConnectionErrorHandler(() => { resolve(); });
+    calcBinding.close();
+  });
+}, 'connection error');
+
+promise_test(async () => {
+  var calc = new math.CalculatorPtr();
+  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
+                                     mojo.makeRequest(calc));
+
+  await new Promise((resolve, reject) => {
+    calc.ptr.setConnectionErrorHandler(({customReason, description}) => {
+      assert_equals(customReason, 42);
+      assert_equals(description, 'hey');
+      resolve();
+    });
+    calcBinding.closeWithReason({customReason: 42, description: 'hey'});
+  });
+}, 'connection error with reason');
+
+promise_test(async () => {
+  var calc = new math.CalculatorPtr();
+  var newCalc = null;
+  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
+                                     mojo.makeRequest(calc));
+
+  assert_equals((await calc.add(2)).value, 2);
+  newCalc = new math.CalculatorPtr();
+  newCalc.ptr.bind(calc.ptr.passInterface());
+  assert_false(calc.ptr.isBound());
+  assert_equals((await newCalc.add(2)).value, 4);
+
+}, 'pass interface');
+
+promise_test(async () => {
+  var pipe = Mojo.createMessagePipe();
+  var calc = new math.CalculatorPtr(pipe.handle0);
+  var newCalc = null;
+  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
+                                     pipe.handle1);
+
+  assert_equals((await calc.add(2)).value, 2);
+
+}, 'bind raw handle');
+
+promise_test(async () => {
+  var integerAccessorPtr = new sample.IntegerAccessorPtr();
+
+  var integerAccessorBinding = new mojo.Binding(
+      sample.IntegerAccessor, new IntegerAccessorImpl(),
+      mojo.makeRequest(integerAccessorPtr));
+  assert_equals(integerAccessorPtr.ptr.version, 0);
+
+  assert_equals(await integerAccessorPtr.ptr.queryVersion(), 3);
+  assert_equals(integerAccessorPtr.ptr.version, 3);
+}, 'query version');
+
+promise_test(async () => {
+  var integerAccessorImpl = new IntegerAccessorImpl();
+  var integerAccessorPtr = new sample.IntegerAccessorPtr();
+  var integerAccessorBinding = new mojo.Binding(
+      sample.IntegerAccessor, integerAccessorImpl,
+      mojo.makeRequest(integerAccessorPtr));
+
+  // Inital version is 0.
+  assert_equals(integerAccessorPtr.ptr.version, 0);
+
+  integerAccessorPtr.ptr.requireVersion(1);
+  assert_equals(integerAccessorPtr.ptr.version, 1);
+  integerAccessorPtr.setInteger(123, sample.Enum.VALUE);
+  assert_equals((await integerAccessorPtr.getInteger()).data, 123);
+
+  integerAccessorPtr.ptr.requireVersion(3);
+  assert_equals(integerAccessorPtr.ptr.version, 3);
+  integerAccessorPtr.setInteger(456, sample.Enum.VALUE);
+  assert_equals((await integerAccessorPtr.getInteger()).data, 456);
+
+  // Require a version that is not supported by the impl side.
+  integerAccessorPtr.ptr.requireVersion(4);
+  assert_equals(integerAccessorPtr.ptr.version, 4);
+  integerAccessorPtr.setInteger(789, sample.Enum.VALUE);
+
+  await new Promise((resolve, reject) => {
+    integerAccessorPtr.ptr.setConnectionErrorHandler(() => {
+      resolve();
+    });
+  });
+  assert_equals(integerAccessorImpl.integer, 456);
+
+}, 'require version');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/lite/constants.html b/third_party/blink/web_tests/http/tests/mojo/lite/constants.html
new file mode 100644
index 0000000..fa6424b3
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/lite/constants.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script>
+<script src="/gen/mojo/public/js/ts/bindings/tests/constants.test-mojom-lite.js"></script>
+<script>
+'use strict';
+
+[{
+  constant: mojo.tstest.BOOL_VALUE,
+  expectedValue: true,
+  type: 'boolean'
+}, {
+  constant: mojo.tstest.INT8_VALUE,
+  expectedValue: -2,
+  type: 'int8'
+}, {
+  constant: mojo.tstest.UINT8_VALUE,
+  expectedValue: 128,
+  type: 'uint8'
+}, {
+  constant: mojo.tstest.INT16_VALUE,
+  expectedValue: -233,
+  type: 'int16'
+}, {
+  constant: mojo.tstest.UINT16_VALUE,
+  expectedValue: 44204,
+  type: 'uint16'
+}, {
+  constant: mojo.tstest.INT32_VALUE,
+  expectedValue: -44204,
+  type: 'int32'
+}, {
+  constant: mojo.tstest.UINT32_VALUE,
+  expectedValue: 4294967295,
+  type: 'uint32'
+}, {
+  // TODO(crbug.com/1009262): Re-enable once we generate the right value for
+  // 64-bit constants.
+  //
+  //  constant: mojo.tstest.kInt64Value,
+  //  expectedValue: -9223372036854775807n,
+  //  type: 'int64'
+  //}, {
+  //  constant: mojo.tstest.kUint64Value,
+  //  expectedValue: 9999999999999999999n,
+  //  type: 'uint64'
+  //}, {
+  constant: mojo.tstest.DOUBLE_VALUE,
+  expectedValue: 3.14159,
+  type: 'double'
+}, {
+  constant: mojo.tstest.DOUBLE_INFINITY,
+  expectedValue: Infinity,
+  type: 'double infinity'
+}, {
+  constant: mojo.tstest.DOUBLE_NEGATIVE_INFINITY,
+  expectedValue: -Infinity,
+  type: 'double negative infinity'
+}, {
+  constant: mojo.tstest.DOUBLE_NA_N,
+  expectedValue: NaN,
+  type: 'double NaN'
+}, {
+  constant: mojo.tstest.FLOAT_VALUE,
+  expectedValue: 2.71828,
+  type: 'float'
+}, {
+  constant: mojo.tstest.FLOAT_INFINITY,
+  expectedValue: Infinity,
+  type: 'float infinity'
+}, {
+  constant: mojo.tstest.FLOAT_NEGATIVE_INFINITY,
+  expectedValue: -Infinity,
+  type: 'float negative infinity'
+}, {
+  constant: mojo.tstest.FLOAT_NA_N,
+  expectedValue: NaN,
+  type: 'NaN'
+}, {
+  constant: mojo.tstest.STRING_VALUE,
+  expectedValue: "test string contents",
+  type: 'string'
+}].forEach(testCase => {
+  test(
+    () => assert_equals(testCase.constant, testCase.expectedValue),
+    `Checks that the value of generated ${testCase.type} constants is correct`);
+});
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/message-pipe.html b/third_party/blink/web_tests/http/tests/mojo/message-pipe.html
new file mode 100644
index 0000000..700872e
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/message-pipe.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<title>Mojo message pipe tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+let testData = (() => {
+  let dataIn = new Uint8Array(42);
+  for (let i = 0; i < dataIn.length; ++i)
+    dataIn[i] = i * i;
+
+  return {
+    read(handle) {
+      let {result, buffer, handles} = handle.readMessage();
+      assert_equals(result, Mojo.RESULT_OK);
+      assert_array_equals(new Uint8Array(buffer), dataIn);
+      assert_array_equals(handles, []);
+    },
+    write(handle) {
+      let result = handle.writeMessage(dataIn, []);
+      assert_equals(result, Mojo.RESULT_OK);
+    }
+  };
+})();
+
+test(() => {
+  let {result, handle0, handle1} = Mojo.createMessagePipe();
+  assert_equals(result, Mojo.RESULT_OK);
+  assert_true(handle0 instanceof MojoHandle);
+  assert_true(handle1 instanceof MojoHandle);
+}, "Create pipe");
+
+test(() => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+  handle0.close();
+  let {result} = handle0.readMessage();
+  assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
+}, "Read from invalid handle");
+
+test(() => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+  let {result} = handle0.readMessage();
+  assert_equals(result, Mojo.RESULT_SHOULD_WAIT);
+}, "Read from empty pipe");
+
+test(() => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+  handle0.close();
+  let result = handle0.writeMessage(new ArrayBuffer(4), []);
+  assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
+}, "Write to invalid handle");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({readable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+    {
+      let {result, buffer, handles} = handle0.readMessage();
+      assert_equals(result, Mojo.RESULT_OK);
+      assert_equals(buffer.byteLength, 0);
+      assert_array_equals(handles, []);
+    }
+  }));
+  let result = handle1.writeMessage(new ArrayBuffer(0), []);
+  assert_equals(result, Mojo.RESULT_OK);
+}, "Send empty message");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({readable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+    testData.read(handle0);
+  }));
+  testData.write(handle1);
+}, "Send buffer");
+
+async_test((test) => {
+  let pipe1 = Mojo.createMessagePipe();
+  let pipe2 = Mojo.createMessagePipe();
+  pipe2.handle0.watch({readable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+    testData.read(pipe2.handle0);
+  }));
+  pipe1.handle0.watch({readable: true}, test.step_func((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+    {
+      let {result, handles} = pipe1.handle0.readMessage();
+      assert_equals(result, Mojo.RESULT_OK);
+      assert_equals(1, handles.length);
+      testData.write(handles[0]);
+    }
+  }));
+  pipe1.handle1.writeMessage(new ArrayBuffer(0), [pipe2.handle1]);
+}, "Send handle");
+
+test(() => {
+  const pipe1 = Mojo.createMessagePipe();
+  const pipe2 = Mojo.createMessagePipe();
+  pipe2.handle0.close();
+  const result = pipe1.handle0.writeMessage(new ArrayBuffer(0), [pipe2.handle0]);
+  assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
+}, "Send invalid handle");
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/module-loading-manual-deps-loading.html b/third_party/blink/web_tests/http/tests/mojo/module-loading-manual-deps-loading.html
new file mode 100644
index 0000000..798520e
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/module-loading-manual-deps-loading.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Mojo JavaScript bindings module loading tests (manual mojom deps loading)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script>
+  mojo.config.autoLoadMojomDeps = false;
+</script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/echo.mojom.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/echo_import/echo_import.mojom.js"></script>
+<script>
+
+promise_test(async () => {
+  function EchoImpl() {}
+  EchoImpl.prototype.echoPoint = function(point) {
+    return Promise.resolve({result: point});
+  };
+
+  var echoServicePtr = new test.echo.mojom.EchoPtr();
+  var echoServiceBinding = new mojo.Binding(test.echo.mojom.Echo,
+                                            new EchoImpl(),
+                                            mojo.makeRequest(echoServicePtr));
+  var result = (await echoServicePtr.echoPoint({x: 1, y: 2})).result;
+  assert_equals(1, result.x);
+  assert_equals(2, result.y);
+}, 'Basics');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/module-loading.html b/third_party/blink/web_tests/http/tests/mojo/module-loading.html
new file mode 100644
index 0000000..a09556a
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/module-loading.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Mojo JavaScript bindings module loading tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/echo.mojom.js"></script>
+<script>
+
+promise_test(async () => {
+  function EchoImpl() {}
+  EchoImpl.prototype.echoPoint = function(point) {
+    return Promise.resolve({result: point});
+  };
+
+  var echoServicePtr = new test.echo.mojom.EchoPtr();
+  var echoServiceBinding = new mojo.Binding(test.echo.mojom.Echo,
+                                            new EchoImpl(),
+                                            mojo.makeRequest(echoServicePtr));
+  var result = (await echoServicePtr.echoPoint({x: 1, y: 2})).result;
+  assert_equals(1, result.x);
+  assert_equals(2, result.y);
+}, 'Basics');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/resources/bind-intercepted-interface-in-worker.js b/third_party/blink/web_tests/http/tests/mojo/resources/bind-intercepted-interface-in-worker.js
new file mode 100644
index 0000000..a18033d8
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/resources/bind-intercepted-interface-in-worker.js
@@ -0,0 +1,35 @@
+importScripts('/resources/testharness.js');
+importScripts('/gen/layout_test_data/mojo/public/js/mojo_bindings.js');
+importScripts('/gen/content/test/data/mojo_web_test_helper_test.mojom.js');
+importScripts('helpers.js');
+
+promise_test(async () => {
+  let helperImpl = new TestHelperImpl;
+  let interceptor =
+      new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name, "context", true);
+  interceptor.oninterfacerequest = e => {
+    helperImpl.bindRequest(e.handle);
+  };
+  interceptor.start();
+
+  let helper = new content.mojom.MojoWebTestHelperPtr;
+  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
+                     mojo.makeRequest(helper).handle, "context", true);
+
+  let response = await helper.reverse('the string');
+  assert_equals(response.reversed, kTestReply);
+  assert_equals(helperImpl.getLastString(), 'the string');
+}, 'Can implement a Mojo service and intercept it from a worker');
+
+test(t => {
+  assert_throws(
+      'NotSupportedError',
+      () => {
+        new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name,
+                                     "process");
+      });
+}, 'Cannot create a MojoInterfaceInterceptor with process scope');
+
+// done() is needed because the testharness is running as if explicit_done
+// was specified.
+done();
diff --git a/third_party/blink/web_tests/mojo/resources/helpers.js b/third_party/blink/web_tests/http/tests/mojo/resources/helpers.js
similarity index 100%
rename from third_party/blink/web_tests/mojo/resources/helpers.js
rename to third_party/blink/web_tests/http/tests/mojo/resources/helpers.js
diff --git a/third_party/blink/web_tests/mojo/resources/validation_test_input_parser.js b/third_party/blink/web_tests/http/tests/mojo/resources/validation_test_input_parser.js
similarity index 100%
rename from third_party/blink/web_tests/mojo/resources/validation_test_input_parser.js
rename to third_party/blink/web_tests/http/tests/mojo/resources/validation_test_input_parser.js
diff --git a/third_party/blink/web_tests/http/tests/mojo/sample_service.html b/third_party/blink/web_tests/http/tests/mojo/sample_service.html
new file mode 100644
index 0000000..d597552
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/sample_service.html
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.js"></script>
+<script>
+'use strict';
+
+// Checks that values are set to the defaults if we don't override them.
+test(() => {
+  var bar = new sample.Bar();
+  assert_equals(bar.alpha, 255);
+  assert_equals(bar.type, sample.Bar.Type.VERTICAL);
+
+  var foo = new sample.Foo();
+  assert_equals(foo.name, "Fooby");
+  assert_true(foo.a);
+  assert_equals(foo.data, null);
+
+  var defaults = new sample.DefaultsTest();
+  assert_equals(defaults.a0, -12);
+  assert_equals(defaults.a1, sample.TWELVE);
+  assert_equals(defaults.a2, 1234);
+  assert_equals(defaults.a3, 34567);
+  assert_equals(defaults.a4, 123456);
+  assert_equals(defaults.a5, 3456789012);
+  assert_equals(defaults.a6, -111111111111);
+  // JS doesn't have a 64 bit integer type so this is just checking that the
+  // expected and actual values have the same closest double value.
+  assert_equals(defaults.a7, 9999999999999999999);
+  assert_equals(defaults.a8, 0x12345);
+  assert_equals(defaults.a9, -0x12345);
+  assert_equals(defaults.a10, 1234);
+  assert_true(defaults.a11);
+  assert_false(defaults.a12);
+  assert_equals(defaults.a13, 123.25);
+  assert_equals(defaults.a14, 1234567890.123);
+  assert_equals(defaults.a15, 1E10);
+  assert_equals(defaults.a16, -1.2E+20);
+  assert_equals(defaults.a17, 1.23E-20);
+  assert_equals(defaults.a20, sample.Bar.Type.BOTH);
+  assert_equals(defaults.a21, null);
+  assert_true(!!defaults.a22);
+  assert_equals(defaults.a22.shape, imported.Shape.RECTANGLE);
+  assert_equals(defaults.a22.color, imported.Color.BLACK);
+  assert_equals(defaults.a23, 0xFFFFFFFFFFFFFFFF);
+  assert_equals(defaults.a24, 0x123456789);
+  assert_equals(defaults.a25, -0x123456789);
+}, 'default values');
+
+promise_test(async () => {
+  function ServiceImpl() {
+  }
+
+  ServiceImpl.prototype.frobinate = function(foo, baz, port) {
+    checkFoo(foo);
+    assert_equals(baz, sample.Service.BazOptions.EXTRA);
+    assert_true(port.ptr.isBound());
+    return Promise.resolve({result: 1234});
+  };
+
+  var foo = makeFoo();
+  checkFoo(foo);
+
+  var service = new sample.ServicePtr();
+  var request = mojo.makeRequest(service);
+  var serviceBinding = new mojo.Binding(
+      sample.Service, new ServiceImpl(), request);
+
+  var port = new sample.PortPtr();
+  mojo.makeRequest(port);
+  assert_equals((await service.frobinate(foo, sample.Service.BazOptions.EXTRA,
+                                         port)).result, 1234);
+
+}, 'sample service');
+
+done();
+
+function makeFoo() {
+  var bar = new sample.Bar();
+  bar.alpha = 20;
+  bar.beta = 40;
+  bar.gamma = 60;
+  bar.type = sample.Bar.Type.VERTICAL;
+
+  var extraBars = new Array(3);
+  for (var i = 0; i < extraBars.length; ++i) {
+    var base = i * 100;
+    var type = i % 2 ? sample.Bar.Type.VERTICAL : sample.Bar.Type.HORIZONTAL;
+    extraBars[i] = new sample.Bar();
+    extraBars[i].alpha = base;
+    extraBars[i].beta = base + 20;
+    extraBars[i].gamma = base + 40;
+    extraBars[i].type = type;
+  }
+
+  var data = new Array(10);
+  for (var i = 0; i < data.length; ++i) {
+    data[i] = data.length - i;
+  }
+
+  var foo = new sample.Foo();
+  foo.name = "foopy";
+  foo.x = 1;
+  foo.y = 2;
+  foo.a = false;
+  foo.b = true;
+  foo.c = false;
+  foo.bar = bar;
+  foo.extraBars = extraBars;
+  foo.data = data;
+
+  foo.source = Mojo.createMessagePipe().handle0;
+
+  return foo;
+}
+
+// Checks that the given |Foo| is identical to the one made by |makeFoo()|.
+function checkFoo(foo) {
+  assert_equals(foo.name, "foopy");
+  assert_equals(foo.x, 1);
+  assert_equals(foo.y, 2);
+  assert_false(foo.a);
+  assert_true(foo.b);
+  assert_false(foo.c);
+  assert_equals(foo.bar.alpha, 20);
+  assert_equals(foo.bar.beta, 40);
+  assert_equals(foo.bar.gamma, 60);
+  assert_equals(foo.bar.type, sample.Bar.Type.VERTICAL);
+
+  assert_equals(foo.extraBars.length, 3);
+  for (var i = 0; i < foo.extraBars.length; ++i) {
+    var base = i * 100;
+    var type = i % 2 ?  sample.Bar.Type.VERTICAL : sample.Bar.Type.HORIZONTAL;
+    assert_equals(foo.extraBars[i].alpha, base);
+    assert_equals(foo.extraBars[i].beta, base + 20);
+    assert_equals(foo.extraBars[i].gamma, base + 40);
+    assert_equals(foo.extraBars[i].type, type);
+  }
+
+  assert_equals(foo.data.length, 10);
+  for (var i = 0; i < foo.data.length; ++i)
+    assert_equals(foo.data[i], foo.data.length -i);
+
+  assert_true(foo.source instanceof MojoHandle);
+}
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/shared-buffer.html b/third_party/blink/web_tests/http/tests/mojo/shared-buffer.html
new file mode 100644
index 0000000..29f2440
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/shared-buffer.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<title>Mojo shared buffer tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+let kBufferSize = 32;
+
+test(() => {
+  let {result, handle} = Mojo.createSharedBuffer(kBufferSize);
+  assert_equals(result, Mojo.RESULT_OK);
+  assert_true(handle instanceof MojoHandle);
+}, "Create shared buffer");
+
+test(() => {
+  let {handle} = Mojo.createSharedBuffer(kBufferSize);
+  let {result, buffer} = handle.mapBuffer(0, kBufferSize);
+  assert_equals(result, Mojo.RESULT_OK);
+  assert_true(buffer instanceof ArrayBuffer);
+}, "Map shared buffer");
+
+test(() => {
+  let {handle: handle0} = Mojo.createSharedBuffer(kBufferSize);
+  let {result, handle: handle1} = handle0.duplicateBufferHandle();
+  assert_equals(result, Mojo.RESULT_OK);
+  assert_true(handle1 instanceof MojoHandle);
+  assert_not_equals(handle1, handle0);
+}, "Duplicate RW shared buffer handle");
+
+test(() => {
+  let {handle: handle0} = Mojo.createSharedBuffer(kBufferSize);
+  let {result, handle: handle1} = handle0.duplicateBufferHandle({readOnly: true});
+  assert_equals(result, Mojo.RESULT_OK);
+  assert_true(handle1 instanceof MojoHandle);
+  assert_not_equals(handle1, handle0);
+}, "Duplicate RO shared buffer handle");
+
+test(() => {
+  let {handle: handle0} = Mojo.createSharedBuffer(kBufferSize);
+  let {buffer: buffer0} = handle0.mapBuffer(0, kBufferSize);
+  let array0 = new Uint8Array(buffer0);
+
+  let {handle: handle1} = handle0.duplicateBufferHandle({readOnly: true});
+  let {buffer: buffer1} = handle1.mapBuffer(0, kBufferSize);
+  let array1 = new Uint8Array(buffer1);
+
+  assert_not_equals(buffer1, buffer0);
+  for (let i = 0; i < kBufferSize; ++i) {
+    array0[i] = i;
+    assert_equals(array1[i], i);
+  }
+}, "Read from RO shared buffer handle");
+
+test(() => {
+  let {handle: handle0} = Mojo.createSharedBuffer(kBufferSize);
+  let {buffer: buffer0} = handle0.mapBuffer(0, kBufferSize);
+  let array0 = new Uint8Array(buffer0);
+
+  let {handle: handle1} = handle0.duplicateBufferHandle();
+  let {buffer: buffer1} = handle1.mapBuffer(0, kBufferSize);
+  let array1 = new Uint8Array(buffer1);
+
+  assert_not_equals(buffer1, buffer0);
+  for (let i = 0; i < kBufferSize; ++i) {
+    array1[i] = i;
+    assert_equals(array0[i], i);
+  }
+}, "Write to RW shared buffer handle");
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/struct.html b/third_party/blink/web_tests/http/tests/mojo/struct.html
new file mode 100644
index 0000000..7565a5f
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/struct.html
@@ -0,0 +1,234 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/js-test-resources/testharness-helpers.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/test_structs.mojom.js"></script>
+<script>
+
+test(() => {
+  var r = new mojo.test.Rect();
+  assert_weak_equals(r, new mojo.test.Rect({x:0, y:0, width:0, height:0}));
+  assert_weak_equals(r, new mojo.test.Rect({foo:100, bar:200}));
+
+  r.x = 10;
+  r.y = 20;
+  r.width = 30;
+  r.height = 40;
+  var rp = new mojo.test.RectPair({first: r, second: r});
+  assert_weak_equals(rp.first, r);
+  assert_weak_equals(rp.second, r);
+
+  assert_equals(new mojo.test.RectPair({second: r}).first, null);
+
+  var nr = new mojo.test.NamedRegion();
+  assert_equals(nr.name, null);
+  assert_equals(nr.rects, null);
+  assert_weak_equals(nr, new mojo.test.NamedRegion({}));
+
+  nr.name = "foo";
+  nr.rects = [r, r, r];
+  assert_weak_equals(nr, new mojo.test.NamedRegion({
+    name: "foo",
+    rects: [r, r, r],
+  }));
+
+  var e = new mojo.test.EmptyStruct();
+  assert_weak_equals(e, new mojo.test.EmptyStruct({foo:123}));
+}, 'constructors');
+
+test(() => {
+  var s = new mojo.test.NoDefaultFieldValues();
+  assert_false(s.f0);
+
+  // f1 - f10, number type fields
+  for (var i = 1; i <= 10; i++)
+    assert_equals(s["f" + i], 0);
+
+  // f11,12 strings, f13-22 handles, f23-f26 arrays, f27,28 structs
+  for (var i = 11; i <= 28; i++)
+    assert_equals(s["f" + i], null);
+
+}, 'no default field values');
+
+test(() => {
+  var s = new mojo.test.DefaultFieldValues();
+  assert_true(s.f0);
+
+  // f1 - f12, number type fields
+  for (var i = 1; i <= 12; i++)
+    assert_equals(s["f" + i], 100);
+
+  // f13,14 "foo"
+  for (var i = 13; i <= 14; i++)
+    assert_equals(s["f" + i], "foo");
+
+  // f15,16 a default instance of Rect
+  var r = new mojo.test.Rect();
+  assert_weak_equals(s.f15, r);
+  assert_weak_equals(s.f16, r);
+}, 'default field values');
+
+test(() => {
+  assert_equals(mojo.test.ScopedConstants.TEN, 10);
+  assert_equals(mojo.test.ScopedConstants.ALSO_TEN, 10);
+
+  assert_equals(mojo.test.ScopedConstants.EType.E0, 0);
+  assert_equals(mojo.test.ScopedConstants.EType.E1, 1);
+  assert_equals(mojo.test.ScopedConstants.EType.E2, 10);
+  assert_equals(mojo.test.ScopedConstants.EType.E3, 10);
+  assert_equals(mojo.test.ScopedConstants.EType.E4, 11);
+
+  var s = new mojo.test.ScopedConstants();
+  assert_equals(s.f0, 0);
+  assert_equals(s.f1, 1);
+  assert_equals(s.f2, 10);
+  assert_equals(s.f3, 10);
+  assert_equals(s.f4, 11);
+  assert_equals(s.f5, 10);
+  assert_equals(s.f6, 10);
+}, 'scoped constants');
+
+function structEncodeDecode(struct) {
+  var structClass = struct.constructor;
+  var builder = new mojo.internal.MessageV0Builder(1234,
+      structClass.encodedSize);
+  builder.encodeStruct(structClass, struct);
+  var message = builder.finish();
+
+  var messageValidator = new mojo.internal.Validator(message);
+  var err = structClass.validate(messageValidator,
+                                 mojo.internal.kMessageV0HeaderSize);
+  assert_equals(err, mojo.internal.validationError.NONE);
+
+  var reader = new mojo.internal.MessageReader(message);
+  return reader.decodeStruct(structClass);
+}
+
+test(() => {
+  var mapFieldsStruct = new mojo.test.MapKeyTypes({
+    f0: new Map([[true, false], [false, true]]),  // map<bool, bool>
+    f1: new Map([[0, 0], [1, 127], [-1, -128]]),  // map<int8, int8>
+    f2: new Map([[0, 0], [1, 127], [2, 255]]),  // map<uint8, uint8>
+    f3: new Map([[0, 0], [1, 32767], [2, -32768]]),  // map<int16, int16>
+    f4: new Map([[0, 0], [1, 32768], [2, 0xFFFF]]),  // map<uint16, uint16>
+    f5: new Map([[0, 0], [1, 32767], [2, -32768]]),  // map<int32, int32>
+    f6: new Map([[0, 0], [1, 32768], [2, 0xFFFF]]),  // map<uint32, uint32>
+    f7: new Map([[0, 0], [1, 32767], [2, -32768]]),  // map<int64, int64>
+    f8: new Map([[0, 0], [1, 32768], [2, 0xFFFF]]),  // map<uint64, uint64>
+    f9: new Map([[1000.5, -50000], [100.5, 5000]]),  // map<float, float>
+    f10: new Map([[-100.5, -50000], [0, 50000000]]),  // map<double, double>
+    f11: new Map([["one", "two"], ["free", "four"]]),  // map<string, string>
+  });
+  var decodedStruct = structEncodeDecode(mapFieldsStruct);
+  assert_weak_equals(decodedStruct, mapFieldsStruct);
+}, 'map key types');
+
+test(() => {
+  var mapFieldsStruct = new mojo.test.MapValueTypes({
+    // map<string, array<string>>
+    f0: new Map([["a", ["b", "c"]], ["d", ["e"]]]),
+    // map<string, array<string>?>
+    f1: new Map([["a", null], ["b", ["c", "d"]]]),
+    // map<string, array<string?>>
+    f2: new Map([["a", [null]], ["b", [null, "d"]]]),
+    // map<string, array<string,2>>
+    f3: new Map([["a", ["1", "2"]], ["b", ["1", "2"]]]),
+    // map<string, array<array<string, 2>?>>
+    f4: new Map([["a", [["1", "2"]]], ["b", [null]]]),
+    // map<string, array<array<string, 2>, 1>>
+    f5: new Map([["a", [["1", "2"]]]]),
+    // map<string, Rect?>
+    f6: new Map([["a", null]]),
+    // map<string, map<string, string>>
+    f7: new Map([["a", new Map([["b", "c"]])]]),
+    // map<string, array<map<string, string>>>
+    f8: new Map([["a", [new Map([["b", "c"]])]]]),
+    // map<string, handle>
+    f9: new Map([["a", 1234]]),
+    // map<string, array<handle>>
+    f10: new Map([["a", [1234, 5678]]]),
+    // map<string, map<string, handle>>
+    f11: new Map([["a", new Map([["b", 1234]])]]),
+  });
+  var decodedStruct = structEncodeDecode(mapFieldsStruct);
+  assert_weak_equals(decodedStruct, mapFieldsStruct);
+}, 'map value types');
+
+test(() => {
+  var decodedStruct = structEncodeDecode(new mojo.test.FloatNumberValues);
+  assert_equals(decodedStruct.f0, mojo.test.FloatNumberValues.V0);
+  assert_equals(decodedStruct.f1, mojo.test.FloatNumberValues.V1);
+  assert_equals(decodedStruct.f2, mojo.test.FloatNumberValues.V2);
+  assert_equals(decodedStruct.f3, mojo.test.FloatNumberValues.V3);
+  assert_equals(decodedStruct.f4, mojo.test.FloatNumberValues.V4);
+  assert_equals(decodedStruct.f5, mojo.test.FloatNumberValues.V5);
+  assert_equals(decodedStruct.f6, mojo.test.FloatNumberValues.V6);
+  assert_equals(decodedStruct.f7, mojo.test.FloatNumberValues.V7);
+  assert_equals(decodedStruct.f8, mojo.test.FloatNumberValues.V8);
+  assert_equals(decodedStruct.f9, mojo.test.FloatNumberValues.V9);
+}, 'float number values');
+
+test(() => {
+  var decodedStruct = structEncodeDecode(new mojo.test.IntegerNumberValues);
+  assert_equals(decodedStruct.f0, mojo.test.IntegerNumberValues.V0);
+  assert_equals(decodedStruct.f1, mojo.test.IntegerNumberValues.V1);
+  assert_equals(decodedStruct.f2, mojo.test.IntegerNumberValues.V2);
+  assert_equals(decodedStruct.f3, mojo.test.IntegerNumberValues.V3);
+  assert_equals(decodedStruct.f4, mojo.test.IntegerNumberValues.V4);
+  assert_equals(decodedStruct.f5, mojo.test.IntegerNumberValues.V5);
+  assert_equals(decodedStruct.f6, mojo.test.IntegerNumberValues.V6);
+  assert_equals(decodedStruct.f7, mojo.test.IntegerNumberValues.V7);
+  assert_equals(decodedStruct.f8, mojo.test.IntegerNumberValues.V8);
+  assert_equals(decodedStruct.f9, mojo.test.IntegerNumberValues.V9);
+  assert_equals(decodedStruct.f10, mojo.test.IntegerNumberValues.V10);
+  assert_equals(decodedStruct.f11, mojo.test.IntegerNumberValues.V11);
+  assert_equals(decodedStruct.f12, mojo.test.IntegerNumberValues.V12);
+  assert_equals(decodedStruct.f13, mojo.test.IntegerNumberValues.V13);
+  assert_equals(decodedStruct.f14, mojo.test.IntegerNumberValues.V14);
+  assert_equals(decodedStruct.f15, mojo.test.IntegerNumberValues.V15);
+  assert_equals(decodedStruct.f16, mojo.test.IntegerNumberValues.V16);
+  assert_equals(decodedStruct.f17, mojo.test.IntegerNumberValues.V17);
+  assert_equals(decodedStruct.f18, mojo.test.IntegerNumberValues.V18);
+  assert_equals(decodedStruct.f19, mojo.test.IntegerNumberValues.V19);
+}, 'integer number values');
+
+test(() => {
+  var decodedStruct =
+      structEncodeDecode(new mojo.test.UnsignedNumberValues);
+  assert_equals(decodedStruct.f0, mojo.test.UnsignedNumberValues.V0);
+  assert_equals(decodedStruct.f1, mojo.test.UnsignedNumberValues.V1);
+  assert_equals(decodedStruct.f2, mojo.test.UnsignedNumberValues.V2);
+  assert_equals(decodedStruct.f3, mojo.test.UnsignedNumberValues.V3);
+  assert_equals(decodedStruct.f4, mojo.test.UnsignedNumberValues.V4);
+  assert_equals(decodedStruct.f5, mojo.test.UnsignedNumberValues.V5);
+  assert_equals(decodedStruct.f6, mojo.test.UnsignedNumberValues.V6);
+  assert_equals(decodedStruct.f7, mojo.test.UnsignedNumberValues.V7);
+  assert_equals(decodedStruct.f8, mojo.test.UnsignedNumberValues.V8);
+  assert_equals(decodedStruct.f9, mojo.test.UnsignedNumberValues.V9);
+  assert_equals(decodedStruct.f10, mojo.test.UnsignedNumberValues.V10);
+  assert_equals(decodedStruct.f11, mojo.test.UnsignedNumberValues.V11);
+}, 'unsigned number values');
+
+test(() => {
+  var bitArraysStruct = new mojo.test.BitArrayValues({
+    // array<bool, 1> f0;
+    f0: [true],
+    // array<bool, 7> f1;
+    f1: [true, false, true, false, true, false, true],
+    // array<bool, 9> f2;
+    f2: [true, false, true, false, true, false, true, false, true],
+    // array<bool> f3;
+    f3: [true, false, true, false, true, false, true, false],
+    // array<array<bool>> f4;
+    f4: [[true], [false], [true, false], [true, false, true, false]],
+    // array<array<bool>?> f5;
+    f5: [[true], null, null, [true, false, true, false]],
+    // array<array<bool, 2>?> f6;
+    f6: [[true, false], [true, false], [true, false]],
+  });
+  var decodedStruct = structEncodeDecode(bitArraysStruct);
+  assert_weak_equals(decodedStruct, bitArraysStruct);
+}, 'bit array values');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/union.html b/third_party/blink/web_tests/http/tests/mojo/union.html
new file mode 100644
index 0000000..49c4d07
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/union.html
@@ -0,0 +1,189 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/js-test-resources/testharness-helpers.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/test_unions.mojom.js"></script>
+<script>
+'use strict';
+
+test(() => {
+  var u = new mojo.test.PodUnion();
+  assert_equals(u.$data, null);
+  assert_equals(u.$tag, undefined);
+
+  u.fUint32 = 32;
+
+  assert_equals(u.fUint32, 32);
+  assert_equals(u.$tag, mojo.test.PodUnion.Tags.fUint32);
+
+  var u = new mojo.test.PodUnion({fUint64: 64});
+  assert_equals(u.fUint64, 64);
+  assert_equals(u.$tag, mojo.test.PodUnion.Tags.fUint64);
+  assert_throws(new ReferenceError, function() {var v = u.fUint32;});
+
+  assert_throws(new TypeError, function() {
+    var u = new mojo.test.PodUnion({
+      fUint64: 64,
+      fUint32: 32,
+    });
+  });
+
+  assert_throws(new ReferenceError, function() {
+    var u = new mojo.test.PodUnion({ foo: 64 });
+  });
+
+  assert_throws(new TypeError, function() {
+    var u = new mojo.test.PodUnion([1,2,3,4]);
+  });
+}, 'constructors');
+
+function structEncodeDecode(struct) {
+  var structClass = struct.constructor;
+  var builder = new mojo.internal.MessageV0Builder(1234,
+                                                   structClass.encodedSize);
+  builder.encodeStruct(structClass, struct);
+
+  var message = builder.finish();
+
+  var messageValidator = new mojo.internal.Validator(message);
+  var err = structClass.validate(messageValidator,
+                                 mojo.internal.kMessageV0HeaderSize);
+  assert_equals(err, mojo.internal.validationError.NONE);
+
+  var reader = new mojo.internal.MessageReader(message);
+  var view = reader.decoder.buffer.dataView;
+
+  return reader.decodeStruct(structClass);
+}
+
+test(() => {
+  var s = new mojo.test.WrapperStruct({
+    podUnion: new mojo.test.PodUnion({fUint64: 64})
+  });
+
+  var decoded = structEncodeDecode(s);
+  assert_weak_equals(decoded, s);
+
+  var s = new mojo.test.WrapperStruct({
+    podUnion: new mojo.test.PodUnion({fBool : true})
+  });
+
+  var decoded = structEncodeDecode(s);
+  assert_equals(decoded.podUnion.$tag, mojo.test.PodUnion.Tags.fBool);
+  assert_true(decoded.podUnion.fBool);
+
+  var s = new mojo.test.WrapperStruct({
+    objectUnion: new mojo.test.ObjectUnion({
+      fDummy: new mojo.test.DummyStruct({fInt8: 8})
+    })
+  });
+
+  var decoded = structEncodeDecode(s);
+  assert_weak_equals(decoded, s);
+
+  var s = new mojo.test.WrapperStruct({
+    objectUnion: new mojo.test.ObjectUnion({fArrayInt8: [1, 2, 3]})
+  });
+
+  var decoded = structEncodeDecode(s);
+  assert_weak_equals(decoded, s);
+
+  var s = new mojo.test.WrapperStruct({
+    objectUnion: new mojo.test.ObjectUnion({
+      fMapInt8: new Map([
+        ["first", 1],
+        ["second", 2],
+      ])
+    })
+  });
+
+  var decoded = structEncodeDecode(s);
+  assert_weak_equals(decoded, s);
+
+  // Encoding a union with no member set is an error.
+  var s = new mojo.test.WrapperStruct({
+    objectUnion: new mojo.test.ObjectUnion()});
+  assert_throws(new TypeError, function() {
+    structEncodeDecode(s);
+  });
+}, 'basic encoding');
+
+test(() => {
+  var s = new mojo.test.SmallStruct({
+    podUnionArray: [
+      new mojo.test.PodUnion({fUint32: 32}),
+      new mojo.test.PodUnion({fUint64: 64}),
+    ]
+  });
+
+  var decoded = structEncodeDecode(s);
+  assert_weak_equals(decoded, s);
+}, 'unions in array encoding');
+
+test(() => {
+  var s = new mojo.test.SmallStruct({
+    podUnionMap: new Map([
+      ["thirty-two", new mojo.test.PodUnion({fUint32: 32})],
+      ["sixty-four", new mojo.test.PodUnion({fUint64: 64})],
+    ])
+  });
+
+  var decoded = structEncodeDecode(s);
+  assert_weak_equals(decoded, s);
+}, 'unions in map encoding');
+
+test(() => {
+  var s = new mojo.test.WrapperStruct({
+    objectUnion: new mojo.test.ObjectUnion({
+      fPodUnion: new mojo.test.PodUnion({fUint32: 32})
+    })
+  });
+  var decoded = structEncodeDecode(s);
+  assert_weak_equals(decoded, s);
+}, 'nested unions encoding');
+
+function structValidate(struct) {
+  var structClass = struct.constructor;
+  var builder = new mojo.internal.MessageV0Builder(1234,
+                                                   structClass.encodedSize);
+  builder.encodeStruct(structClass, struct);
+
+  var message = builder.finish();
+
+  var messageValidator = new mojo.internal.Validator(message);
+  return structClass.validate(messageValidator,
+                              mojo.internal.kMessageV0HeaderSize);
+}
+
+test(() => {
+  var s = new mojo.test.WrapperStruct({
+    objectUnion: new mojo.test.ObjectUnion({fDummy: null})
+  });
+
+  var err = structValidate(s);
+  assert_equals(err, mojo.internal.validationError.UNEXPECTED_NULL_POINTER);
+
+  var s = new mojo.test.WrapperStruct({
+    objectUnion: new mojo.test.ObjectUnion({fNullable: null})
+  });
+
+  var err = structValidate(s);
+  assert_equals(err, mojo.internal.validationError.NONE);
+}, 'null union member validation');
+
+test(() => {
+  var s = new mojo.test.SmallStructNonNullableUnion({podUnion: null});
+
+  var err = structValidate(s);
+  assert_equals(err, mojo.internal.validationError.UNEXPECTED_NULL_UNION);
+
+  var s = new mojo.test.WrapperStruct({
+    objectUnion: new mojo.test.ObjectUnion({fPodUnion: null})
+  });
+
+  var err = structValidate(s);
+  assert_equals(err, mojo.internal.validationError.UNEXPECTED_NULL_UNION);
+}, 'null union validation');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/validation.html b/third_party/blink/web_tests/http/tests/mojo/validation.html
new file mode 100644
index 0000000..1b308aa
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/validation.html
@@ -0,0 +1,297 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom.js"></script>
+<script src="resources/validation_test_input_parser.js"></script>
+<script>
+'use strict';
+
+var noError = mojo.internal.validationError.NONE;
+
+function checkData(data, expectedData, input) {
+  assert_equals(data.byteLength, expectedData.byteLength,
+      'message length (' + data.byteLength + ') doesn\'t match ' +
+      'expected length: ' + expectedData.byteLength + ' for ' + input);
+
+  for (var i = 0; i < data.byteLength; i++) {
+    assert_equals(data.getUint8(i), expectedData.getUint8(i),
+        'message data mismatch at byte offset ' + i + 'for' + input);
+  }
+}
+
+test(() => {
+  var input = '[f]+.3e9 [d]-10.03';
+  var msg = mojo.test.parseTestMessage(input);
+  var expectedData = new mojo.internal.Buffer(12);
+  expectedData.setFloat32(0, +.3e9);
+  expectedData.setFloat64(4, -10.03);
+  checkData(msg.buffer, expectedData, input);
+}, 'message parser: float items');
+
+test(() => {
+  var input = '[u1]0x10// hello world !! \n\r  \t [u2]65535 \n' +
+      '[u4]65536 [u8]0xFFFFFFFFFFFFF 0 0Xff';
+  var msg = mojo.test.parseTestMessage(input);
+  var expectedData = new mojo.internal.Buffer(17);
+  expectedData.setUint8(0, 0x10);
+  expectedData.setUint16(1, 65535);
+  expectedData.setUint32(3, 65536);
+  expectedData.setUint64(7, 0xFFFFFFFFFFFFF);
+  expectedData.setUint8(15, 0);
+  expectedData.setUint8(16, 0xff);
+  checkData(msg.buffer, expectedData, input);
+}, 'message parser: unsigned integer items');
+
+test(() => {
+  var input = '[s8]-0x800 [s1]-128\t[s2]+0 [s4]-40';
+  var msg = mojo.test.parseTestMessage(input);
+  var expectedData = new mojo.internal.Buffer(15);
+  expectedData.setInt64(0, -0x800);
+  expectedData.setInt8(8, -128);
+  expectedData.setInt16(9, 0);
+  expectedData.setInt32(11, -40);
+  checkData(msg.buffer, expectedData, input);
+}, 'message parser: signed integer items');
+
+test(() => {
+  var input = '[b]00001011 [b]10000000  // hello world\n [b]00000000';
+  var msg = mojo.test.parseTestMessage(input);
+  var expectedData = new mojo.internal.Buffer(3);
+  expectedData.setUint8(0, 11);
+  expectedData.setUint8(1, 128);
+  expectedData.setUint8(2, 0);
+  checkData(msg.buffer, expectedData, input);
+}, 'message parser: byte items');
+
+test(() => {
+  var input = '[dist4]foo 0 [dist8]bar 0 [anchr]foo [anchr]bar';
+  var msg = mojo.test.parseTestMessage(input);
+  var expectedData = new mojo.internal.Buffer(14);
+  expectedData.setUint32(0, 14);
+  expectedData.setUint8(4, 0);
+  expectedData.setUint64(5, 9);
+  expectedData.setUint8(13, 0);
+  checkData(msg.buffer, expectedData, input);
+}, 'message parser: anchors');
+
+test(() => {
+  var input = '// This message has handles! \n[handles]50 [u8]2';
+  var msg = mojo.test.parseTestMessage(input);
+  var expectedData = new mojo.internal.Buffer(8);
+  expectedData.setUint64(0, 2);
+
+  assert_equals(msg.handleCount, 50,
+      'wrong handle count (' + msg.handleConut + ') for ' + input);
+  checkData(msg.buffer, expectedData, input);
+}, 'message parser: handles');
+
+test(() => {
+  var msg = mojo.test.parseTestMessage('');
+  assert_equals(msg.buffer.byteLength, 0, 'expected empty message for ');
+}, 'message parser: empty input');
+
+test(() => {
+  var input = '    \t  // hello world \n\r \t// the answer is 42   ';
+  var msg = mojo.test.parseTestMessage(input);
+  assert_equals(msg.buffer.byteLength, 0,
+      'expected empty message for ' + input);
+}, 'message parser: blank input');
+
+test(() => {
+  function parserShouldFail(input) {
+    assert_throws(new mojo.test.InputError(), function() {
+      mojo.test.parseTestMessage(input);
+    });
+  }
+
+  ['/ hello world',
+   '[u1]x',
+   '[u2]-1000',
+   '[u1]0x100',
+   '[s2]-0x8001',
+   '[b]1',
+   '[b]1111111k',
+   '[dist4]unmatched',
+   '[anchr]hello [dist8]hello',
+   '[dist4]a [dist4]a [anchr]a',
+   // '[dist4]a [anchr]a [dist4]a [anchr]a',
+   '0 [handles]50'
+  ].forEach(parserShouldFail);
+}, 'message parser: invalid input');
+
+function fetchLite(url) {
+  return new Promise((resolve, reject) => {
+    var xhr = new XMLHttpRequest();
+    xhr.open('GET', url);
+    xhr.onreadystatechange = () => {
+      if (xhr.readyState != 4) return;
+      resolve(xhr.responseText);
+    };
+    xhr.send();
+  });
+}
+
+function getMessageTestFiles(prefix) {
+  let dataDirectory =
+      '/gen/layout_test_data/mojo/public/interfaces/bindings/tests/data/validation';
+  return fetchLite(dataDirectory + '_index.txt').then((response) => {
+    assert_not_equals(response, null);
+    var testFiles = response.split(/\s+/);
+    assert_greater_than(testFiles.length, 0);
+    return testFiles.filter(function(s) {
+      return s.substr(-5) == '.data' && s.indexOf(prefix) == 0;
+    }).map(function(s) {
+      return dataDirectory + '/' + s.slice(0, -5);
+    });
+  });
+}
+
+function readTestMessage(filename) {
+  return fetchLite(filename + '.data').then((response) => {
+    assert_not_equals(response, null);
+    return mojo.test.parseTestMessage(response);
+  });
+}
+
+function readTestExpected(filename) {
+  return fetchLite(filename + '.expected').then((response) => {
+    assert_not_equals(response, null);
+    return response.trim();
+  });
+}
+
+async function checkValidationResult(testFile, err) {
+  var actualResult = (err === noError) ? 'PASS' : err;
+  var expectedResult = await readTestExpected(testFile);
+  assert_equals(actualResult, expectedResult,
+      '[Test message validation failed: ' + testFile + ' ]');
+}
+
+async function testMessageValidation(prefix, filters) {
+  var testFiles = await getMessageTestFiles(prefix);
+  assert_greater_than(testFiles.length, 0);
+
+  for (var i = 0; i < testFiles.length; i++) {
+    // TODO(hansmuller) Temporarily skipping array pointer overflow tests
+    // because JS numbers are limited to 53 bits.
+    // TODO(rudominer): Temporarily skipping 'no-such-method',
+    // 'invalid_request_flags', and 'invalid_response_flags' until additional
+    // logic in *RequestValidator and *ResponseValidator is ported from
+    // cpp to js.
+    // TODO(crbug/640298): Implement max recursion depth for JS.
+    // TODO(crbug/628104): Support struct map keys for JS.
+    if (testFiles[i].indexOf('overflow') != -1 ||
+        testFiles[i].indexOf('conformance_mthd19') != -1 ||
+        testFiles[i].indexOf('conformance_mthd20') != -1 ||
+        testFiles[i].indexOf('no_such_method') != -1 ||
+        testFiles[i].indexOf('invalid_request_flags') != -1 ||
+        testFiles[i].indexOf('invalid_response_flags') != -1) {
+      console.log('[Skipping ' + testFiles[i] + ']');
+      continue;
+    }
+
+    var testMessage = await readTestMessage(testFiles[i]);
+    var handles = new Array(testMessage.handleCount);
+    var message = new mojo.internal.Message(testMessage.buffer, handles);
+    var messageValidator = new mojo.internal.Validator(message);
+
+    var err = messageValidator.validateMessageHeader();
+    for (var j = 0; err === noError && j < filters.length; ++j)
+      err = filters[j](messageValidator);
+
+    await checkValidationResult(testFiles[i], err);
+  }
+}
+
+promise_test(() => {
+  return testMessageValidation('conformance_', [
+      mojo.test.ConformanceTestInterface.validateRequest]);
+}, 'conformance message validation');
+
+promise_test(() => {
+  return testMessageValidation('boundscheck_', [
+      mojo.test.BoundsCheckTestInterface.validateRequest]);
+}, 'bounds check message validation');
+
+promise_test(() => {
+  return testMessageValidation('resp_conformance_', [
+      mojo.test.ConformanceTestInterface.validateResponse]);
+}, 'response conformance message validation');
+
+promise_test(() => {
+  return testMessageValidation('resp_boundscheck_', [
+      mojo.test.BoundsCheckTestInterface.validateResponse]);
+}, 'response bounds check message validation');
+
+async function testIntegratedMessageValidation(testFilesPattern, endpoint) {
+  var testFiles = await getMessageTestFiles(testFilesPattern);
+  assert_greater_than(testFiles.length, 0);
+
+  var testMessagePipe = Mojo.createMessagePipe();
+  assert_equals(testMessagePipe.result, Mojo.RESULT_OK);
+
+  endpoint.bind(testMessagePipe.handle1);
+  if (endpoint instanceof mojo.InterfacePtrController) {
+    // Make sure the router and connector are initialized.
+    endpoint.getProxy();
+  }
+
+  var originalReceiver = endpoint.router_.connector_.incomingReceiver_.accept;
+  var nextMessageCallback = null;
+  endpoint.router_.connector_.incomingReceiver_.accept = function(message) {
+    var result = originalReceiver(message);
+    if (nextMessageCallback) {
+      setTimeout(() => {
+        nextMessageCallback();
+        nextMessageCallback = null;
+      }, 0);
+    }
+    return result;
+  }
+
+  var observer = mojo.internal.ValidationErrorObserverForTesting.getInstance();
+
+  for (var i = 0; i < testFiles.length; i++) {
+    var testMessage = await readTestMessage(testFiles[i]);
+    var handles = new Array(testMessage.handleCount);
+
+    await new Promise((resolve, reject) => {
+      nextMessageCallback = resolve;
+
+      var writeMessageValue = testMessagePipe.handle0.writeMessage(
+          new Uint8Array(testMessage.buffer.arrayBuffer),
+          new Array(testMessage.handleCount));
+      assert_equals(writeMessageValue, Mojo.RESULT_OK);
+    });
+    await checkValidationResult(testFiles[i], observer.lastError);
+    observer.reset();
+  }
+
+  testMessagePipe.handle0.close();
+}
+
+promise_test(() => {
+  return testIntegratedMessageValidation(
+      'integration_msghdr',
+      new mojo.Binding(mojo.test.IntegrationTestInterface, {}))
+    .then(() => {
+      return testIntegratedMessageValidation(
+          'integration_msghdr',
+          new mojo.test.IntegrationTestInterfacePtr().ptr);
+    });
+}, 'integrated message header validation');
+
+promise_test(() => {
+  return testIntegratedMessageValidation(
+      'integration_intf_rqst',
+      new mojo.Binding(mojo.test.IntegrationTestInterface, {}));
+}, 'integrated request message validation');
+
+promise_test(() => {
+  return testIntegratedMessageValidation(
+      'integration_intf_resp',
+      new mojo.test.IntegrationTestInterfacePtr().ptr);
+}, 'integrated response message validation');
+
+</script>
diff --git a/third_party/blink/web_tests/http/tests/mojo/watch.html b/third_party/blink/web_tests/http/tests/mojo/watch.html
new file mode 100644
index 0000000..4becc55
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/mojo/watch.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>mojo watch tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({readable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+  }));
+  handle1.writeMessage(new ArrayBuffer(4), []);
+}, "Watch handle readable");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({writable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+  }));
+}, "Watch handle writable");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({peerClosed: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_OK);
+  }));
+  handle1.close();
+}, "Watch handle peer closed");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.close();
+  handle0.watch({writable: true}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
+  }));
+}, "Watch invalid handle");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  handle0.watch({}, test.step_func_done((result) => {
+    assert_equals(result, Mojo.RESULT_FAILED_PRECONDITION);
+  }));
+}, "Watch with default MojoHandleSignals");
+
+async_test((test) => {
+  let {handle0, handle1} = Mojo.createMessagePipe();
+
+  let watcher = handle0.watch(
+      {writable: true},
+      test.unreached_func("callback triggered after canceling watch"));
+  watcher.cancel();
+  setTimeout(() => { test.done(); });
+}, "Cancel watch");
+
+</script>
diff --git a/third_party/blink/web_tests/mojo/associated_binding.html b/third_party/blink/web_tests/mojo/associated_binding.html
deleted file mode 100644
index ddecf92d..0000000
--- a/third_party/blink/web_tests/mojo/associated_binding.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.js"></script>
-<script>
-'use strict';
-
-function SenderImpl(callback) {
-  this.callback = callback;
-}
-
-SenderImpl.prototype.echo = function(value) {
-  return Promise.resolve({value: value});
-};
-
-SenderImpl.prototype.send = function(value) {
-  if (this.callback) {
-    this.callback(value);
-  }
-};
-
-var IntegerSenderImpl = SenderImpl;
-
-function IntegerSenderConnectionImpl() {
-  this.integerSenderBindings = new mojo.AssociatedBindingSet(
-      mojo.test.IntegerSender);
-}
-
-IntegerSenderConnectionImpl.prototype.getSender = function(
-    integerSenderRequest) {
-  this.integerSenderBindings.addBinding(new IntegerSenderImpl(),
-      integerSenderRequest);
-};
-
-promise_test(async () => {
-  var integerSenderConnection = new mojo.test.IntegerSenderConnectionPtr();
-  var integerSenderConnectionImpl = new IntegerSenderConnectionImpl();
-  var integerSenderConnectionBinding = new mojo.Binding(
-      mojo.test.IntegerSenderConnection,
-      integerSenderConnectionImpl,
-      mojo.makeRequest(integerSenderConnection));
-
-  // AssociatedInterfaceRequest for integerSender.
-  var integerSenderPtrInfo0 = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest0 = mojo.makeRequest(integerSenderPtrInfo0);
-  var integerSender0 = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo0);
-
-  var integerSenderPtrInfo1 = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest1 = mojo.makeRequest(integerSenderPtrInfo1);
-  var integerSender1 = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo1);
-
-  integerSenderConnection.getSender(integerSenderRequest0);
-  integerSenderConnection.getSender(integerSenderRequest1);
-
-  // Master Binding close triggers connection error handler on
-  // interface endpoint clients for all associated endpoints.
-  var connectionErrorHandler0 = new Promise((resolve, reject) => {
-    integerSender0.ptr.setConnectionErrorHandler(() => {
-      resolve();
-    });
-  });
-
-  var connectionErrorHandler1 = new Promise((resolve, reject) => {
-    integerSender1.ptr.setConnectionErrorHandler(() => {
-      resolve();
-    });
-  });
-
-  setTimeout(integerSenderConnectionBinding.close.bind(
-      integerSenderConnectionBinding), 0);
-  await Promise.all([connectionErrorHandler0, connectionErrorHandler1]);
-}, 'all endpoints connectionErrorHandler called on master binding close');
-
-promise_test(async () => {
-  var integerSenderConnection = new mojo.test.IntegerSenderConnectionPtr();
-  var integerSenderConnectionImpl = new IntegerSenderConnectionImpl();
-  var integerSenderConnectionBinding = new mojo.Binding(
-      mojo.test.IntegerSenderConnection,
-      integerSenderConnectionImpl,
-      mojo.makeRequest(integerSenderConnection));
-
-  var integerSenders = [];
-  for (var i = 0; i < 3; i++) {
-    // AssociatedInterfaceRequest for integerSender.
-    var integerSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
-    var integerSenderRequest = mojo.makeRequest(integerSenderPtrInfo);
-    var integerSender =
-        new mojo.test.IntegerSenderAssociatedPtr(integerSenderPtrInfo);
-    integerSenderConnection.getSender(integerSenderRequest);
-
-    // Wait for integerSenderConnection getSender message to be received by
-    // integerSenderConnection's binding side and all integerSender binding
-    // to be created.
-    assert_equals((await integerSender.echo(3)).value, 3);
-    integerSenders.push(integerSender);
-  }
-
-  await new Promise((resolve, reject) => {
-    integerSenderConnectionImpl.integerSenderBindings
-        .setConnectionErrorHandler(() => {resolve();});
-    integerSenders[0].ptr.reset();
-  });
-
-  await new Promise((resolve, reject) => {
-    integerSenderConnectionImpl.integerSenderBindings
-        .setConnectionErrorHandler(function({customReason, description}) {
-      assert_equals(customReason, 32);
-      assert_equals(description, 'goodbye');
-      resolve();
-    });
-    integerSenders[1].ptr.resetWithReason({customReason: 32,
-        description: 'goodbye'});
-  });
-
-  // integerSender2's binding should still exist.
-  assert_equals((await integerSenders[2].echo(11)).value, 11);
-
-  integerSenderConnectionImpl.integerSenderBindings.closeAllBindings();
-  assert_true(integerSenderConnectionImpl.integerSenderBindings.isEmpty());
-}, 'associated binding set');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/associated_interface_ptr.html b/third_party/blink/web_tests/mojo/associated_interface_ptr.html
deleted file mode 100644
index ef9e4c7..0000000
--- a/third_party/blink/web_tests/mojo/associated_interface_ptr.html
+++ /dev/null
@@ -1,345 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.js"></script>
-<script>
-'use strict';
-
-function SenderImpl(callback) {
-  this.callback = callback;
-}
-
-SenderImpl.prototype.echo = function(value) {
-  return Promise.resolve({value: value});
-};
-
-SenderImpl.prototype.send = function(value) {
-  if (this.callback) {
-    this.callback(value);
-  }
-};
-
-var IntegerSenderImpl = SenderImpl;
-var StringSenderImpl = SenderImpl;
-
-function IntegerSenderConnectionImpl() {
-  this.integerSenderBinding_ = null;
-}
-
-IntegerSenderConnectionImpl.prototype.getSender = function(
-    integerSenderRequest) {
-  this.integerSenderBinding_ = new mojo.AssociatedBinding(
-      mojo.test.IntegerSender, new IntegerSenderImpl(), integerSenderRequest);
-};
-
-IntegerSenderConnectionImpl.prototype.asyncGetSender = function() {
-  var integerSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest = mojo.makeRequest(integerSenderPtrInfo);
-  this.getSender(integerSenderRequest);
-  return Promise.resolve({sender: integerSenderPtrInfo});
-};
-
-function IntegerSenderConnectionAtBothEndsImpl() {
-  this.integerSender_ = null;
-}
-
-IntegerSenderConnectionAtBothEndsImpl.prototype.getSender =
-    IntegerSenderConnectionImpl.prototype.getSender;
-
-IntegerSenderConnectionAtBothEndsImpl.prototype.setSender = function(
-    integerSenderPtrInfo) {
-  this.integerSender_ = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo);
-  return this.integerSender_.echo(456);
-};
-
-function IntegerSenderConnectionImplWithConnectionError() {
-  this.integerSenderBinding_ = null;
-}
-
-IntegerSenderConnectionImplWithConnectionError.prototype.getSender =
-    function(integerSenderRequest) {
-  this.integerSenderBinding_ = new mojo.AssociatedBinding(
-      mojo.test.IntegerSender, new IntegerSenderImpl(), integerSenderRequest);
-  this.integerSenderBinding_.closeWithReason(
-      {customReason: 42, description: 'hey'});
-};
-
-function SenderConnectionBindLaterImpl({getIntegerSenderCallback,
-    getStringSenderCallback} = {}) {
-  this.getIntegerSenderCallback = getIntegerSenderCallback;
-  this.getStringSenderCallback = getStringSenderCallback;
-  this.integerSenderBinding_ = null;
-  this.stringSenderBinding_ = null;
-}
-
-SenderConnectionBindLaterImpl.prototype.getIntegerSender =
-    function(integerSenderRequest) {
-  setTimeout(() => {
-    this.integerSenderBinding_ = new mojo.AssociatedBinding(
-        mojo.test.IntegerSender,
-        new IntegerSenderImpl(this.getIntegerSenderCallback),
-        integerSenderRequest);
-  }, 0);
-};
-
-SenderConnectionBindLaterImpl.prototype.getStringSender =
-    function(stringSenderRequest) {
-  this.stringSenderBinding_ = new mojo.AssociatedBinding(
-      mojo.test.StringSender,
-      new StringSenderImpl(this.getStringSenderCallback),
-      stringSenderRequest);
-};
-
-function SenderConnectionImpl({getIntegerSenderCallback,
-    getStringSenderCallback} = {}) {
-  this.getIntegerSenderCallback = getIntegerSenderCallback;
-  this.getStringSenderCallback = getStringSenderCallback;
-  this.integerSenderBinding_ = null;
-  this.stringSenderBinding_ = null;
-}
-
-SenderConnectionImpl.prototype.getIntegerSender =
-    function(integerSenderRequest) {
-  this.integerSenderBinding_ = new mojo.AssociatedBinding(
-      mojo.test.IntegerSender,
-      new IntegerSenderImpl(this.getIntegerSenderCallback),
-      integerSenderRequest);
-};
-
-SenderConnectionImpl.prototype.getStringSender =
-    function(stringSenderRequest) {
-  this.stringSenderBinding_ = new mojo.AssociatedBinding(
-      mojo.test.StringSender,
-      new StringSenderImpl(this.getStringSenderCallback),
-      stringSenderRequest);
-};
-
-promise_test(async () => {
-  var integerSenderConnection = new
-      mojo.test.IntegerSenderConnectionPtr();
-  var integerSenderConnectionBinding = new mojo.Binding(
-      mojo.test.IntegerSenderConnection,
-      new IntegerSenderConnectionImpl(),
-      mojo.makeRequest(integerSenderConnection));
-
-  // Sending AssociatedInterfaceRequest.
-  var integerSenderPtrInfo0 = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest0 = mojo.makeRequest(integerSenderPtrInfo0);
-
-  var integerSender0 = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo0);
-
-  integerSenderConnection.getSender(integerSenderRequest0);
-  assert_equals((await integerSender0.echo(123)).value, 123);
-
-  // Recieving AssociatedInterfacePtrInfo.
-  var integerSenderPtrInfo1 =
-      (await integerSenderConnection.asyncGetSender()).sender;
-  var integerSender1 = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo1);
-  assert_equals((await integerSender1.echo(456)).value, 456);
-}, 'pass associated interfaces');
-
-// Bind to the same pipe two associated interfaces, whose implementation
-// lives at different ends. Test that the two don't interfere.
-promise_test(async () => {
-  var integerSenderConnectionAtBothEnds = new
-      mojo.test.IntegerSenderConnectionAtBothEndsPtr();
-  var integerSenderConnectionAtBothEndsBinding = new mojo.Binding(
-      mojo.test.IntegerSenderConnectionAtBothEnds,
-      new IntegerSenderConnectionAtBothEndsImpl(),
-      mojo.makeRequest(integerSenderConnectionAtBothEnds));
-
-  // Associated Interface whose Binding Impl lives on the other side.
-  // Sending AssociatedInterfaceRequest.
-  var integerSenderPtrInfo0 = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest0 = mojo.makeRequest(integerSenderPtrInfo0);
-
-  var integerSender0 = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo0);
-
-  integerSenderConnectionAtBothEnds.getSender(integerSenderRequest0);
-  assert_equals((await integerSender0.echo(123)).value, 123);
-
-  // Associated Interface whose Binding Impl lives on this side.
-  // Sending AssociatedInterfacePtrInfo.
-  var integerSenderPtrInfo1 = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest1 = mojo.makeRequest(integerSenderPtrInfo1);
-
-  var integerSenderBinding = new mojo.AssociatedBinding(
-      mojo.test.IntegerSender, new IntegerSenderImpl(),
-      integerSenderRequest1);
-
-  assert_equals((await integerSenderConnectionAtBothEnds.setSender(
-      integerSenderPtrInfo1)).value, 456);
-}, 'associated interfaces on both ends');
-
-promise_test(async () => {
-  var integerSenderConnection = new mojo.test.IntegerSenderConnectionPtr();
-  var integerSenderConnectionBinding = new mojo.Binding(
-      mojo.test.IntegerSenderConnection,
-      new IntegerSenderConnectionImplWithConnectionError(),
-      mojo.makeRequest(integerSenderConnection));
-
-  // Sending AssociatedInterfaceRequest.
-  var integerSenderPtrInfo0 = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest0 = mojo.makeRequest(integerSenderPtrInfo0);
-
-  var integerSender0 = new mojo.test.IntegerSenderAssociatedPtr(
-          integerSenderPtrInfo0);
-
-  integerSenderConnection.getSender(integerSenderRequest0);
-  await new Promise((resolve, reject) => {
-    integerSender0.ptr.setConnectionErrorHandler(function({customReason,
-        description}) {
-      assert_equals(customReason, 42);
-      assert_equals(description, 'hey');
-      resolve();
-    });
-  });
-}, 'connection error with reason');
-
-// Test that AssociatedInterfacePtr is notified with connection error when
-// the interface hasn't associated with a message pipe and the peer is
-// closed.
-promise_test(async () => {
-  var integerSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest = mojo.makeRequest(integerSenderPtrInfo);
-
-  var integerSender = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo);
-
-  await new Promise((resolve, reject) => {
-    integerSender.ptr.setConnectionErrorHandler(function({customReason,
-        description}) {
-      assert_equals(customReason, 42);
-      assert_equals(description, 'hey');
-      resolve();
-    });
-    integerSenderRequest.resetWithReason({customReason: 42,
-        description: 'hey'})
-  });
-}, 'pending AssociatedInterfacePtr connection error with reason');
-
-promise_test(async () => {
-  var integerSenderConnection = new mojo.test.IntegerSenderConnectionPtr();
-  var integerSenderConnectionBinding = new mojo.Binding(
-      mojo.test.IntegerSenderConnection, new IntegerSenderConnectionImpl(),
-      mojo.makeRequest(integerSenderConnection));
-
-  // Sending AssociatedInterfaceRequest.
-  var integerSenderPtrInfo0 = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest0 = mojo.makeRequest(integerSenderPtrInfo0);
-  var integerSender0 = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo0);
-  integerSenderConnection.getSender(integerSenderRequest0);
-
-  // Recieving AssociatedInterfacePtrInfo.
-  var integerSenderPtrInfo1 =
-      (await integerSenderConnection.asyncGetSender()).sender;
-  var integerSender1 = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo1);
-
-  // Master InterfacePtrController reset triggers connection error handler on
-  // interface endpoint clients for all associated endpoints.
-  var connectionErrorHandler0 = new Promise((resolve, reject) => {
-    integerSender0.ptr.setConnectionErrorHandler(() => {
-      resolve();
-    });
-  });
-
-  var connectionErrorHandler1 = new Promise((resolve, reject) => {
-    integerSender1.ptr.setConnectionErrorHandler(() => {
-      resolve();
-    });
-  });
-
-  setTimeout(integerSenderConnection.ptr.reset.bind(
-      integerSenderConnection.ptr), 0);
-  await Promise.all([connectionErrorHandler0, connectionErrorHandler1]);
-}, 'all endpoints connectionErrorHandler called on master interface reset');
-
-// Cache the current message and pause processing incoming messages if
-// endpoint does not have client attached yet to ensure fifo message arrival.
-promise_test(async () => {
-  var senderConnection = new mojo.test.SenderConnectionPtr();
-  var senderConnectionBindLaterImpl = new SenderConnectionBindLaterImpl();
-  var senderConnectionBinding = new mojo.Binding(
-      mojo.test.SenderConnection, senderConnectionBindLaterImpl,
-      mojo.makeRequest(senderConnection));
-
-  // AssociatedInterfaceRequest for stringSender.
-  var stringSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
-  var stringSenderRequest = mojo.makeRequest(stringSenderPtrInfo);
-  var stringSender = new mojo.test.StringSenderAssociatedPtr(
-      stringSenderPtrInfo);
-
-  // AssociatedInterfaceRequest for integerSender.
-  var integerSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest = mojo.makeRequest(integerSenderPtrInfo);
-  var integerSender = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo);
-
-  var value = await new Promise(function(resolve, reject) {
-    senderConnectionBindLaterImpl.getIntegerSenderCallback = resolve;
-    senderConnectionBindLaterImpl.getStringSenderCallback= reject;
-    senderConnection.getStringSender(stringSenderRequest);
-    senderConnection.getIntegerSender(integerSenderRequest);
-    // Test FIFO arrival order of message.
-    integerSender.send(456); // This message should arrive first.
-    stringSender.send('goodbye');
-  });
-
-  assert_equals(value, 456);
-}, 'fifo order should be preserved for messages');
-
-promise_test(async () => {
-  var senderConnection = new mojo.test.SenderConnectionPtr();
-  var senderConnectionImpl = new SenderConnectionImpl();
-  var senderConnectionBinding = new mojo.Binding(
-      mojo.test.SenderConnection, senderConnectionImpl,
-      mojo.makeRequest(senderConnection));
-
-  // AssociatedInterfaceRequest for stringSender.
-  var stringSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
-  var stringSenderRequest = mojo.makeRequest(stringSenderPtrInfo);
-  var stringSender = new mojo.test.StringSenderAssociatedPtr(
-      stringSenderPtrInfo);
-
-  // AssociatedInterfaceRequest for integerSender.
-  var integerSenderPtrInfo = new mojo.AssociatedInterfacePtrInfo();
-  var integerSenderRequest = mojo.makeRequest(integerSenderPtrInfo);
-  var integerSender = new mojo.test.IntegerSenderAssociatedPtr(
-      integerSenderPtrInfo);
-
-  var value = await new Promise(function(resolve, reject) {
-    senderConnectionImpl.getIntegerSenderCallback = reject;
-    senderConnectionImpl.getStringSenderCallback= resolve;
-    senderConnection.getStringSender(stringSenderRequest);
-    senderConnection.getIntegerSender(integerSenderRequest);
-
-    // Wait for integerSenderBinding to be created.
-    integerSender.echo(100).then(function(result) {
-      assert_equals(result.value, 100);
-
-      // This causes this endpoint handle's endpoint client to be detached.
-      var handle = senderConnectionImpl.integerSenderBinding_.
-          interfaceEndpointClient_.passHandle();
-
-      // Cache message. Connector will pause processing incoming messages.
-      integerSender.send(456);
-      stringSender.send('goodbye');
-
-      // Closing the target endpoint handle of the cached message will cause
-      // the cached message to be discarded and the connector to resume
-      // processing incoming messages.
-      setTimeout(handle.reset.bind(handle), 0);
-    });
-  });
-
-  assert_equals(value, 'goodbye');
-}, 'discard cached message if target endpoint closed');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/bind-intercepted-interface-in-worker.html b/third_party/blink/web_tests/mojo/bind-intercepted-interface-in-worker.html
deleted file mode 100644
index 6158ef1..0000000
--- a/third_party/blink/web_tests/mojo/bind-intercepted-interface-in-worker.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script>
-'use strict';
-
-let worker = new Worker('resources/bind-intercepted-interface-in-worker.js');
-fetch_tests_from_worker(worker);
-</script>
diff --git a/third_party/blink/web_tests/mojo/bind-interface.html b/third_party/blink/web_tests/mojo/bind-interface.html
deleted file mode 100644
index c11e1e8..0000000
--- a/third_party/blink/web_tests/mojo/bind-interface.html
+++ /dev/null
@@ -1,151 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/content/test/data/mojo_web_test_helper_test.mojom.js"></script>
-<script src="resources/helpers.js"></script>
-<script>
-
-promise_test(() => {
-  let helper = new content.mojom.MojoWebTestHelperPtr;
-  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
-                     mojo.makeRequest(helper).handle);
-
-  const kTestMessage = "hello world.";
-  const kExpectedReply = ".dlrow olleh";
-  return helper.reverse(kTestMessage).then(reply => {
-    assert_equals(reply.reversed, kExpectedReply);
-  });
-}, "can bind interfaces");
-
-promise_test(() => {
-  let helperImpl = new TestHelperImpl;
-  let interceptor =
-      new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
-  interceptor.oninterfacerequest = e => {
-    helperImpl.bindRequest(e.handle);
-  };
-  interceptor.start();
-
-  let helper = new content.mojom.MojoWebTestHelperPtr;
-  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
-                     mojo.makeRequest(helper).handle);
-  interceptor.stop();
-
-  return helper.reverse("doesn't matter").then(reply => {
-    assert_equals(reply.reversed, kTestReply);
-  });
-}, "can intercept calls to bindInterface");
-
-promise_test(async () => {
-  // Intercept this interface at "context" scope to check that it is being
-  // requested at "process" scope.
-  let helperImpl = new TestHelperImpl;
-  let interceptor =
-      new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
-  interceptor.oninterfacerequest = e => {
-    helperImpl.bindRequest(e.handle);
-  };
-  interceptor.start();
-
-  let helper = new content.mojom.MojoWebTestHelperPtr;
-  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
-                     mojo.makeRequest(helper).handle,
-                     "process");
-
-  const kTestMessage = "hello world.";
-  const kExpectedReply = ".dlrow olleh";
-  await helper.reverse(kTestMessage).then(reply => {
-    assert_equals(reply.reversed, kExpectedReply);
-  });
-
-  interceptor.stop();
-}, "can request interfaces at process scope");
-
-promise_test(() => {
-  let helperImpl = new TestHelperImpl;
-  let interceptor = new MojoInterfaceInterceptor(
-      content.mojom.MojoWebTestHelper.name, "process");
-  interceptor.oninterfacerequest = e => {
-    helperImpl.bindRequest(e.handle);
-  };
-  interceptor.start();
-
-  let helper = new content.mojom.MojoWebTestHelperPtr;
-  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
-                     mojo.makeRequest(helper).handle,
-                     "process");
-  interceptor.stop();
-
-  return helper.reverse("doesn't matter").then(reply => {
-    assert_equals(reply.reversed, kTestReply);
-  });
-}, "can intercept interfaces at process scope");
-
-test(() => {
-  let a = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
-  let b = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
-  a.oninterfacerequest = () => {};
-  b.oninterfacerequest = () => {};
-  a.start();
-  assert_throws('InvalidModificationError', () => { b.start(); });
-  a.stop();
-}, "interface interceptors are mutually exclusive");
-
-test(() => {
-  let a = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name,
-                                       "process");
-  let b = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name,
-                                       "process");
-  a.oninterfacerequest = () => {};
-  b.oninterfacerequest = () => {};
-  a.start();
-  assert_throws('InvalidModificationError', () => { b.start(); });
-  a.stop();
-}, "process scope interface interceptors are mutually exclusive");
-
-promise_test(async t => {
-  // First check that the interceptor can be started and intercepts requests.
-  let interceptor =
-      new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
-  let promise = new Promise(resolve => {
-    interceptor.oninterfacerequest = e => {
-      resolve(e.handle);
-    };
-  });
-  interceptor.start();
-
-  let pipe = Mojo.createMessagePipe();
-  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name, pipe.handle0);
-  let interceptedHandle = await promise;
-  assert_true(interceptedHandle instanceof MojoHandle);
-  interceptedHandle.close();
-  pipe.handle1.close();
-
-  // Stop the interceptor and make another request.
-  interceptor.stop();
-
-  let helper = new content.mojom.MojoWebTestHelperPtr;
-  interceptor.oninterfacerequest = t.step_func(() => {
-    assert_unreached("unexpected 'interfacerequest' event after stop");
-  });
-  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
-                     mojo.makeRequest(helper).handle);
-
-  // Enusre that the interface is functioning, i.e. the request definitely was
-  // not intercepted.
-  await helper.reverse("abc").then(reply => {
-    assert_equals(reply.reversed, "cba");
-  });
-  pipe.handle1.close();
-
-  // And ensure that we can start a new interceptor for the same interface since
-  // the previous one was stopped.
-  interceptor =
-      new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name);
-  interceptor.oninterfacerequest = e => {};
-  interceptor.start();
-  interceptor.stop();
-}, "interceptors cancel properly");
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/binding.html b/third_party/blink/web_tests/mojo/binding.html
deleted file mode 100644
index 1bd504a..0000000
--- a/third_party/blink/web_tests/mojo/binding.html
+++ /dev/null
@@ -1,118 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/math_calculator.mojom.js"></script>
-<script>
-'use strict';
-
-function CalculatorImpl() {
-  this.total = 0;
-}
-
-CalculatorImpl.prototype.clear = function() {
-  this.total = 0;
-  return Promise.resolve({value: this.total});
-};
-
-CalculatorImpl.prototype.add = function(value) {
-  this.total += value;
-  return Promise.resolve({value: this.total});
-};
-
-CalculatorImpl.prototype.multiply = function(value) {
-  this.total *= value;
-  return Promise.resolve({value: this.total});
-};
-
-test(() => {
-  var binding = new mojo.Binding(math.Calculator, new CalculatorImpl());
-  assert_false(binding.isBound());
-
-  var calc = new math.CalculatorPtr();
-  var request = mojo.makeRequest(calc);
-  binding.bind(request);
-  assert_true(binding.isBound());
-
-  binding.close();
-  assert_false(binding.isBound());
-}, 'is bound');
-
-promise_test(async () => {
-  var calc1 = new math.CalculatorPtr();
-  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
-                                     mojo.makeRequest(calc1));
-  assert_equals((await calc1.add(2)).value, 2);
-
-  var calc2 = new math.CalculatorPtr();
-  calcBinding.bind(mojo.makeRequest(calc2));
-  assert_equals((await calc2.add(2)).value, 4);
-}, 'reusable');
-
-promise_test(async () => {
-  var calc = new math.CalculatorPtr();
-  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
-                                     mojo.makeRequest(calc));
-
-  await new Promise((resolve, reject) => {
-    calcBinding.setConnectionErrorHandler(() => { resolve(); });
-    calc.ptr.reset();
-  });
-}, 'connection error');
-
-promise_test(async () => {
-  var calc = new math.CalculatorPtr();
-  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
-                                     mojo.makeRequest(calc));
-
-  await new Promise((resolve, reject) => {
-    calcBinding.setConnectionErrorHandler(({customReason, description}) => {
-      assert_equals(customReason, 32);
-      assert_equals(description, 'goodbye');
-      resolve();
-    });
-    calc.ptr.resetWithReason({customReason: 32, description: 'goodbye'});
-  });
-}, 'connection error with reason');
-
-promise_test(async () => {
-  var calc = new math.CalculatorPtr();
-  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
-                                     mojo.makeRequest(calc));
-  assert_equals((await calc.add(2)).value, 2);
-
-  var interfaceRequest = calcBinding.unbind();
-  assert_false(calcBinding.isBound());
-
-  var newCalcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
-                                        interfaceRequest);
-  assert_equals((await calc.add(2)).value, 2);
-}, 'unbind');
-
-promise_test(async () => {
-  var calc1 = new math.CalculatorPtr();
-  var calc2 = new math.CalculatorPtr();
-  var calcImpl = new CalculatorImpl();
-
-  var bindingSet = new mojo.BindingSet(math.Calculator);
-  assert_true(bindingSet.isEmpty());
-
-  bindingSet.addBinding(calcImpl, mojo.makeRequest(calc1));
-  bindingSet.addBinding(calcImpl, mojo.makeRequest(calc2));
-  assert_false(bindingSet.isEmpty());
-
-  assert_equals((await calc1.add(3)).value, 3);
-  assert_equals((await calc2.add(4)).value, 7);
-
-  await new Promise((resolve, reject) => {
-    bindingSet.setConnectionErrorHandler(() => { resolve(); });
-    calc1.ptr.reset();
-  });
-
-  assert_equals((await calc2.add(5)).value, 12);
-
-  bindingSet.closeAllBindings();
-  assert_true(bindingSet.isEmpty());
-}, 'binding set');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/bindings-lite-old-names.html b/third_party/blink/web_tests/mojo/bindings-lite-old-names.html
deleted file mode 100644
index 9c63bcb..0000000
--- a/third_party/blink/web_tests/mojo/bindings-lite-old-names.html
+++ /dev/null
@@ -1,209 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script>
-<script src="file:///gen/content/test/data/lite_js_old_names_test.mojom-lite.js"></script>
-<script>
-'use strict';
-
-const kTestMessage = 'hello there';
-const kTestNumbers = [0, 1, 1, 2, 3, 5, 8, 13, 21];
-
-class TargetImpl {
-  constructor() {
-    this.numPokes = 0;
-    this.target = new liteJsOldNamesTest.mojom.TestMessageTarget(this);
-  }
-
-  poke() { this.numPokes++; }
-  ping() { return Promise.resolve(); }
-  repeat(message, numbers) { return {message: message, numbers: numbers}; }
-  flatten(values) {}
-  flattenUnions(unions) {}
-  requestSubinterface(request, client) {}
-}
-
-promise_test(() => {
-  let impl = new TargetImpl;
-  let proxy = impl.target.$.createProxy();
-  proxy.poke();
-  return proxy.ping().then(() => {
-    assert_equals(impl.numPokes, 1);
-  });
-}, 'messages with replies return Promises that resolve on reply received');
-
-promise_test(() => {
-  let impl = new TargetImpl;
-  let proxy = impl.target.$.createProxy();
-  return proxy.repeat(kTestMessage, kTestNumbers)
-              .then(reply => {
-                assert_equals(reply.message, kTestMessage);
-                assert_array_equals(reply.numbers, kTestNumbers);
-              });
-}, 'implementations can reply with multiple reply arguments');
-
-promise_test(async (t) => {
-  const impl = new TargetImpl;
-  const proxy = impl.target.$.createProxy();
-
-  await proxy.ping();
-  proxy.$.close();
-
-  await promise_rejects(t, new Error(), proxy.ping());
-}, 'after the pipe is closed all future calls should fail');
-
-promise_test(async (t) => {
-  const impl = new TargetImpl;
-  const proxy = impl.target.$.createProxy();
-
-  // None of these promises should successfully resolve because we are
-  // immediately closing the pipe.
-  const promises = []
-  for (let i = 0; i < 10; i++) {
-    promises.push(proxy.ping());
-  }
-
-  proxy.$.close();
-
-  for (const promise of promises) {
-    await promise_rejects(t, new Error(), promise);
-  }
-}, 'closing the pipe drops any pending messages');
-
-promise_test(() => {
-  let impl = new TargetImpl;
-
-  // Intercept any browser-bound request for TestMessageTarget and bind it
-  // instead to the local |impl| object.
-  let interceptor = new MojoInterfaceInterceptor(
-    liteJsOldNamesTest.mojom.TestMessageTarget.$interfaceName);
-  interceptor.oninterfacerequest = e => {
-    impl.target.$.bindHandle(e.handle);
-  }
-  interceptor.start();
-
-  let proxy = liteJsOldNamesTest.mojom.TestMessageTarget.getProxy();
-  proxy.poke();
-
-  return proxy.ping().then(() => {
-    assert_equals(impl.numPokes, 1);
-  });
-}, 'getProxy() attempts to send requests to the frame host');
-
-promise_test(() => {
-  let router = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
-  let proxy = router.$.createProxy();
-  return new Promise(resolve => {
-    router.poke.addListener(resolve);
-    proxy.poke();
-  });
-}, 'basic generated CallbackRouter behavior works as intended');
-
-promise_test(() => {
-  let router = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
-  let proxy = router.$.createProxy();
-  let numPokes = 0;
-  router.poke.addListener(() => ++numPokes);
-  router.ping.addListener(() => Promise.resolve());
-  proxy.poke();
-  return proxy.ping().then(() => assert_equals(numPokes, 1));
-}, 'CallbackRouter listeners can reply to messages');
-
-promise_test(() => {
-  let router = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
-  let proxy = router.$.createProxy();
-  router.repeat.addListener(
-    (message, numbers) => ({message: message, numbers: numbers}));
-  return proxy.repeat(kTestMessage, kTestNumbers)
-              .then(reply => {
-                assert_equals(reply.message, kTestMessage);
-                assert_array_equals(reply.numbers, kTestNumbers);
-              });
-}, 'CallbackRouter listeners can reply with multiple reply arguments');
-
-promise_test(() => {
-  let targetRouter = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
-  let targetProxy = targetRouter.$.createProxy();
-  let subinterfaceRouter = new liteJsOldNamesTest.mojom.SubinterfaceCallbackRouter;
-  targetRouter.requestSubinterface.addListener((request, client) => {
-    let values = [];
-    subinterfaceRouter.$.bindHandle(request.handle);
-    subinterfaceRouter.push.addListener(value => values.push(value));
-    subinterfaceRouter.flush.addListener(() => {
-      client.didFlush(values);
-      values = [];
-    });
-  });
-
-  let clientRouter = new liteJsOldNamesTest.mojom.SubinterfaceClientCallbackRouter;
-  let subinterfaceProxy = new liteJsOldNamesTest.mojom.SubinterfaceProxy;
-  targetProxy.requestSubinterface(
-    subinterfaceProxy.$.createRequest(), clientRouter.$.createProxy());
-  return new Promise(resolve => {
-    clientRouter.didFlush.addListener(values => {
-      assert_array_equals(values, kTestNumbers);
-      resolve();
-    });
-
-    kTestNumbers.forEach(n => subinterfaceProxy.push(n));
-    subinterfaceProxy.flush();
-  });
-}, 'can send and receive interface requests and proxies');
-
-promise_test(() => {
-  const targetRouter = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
-  const targetProxy = targetRouter.$.createProxy();
-  targetRouter.flatten.addListener(values => ({values: values.map(v => v.x)}));
-  return targetProxy.flatten([{x: 1}, {x: 2}, {x: 3}]).then(reply => {
-    assert_array_equals(reply.values, [1, 2, 3]);
-  });
-}, 'regression test for complex array serialization');
-
-promise_test(() => {
-  const targetRouter = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
-  const targetProxy = targetRouter.$.createProxy();
-  targetRouter.flattenUnions.addListener(unions => {
-    return {x: unions.filter(u => u.x !== undefined).map(u => u.x),
-            s: unions.filter(u => u.s !== undefined).map(u => u.s.x)};
-  });
-
-  return targetProxy.flattenUnions(
-    [{x: 1}, {x: 2}, {s: {x: 3}}, {s: {x: 4}}, {x: 5}, {s: {x: 6}}])
-                    .then(reply => {
-                      assert_array_equals(reply.x, [1, 2, 5]);
-                      assert_array_equals(reply.s, [3, 4, 6]);
-                    });
-}, 'can serialize and deserialize unions');
-
-promise_test(() => {
-  let impl = new TargetImpl;
-  let proxy = impl.target.$.createProxy();
-
-  // Poke a bunch of times. These should never race with the assertion below,
-  // because the |flushForTesting| request/response is ordered against other
-  // messages on |proxy|.
-  const kNumPokes = 100;
-  for (let i = 0; i < kNumPokes; ++i)
-    proxy.poke();
-  return proxy.$.flushForTesting().then(() => {
-    assert_equals(impl.numPokes, kNumPokes);
-  });
-}, 'can use generated flushForTesting API for synchronization in tests');
-
-promise_test(async(t) => {
-  const impl = new TargetImpl;
-  const proxy = impl.target.$.createProxy();
-  const disconnectPromise = new Promise(resolve => impl.target.onConnectionError.addListener(resolve));
-  proxy.$.close();
-  return disconnectPromise;
-}, 'InterfaceTarget connection error handler runs when set on an Interface object');
-
-promise_test(() => {
-  const router = new liteJsOldNamesTest.mojom.TestMessageTargetCallbackRouter;
-  const proxy = router.$.createProxy();
-  const disconnectPromise = new Promise(resolve => router.onConnectionError.addListener(resolve));
-  proxy.$.close();
-  return disconnectPromise;
-}, 'InterfaceTarget connection error handler runs when set on an InterfaceCallbackRouter object');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/bindings-lite.html b/third_party/blink/web_tests/mojo/bindings-lite.html
deleted file mode 100644
index 8e7133cf..0000000
--- a/third_party/blink/web_tests/mojo/bindings-lite.html
+++ /dev/null
@@ -1,218 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script>
-<script src="file:///gen/content/test/data/lite_js_test.mojom-lite.js"></script>
-<script>
-'use strict';
-
-const kTestMessage = 'hello there';
-const kTestNumbers = [0, 1, 1, 2, 3, 5, 8, 13, 21];
-
-class TargetImpl {
-  constructor() {
-    this.numPokes = 0;
-    this.target = new liteJsTest.mojom.TestMessageTargetReceiver(this);
-  }
-
-  poke() { this.numPokes++; }
-  ping() { return Promise.resolve(); }
-  repeat(message, numbers) { return {message: message, numbers: numbers}; }
-  echo(nested) { return Promise.resolve({nested: nested}); }
-  flatten(values) {}
-  flattenUnions(unions) {}
-  requestSubinterface(request, client) {}
-}
-
-promise_test(() => {
-  let impl = new TargetImpl;
-  let remote = impl.target.$.bindNewPipeAndPassRemote();
-  remote.poke();
-  return remote.ping().then(() => {
-    assert_equals(impl.numPokes, 1);
-  });
-}, 'messages with replies return Promises that resolve on reply received');
-
-promise_test(() => {
-  let impl = new TargetImpl;
-  let remote = impl.target.$.bindNewPipeAndPassRemote();
-  return remote.repeat(kTestMessage, kTestNumbers)
-      .then(reply => {
-        assert_equals(reply.message, kTestMessage);
-        assert_array_equals(reply.numbers, kTestNumbers);
-      });
-}, 'implementations can reply with multiple reply arguments');
-
-promise_test(() => {
-  let impl = new TargetImpl;
-  let remote = impl.target.$.bindNewPipeAndPassRemote();
-  const enumValue = liteJsTest.mojom.TestMessageTarget_NestedEnum.kFoo;
-  return remote.echo(enumValue)
-      .then(({nested}) => assert_equals(nested, enumValue));
-}, 'nested enums are usable as arguments and responses.');
-
-promise_test(async (t) => {
-  const impl = new TargetImpl;
-  const remote = impl.target.$.bindNewPipeAndPassRemote();
-
-  await remote.ping();
-  remote.$.close();
-
-  await promise_rejects(t, new Error(), remote.ping());
-}, 'after the pipe is closed all future calls should fail');
-
-promise_test(async (t) => {
-  const impl = new TargetImpl;
-  const remote = impl.target.$.bindNewPipeAndPassRemote();
-
-  // None of these promises should successfully resolve because we are
-  // immediately closing the pipe.
-  const promises = []
-  for (let i = 0; i < 10; i++) {
-    promises.push(remote.ping());
-  }
-
-  remote.$.close();
-
-  for (const promise of promises) {
-    await promise_rejects(t, new Error(), promise);
-  }
-}, 'closing the pipe drops any pending messages');
-
-promise_test(() => {
-  let impl = new TargetImpl;
-
-  // Intercept any browser-bound request for TestMessageTarget and bind it
-  // instead to the local |impl| object.
-  let interceptor = new MojoInterfaceInterceptor(
-      liteJsTest.mojom.TestMessageTarget.$interfaceName);
-  interceptor.oninterfacerequest = e => {
-    impl.target.$.bindHandle(e.handle);
-  }
-  interceptor.start();
-
-  let remote = liteJsTest.mojom.TestMessageTarget.getRemote();
-  remote.poke();
-  return remote.ping().then(() => {
-    assert_equals(impl.numPokes, 1);
-  });
-}, 'getRemote() attempts to send requests to the frame host');
-
-promise_test(() => {
-  let router = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
-  let remote = router.$.bindNewPipeAndPassRemote();
-  return new Promise(resolve => {
-    router.poke.addListener(resolve);
-    remote.poke();
-  });
-}, 'basic generated CallbackRouter behavior works as intended');
-
-promise_test(() => {
-  let router = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
-  let remote = router.$.bindNewPipeAndPassRemote();
-  let numPokes = 0;
-  router.poke.addListener(() => ++numPokes);
-  router.ping.addListener(() => Promise.resolve());
-  remote.poke();
-  return remote.ping().then(() => assert_equals(numPokes, 1));
-}, 'CallbackRouter listeners can reply to messages');
-
-promise_test(() => {
-  let router = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
-  let remote = router.$.bindNewPipeAndPassRemote();
-  router.repeat.addListener(
-      (message, numbers) => ({message: message, numbers: numbers}));
-  return remote.repeat(kTestMessage, kTestNumbers)
-      .then(reply => {
-        assert_equals(reply.message, kTestMessage);
-        assert_array_equals(reply.numbers, kTestNumbers);
-      });
-}, 'CallbackRouter listeners can reply with multiple reply arguments');
-
-promise_test(() => {
-  let targetRouter = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
-  let targetRemote = targetRouter.$.bindNewPipeAndPassRemote();
-  let subinterfaceRouter = new liteJsTest.mojom.SubinterfaceCallbackRouter;
-  targetRouter.requestSubinterface.addListener((request, client) => {
-    let values = [];
-    subinterfaceRouter.$.bindHandle(request.handle);
-    subinterfaceRouter.push.addListener(value => values.push(value));
-    subinterfaceRouter.flush.addListener(() => {
-      client.didFlush(values);
-      values = [];
-    });
-  });
-
-  let clientRouter = new liteJsTest.mojom.SubinterfaceClientCallbackRouter;
-  let subinterfaceRemote = new liteJsTest.mojom.SubinterfaceRemote;
-  targetRemote.requestSubinterface(
-    subinterfaceRemote.$.bindNewPipeAndPassReceiver(),
-    clientRouter.$.bindNewPipeAndPassRemote());
-  return new Promise(resolve => {
-    clientRouter.didFlush.addListener(values => {
-      assert_array_equals(values, kTestNumbers);
-      resolve();
-    });
-
-    kTestNumbers.forEach(n => subinterfaceRemote.push(n));
-    subinterfaceRemote.flush();
-  });
-}, 'can send and receive interface requests and proxies');
-
-promise_test(() => {
-  const targetRouter = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
-  const targetRemote = targetRouter.$.bindNewPipeAndPassRemote();
-  targetRouter.flatten.addListener(values => ({values: values.map(v => v.x)}));
-  return targetRemote.flatten([{x: 1}, {x: 2}, {x: 3}]).then(reply => {
-    assert_array_equals(reply.values, [1, 2, 3]);
-  });
-}, 'regression test for complex array serialization');
-
-promise_test(() => {
-  const targetRouter = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
-  const targetRemote = targetRouter.$.bindNewPipeAndPassRemote();
-  targetRouter.flattenUnions.addListener(unions => {
-    return {x: unions.filter(u => u.x !== undefined).map(u => u.x),
-            s: unions.filter(u => u.s !== undefined).map(u => u.s.x)};
-  });
-
-  return targetRemote.flattenUnions(
-      [{x: 1}, {x: 2}, {s: {x: 3}}, {s: {x: 4}}, {x: 5}, {s: {x: 6}}])
-      .then(reply => {
-    assert_array_equals(reply.x, [1, 2, 5]);
-    assert_array_equals(reply.s, [3, 4, 6]);
-  });
-}, 'can serialize and deserialize unions');
-
-promise_test(() => {
-  let impl = new TargetImpl;
-  let remote = impl.target.$.bindNewPipeAndPassRemote();
-
-  // Poke a bunch of times. These should never race with the assertion below,
-  // because the |flushForTesting| request/response is ordered against other
-  // messages on |remote|.
-  const kNumPokes = 100;
-  for (let i = 0; i < kNumPokes; ++i)
-    remote.poke();
-  return remote.$.flushForTesting().then(() => {
-    assert_equals(impl.numPokes, kNumPokes);
-  });
-}, 'can use generated flushForTesting API for synchronization in tests');
-
-promise_test(async(t) => {
-  const impl = new TargetImpl;
-  const remote = impl.target.$.bindNewPipeAndPassRemote();
-  const disconnectPromise = new Promise(resolve => impl.target.onConnectionError.addListener(resolve));
-  remote.$.close();
-  return disconnectPromise;
-}, 'InterfaceTarget connection error handler runs when set on an Interface object');
-
-promise_test(() => {
-  const router = new liteJsTest.mojom.TestMessageTargetCallbackRouter;
-  const remote = router.$.bindNewPipeAndPassRemote();
-  const disconnectPromise = new Promise(resolve => router.onConnectionError.addListener(resolve));
-  remote.$.close();
-  return disconnectPromise;
-  }, 'InterfaceTarget connection error handler runs when set on an InterfaceCallbackRouter object');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/codec.html b/third_party/blink/web_tests/mojo/codec.html
deleted file mode 100644
index 9fdd2fc..0000000
--- a/third_party/blink/web_tests/mojo/codec.html
+++ /dev/null
@@ -1,319 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="../resources/testharness-helpers.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/test_structs.mojom.js"></script>
-<script>
-'use strict';
-
-test(() => {
-  var bar = new sample.Bar();
-  bar.alpha = 1;
-  bar.beta = 2;
-  bar.gamma = 3;
-  bar.type = 0x08070605;
-  bar.extraProperty = "banana";
-
-  var messageName = 42;
-  var payloadSize = sample.Bar.encodedSize;
-
-  var builder = new mojo.internal.MessageV0Builder(messageName, payloadSize);
-  builder.encodeStruct(sample.Bar, bar);
-
-  var message = builder.finish();
-
-  var expectedMemory = new Uint8Array([
-    24, 0, 0, 0,
-     0, 0, 0, 0,
-     0, 0, 0, 0,
-    42, 0, 0, 0,
-     0, 0, 0, 0,
-     0, 0, 0, 0,
-
-    16, 0, 0, 0,
-     0, 0, 0, 0,
-
-     1, 2, 3, 0,
-     5, 6, 7, 8,
-  ]);
-
-  var actualMemory = new Uint8Array(message.buffer.arrayBuffer);
-  assert_weak_equals(actualMemory, expectedMemory);
-
-  var reader = new mojo.internal.MessageReader(message);
-
-  assert_equals(reader.payloadSize, payloadSize);
-  assert_equals(reader.messageName, messageName);
-
-  var bar2 = reader.decodeStruct(sample.Bar);
-
-  assert_equals(bar2.alpha, bar.alpha);
-  assert_equals(bar2.beta, bar.beta);
-  assert_equals(bar2.gamma, bar.gamma);
-  assert_false("extraProperty" in bar2);
-}, 'bar');
-
-test(() => {
-  var foo = new sample.Foo();
-  foo.x = 0x212B4D5;
-  foo.y = 0x16E93;
-  foo.a = 1;
-  foo.b = 0;
-  foo.c = 3; // This will get truncated to one bit.
-  foo.bar = new sample.Bar();
-  foo.bar.alpha = 91;
-  foo.bar.beta = 82;
-  foo.bar.gamma = 73;
-  foo.data = [
-    4, 5, 6, 7, 8,
-  ];
-  foo.extraBars = [
-    new sample.Bar(), new sample.Bar(), new sample.Bar(),
-  ];
-  for (var i = 0; i < foo.extraBars.length; ++i) {
-    foo.extraBars[i].alpha = 1 * i;
-    foo.extraBars[i].beta = 2 * i;
-    foo.extraBars[i].gamma = 3 * i;
-  }
-  foo.name = "I am a banana";
-  // This is supposed to be a handle, but we fake it with an integer.
-  foo.source = 23423782;
-  foo.arrayOfArrayOfBools = [
-    [true], [false, true]
-  ];
-  foo.arrayOfBools = [
-    true, false, true, false, true, false, true, true
-  ];
-
-
-  var messageName = 31;
-  var payloadSize = 304;
-
-  var builder = new mojo.internal.MessageV0Builder(messageName, payloadSize);
-  builder.encodeStruct(sample.Foo, foo);
-
-  var message = builder.finish();
-
-  var expectedMemory = new Uint8Array([
-    /*  0: */   24,    0,    0,    0,    0,    0,    0,    0,
-    /*  8: */    0,    0,    0,    0,   31,    0,    0,    0,
-    /* 16: */    0,    0,    0,    0,    0,    0,    0,    0,
-    /* 24: */   96,    0,    0,    0,    0,    0,    0,    0,
-    /* 32: */ 0xD5, 0xB4, 0x12, 0x02, 0x93, 0x6E, 0x01,    0,
-    /* 40: */    5,    0,    0,    0,    0,    0,    0,    0,
-    /* 48: */   72,    0,    0,    0,    0,    0,    0,    0,
-  ]);
-  // TODO(abarth): Test more of the message's raw memory.
-  var actualMemory = new Uint8Array(message.buffer.arrayBuffer,
-                                    0, expectedMemory.length);
-  assert_weak_equals(actualMemory, expectedMemory);
-
-  var expectedHandles = [
-    23423782,
-  ];
-
-  assert_weak_equals(message.handles, expectedHandles);
-
-  var reader = new mojo.internal.MessageReader(message);
-
-  assert_equals(reader.payloadSize, payloadSize);
-  assert_equals(reader.messageName, messageName);
-
-  var foo2 = reader.decodeStruct(sample.Foo);
-
-  assert_equals(foo2.x, foo.x);
-  assert_equals(foo2.y, foo.y);
-
-  assert_equals(foo2.a, foo.a & 1 ? true : false);
-  assert_equals(foo2.b, foo.b & 1 ? true : false);
-  assert_equals(foo2.c, foo.c & 1 ? true : false);
-
-  assert_weak_equals(foo2.bar, foo.bar);
-  assert_weak_equals(foo2.data, foo.data);
-
-  assert_weak_equals(foo2.extraBars, foo.extraBars);
-  assert_equals(foo2.name, foo.name);
-  assert_equals(foo2.source, foo.source);
-
-  assert_weak_equals(foo2.arrayOfBools, foo.arrayOfBools);
-}, 'foo');
-
-
-// Verify that the references to the imported Rect type in test_structs.mojom
-// are generated correctly.
-test(() => {
-
-  function createRect(x, y, width, height) {
-    var r = new mojo.test.Rect();
-    r.x = x;
-    r.y = y;
-    r.width = width;
-    r.height = height;
-    return r;
-  }
-
-  var r = new mojo.test.NamedRegion();
-  r.name = "rectangle";
-  r.rects = new Array(createRect(1, 2, 3, 4), createRect(10, 20, 30, 40));
-
-  var builder = new mojo.internal.MessageV0Builder(
-      1, mojo.test.NamedRegion.encodedSize);
-  builder.encodeStruct(mojo.test.NamedRegion, r);
-  var reader = new mojo.internal.MessageReader(builder.finish());
-  var result = reader.decodeStruct(mojo.test.NamedRegion);
-
-  assert_equals(result.name, "rectangle");
-  assert_weak_equals(result.rects[0], createRect(1, 2, 3, 4));
-  assert_weak_equals(result.rects[1], createRect(10, 20, 30, 40));
-}, 'named region');
-
-// Verify that a single boolean field in a struct is correctly decoded to
-// boolean type.
-test(() => {
-  var singleBool = new mojo.test.SingleBoolStruct();
-  singleBool.value = true;
-
-  var builder = new mojo.internal.MessageV0Builder(
-      1, mojo.test.SingleBoolStruct.encodedSize);
-  builder.encodeStruct(mojo.test.SingleBoolStruct, singleBool);
-  var reader = new mojo.internal.MessageReader(builder.finish());
-  var result = reader.decodeStruct(mojo.test.SingleBoolStruct);
-
-  assert_true(result.value);
-}, 'single boolean struct');
-
-test(() => {
-  function encodeDecode(cls, input, expectedResult, encodedSize) {
-    var messageName = 42;
-    var payloadSize = encodedSize || cls.encodedSize;
-
-    var builder = new mojo.internal.MessageV0Builder(messageName, payloadSize);
-    builder.encodeStruct(cls, input)
-    var message = builder.finish();
-
-    var reader = new mojo.internal.MessageReader(message);
-    assert_equals(reader.payloadSize, payloadSize);
-    assert_equals(reader.messageName, messageName);
-    var result = reader.decodeStruct(cls);
-    assert_equals(result, expectedResult);
-  }
-  encodeDecode(mojo.internal.String, "banana", "banana", 24);
-  encodeDecode(mojo.internal.NullableString, null, null, 8);
-  encodeDecode(mojo.internal.Int8, -1, -1);
-  encodeDecode(mojo.internal.Int8, 0xff, -1);
-  encodeDecode(mojo.internal.Int16, -1, -1);
-  encodeDecode(mojo.internal.Int16, 0xff, 0xff);
-  encodeDecode(mojo.internal.Int16, 0xffff, -1);
-  encodeDecode(mojo.internal.Int32, -1, -1);
-  encodeDecode(mojo.internal.Int32, 0xffff, 0xffff);
-  encodeDecode(mojo.internal.Int32, 0xffffffff, -1);
-  encodeDecode(mojo.internal.Float, 1.0, 1.0);
-  encodeDecode(mojo.internal.Double, 1.0, 1.0);
-}, 'types');
-
-test(() => {
-  var aligned = [
-    0, // 0
-    8, // 1
-    8, // 2
-    8, // 3
-    8, // 4
-    8, // 5
-    8, // 6
-    8, // 7
-    8, // 8
-    16, // 9
-    16, // 10
-    16, // 11
-    16, // 12
-    16, // 13
-    16, // 14
-    16, // 15
-    16, // 16
-    24, // 17
-    24, // 18
-    24, // 19
-    24, // 20
-  ];
-  for (var i = 0; i < aligned.length; ++i)
-    assert_equals(mojo.internal.align(i), aligned[i]);
-
-}, 'align');
-
-test(() => {
-  var str = "B\u03ba\u1f79";  // some UCS-2 codepoints
-  var messageName = 42;
-  var payloadSize = 24;
-
-  var builder = new mojo.internal.MessageV0Builder(messageName, payloadSize);
-  var encoder = builder.createEncoder(8);
-  encoder.encodeStringPointer(str);
-  var message = builder.finish();
-  var expectedMemory = new Uint8Array([
-    /*  0: */   24,    0,    0,    0,    0,    0,    0,    0,
-    /*  8: */    0,    0,    0,    0,   42,    0,    0,    0,
-    /* 16: */    0,    0,    0,    0,    0,    0,    0,    0,
-    /* 24: */    8,    0,    0,    0,    0,    0,    0,    0,
-    /* 32: */   14,    0,    0,    0,    6,    0,    0,    0,
-    /* 40: */ 0x42, 0xCE, 0xBA, 0xE1, 0xBD, 0xB9,    0,    0,
-  ]);
-  var actualMemory = new Uint8Array(message.buffer.arrayBuffer);
-  assert_weak_equals(actualMemory, expectedMemory);
-
-  var reader = new mojo.internal.MessageReader(message);
-  assert_equals(reader.payloadSize, payloadSize);
-  assert_equals(reader.messageName, messageName);
-  var str2 = reader.decoder.decodeStringPointer();
-  assert_equals(str2, str);
-}, 'utf8');
-
-test(() => {
-  var str = "Hello world ".repeat(100000);
-  var messageName = 42;
-  var payloadSize = 1200000;
-
-  var builder = new mojo.internal.MessageV0Builder(messageName, payloadSize);;
-  var encoder = builder.createEncoder(1200000);
-  encoder.encodeStringPointer(str);
-  var message = builder.finish();
-
-  var reader = new mojo.internal.MessageReader(message);
-  var str2 = reader.decoder.decodeStringPointer();
-  assert_equals(str2, str);
-}, 'very long utf8');
-
-test(() => {
-  var encoder = new mojo.internal.MessageV0Builder(42, 24).createEncoder(8);
-  function DummyClass() {};
-  var testCases = [
-    // method, args, invalid examples, valid examples
-    [encoder.encodeArrayPointer, [DummyClass], [75],
-        [[], null, undefined, new Uint8Array([])]],
-    [encoder.encodeStringPointer, [], [75, new String("foo")],
-        ["", "bar", null, undefined]],
-    [encoder.encodeMapPointer, [DummyClass, DummyClass], [75],
-        [new Map(), null, undefined]],
-  ];
-
-  testCases.forEach(function(test) {
-    var method = test[0];
-    var baseArgs = test[1];
-    var invalidExamples = test[2];
-    var validExamples = test[3];
-
-    var encoder = new mojo.internal.MessageV0Builder(42, 24).createEncoder(8);
-    invalidExamples.forEach(function(invalid) {
-      assert_throws(new Error, function() {
-        method.apply(encoder, baseArgs.concat(invalid));
-      });
-    });
-
-    validExamples.forEach(function(valid) {
-      var encoder = new mojo.internal.MessageV0Builder(42, 24).createEncoder(8);
-      method.apply(encoder, baseArgs.concat(valid));
-    });
-  });
-}, 'typed pointer validation');
-</script>
diff --git a/third_party/blink/web_tests/mojo/connection.html b/third_party/blink/web_tests/mojo/connection.html
deleted file mode 100644
index 156a541..0000000
--- a/third_party/blink/web_tests/mojo/connection.html
+++ /dev/null
@@ -1,83 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.js"></script>
-<script>
-'use strict';
-
-promise_test(async () => {
-  function ServiceImpl() {
-  }
-
-  ServiceImpl.prototype.frobinate = function(foo, baz, port) {
-    assert_equals(foo.name, "Example name");
-    assert_equals(baz, sample.Service.BazOptions.REGULAR);
-    assert_true(port.ptr.isBound());
-    port.ptr.reset();
-
-    return Promise.resolve({result: 42});
-  };
-
-  var service = new sample.ServicePtr();
-  var serviceBinding = new mojo.Binding(
-      sample.Service, new ServiceImpl(), mojo.makeRequest(service));
-  var sourcePipe = Mojo.createMessagePipe();
-  var port = new sample.PortPtr();
-  var portRequest = mojo.makeRequest(port);
-
-  var foo = new sample.Foo();
-  foo.bar = new sample.Bar();
-  foo.name = "Example name";
-  foo.source = sourcePipe.handle0;
-
-  assert_equals((await service.frobinate(
-      foo, sample.Service.BazOptions.REGULAR, port)).result, 42);
-
-  service.ptr.reset();
-  serviceBinding.close();
-
-  // sourcePipe.handle1 hasn't been closed yet.
-  sourcePipe.handle1.close();
-
-  // portRequest.handle hasn't been closed yet.
-  portRequest.handle.close();
-}, 'client server');
-
-promise_test(async () => {
-  var service = new sample.ServicePtr();
-  // Discard the interface request.
-  var interfaceRequest = mojo.makeRequest(service);
-  interfaceRequest.close();
-
-  try {
-    await service.frobinate(null, sample.Service.BazOptions.REGULAR, null);
-    assert_unreached();
-  } catch (e) {
-    assert_not_equals(e, null);
-  }
-}, 'write to closed pipe');
-
-promise_test(async () => {
-  function ProviderImpl() {
-  }
-
-  ProviderImpl.prototype.echoString = function(a) {
-    return Promise.resolve({a: a});
-  };
-
-  ProviderImpl.prototype.echoStrings = function(a, b) {
-    return Promise.resolve({a: a, b: b});
-  };
-
-  var provider = new sample.ProviderPtr();
-  var providerBinding = new mojo.Binding(
-      sample.Provider, new ProviderImpl(), mojo.makeRequest(provider));
-  assert_equals((await provider.echoString("hello")).a, "hello");
-  var response = await provider.echoStrings("hello", "world");
-  assert_equals(response.a, "hello");
-  assert_equals(response.b, "world");
-}, 'request response');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/data-pipe.html b/third_party/blink/web_tests/mojo/data-pipe.html
deleted file mode 100644
index 1e3f089..0000000
--- a/third_party/blink/web_tests/mojo/data-pipe.html
+++ /dev/null
@@ -1,154 +0,0 @@
-<!DOCTYPE html>
-<title>Mojo data pipe tests</title>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script>
-
-let kElementNumBytes = 1;
-let kCapacityNumBytes = 64;
-
-function createDataPipe() {
-  return Mojo.createDataPipe({
-      elementNumBytes: kElementNumBytes,
-      capacityNumBytes: kCapacityNumBytes
-  });
-};
-
-test(() => {
-  let {result, producer, consumer} = createDataPipe();
-  assert_equals(result, Mojo.RESULT_OK);
-  assert_true(producer instanceof MojoHandle);
-  assert_true(consumer instanceof MojoHandle);
-}, "Create data pipe");
-
-test(() => {
-  assert_equals(Mojo.createDataPipe({}).result, Mojo.RESULT_INVALID_ARGUMENT);
-  assert_equals(Mojo.createDataPipe({elementNumBytes: kElementNumBytes}).result,
-                Mojo.RESULT_INVALID_ARGUMENT);
-  assert_equals(
-      Mojo.createDataPipe({capacityNumBytes: kCapacityNumBytes}).result,
-      Mojo.RESULT_INVALID_ARGUMENT);
-})
-
-test(() => {
-  let {producer, consumer} = createDataPipe();
-  let data = new Uint8Array(kCapacityNumBytes);
-
-  let {result, numBytes} = producer.writeData(data);
-  assert_equals(result, Mojo.RESULT_OK);
-  assert_equals(numBytes, data.length);
-}, "Write data");
-
-test(() => {
-  let {producer, consumer} = createDataPipe();
-  let data = new Uint8Array(kCapacityNumBytes + 1);
-
-  let {result, numBytes} = producer.writeData(data, {allOrNone: true});
-  assert_equals(result, Mojo.RESULT_OUT_OF_RANGE);
-  assert_equals(numBytes, 0);
-}, "Write data all or none");
-
-async_test((test) => {
-  let {producer, consumer} = createDataPipe();
-  let data = new Uint8Array(kCapacityNumBytes);
-
-  consumer.watch({readable: true}, test.step_func_done((result) => {
-    var {result, numBytes} = consumer.queryData();
-    assert_equals(result, Mojo.RESULT_OK);
-    assert_equals(numBytes, data.length);
-  }));
-  producer.writeData(data);
-}, "Query data");
-
-async_test((test) => {
-  let {producer, consumer} = createDataPipe();
-  let data = new Uint8Array(kCapacityNumBytes);
-  for (let i = 0; i < data.length; ++i)
-    data[i] = i;
-
-  consumer.watch({readable: true}, test.step_func_done((result) => {
-    var kDiscardNumBytes = data.length / 2;
-
-    var {result, numBytes} = consumer.discardData(kDiscardNumBytes);
-    assert_equals(result, Mojo.RESULT_OK);
-    assert_equals(numBytes, kDiscardNumBytes);
-
-    var {result, numBytes} = consumer.queryData();
-    assert_equals(result, Mojo.RESULT_OK);
-    assert_equals(numBytes, kDiscardNumBytes);
-
-    var buffer = new Uint8Array(kDiscardNumBytes);
-    var {result, numBytes} = consumer.readData(buffer);
-    assert_equals(result, Mojo.RESULT_OK);
-    assert_equals(numBytes, kDiscardNumBytes);
-    assert_array_equals(buffer, data.slice(kDiscardNumBytes));
-  }));
-  producer.writeData(data);
-}, "Discard data");
-
-async_test((test) => {
-  let {producer, consumer} = createDataPipe();
-  let data = new Uint8Array(kCapacityNumBytes);
-
-  consumer.watch({readable: true}, test.step_func_done((result) => {
-    var {result, numBytes} = consumer.discardData(data.length + 1, {allOrNone: true});
-    assert_equals(result, Mojo.RESULT_OUT_OF_RANGE);
-    assert_equals(numBytes, 0);
-  }));
-  producer.writeData(data);
-}, "Discard data all or none");
-
-async_test((test) => {
-  let {producer, consumer} = createDataPipe();
-  let data = new Uint8Array(kCapacityNumBytes);
-  for (let i = 0; i < data.length; ++i)
-    data[i] = i;
-
-  consumer.watch({readable: true}, test.step_func_done((result) => {
-    var buffer = new Uint8Array(data.length);
-    var {result, numBytes} = consumer.readData(buffer);
-    assert_equals(result, Mojo.RESULT_OK);
-    assert_equals(numBytes, data.length);
-    assert_array_equals(buffer, data);
-
-    var {result, numBytes} = consumer.queryData();
-    assert_equals(result, Mojo.RESULT_OK);
-    assert_equals(numBytes, 0);
-  }));
-  producer.writeData(data);
-}, "Read data");
-
-async_test((test) => {
-  let {producer, consumer} = createDataPipe();
-  let data = new Uint8Array(kCapacityNumBytes);
-
-  consumer.watch({readable: true}, test.step_func_done((result) => {
-    var buffer = new Uint8Array(data.length + 1);
-    var {result, numBytes} = consumer.readData(buffer, {allOrNone: true});
-    assert_equals(result, Mojo.RESULT_OUT_OF_RANGE);
-    assert_equals(numBytes, 0);
-  }));
-  producer.writeData(data);
-}, "Read data all or none");
-
-async_test((test) => {
-  let {producer, consumer} = createDataPipe();
-  let data = new Uint8Array(kCapacityNumBytes);
-  for (let i = 0; i < data.length; ++i)
-    data[i] = i;
-
-  consumer.watch({readable: true}, test.step_func_done((result) => {
-    var buffer = new Uint8Array(data.length);
-    var {result, numBytes} = consumer.readData(buffer, {peek: true});
-    assert_equals(result, Mojo.RESULT_OK);
-    assert_equals(numBytes, data.length);
-    assert_array_equals(buffer, data);
-
-    var {result, numBytes} = consumer.queryData();
-    assert_equals(result, Mojo.RESULT_OK);
-    assert_equals(numBytes, data.length);
-  }));
-  producer.writeData(data);
-}, "Peek data");
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/detached-frame.html b/third_party/blink/web_tests/mojo/detached-frame.html
deleted file mode 100644
index b8a7d644..0000000
--- a/third_party/blink/web_tests/mojo/detached-frame.html
+++ /dev/null
@@ -1,102 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/content/test/data/mojo_web_test_helper_test.mojom.js"></script>
-<body>
-<script>
-
-function frameLoaded(frame) {
-  return new Promise(resolve => {
-    let eventHandler = e => {
-      frame.removeEventListener('load', eventHandler);
-      resolve();
-    };
-    frame.addEventListener('load', eventHandler);
-  });
-}
-
-promise_test(async () => {
-  let frame = document.createElement("iframe");
-  let promise = frameLoaded(frame);
-  document.body.appendChild(frame);
-  await promise;
-
-  // Save a reference to the Mojo object from the child frame so that we can
-  // make calls to it after the context has been destroyed.
-  let frameMojo = frame.contentWindow.Mojo;
-  document.body.removeChild(frame);
-
-  let helper = new content.mojom.MojoWebTestHelperPtr;
-  frameMojo.bindInterface(content.mojom.MojoWebTestHelper.name,
-                          mojo.makeRequest(helper).handle);
-
-  try {
-    let reply = await helper.reverse("hello world.");
-    assert_unreached();
-  } catch (e) {
-    // Connection failure expected.
-  }
-}, "Mojo object is safe to use after its frame has been detached");
-
-promise_test(async () => {
-  let frame = document.createElement("iframe");
-  let promise = frameLoaded(frame);
-  document.body.appendChild(frame);
-  await promise;
-
-  // Save a reference to the MojoInterfaceInterceptor constructor from the child
-  // frame so that we can be used after the context has been destroyed.
-  let frameMojoInterfaceInterceptor =
-      frame.contentWindow.MojoInterfaceInterceptor;
-  document.body.removeChild(frame);
-
-  let interceptor = new frameMojoInterfaceInterceptor(
-      content.mojom.MojoWebTestHelper.name);
-  try {
-    interceptor.start();
-    assert_unreached();
-  } catch (e) {
-    // Failure expected.
-  }
-}, "MojoInterfaceInterceptor constructor is safe to use after its frame has been detached");
-
-promise_test(async () => {
-  let frame = document.createElement("iframe");
-  let promise = frameLoaded(frame);
-  document.body.appendChild(frame);
-  await promise;
-
-  // Create the interceptor while the frame is attached so that it is associated
-  // with the frame's execution context.
-  let interceptor = new frame.contentWindow.MojoInterfaceInterceptor(
-      content.mojom.MojoWebTestHelper.name);
-  document.body.removeChild(frame);
-
-  try {
-    interceptor.start();
-    assert_unreached();
-  } catch (e) {
-    // Failure expected.
-  }
-}, "MojoInterfaceInterceptor can't be started after its frame has been detached");
-
-promise_test(async () => {
-  let frame = document.createElement("iframe");
-  let promise = frameLoaded(frame);
-  document.body.appendChild(frame);
-  await promise;
-
-  // Create the interceptor and start it while the frame is attached.
-  let interceptor = new frame.contentWindow.MojoInterfaceInterceptor(
-      content.mojom.MojoWebTestHelper.name);
-  interceptor.start();
-  document.body.removeChild(frame);
-
-  // stop() will succeed because it is implicitly called when the execution
-  // context is destroyed.
-  interceptor.stop();
-}, "MojoInterfaceInterceptor is stopped on frame destruction");
-
-</script>
-</body>
diff --git a/third_party/blink/web_tests/mojo/document-interface-broker-override.html b/third_party/blink/web_tests/mojo/document-interface-broker-override.html
deleted file mode 100644
index 664f7e6..0000000
--- a/third_party/blink/web_tests/mojo/document-interface-broker-override.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<body>
-<script src="../resources/document-interface-broker-helpers.js"></script>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script>
-<script src="file:///gen/mojo/public/mojom/base/unguessable_token.mojom-lite.js"></script>
-<script src="file:///gen/url/mojom/url.mojom-lite.js"></script>
-<script src="file:///gen/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom-lite.js"></script>
-<script src="file:///gen/third_party/blink/public/mojom/frame/document_interface_broker.mojom-lite.js"></script>
-<script>
-'use strict';
-
-promise_test(async t => {
-  // Create a test implementation of FrameHostTestInterface
-  const frameHostTestImpl = new blink.mojom.FrameHostTestInterfaceCallbackRouter;
-  frameHostTestImpl.getName.addListener(() => ({ name: 'TestFrameHostTestImpl' }));
-
-  const broker = new blink.mojom.DocumentInterfaceBrokerRemote(
-      Mojo.getDocumentInterfaceBrokerHandle());
-
-  const testInterfaceBeforeOverride = new blink.mojom.FrameHostTestInterfaceRemote;
-  broker.getFrameHostTestInterface(testInterfaceBeforeOverride.$.bindNewPipeAndPassReceiver());
-
-  setDocumentInterfaceBrokerOverrides({ getFrameHostTestInterface: request => {
-    frameHostTestImpl.$.bindHandle(request.handle);
-  }});
-
-  const testInterfaceAfterOverride = new blink.mojom.FrameHostTestInterfaceRemote;
-  broker.getFrameHostTestInterface(testInterfaceAfterOverride.$.bindNewPipeAndPassReceiver());
-
-  // Verify that RenderFrameHostImpl's implementation gets called without an override
-  let reply = await testInterfaceBeforeOverride.getName();
-  assert_equals(reply.name, 'RenderFrameHostImpl');
-
-  // Verify that the test implementation gets called after the override
-  reply = await testInterfaceAfterOverride.getName();
-  assert_equals(reply.name, 'TestFrameHostTestImpl');
-},
-'Appropriate DocumentInterfaceBroker implementations are called before and after overriding');
-
-</script>
- </body>
- </html>
diff --git a/third_party/blink/web_tests/mojo/interface_ptr.html b/third_party/blink/web_tests/mojo/interface_ptr.html
deleted file mode 100644
index 3dbe652..0000000
--- a/third_party/blink/web_tests/mojo/interface_ptr.html
+++ /dev/null
@@ -1,174 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/math_calculator.mojom.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.js"></script>
-<script>
-'use strict';
-
-function CalculatorImpl() {
-  this.total = 0;
-}
-
-CalculatorImpl.prototype.clear = function() {
-  this.total = 0;
-  return Promise.resolve({value: this.total});
-};
-
-CalculatorImpl.prototype.add = function(value) {
-  this.total += value;
-  return Promise.resolve({value: this.total});
-};
-
-CalculatorImpl.prototype.multiply = function(value) {
-  this.total *= value;
-  return Promise.resolve({value: this.total});
-};
-
-function IntegerAccessorImpl() {
-  this.integer = 0;
-}
-
-IntegerAccessorImpl.prototype.getInteger = function() {
-  return Promise.resolve({data: this.integer});
-};
-
-IntegerAccessorImpl.prototype.setInteger = function(value) {
-  this.integer = value;
-};
-
-test(() => {
-  var calc = new math.CalculatorPtr();
-  assert_false(calc.ptr.isBound());
-
-  var request = mojo.makeRequest(calc);
-  assert_true(calc.ptr.isBound());
-
-  calc.ptr.reset();
-  assert_false(calc.ptr.isBound());
-}, 'is bound');
-
-promise_test(async () => {
-  var calc = new math.CalculatorPtr();
-  var calcBinding = new mojo.Binding(
-      math.Calculator, new CalculatorImpl(), mojo.makeRequest(calc));
-
-  assert_equals((await calc.add(2)).value, 2);
-  assert_equals((await calc.multiply(5)).value, 10);
-  assert_equals((await calc.clear()).value, 0);
-}, 'end to end');
-
-promise_test(async () => {
-  var calc = new math.CalculatorPtr();
-  var calcImpl1 = new CalculatorImpl();
-  var calcBinding1 = new mojo.Binding(math.Calculator, calcImpl1,
-                                      mojo.makeRequest(calc));
-  var calcImpl2 = new CalculatorImpl();
-  var calcBinding2 = new mojo.Binding(math.Calculator, calcImpl2);
-
-  assert_equals((await calc.add(2)).value, 2);
-  calcBinding2.bind(mojo.makeRequest(calc));
-  assert_equals((await calc.add(2)).value, 2);
-  assert_equals(calcImpl1.total, 2);
-  assert_equals(calcImpl2.total, 2);
-}, 'reusable');
-
-promise_test(async () => {
-  var calc = new math.CalculatorPtr();
-  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
-                                     mojo.makeRequest(calc));
-
-  await new Promise((resolve, reject) => {
-    calc.ptr.setConnectionErrorHandler(() => { resolve(); });
-    calcBinding.close();
-  });
-}, 'connection error');
-
-promise_test(async () => {
-  var calc = new math.CalculatorPtr();
-  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
-                                     mojo.makeRequest(calc));
-
-  await new Promise((resolve, reject) => {
-    calc.ptr.setConnectionErrorHandler(({customReason, description}) => {
-      assert_equals(customReason, 42);
-      assert_equals(description, 'hey');
-      resolve();
-    });
-    calcBinding.closeWithReason({customReason: 42, description: 'hey'});
-  });
-}, 'connection error with reason');
-
-promise_test(async () => {
-  var calc = new math.CalculatorPtr();
-  var newCalc = null;
-  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
-                                     mojo.makeRequest(calc));
-
-  assert_equals((await calc.add(2)).value, 2);
-  newCalc = new math.CalculatorPtr();
-  newCalc.ptr.bind(calc.ptr.passInterface());
-  assert_false(calc.ptr.isBound());
-  assert_equals((await newCalc.add(2)).value, 4);
-
-}, 'pass interface');
-
-promise_test(async () => {
-  var pipe = Mojo.createMessagePipe();
-  var calc = new math.CalculatorPtr(pipe.handle0);
-  var newCalc = null;
-  var calcBinding = new mojo.Binding(math.Calculator, new CalculatorImpl(),
-                                     pipe.handle1);
-
-  assert_equals((await calc.add(2)).value, 2);
-
-}, 'bind raw handle');
-
-promise_test(async () => {
-  var integerAccessorPtr = new sample.IntegerAccessorPtr();
-
-  var integerAccessorBinding = new mojo.Binding(
-      sample.IntegerAccessor, new IntegerAccessorImpl(),
-      mojo.makeRequest(integerAccessorPtr));
-  assert_equals(integerAccessorPtr.ptr.version, 0);
-
-  assert_equals(await integerAccessorPtr.ptr.queryVersion(), 3);
-  assert_equals(integerAccessorPtr.ptr.version, 3);
-}, 'query version');
-
-promise_test(async () => {
-  var integerAccessorImpl = new IntegerAccessorImpl();
-  var integerAccessorPtr = new sample.IntegerAccessorPtr();
-  var integerAccessorBinding = new mojo.Binding(
-      sample.IntegerAccessor, integerAccessorImpl,
-      mojo.makeRequest(integerAccessorPtr));
-
-  // Inital version is 0.
-  assert_equals(integerAccessorPtr.ptr.version, 0);
-
-  integerAccessorPtr.ptr.requireVersion(1);
-  assert_equals(integerAccessorPtr.ptr.version, 1);
-  integerAccessorPtr.setInteger(123, sample.Enum.VALUE);
-  assert_equals((await integerAccessorPtr.getInteger()).data, 123);
-
-  integerAccessorPtr.ptr.requireVersion(3);
-  assert_equals(integerAccessorPtr.ptr.version, 3);
-  integerAccessorPtr.setInteger(456, sample.Enum.VALUE);
-  assert_equals((await integerAccessorPtr.getInteger()).data, 456);
-
-  // Require a version that is not supported by the impl side.
-  integerAccessorPtr.ptr.requireVersion(4);
-  assert_equals(integerAccessorPtr.ptr.version, 4);
-  integerAccessorPtr.setInteger(789, sample.Enum.VALUE);
-
-  await new Promise((resolve, reject) => {
-    integerAccessorPtr.ptr.setConnectionErrorHandler(() => {
-      resolve();
-    });
-  });
-  assert_equals(integerAccessorImpl.integer, 456);
-
-}, 'require version');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/lite/constants.html b/third_party/blink/web_tests/mojo/lite/constants.html
deleted file mode 100644
index 09f076d..0000000
--- a/third_party/blink/web_tests/mojo/lite/constants.html
+++ /dev/null
@@ -1,89 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script>
-<script src="file:///gen/mojo/public/js/ts/bindings/tests/constants.test-mojom-lite.js"></script>
-<script>
-'use strict';
-
-[{
-  constant: mojo.tstest.BOOL_VALUE,
-  expectedValue: true,
-  type: 'boolean'
-}, {
-  constant: mojo.tstest.INT8_VALUE,
-  expectedValue: -2,
-  type: 'int8'
-}, {
-  constant: mojo.tstest.UINT8_VALUE,
-  expectedValue: 128,
-  type: 'uint8'
-}, {
-  constant: mojo.tstest.INT16_VALUE,
-  expectedValue: -233,
-  type: 'int16'
-}, {
-  constant: mojo.tstest.UINT16_VALUE,
-  expectedValue: 44204,
-  type: 'uint16'
-}, {
-  constant: mojo.tstest.INT32_VALUE,
-  expectedValue: -44204,
-  type: 'int32'
-}, {
-  constant: mojo.tstest.UINT32_VALUE,
-  expectedValue: 4294967295,
-  type: 'uint32'
-}, {
-  // TODO(crbug.com/1009262): Re-enable once we generate the right value for
-  // 64-bit constants.
-  //
-  //  constant: mojo.tstest.kInt64Value,
-  //  expectedValue: -9223372036854775807n,
-  //  type: 'int64'
-  //}, {
-  //  constant: mojo.tstest.kUint64Value,
-  //  expectedValue: 9999999999999999999n,
-  //  type: 'uint64'
-  //}, {
-  constant: mojo.tstest.DOUBLE_VALUE,
-  expectedValue: 3.14159,
-  type: 'double'
-}, {
-  constant: mojo.tstest.DOUBLE_INFINITY,
-  expectedValue: Infinity,
-  type: 'double infinity'
-}, {
-  constant: mojo.tstest.DOUBLE_NEGATIVE_INFINITY,
-  expectedValue: -Infinity,
-  type: 'double negative infinity'
-}, {
-  constant: mojo.tstest.DOUBLE_NA_N,
-  expectedValue: NaN,
-  type: 'double NaN'
-}, {
-  constant: mojo.tstest.FLOAT_VALUE,
-  expectedValue: 2.71828,
-  type: 'float'
-}, {
-  constant: mojo.tstest.FLOAT_INFINITY,
-  expectedValue: Infinity,
-  type: 'float infinity'
-}, {
-  constant: mojo.tstest.FLOAT_NEGATIVE_INFINITY,
-  expectedValue: -Infinity,
-  type: 'float negative infinity'
-}, {
-  constant: mojo.tstest.FLOAT_NA_N,
-  expectedValue: NaN,
-  type: 'NaN'
-}, {
-  constant: mojo.tstest.STRING_VALUE,
-  expectedValue: "test string contents",
-  type: 'string'
-}].forEach(testCase => {
-  test(
-    () => assert_equals(testCase.constant, testCase.expectedValue),
-    `Checks that the value of generated ${testCase.type} constants is correct`);
-});
-</script>
diff --git a/third_party/blink/web_tests/mojo/message-pipe.html b/third_party/blink/web_tests/mojo/message-pipe.html
deleted file mode 100644
index 4eb879c..0000000
--- a/third_party/blink/web_tests/mojo/message-pipe.html
+++ /dev/null
@@ -1,106 +0,0 @@
-<!DOCTYPE html>
-<title>Mojo message pipe tests</title>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script>
-
-let testData = (() => {
-  let dataIn = new Uint8Array(42);
-  for (let i = 0; i < dataIn.length; ++i)
-    dataIn[i] = i * i;
-
-  return {
-    read(handle) {
-      let {result, buffer, handles} = handle.readMessage();
-      assert_equals(result, Mojo.RESULT_OK);
-      assert_array_equals(new Uint8Array(buffer), dataIn);
-      assert_array_equals(handles, []);
-    },
-    write(handle) {
-      let result = handle.writeMessage(dataIn, []);
-      assert_equals(result, Mojo.RESULT_OK);
-    }
-  };
-})();
-
-test(() => {
-  let {result, handle0, handle1} = Mojo.createMessagePipe();
-  assert_equals(result, Mojo.RESULT_OK);
-  assert_true(handle0 instanceof MojoHandle);
-  assert_true(handle1 instanceof MojoHandle);
-}, "Create pipe");
-
-test(() => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-  handle0.close();
-  let {result} = handle0.readMessage();
-  assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
-}, "Read from invalid handle");
-
-test(() => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-  let {result} = handle0.readMessage();
-  assert_equals(result, Mojo.RESULT_SHOULD_WAIT);
-}, "Read from empty pipe");
-
-test(() => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-  handle0.close();
-  let result = handle0.writeMessage(new ArrayBuffer(4), []);
-  assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
-}, "Write to invalid handle");
-
-async_test((test) => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-
-  handle0.watch({readable: true}, test.step_func_done((result) => {
-    assert_equals(result, Mojo.RESULT_OK);
-    {
-      let {result, buffer, handles} = handle0.readMessage();
-      assert_equals(result, Mojo.RESULT_OK);
-      assert_equals(buffer.byteLength, 0);
-      assert_array_equals(handles, []);
-    }
-  }));
-  let result = handle1.writeMessage(new ArrayBuffer(0), []);
-  assert_equals(result, Mojo.RESULT_OK);
-}, "Send empty message");
-
-async_test((test) => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-
-  handle0.watch({readable: true}, test.step_func_done((result) => {
-    assert_equals(result, Mojo.RESULT_OK);
-    testData.read(handle0);
-  }));
-  testData.write(handle1);
-}, "Send buffer");
-
-async_test((test) => {
-  let pipe1 = Mojo.createMessagePipe();
-  let pipe2 = Mojo.createMessagePipe();
-  pipe2.handle0.watch({readable: true}, test.step_func_done((result) => {
-    assert_equals(result, Mojo.RESULT_OK);
-    testData.read(pipe2.handle0);
-  }));
-  pipe1.handle0.watch({readable: true}, test.step_func((result) => {
-    assert_equals(result, Mojo.RESULT_OK);
-    {
-      let {result, handles} = pipe1.handle0.readMessage();
-      assert_equals(result, Mojo.RESULT_OK);
-      assert_equals(1, handles.length);
-      testData.write(handles[0]);
-    }
-  }));
-  pipe1.handle1.writeMessage(new ArrayBuffer(0), [pipe2.handle1]);
-}, "Send handle");
-
-test(() => {
-  const pipe1 = Mojo.createMessagePipe();
-  const pipe2 = Mojo.createMessagePipe();
-  pipe2.handle0.close();
-  const result = pipe1.handle0.writeMessage(new ArrayBuffer(0), [pipe2.handle0]);
-  assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
-}, "Send invalid handle");
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/module-loading-manual-deps-loading.html b/third_party/blink/web_tests/mojo/module-loading-manual-deps-loading.html
deleted file mode 100644
index fc92d3f0..0000000
--- a/third_party/blink/web_tests/mojo/module-loading-manual-deps-loading.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-<title>Mojo JavaScript bindings module loading tests (manual mojom deps loading)</title>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script>
-  mojo.config.autoLoadMojomDeps = false;
-</script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/echo.mojom.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/echo_import/echo_import.mojom.js"></script>
-<script>
-
-promise_test(async () => {
-  function EchoImpl() {}
-  EchoImpl.prototype.echoPoint = function(point) {
-    return Promise.resolve({result: point});
-  };
-
-  var echoServicePtr = new test.echo.mojom.EchoPtr();
-  var echoServiceBinding = new mojo.Binding(test.echo.mojom.Echo,
-                                            new EchoImpl(),
-                                            mojo.makeRequest(echoServicePtr));
-  var result = (await echoServicePtr.echoPoint({x: 1, y: 2})).result;
-  assert_equals(1, result.x);
-  assert_equals(2, result.y);
-}, 'Basics');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/module-loading.html b/third_party/blink/web_tests/mojo/module-loading.html
deleted file mode 100644
index cddb67d0..0000000
--- a/third_party/blink/web_tests/mojo/module-loading.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<title>Mojo JavaScript bindings module loading tests</title>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/echo.mojom.js"></script>
-<script>
-
-promise_test(async () => {
-  function EchoImpl() {}
-  EchoImpl.prototype.echoPoint = function(point) {
-    return Promise.resolve({result: point});
-  };
-
-  var echoServicePtr = new test.echo.mojom.EchoPtr();
-  var echoServiceBinding = new mojo.Binding(test.echo.mojom.Echo,
-                                            new EchoImpl(),
-                                            mojo.makeRequest(echoServicePtr));
-  var result = (await echoServicePtr.echoPoint({x: 1, y: 2})).result;
-  assert_equals(1, result.x);
-  assert_equals(2, result.y);
-}, 'Basics');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/resources/bind-intercepted-interface-in-worker.js b/third_party/blink/web_tests/mojo/resources/bind-intercepted-interface-in-worker.js
deleted file mode 100644
index a520aa3..0000000
--- a/third_party/blink/web_tests/mojo/resources/bind-intercepted-interface-in-worker.js
+++ /dev/null
@@ -1,35 +0,0 @@
-importScripts('../../resources/testharness.js');
-importScripts('file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js');
-importScripts('file:///gen/content/test/data/mojo_web_test_helper_test.mojom.js');
-importScripts('helpers.js');
-
-promise_test(async () => {
-  let helperImpl = new TestHelperImpl;
-  let interceptor =
-      new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name, "context", true);
-  interceptor.oninterfacerequest = e => {
-    helperImpl.bindRequest(e.handle);
-  };
-  interceptor.start();
-
-  let helper = new content.mojom.MojoWebTestHelperPtr;
-  Mojo.bindInterface(content.mojom.MojoWebTestHelper.name,
-                     mojo.makeRequest(helper).handle, "context", true);
-
-  let response = await helper.reverse('the string');
-  assert_equals(response.reversed, kTestReply);
-  assert_equals(helperImpl.getLastString(), 'the string');
-}, 'Can implement a Mojo service and intercept it from a worker');
-
-test(t => {
-  assert_throws(
-      'NotSupportedError',
-      () => {
-        new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name,
-                                     "process");
-      });
-}, 'Cannot create a MojoInterfaceInterceptor with process scope');
-
-// done() is needed because the testharness is running as if explicit_done
-// was specified.
-done();
diff --git a/third_party/blink/web_tests/mojo/sample_service.html b/third_party/blink/web_tests/mojo/sample_service.html
deleted file mode 100644
index 06193ed..0000000
--- a/third_party/blink/web_tests/mojo/sample_service.html
+++ /dev/null
@@ -1,147 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/sample_service.mojom.js"></script>
-<script>
-'use strict';
-
-// Checks that values are set to the defaults if we don't override them.
-test(() => {
-  var bar = new sample.Bar();
-  assert_equals(bar.alpha, 255);
-  assert_equals(bar.type, sample.Bar.Type.VERTICAL);
-
-  var foo = new sample.Foo();
-  assert_equals(foo.name, "Fooby");
-  assert_true(foo.a);
-  assert_equals(foo.data, null);
-
-  var defaults = new sample.DefaultsTest();
-  assert_equals(defaults.a0, -12);
-  assert_equals(defaults.a1, sample.TWELVE);
-  assert_equals(defaults.a2, 1234);
-  assert_equals(defaults.a3, 34567);
-  assert_equals(defaults.a4, 123456);
-  assert_equals(defaults.a5, 3456789012);
-  assert_equals(defaults.a6, -111111111111);
-  // JS doesn't have a 64 bit integer type so this is just checking that the
-  // expected and actual values have the same closest double value.
-  assert_equals(defaults.a7, 9999999999999999999);
-  assert_equals(defaults.a8, 0x12345);
-  assert_equals(defaults.a9, -0x12345);
-  assert_equals(defaults.a10, 1234);
-  assert_true(defaults.a11);
-  assert_false(defaults.a12);
-  assert_equals(defaults.a13, 123.25);
-  assert_equals(defaults.a14, 1234567890.123);
-  assert_equals(defaults.a15, 1E10);
-  assert_equals(defaults.a16, -1.2E+20);
-  assert_equals(defaults.a17, 1.23E-20);
-  assert_equals(defaults.a20, sample.Bar.Type.BOTH);
-  assert_equals(defaults.a21, null);
-  assert_true(!!defaults.a22);
-  assert_equals(defaults.a22.shape, imported.Shape.RECTANGLE);
-  assert_equals(defaults.a22.color, imported.Color.BLACK);
-  assert_equals(defaults.a23, 0xFFFFFFFFFFFFFFFF);
-  assert_equals(defaults.a24, 0x123456789);
-  assert_equals(defaults.a25, -0x123456789);
-}, 'default values');
-
-promise_test(async () => {
-  function ServiceImpl() {
-  }
-
-  ServiceImpl.prototype.frobinate = function(foo, baz, port) {
-    checkFoo(foo);
-    assert_equals(baz, sample.Service.BazOptions.EXTRA);
-    assert_true(port.ptr.isBound());
-    return Promise.resolve({result: 1234});
-  };
-
-  var foo = makeFoo();
-  checkFoo(foo);
-
-  var service = new sample.ServicePtr();
-  var request = mojo.makeRequest(service);
-  var serviceBinding = new mojo.Binding(
-      sample.Service, new ServiceImpl(), request);
-
-  var port = new sample.PortPtr();
-  mojo.makeRequest(port);
-  assert_equals((await service.frobinate(foo, sample.Service.BazOptions.EXTRA,
-                                         port)).result, 1234);
-
-}, 'sample service');
-
-done();
-
-function makeFoo() {
-  var bar = new sample.Bar();
-  bar.alpha = 20;
-  bar.beta = 40;
-  bar.gamma = 60;
-  bar.type = sample.Bar.Type.VERTICAL;
-
-  var extraBars = new Array(3);
-  for (var i = 0; i < extraBars.length; ++i) {
-    var base = i * 100;
-    var type = i % 2 ? sample.Bar.Type.VERTICAL : sample.Bar.Type.HORIZONTAL;
-    extraBars[i] = new sample.Bar();
-    extraBars[i].alpha = base;
-    extraBars[i].beta = base + 20;
-    extraBars[i].gamma = base + 40;
-    extraBars[i].type = type;
-  }
-
-  var data = new Array(10);
-  for (var i = 0; i < data.length; ++i) {
-    data[i] = data.length - i;
-  }
-
-  var foo = new sample.Foo();
-  foo.name = "foopy";
-  foo.x = 1;
-  foo.y = 2;
-  foo.a = false;
-  foo.b = true;
-  foo.c = false;
-  foo.bar = bar;
-  foo.extraBars = extraBars;
-  foo.data = data;
-
-  foo.source = Mojo.createMessagePipe().handle0;
-
-  return foo;
-}
-
-// Checks that the given |Foo| is identical to the one made by |makeFoo()|.
-function checkFoo(foo) {
-  assert_equals(foo.name, "foopy");
-  assert_equals(foo.x, 1);
-  assert_equals(foo.y, 2);
-  assert_false(foo.a);
-  assert_true(foo.b);
-  assert_false(foo.c);
-  assert_equals(foo.bar.alpha, 20);
-  assert_equals(foo.bar.beta, 40);
-  assert_equals(foo.bar.gamma, 60);
-  assert_equals(foo.bar.type, sample.Bar.Type.VERTICAL);
-
-  assert_equals(foo.extraBars.length, 3);
-  for (var i = 0; i < foo.extraBars.length; ++i) {
-    var base = i * 100;
-    var type = i % 2 ?  sample.Bar.Type.VERTICAL : sample.Bar.Type.HORIZONTAL;
-    assert_equals(foo.extraBars[i].alpha, base);
-    assert_equals(foo.extraBars[i].beta, base + 20);
-    assert_equals(foo.extraBars[i].gamma, base + 40);
-    assert_equals(foo.extraBars[i].type, type);
-  }
-
-  assert_equals(foo.data.length, 10);
-  for (var i = 0; i < foo.data.length; ++i)
-    assert_equals(foo.data[i], foo.data.length -i);
-
-  assert_true(foo.source instanceof MojoHandle);
-}
-</script>
diff --git a/third_party/blink/web_tests/mojo/shared-buffer.html b/third_party/blink/web_tests/mojo/shared-buffer.html
deleted file mode 100644
index fa95f92..0000000
--- a/third_party/blink/web_tests/mojo/shared-buffer.html
+++ /dev/null
@@ -1,70 +0,0 @@
-<!DOCTYPE html>
-<title>Mojo shared buffer tests</title>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script>
-
-let kBufferSize = 32;
-
-test(() => {
-  let {result, handle} = Mojo.createSharedBuffer(kBufferSize);
-  assert_equals(result, Mojo.RESULT_OK);
-  assert_true(handle instanceof MojoHandle);
-}, "Create shared buffer");
-
-test(() => {
-  let {handle} = Mojo.createSharedBuffer(kBufferSize);
-  let {result, buffer} = handle.mapBuffer(0, kBufferSize);
-  assert_equals(result, Mojo.RESULT_OK);
-  assert_true(buffer instanceof ArrayBuffer);
-}, "Map shared buffer");
-
-test(() => {
-  let {handle: handle0} = Mojo.createSharedBuffer(kBufferSize);
-  let {result, handle: handle1} = handle0.duplicateBufferHandle();
-  assert_equals(result, Mojo.RESULT_OK);
-  assert_true(handle1 instanceof MojoHandle);
-  assert_not_equals(handle1, handle0);
-}, "Duplicate RW shared buffer handle");
-
-test(() => {
-  let {handle: handle0} = Mojo.createSharedBuffer(kBufferSize);
-  let {result, handle: handle1} = handle0.duplicateBufferHandle({readOnly: true});
-  assert_equals(result, Mojo.RESULT_OK);
-  assert_true(handle1 instanceof MojoHandle);
-  assert_not_equals(handle1, handle0);
-}, "Duplicate RO shared buffer handle");
-
-test(() => {
-  let {handle: handle0} = Mojo.createSharedBuffer(kBufferSize);
-  let {buffer: buffer0} = handle0.mapBuffer(0, kBufferSize);
-  let array0 = new Uint8Array(buffer0);
-
-  let {handle: handle1} = handle0.duplicateBufferHandle({readOnly: true});
-  let {buffer: buffer1} = handle1.mapBuffer(0, kBufferSize);
-  let array1 = new Uint8Array(buffer1);
-
-  assert_not_equals(buffer1, buffer0);
-  for (let i = 0; i < kBufferSize; ++i) {
-    array0[i] = i;
-    assert_equals(array1[i], i);
-  }
-}, "Read from RO shared buffer handle");
-
-test(() => {
-  let {handle: handle0} = Mojo.createSharedBuffer(kBufferSize);
-  let {buffer: buffer0} = handle0.mapBuffer(0, kBufferSize);
-  let array0 = new Uint8Array(buffer0);
-
-  let {handle: handle1} = handle0.duplicateBufferHandle();
-  let {buffer: buffer1} = handle1.mapBuffer(0, kBufferSize);
-  let array1 = new Uint8Array(buffer1);
-
-  assert_not_equals(buffer1, buffer0);
-  for (let i = 0; i < kBufferSize; ++i) {
-    array1[i] = i;
-    assert_equals(array0[i], i);
-  }
-}, "Write to RW shared buffer handle");
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/struct.html b/third_party/blink/web_tests/mojo/struct.html
deleted file mode 100644
index 86485de..0000000
--- a/third_party/blink/web_tests/mojo/struct.html
+++ /dev/null
@@ -1,234 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="../resources/testharness-helpers.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/test_structs.mojom.js"></script>
-<script>
-
-test(() => {
-  var r = new mojo.test.Rect();
-  assert_weak_equals(r, new mojo.test.Rect({x:0, y:0, width:0, height:0}));
-  assert_weak_equals(r, new mojo.test.Rect({foo:100, bar:200}));
-
-  r.x = 10;
-  r.y = 20;
-  r.width = 30;
-  r.height = 40;
-  var rp = new mojo.test.RectPair({first: r, second: r});
-  assert_weak_equals(rp.first, r);
-  assert_weak_equals(rp.second, r);
-
-  assert_equals(new mojo.test.RectPair({second: r}).first, null);
-
-  var nr = new mojo.test.NamedRegion();
-  assert_equals(nr.name, null);
-  assert_equals(nr.rects, null);
-  assert_weak_equals(nr, new mojo.test.NamedRegion({}));
-
-  nr.name = "foo";
-  nr.rects = [r, r, r];
-  assert_weak_equals(nr, new mojo.test.NamedRegion({
-    name: "foo",
-    rects: [r, r, r],
-  }));
-
-  var e = new mojo.test.EmptyStruct();
-  assert_weak_equals(e, new mojo.test.EmptyStruct({foo:123}));
-}, 'constructors');
-
-test(() => {
-  var s = new mojo.test.NoDefaultFieldValues();
-  assert_false(s.f0);
-
-  // f1 - f10, number type fields
-  for (var i = 1; i <= 10; i++)
-    assert_equals(s["f" + i], 0);
-
-  // f11,12 strings, f13-22 handles, f23-f26 arrays, f27,28 structs
-  for (var i = 11; i <= 28; i++)
-    assert_equals(s["f" + i], null);
-
-}, 'no default field values');
-
-test(() => {
-  var s = new mojo.test.DefaultFieldValues();
-  assert_true(s.f0);
-
-  // f1 - f12, number type fields
-  for (var i = 1; i <= 12; i++)
-    assert_equals(s["f" + i], 100);
-
-  // f13,14 "foo"
-  for (var i = 13; i <= 14; i++)
-    assert_equals(s["f" + i], "foo");
-
-  // f15,16 a default instance of Rect
-  var r = new mojo.test.Rect();
-  assert_weak_equals(s.f15, r);
-  assert_weak_equals(s.f16, r);
-}, 'default field values');
-
-test(() => {
-  assert_equals(mojo.test.ScopedConstants.TEN, 10);
-  assert_equals(mojo.test.ScopedConstants.ALSO_TEN, 10);
-
-  assert_equals(mojo.test.ScopedConstants.EType.E0, 0);
-  assert_equals(mojo.test.ScopedConstants.EType.E1, 1);
-  assert_equals(mojo.test.ScopedConstants.EType.E2, 10);
-  assert_equals(mojo.test.ScopedConstants.EType.E3, 10);
-  assert_equals(mojo.test.ScopedConstants.EType.E4, 11);
-
-  var s = new mojo.test.ScopedConstants();
-  assert_equals(s.f0, 0);
-  assert_equals(s.f1, 1);
-  assert_equals(s.f2, 10);
-  assert_equals(s.f3, 10);
-  assert_equals(s.f4, 11);
-  assert_equals(s.f5, 10);
-  assert_equals(s.f6, 10);
-}, 'scoped constants');
-
-function structEncodeDecode(struct) {
-  var structClass = struct.constructor;
-  var builder = new mojo.internal.MessageV0Builder(1234,
-      structClass.encodedSize);
-  builder.encodeStruct(structClass, struct);
-  var message = builder.finish();
-
-  var messageValidator = new mojo.internal.Validator(message);
-  var err = structClass.validate(messageValidator,
-                                 mojo.internal.kMessageV0HeaderSize);
-  assert_equals(err, mojo.internal.validationError.NONE);
-
-  var reader = new mojo.internal.MessageReader(message);
-  return reader.decodeStruct(structClass);
-}
-
-test(() => {
-  var mapFieldsStruct = new mojo.test.MapKeyTypes({
-    f0: new Map([[true, false], [false, true]]),  // map<bool, bool>
-    f1: new Map([[0, 0], [1, 127], [-1, -128]]),  // map<int8, int8>
-    f2: new Map([[0, 0], [1, 127], [2, 255]]),  // map<uint8, uint8>
-    f3: new Map([[0, 0], [1, 32767], [2, -32768]]),  // map<int16, int16>
-    f4: new Map([[0, 0], [1, 32768], [2, 0xFFFF]]),  // map<uint16, uint16>
-    f5: new Map([[0, 0], [1, 32767], [2, -32768]]),  // map<int32, int32>
-    f6: new Map([[0, 0], [1, 32768], [2, 0xFFFF]]),  // map<uint32, uint32>
-    f7: new Map([[0, 0], [1, 32767], [2, -32768]]),  // map<int64, int64>
-    f8: new Map([[0, 0], [1, 32768], [2, 0xFFFF]]),  // map<uint64, uint64>
-    f9: new Map([[1000.5, -50000], [100.5, 5000]]),  // map<float, float>
-    f10: new Map([[-100.5, -50000], [0, 50000000]]),  // map<double, double>
-    f11: new Map([["one", "two"], ["free", "four"]]),  // map<string, string>
-  });
-  var decodedStruct = structEncodeDecode(mapFieldsStruct);
-  assert_weak_equals(decodedStruct, mapFieldsStruct);
-}, 'map key types');
-
-test(() => {
-  var mapFieldsStruct = new mojo.test.MapValueTypes({
-    // map<string, array<string>>
-    f0: new Map([["a", ["b", "c"]], ["d", ["e"]]]),
-    // map<string, array<string>?>
-    f1: new Map([["a", null], ["b", ["c", "d"]]]),
-    // map<string, array<string?>>
-    f2: new Map([["a", [null]], ["b", [null, "d"]]]),
-    // map<string, array<string,2>>
-    f3: new Map([["a", ["1", "2"]], ["b", ["1", "2"]]]),
-    // map<string, array<array<string, 2>?>>
-    f4: new Map([["a", [["1", "2"]]], ["b", [null]]]),
-    // map<string, array<array<string, 2>, 1>>
-    f5: new Map([["a", [["1", "2"]]]]),
-    // map<string, Rect?>
-    f6: new Map([["a", null]]),
-    // map<string, map<string, string>>
-    f7: new Map([["a", new Map([["b", "c"]])]]),
-    // map<string, array<map<string, string>>>
-    f8: new Map([["a", [new Map([["b", "c"]])]]]),
-    // map<string, handle>
-    f9: new Map([["a", 1234]]),
-    // map<string, array<handle>>
-    f10: new Map([["a", [1234, 5678]]]),
-    // map<string, map<string, handle>>
-    f11: new Map([["a", new Map([["b", 1234]])]]),
-  });
-  var decodedStruct = structEncodeDecode(mapFieldsStruct);
-  assert_weak_equals(decodedStruct, mapFieldsStruct);
-}, 'map value types');
-
-test(() => {
-  var decodedStruct = structEncodeDecode(new mojo.test.FloatNumberValues);
-  assert_equals(decodedStruct.f0, mojo.test.FloatNumberValues.V0);
-  assert_equals(decodedStruct.f1, mojo.test.FloatNumberValues.V1);
-  assert_equals(decodedStruct.f2, mojo.test.FloatNumberValues.V2);
-  assert_equals(decodedStruct.f3, mojo.test.FloatNumberValues.V3);
-  assert_equals(decodedStruct.f4, mojo.test.FloatNumberValues.V4);
-  assert_equals(decodedStruct.f5, mojo.test.FloatNumberValues.V5);
-  assert_equals(decodedStruct.f6, mojo.test.FloatNumberValues.V6);
-  assert_equals(decodedStruct.f7, mojo.test.FloatNumberValues.V7);
-  assert_equals(decodedStruct.f8, mojo.test.FloatNumberValues.V8);
-  assert_equals(decodedStruct.f9, mojo.test.FloatNumberValues.V9);
-}, 'float number values');
-
-test(() => {
-  var decodedStruct = structEncodeDecode(new mojo.test.IntegerNumberValues);
-  assert_equals(decodedStruct.f0, mojo.test.IntegerNumberValues.V0);
-  assert_equals(decodedStruct.f1, mojo.test.IntegerNumberValues.V1);
-  assert_equals(decodedStruct.f2, mojo.test.IntegerNumberValues.V2);
-  assert_equals(decodedStruct.f3, mojo.test.IntegerNumberValues.V3);
-  assert_equals(decodedStruct.f4, mojo.test.IntegerNumberValues.V4);
-  assert_equals(decodedStruct.f5, mojo.test.IntegerNumberValues.V5);
-  assert_equals(decodedStruct.f6, mojo.test.IntegerNumberValues.V6);
-  assert_equals(decodedStruct.f7, mojo.test.IntegerNumberValues.V7);
-  assert_equals(decodedStruct.f8, mojo.test.IntegerNumberValues.V8);
-  assert_equals(decodedStruct.f9, mojo.test.IntegerNumberValues.V9);
-  assert_equals(decodedStruct.f10, mojo.test.IntegerNumberValues.V10);
-  assert_equals(decodedStruct.f11, mojo.test.IntegerNumberValues.V11);
-  assert_equals(decodedStruct.f12, mojo.test.IntegerNumberValues.V12);
-  assert_equals(decodedStruct.f13, mojo.test.IntegerNumberValues.V13);
-  assert_equals(decodedStruct.f14, mojo.test.IntegerNumberValues.V14);
-  assert_equals(decodedStruct.f15, mojo.test.IntegerNumberValues.V15);
-  assert_equals(decodedStruct.f16, mojo.test.IntegerNumberValues.V16);
-  assert_equals(decodedStruct.f17, mojo.test.IntegerNumberValues.V17);
-  assert_equals(decodedStruct.f18, mojo.test.IntegerNumberValues.V18);
-  assert_equals(decodedStruct.f19, mojo.test.IntegerNumberValues.V19);
-}, 'integer number values');
-
-test(() => {
-  var decodedStruct =
-      structEncodeDecode(new mojo.test.UnsignedNumberValues);
-  assert_equals(decodedStruct.f0, mojo.test.UnsignedNumberValues.V0);
-  assert_equals(decodedStruct.f1, mojo.test.UnsignedNumberValues.V1);
-  assert_equals(decodedStruct.f2, mojo.test.UnsignedNumberValues.V2);
-  assert_equals(decodedStruct.f3, mojo.test.UnsignedNumberValues.V3);
-  assert_equals(decodedStruct.f4, mojo.test.UnsignedNumberValues.V4);
-  assert_equals(decodedStruct.f5, mojo.test.UnsignedNumberValues.V5);
-  assert_equals(decodedStruct.f6, mojo.test.UnsignedNumberValues.V6);
-  assert_equals(decodedStruct.f7, mojo.test.UnsignedNumberValues.V7);
-  assert_equals(decodedStruct.f8, mojo.test.UnsignedNumberValues.V8);
-  assert_equals(decodedStruct.f9, mojo.test.UnsignedNumberValues.V9);
-  assert_equals(decodedStruct.f10, mojo.test.UnsignedNumberValues.V10);
-  assert_equals(decodedStruct.f11, mojo.test.UnsignedNumberValues.V11);
-}, 'unsigned number values');
-
-test(() => {
-  var bitArraysStruct = new mojo.test.BitArrayValues({
-    // array<bool, 1> f0;
-    f0: [true],
-    // array<bool, 7> f1;
-    f1: [true, false, true, false, true, false, true],
-    // array<bool, 9> f2;
-    f2: [true, false, true, false, true, false, true, false, true],
-    // array<bool> f3;
-    f3: [true, false, true, false, true, false, true, false],
-    // array<array<bool>> f4;
-    f4: [[true], [false], [true, false], [true, false, true, false]],
-    // array<array<bool>?> f5;
-    f5: [[true], null, null, [true, false, true, false]],
-    // array<array<bool, 2>?> f6;
-    f6: [[true, false], [true, false], [true, false]],
-  });
-  var decodedStruct = structEncodeDecode(bitArraysStruct);
-  assert_weak_equals(decodedStruct, bitArraysStruct);
-}, 'bit array values');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/union.html b/third_party/blink/web_tests/mojo/union.html
deleted file mode 100644
index 3c99760..0000000
--- a/third_party/blink/web_tests/mojo/union.html
+++ /dev/null
@@ -1,189 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="../resources/testharness-helpers.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/test_unions.mojom.js"></script>
-<script>
-'use strict';
-
-test(() => {
-  var u = new mojo.test.PodUnion();
-  assert_equals(u.$data, null);
-  assert_equals(u.$tag, undefined);
-
-  u.fUint32 = 32;
-
-  assert_equals(u.fUint32, 32);
-  assert_equals(u.$tag, mojo.test.PodUnion.Tags.fUint32);
-
-  var u = new mojo.test.PodUnion({fUint64: 64});
-  assert_equals(u.fUint64, 64);
-  assert_equals(u.$tag, mojo.test.PodUnion.Tags.fUint64);
-  assert_throws(new ReferenceError, function() {var v = u.fUint32;});
-
-  assert_throws(new TypeError, function() {
-    var u = new mojo.test.PodUnion({
-      fUint64: 64,
-      fUint32: 32,
-    });
-  });
-
-  assert_throws(new ReferenceError, function() {
-    var u = new mojo.test.PodUnion({ foo: 64 });
-  });
-
-  assert_throws(new TypeError, function() {
-    var u = new mojo.test.PodUnion([1,2,3,4]);
-  });
-}, 'constructors');
-
-function structEncodeDecode(struct) {
-  var structClass = struct.constructor;
-  var builder = new mojo.internal.MessageV0Builder(1234,
-                                                   structClass.encodedSize);
-  builder.encodeStruct(structClass, struct);
-
-  var message = builder.finish();
-
-  var messageValidator = new mojo.internal.Validator(message);
-  var err = structClass.validate(messageValidator,
-                                 mojo.internal.kMessageV0HeaderSize);
-  assert_equals(err, mojo.internal.validationError.NONE);
-
-  var reader = new mojo.internal.MessageReader(message);
-  var view = reader.decoder.buffer.dataView;
-
-  return reader.decodeStruct(structClass);
-}
-
-test(() => {
-  var s = new mojo.test.WrapperStruct({
-    podUnion: new mojo.test.PodUnion({fUint64: 64})
-  });
-
-  var decoded = structEncodeDecode(s);
-  assert_weak_equals(decoded, s);
-
-  var s = new mojo.test.WrapperStruct({
-    podUnion: new mojo.test.PodUnion({fBool : true})
-  });
-
-  var decoded = structEncodeDecode(s);
-  assert_equals(decoded.podUnion.$tag, mojo.test.PodUnion.Tags.fBool);
-  assert_true(decoded.podUnion.fBool);
-
-  var s = new mojo.test.WrapperStruct({
-    objectUnion: new mojo.test.ObjectUnion({
-      fDummy: new mojo.test.DummyStruct({fInt8: 8})
-    })
-  });
-
-  var decoded = structEncodeDecode(s);
-  assert_weak_equals(decoded, s);
-
-  var s = new mojo.test.WrapperStruct({
-    objectUnion: new mojo.test.ObjectUnion({fArrayInt8: [1, 2, 3]})
-  });
-
-  var decoded = structEncodeDecode(s);
-  assert_weak_equals(decoded, s);
-
-  var s = new mojo.test.WrapperStruct({
-    objectUnion: new mojo.test.ObjectUnion({
-      fMapInt8: new Map([
-        ["first", 1],
-        ["second", 2],
-      ])
-    })
-  });
-
-  var decoded = structEncodeDecode(s);
-  assert_weak_equals(decoded, s);
-
-  // Encoding a union with no member set is an error.
-  var s = new mojo.test.WrapperStruct({
-    objectUnion: new mojo.test.ObjectUnion()});
-  assert_throws(new TypeError, function() {
-    structEncodeDecode(s);
-  });
-}, 'basic encoding');
-
-test(() => {
-  var s = new mojo.test.SmallStruct({
-    podUnionArray: [
-      new mojo.test.PodUnion({fUint32: 32}),
-      new mojo.test.PodUnion({fUint64: 64}),
-    ]
-  });
-
-  var decoded = structEncodeDecode(s);
-  assert_weak_equals(decoded, s);
-}, 'unions in array encoding');
-
-test(() => {
-  var s = new mojo.test.SmallStruct({
-    podUnionMap: new Map([
-      ["thirty-two", new mojo.test.PodUnion({fUint32: 32})],
-      ["sixty-four", new mojo.test.PodUnion({fUint64: 64})],
-    ])
-  });
-
-  var decoded = structEncodeDecode(s);
-  assert_weak_equals(decoded, s);
-}, 'unions in map encoding');
-
-test(() => {
-  var s = new mojo.test.WrapperStruct({
-    objectUnion: new mojo.test.ObjectUnion({
-      fPodUnion: new mojo.test.PodUnion({fUint32: 32})
-    })
-  });
-  var decoded = structEncodeDecode(s);
-  assert_weak_equals(decoded, s);
-}, 'nested unions encoding');
-
-function structValidate(struct) {
-  var structClass = struct.constructor;
-  var builder = new mojo.internal.MessageV0Builder(1234,
-                                                   structClass.encodedSize);
-  builder.encodeStruct(structClass, struct);
-
-  var message = builder.finish();
-
-  var messageValidator = new mojo.internal.Validator(message);
-  return structClass.validate(messageValidator,
-                              mojo.internal.kMessageV0HeaderSize);
-}
-
-test(() => {
-  var s = new mojo.test.WrapperStruct({
-    objectUnion: new mojo.test.ObjectUnion({fDummy: null})
-  });
-
-  var err = structValidate(s);
-  assert_equals(err, mojo.internal.validationError.UNEXPECTED_NULL_POINTER);
-
-  var s = new mojo.test.WrapperStruct({
-    objectUnion: new mojo.test.ObjectUnion({fNullable: null})
-  });
-
-  var err = structValidate(s);
-  assert_equals(err, mojo.internal.validationError.NONE);
-}, 'null union member validation');
-
-test(() => {
-  var s = new mojo.test.SmallStructNonNullableUnion({podUnion: null});
-
-  var err = structValidate(s);
-  assert_equals(err, mojo.internal.validationError.UNEXPECTED_NULL_UNION);
-
-  var s = new mojo.test.WrapperStruct({
-    objectUnion: new mojo.test.ObjectUnion({fPodUnion: null})
-  });
-
-  var err = structValidate(s);
-  assert_equals(err, mojo.internal.validationError.UNEXPECTED_NULL_UNION);
-}, 'null union validation');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/validation.html b/third_party/blink/web_tests/mojo/validation.html
deleted file mode 100644
index 1bd32b8..0000000
--- a/third_party/blink/web_tests/mojo/validation.html
+++ /dev/null
@@ -1,297 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
-<script src="file:///gen/mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom.js"></script>
-<script src="resources/validation_test_input_parser.js"></script>
-<script>
-'use strict';
-
-var noError = mojo.internal.validationError.NONE;
-
-function checkData(data, expectedData, input) {
-  assert_equals(data.byteLength, expectedData.byteLength,
-      'message length (' + data.byteLength + ') doesn\'t match ' +
-      'expected length: ' + expectedData.byteLength + ' for ' + input);
-
-  for (var i = 0; i < data.byteLength; i++) {
-    assert_equals(data.getUint8(i), expectedData.getUint8(i),
-        'message data mismatch at byte offset ' + i + 'for' + input);
-  }
-}
-
-test(() => {
-  var input = '[f]+.3e9 [d]-10.03';
-  var msg = mojo.test.parseTestMessage(input);
-  var expectedData = new mojo.internal.Buffer(12);
-  expectedData.setFloat32(0, +.3e9);
-  expectedData.setFloat64(4, -10.03);
-  checkData(msg.buffer, expectedData, input);
-}, 'message parser: float items');
-
-test(() => {
-  var input = '[u1]0x10// hello world !! \n\r  \t [u2]65535 \n' +
-      '[u4]65536 [u8]0xFFFFFFFFFFFFF 0 0Xff';
-  var msg = mojo.test.parseTestMessage(input);
-  var expectedData = new mojo.internal.Buffer(17);
-  expectedData.setUint8(0, 0x10);
-  expectedData.setUint16(1, 65535);
-  expectedData.setUint32(3, 65536);
-  expectedData.setUint64(7, 0xFFFFFFFFFFFFF);
-  expectedData.setUint8(15, 0);
-  expectedData.setUint8(16, 0xff);
-  checkData(msg.buffer, expectedData, input);
-}, 'message parser: unsigned integer items');
-
-test(() => {
-  var input = '[s8]-0x800 [s1]-128\t[s2]+0 [s4]-40';
-  var msg = mojo.test.parseTestMessage(input);
-  var expectedData = new mojo.internal.Buffer(15);
-  expectedData.setInt64(0, -0x800);
-  expectedData.setInt8(8, -128);
-  expectedData.setInt16(9, 0);
-  expectedData.setInt32(11, -40);
-  checkData(msg.buffer, expectedData, input);
-}, 'message parser: signed integer items');
-
-test(() => {
-  var input = '[b]00001011 [b]10000000  // hello world\n [b]00000000';
-  var msg = mojo.test.parseTestMessage(input);
-  var expectedData = new mojo.internal.Buffer(3);
-  expectedData.setUint8(0, 11);
-  expectedData.setUint8(1, 128);
-  expectedData.setUint8(2, 0);
-  checkData(msg.buffer, expectedData, input);
-}, 'message parser: byte items');
-
-test(() => {
-  var input = '[dist4]foo 0 [dist8]bar 0 [anchr]foo [anchr]bar';
-  var msg = mojo.test.parseTestMessage(input);
-  var expectedData = new mojo.internal.Buffer(14);
-  expectedData.setUint32(0, 14);
-  expectedData.setUint8(4, 0);
-  expectedData.setUint64(5, 9);
-  expectedData.setUint8(13, 0);
-  checkData(msg.buffer, expectedData, input);
-}, 'message parser: anchors');
-
-test(() => {
-  var input = '// This message has handles! \n[handles]50 [u8]2';
-  var msg = mojo.test.parseTestMessage(input);
-  var expectedData = new mojo.internal.Buffer(8);
-  expectedData.setUint64(0, 2);
-
-  assert_equals(msg.handleCount, 50,
-      'wrong handle count (' + msg.handleConut + ') for ' + input);
-  checkData(msg.buffer, expectedData, input);
-}, 'message parser: handles');
-
-test(() => {
-  var msg = mojo.test.parseTestMessage('');
-  assert_equals(msg.buffer.byteLength, 0, 'expected empty message for ');
-}, 'message parser: empty input');
-
-test(() => {
-  var input = '    \t  // hello world \n\r \t// the answer is 42   ';
-  var msg = mojo.test.parseTestMessage(input);
-  assert_equals(msg.buffer.byteLength, 0,
-      'expected empty message for ' + input);
-}, 'message parser: blank input');
-
-test(() => {
-  function parserShouldFail(input) {
-    assert_throws(new mojo.test.InputError(), function() {
-      mojo.test.parseTestMessage(input);
-    });
-  }
-
-  ['/ hello world',
-   '[u1]x',
-   '[u2]-1000',
-   '[u1]0x100',
-   '[s2]-0x8001',
-   '[b]1',
-   '[b]1111111k',
-   '[dist4]unmatched',
-   '[anchr]hello [dist8]hello',
-   '[dist4]a [dist4]a [anchr]a',
-   // '[dist4]a [anchr]a [dist4]a [anchr]a',
-   '0 [handles]50'
-  ].forEach(parserShouldFail);
-}, 'message parser: invalid input');
-
-function fetchLite(url) {
-  return new Promise((resolve, reject) => {
-    var xhr = new XMLHttpRequest();
-    xhr.open('GET', url);
-    xhr.onreadystatechange = () => {
-      if (xhr.readyState != 4) return;
-      resolve(xhr.responseText);
-    };
-    xhr.send();
-  });
-}
-
-function getMessageTestFiles(prefix) {
-  let dataDirectory =
-      'file:///gen/layout_test_data/mojo/public/interfaces/bindings/tests/data/validation';
-  return fetchLite(dataDirectory + '_index.txt').then((response) => {
-    assert_not_equals(response, null);
-    var testFiles = response.split(/\s+/);
-    assert_greater_than(testFiles.length, 0);
-    return testFiles.filter(function(s) {
-      return s.substr(-5) == '.data' && s.indexOf(prefix) == 0;
-    }).map(function(s) {
-      return dataDirectory + '/' + s.slice(0, -5);
-    });
-  });
-}
-
-function readTestMessage(filename) {
-  return fetchLite(filename + '.data').then((response) => {
-    assert_not_equals(response, null);
-    return mojo.test.parseTestMessage(response);
-  });
-}
-
-function readTestExpected(filename) {
-  return fetchLite(filename + '.expected').then((response) => {
-    assert_not_equals(response, null);
-    return response.trim();
-  });
-}
-
-async function checkValidationResult(testFile, err) {
-  var actualResult = (err === noError) ? 'PASS' : err;
-  var expectedResult = await readTestExpected(testFile);
-  assert_equals(actualResult, expectedResult,
-      '[Test message validation failed: ' + testFile + ' ]');
-}
-
-async function testMessageValidation(prefix, filters) {
-  var testFiles = await getMessageTestFiles(prefix);
-  assert_greater_than(testFiles.length, 0);
-
-  for (var i = 0; i < testFiles.length; i++) {
-    // TODO(hansmuller) Temporarily skipping array pointer overflow tests
-    // because JS numbers are limited to 53 bits.
-    // TODO(rudominer): Temporarily skipping 'no-such-method',
-    // 'invalid_request_flags', and 'invalid_response_flags' until additional
-    // logic in *RequestValidator and *ResponseValidator is ported from
-    // cpp to js.
-    // TODO(crbug/640298): Implement max recursion depth for JS.
-    // TODO(crbug/628104): Support struct map keys for JS.
-    if (testFiles[i].indexOf('overflow') != -1 ||
-        testFiles[i].indexOf('conformance_mthd19') != -1 ||
-        testFiles[i].indexOf('conformance_mthd20') != -1 ||
-        testFiles[i].indexOf('no_such_method') != -1 ||
-        testFiles[i].indexOf('invalid_request_flags') != -1 ||
-        testFiles[i].indexOf('invalid_response_flags') != -1) {
-      console.log('[Skipping ' + testFiles[i] + ']');
-      continue;
-    }
-
-    var testMessage = await readTestMessage(testFiles[i]);
-    var handles = new Array(testMessage.handleCount);
-    var message = new mojo.internal.Message(testMessage.buffer, handles);
-    var messageValidator = new mojo.internal.Validator(message);
-
-    var err = messageValidator.validateMessageHeader();
-    for (var j = 0; err === noError && j < filters.length; ++j)
-      err = filters[j](messageValidator);
-
-    await checkValidationResult(testFiles[i], err);
-  }
-}
-
-promise_test(() => {
-  return testMessageValidation('conformance_', [
-      mojo.test.ConformanceTestInterface.validateRequest]);
-}, 'conformance message validation');
-
-promise_test(() => {
-  return testMessageValidation('boundscheck_', [
-      mojo.test.BoundsCheckTestInterface.validateRequest]);
-}, 'bounds check message validation');
-
-promise_test(() => {
-  return testMessageValidation('resp_conformance_', [
-      mojo.test.ConformanceTestInterface.validateResponse]);
-}, 'response conformance message validation');
-
-promise_test(() => {
-  return testMessageValidation('resp_boundscheck_', [
-      mojo.test.BoundsCheckTestInterface.validateResponse]);
-}, 'response bounds check message validation');
-
-async function testIntegratedMessageValidation(testFilesPattern, endpoint) {
-  var testFiles = await getMessageTestFiles(testFilesPattern);
-  assert_greater_than(testFiles.length, 0);
-
-  var testMessagePipe = Mojo.createMessagePipe();
-  assert_equals(testMessagePipe.result, Mojo.RESULT_OK);
-
-  endpoint.bind(testMessagePipe.handle1);
-  if (endpoint instanceof mojo.InterfacePtrController) {
-    // Make sure the router and connector are initialized.
-    endpoint.getProxy();
-  }
-
-  var originalReceiver = endpoint.router_.connector_.incomingReceiver_.accept;
-  var nextMessageCallback = null;
-  endpoint.router_.connector_.incomingReceiver_.accept = function(message) {
-    var result = originalReceiver(message);
-    if (nextMessageCallback) {
-      setTimeout(() => {
-        nextMessageCallback();
-        nextMessageCallback = null;
-      }, 0);
-    }
-    return result;
-  }
-
-  var observer = mojo.internal.ValidationErrorObserverForTesting.getInstance();
-
-  for (var i = 0; i < testFiles.length; i++) {
-    var testMessage = await readTestMessage(testFiles[i]);
-    var handles = new Array(testMessage.handleCount);
-
-    await new Promise((resolve, reject) => {
-      nextMessageCallback = resolve;
-
-      var writeMessageValue = testMessagePipe.handle0.writeMessage(
-          new Uint8Array(testMessage.buffer.arrayBuffer),
-          new Array(testMessage.handleCount));
-      assert_equals(writeMessageValue, Mojo.RESULT_OK);
-    });
-    await checkValidationResult(testFiles[i], observer.lastError);
-    observer.reset();
-  }
-
-  testMessagePipe.handle0.close();
-}
-
-promise_test(() => {
-  return testIntegratedMessageValidation(
-      'integration_msghdr',
-      new mojo.Binding(mojo.test.IntegrationTestInterface, {}))
-    .then(() => {
-      return testIntegratedMessageValidation(
-          'integration_msghdr',
-          new mojo.test.IntegrationTestInterfacePtr().ptr);
-    });
-}, 'integrated message header validation');
-
-promise_test(() => {
-  return testIntegratedMessageValidation(
-      'integration_intf_rqst',
-      new mojo.Binding(mojo.test.IntegrationTestInterface, {}));
-}, 'integrated request message validation');
-
-promise_test(() => {
-  return testIntegratedMessageValidation(
-      'integration_intf_resp',
-      new mojo.test.IntegrationTestInterfacePtr().ptr);
-}, 'integrated response message validation');
-
-</script>
diff --git a/third_party/blink/web_tests/mojo/watch.html b/third_party/blink/web_tests/mojo/watch.html
deleted file mode 100644
index 3a0eb37..0000000
--- a/third_party/blink/web_tests/mojo/watch.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!DOCTYPE html>
-<title>mojo watch tests</title>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script>
-
-async_test((test) => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-
-  handle0.watch({readable: true}, test.step_func_done((result) => {
-    assert_equals(result, Mojo.RESULT_OK);
-  }));
-  handle1.writeMessage(new ArrayBuffer(4), []);
-}, "Watch handle readable");
-
-async_test((test) => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-
-  handle0.watch({writable: true}, test.step_func_done((result) => {
-    assert_equals(result, Mojo.RESULT_OK);
-  }));
-}, "Watch handle writable");
-
-async_test((test) => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-
-  handle0.watch({peerClosed: true}, test.step_func_done((result) => {
-    assert_equals(result, Mojo.RESULT_OK);
-  }));
-  handle1.close();
-}, "Watch handle peer closed");
-
-async_test((test) => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-
-  handle0.close();
-  handle0.watch({writable: true}, test.step_func_done((result) => {
-    assert_equals(result, Mojo.RESULT_INVALID_ARGUMENT);
-  }));
-}, "Watch invalid handle");
-
-async_test((test) => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-
-  handle0.watch({}, test.step_func_done((result) => {
-    assert_equals(result, Mojo.RESULT_FAILED_PRECONDITION);
-  }));
-}, "Watch with default MojoHandleSignals");
-
-async_test((test) => {
-  let {handle0, handle1} = Mojo.createMessagePipe();
-
-  let watcher = handle0.watch(
-      {writable: true},
-      test.unreached_func("callback triggered after canceling watch"));
-  watcher.cancel();
-  setTimeout(() => { test.done(); });
-}, "Cancel watch");
-
-</script>
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t040302-c61-phys-len-00-b-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t040302-c61-phys-len-00-b-expected.png
deleted file mode 100644
index 3be5493..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t040302-c61-phys-len-00-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t0805-c5522-brdr-02-e-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t0805-c5522-brdr-02-e-expected.png
deleted file mode 100644
index 1ceacb8..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t0805-c5522-brdr-02-e-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t1202-counter-08-b-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t1202-counter-08-b-expected.png
deleted file mode 100644
index ad81f6b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t1202-counter-08-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t1205-c561-list-displ-00-b-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t1205-c561-list-displ-00-b-expected.png
deleted file mode 100644
index 6e5ac82..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/css2.1/t1205-c561-list-displ-00-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/css3/selectors3/html/css3-modsel-80-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/css3/selectors3/html/css3-modsel-80-expected.png
deleted file mode 100644
index 9b1940d..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/css3/selectors3/html/css3-modsel-80-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/editing/selection/5232159-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/editing/selection/5232159-expected.png
deleted file mode 100644
index d399e13..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/editing/selection/5232159-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/button/button-inner-block-reuse-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/button/button-inner-block-reuse-expected.png
deleted file mode 100644
index dfd9bcf..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/button/button-inner-block-reuse-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/formmove2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/formmove2-expected.png
deleted file mode 100644
index a936e77..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/formmove2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/indeterminate-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/indeterminate-expected.png
deleted file mode 100644
index 12f91d7..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/indeterminate-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/input-appearance-height-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/input-appearance-height-expected.png
deleted file mode 100644
index 223d745..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/input-appearance-height-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/search/search-vertical-alignment-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/search/search-vertical-alignment-expected.png
deleted file mode 100644
index da608b7..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/search/search-vertical-alignment-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/select/select-align-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/select/select-align-expected.png
deleted file mode 100644
index e51e07f2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/select/select-align-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/select/select-disabled-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/select/select-disabled-appearance-expected.png
deleted file mode 100644
index 6649cd4..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/select/select-disabled-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew-expected.png
deleted file mode 100644
index 96969c5..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/targeted-frame-submission-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/targeted-frame-submission-expected.png
deleted file mode 100644
index 30dd729..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/targeted-frame-submission-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/text/textfield-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/text/textfield-focus-ring-expected.png
deleted file mode 100644
index f484194c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/text/textfield-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/inline-block/baseline-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/inline-block/baseline-vertical-expected.png
deleted file mode 100644
index 8ad87dd..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/inline-block/baseline-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/inline/002-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/inline/002-expected.png
deleted file mode 100644
index c1173c0..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/inline/002-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/inline/br-text-decoration-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/inline/br-text-decoration-expected.png
deleted file mode 100644
index 6ce6468..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/inline/br-text-decoration-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/010-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/010-expected.png
deleted file mode 100644
index 1ea758b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/010-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/021-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/021-expected.png
deleted file mode 100644
index f56c9a5..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/021-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/missing-dt-end-tag-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/missing-dt-end-tag-expected.png
deleted file mode 100644
index ac99d44..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/missing-dt-end-tag-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/nestedh3s-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/nestedh3s-expected.png
deleted file mode 100644
index 9319f7e..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/invalid/nestedh3s-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/003-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/003-expected.png
deleted file mode 100644
index d84cd1734..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/003-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/003-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/003-vertical-expected.png
deleted file mode 100644
index 2f957c0..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/003-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/007-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/007-expected.png
deleted file mode 100644
index 96525963..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/007-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/007-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/007-vertical-expected.png
deleted file mode 100644
index 88541de..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/lists/007-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/multicol/composited-inner-multicol-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/multicol/composited-inner-multicol-expected.png
deleted file mode 100644
index 08346e2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/multicol/composited-inner-multicol-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/multicol/composited-layer-multiple-fragments-translated-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/multicol/composited-layer-multiple-fragments-translated-expected.png
deleted file mode 100644
index 3ad6d33..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/multicol/composited-layer-multiple-fragments-translated-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/overflow/overflow-auto-table-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/overflow/overflow-auto-table-expected.png
deleted file mode 100644
index 9b92181..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/overflow/overflow-auto-table-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/overflow/table-overflow-float-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/overflow/table-overflow-float-expected.png
deleted file mode 100644
index 125d2fbf..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/overflow/table-overflow-float-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/parser/fonts-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/parser/fonts-expected.png
deleted file mode 100644
index d3f04a50..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/parser/fonts-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/parser/xhtml-alternate-entities-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/parser/xhtml-alternate-entities-expected.png
deleted file mode 100644
index 06638e2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/parser/xhtml-alternate-entities-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/replaced/max-width-percent-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/replaced/max-width-percent-expected.png
deleted file mode 100644
index a489c39ab..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/replaced/max-width-percent-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/replaced/selection-rect-transform-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/replaced/selection-rect-transform-expected.png
deleted file mode 100644
index 46fb3ae..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/replaced/selection-rect-transform-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/replaced/table-replaced-element-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/fast/replaced/table-replaced-element-expected.txt
deleted file mode 100644
index 46faf40..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/replaced/table-replaced-element-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Layout test for WebKit bug 85581.
-
-This tests that the contents of a table do not overflow when the table contains an image with percentage height. For this test to pass, the blue rectangle should be entirely within the table border and/or you should see a 'PASS' message below.
-
-Height of table: 290
-Height of table contents: 280
-PASS: Table contents do not overflow outside of table border.
-
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/020-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/020-expected.png
deleted file mode 100644
index 2b8682d..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/020-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/040-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/040-expected.png
deleted file mode 100644
index 997257f..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/040-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/042-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/042-expected.png
deleted file mode 100644
index fb9a8aa..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/042-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/066-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/066-expected.png
deleted file mode 100644
index 7cc7061b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/066-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/078b-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/078b-expected.png
deleted file mode 100644
index 2509fba8..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/078b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/lang-inheritance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/lang-inheritance-expected.png
deleted file mode 100644
index e78ec7ac..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/lang-inheritance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/lang-vs-xml-lang-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/lang-vs-xml-lang-expected.png
deleted file mode 100644
index a2f5a11..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/selectors/lang-vs-xml-lang-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/040-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/040-vertical-expected.png
deleted file mode 100644
index b0a85d0..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/040-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/100-percent-cell-width-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/100-percent-cell-width-expected.png
deleted file mode 100644
index d89ea08..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/100-percent-cell-width-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-cell-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-cell-collapsed-border-expected.png
deleted file mode 100644
index 6c713c3..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-cell-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-cell-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-cell-expected.png
deleted file mode 100644
index a0ef5ca..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-cell-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-column-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-column-collapsed-border-expected.png
deleted file mode 100644
index 5d4ebb6..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-column-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-column-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-column-expected.png
deleted file mode 100644
index 5946468..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-column-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-column-group-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-column-group-collapsed-border-expected.png
deleted file mode 100644
index 9ca7d68..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_border-table-column-group-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_fixed-bg-table-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_fixed-bg-table-expected.png
deleted file mode 100644
index a1a5d7a..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_fixed-bg-table-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_layers-show-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_layers-show-collapsed-border-expected.png
deleted file mode 100644
index 873bd40a..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_layers-show-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_layers-show-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_layers-show-expected.png
deleted file mode 100644
index 69a6d521..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_layers-show-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_position-table-row-group-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_position-table-row-group-collapsed-border-expected.png
deleted file mode 100644
index bbdccdb4..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_position-table-row-group-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_position-table-row-group-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_position-table-row-group-expected.png
deleted file mode 100644
index f36219f..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_position-table-row-group-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-cell-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-cell-expected.png
deleted file mode 100644
index 288d4eb4..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-cell-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-collapsed-border-expected.png
deleted file mode 100644
index 1324799..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-column-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-column-collapsed-border-expected.png
deleted file mode 100644
index f5cac25..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-column-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-expected.png
deleted file mode 100644
index 402614c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/backgr_simple-table-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/form-with-table-style-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/form-with-table-style-expected.png
deleted file mode 100644
index da5d2024..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/form-with-table-style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/insert-row-before-form-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/insert-row-before-form-expected.png
deleted file mode 100644
index ebfbf44..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/insert-row-before-form-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/prepend-in-anonymous-table-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/prepend-in-anonymous-table-expected.png
deleted file mode 100644
index a0caf48..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/prepend-in-anonymous-table-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/rowspan-paint-order-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/rowspan-paint-order-vertical-expected.png
deleted file mode 100644
index 6c87a0e2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/rowspan-paint-order-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/split-table-section-before-anonymous-block-3-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/split-table-section-before-anonymous-block-3-expected.png
deleted file mode 100644
index df10010..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/split-table-section-before-anonymous-block-3-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/tbody-background-image-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/tbody-background-image-expected.png
deleted file mode 100644
index 007f4d7..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/tbody-background-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/tbody-background-image-repeat-x-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/tbody-background-image-repeat-x-expected.png
deleted file mode 100644
index 383c92b2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/tbody-background-image-repeat-x-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/unused-percent-heights-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/unused-percent-heights-expected.png
deleted file mode 100644
index fc0ac13..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/table/unused-percent-heights-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/ellipsis-platform-font-change-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/ellipsis-platform-font-change-expected.png
deleted file mode 100644
index fa4f132bd..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/ellipsis-platform-font-change-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/international/shape-across-elements-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/international/shape-across-elements-expected.txt
deleted file mode 100644
index 2dafceb..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/international/shape-across-elements-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-PASS Width of isolated word does match width of word with markup.
-PASS Width of partial glyph in ligature does not match width of isolated glyph.
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-Shape across element boundary test
-سلام The word by itself.
-سلام Adding a span around a character that forms a ligature. Should render the same as the above, except that half of the middle glyph should be red.
-سل‍ام Same word with a ZWJ character to disallow the ligature.
-Ù„ The letter in red, in isolation.
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/justify-ideograph-vertical-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/justify-ideograph-vertical-expected.png
deleted file mode 100644
index 6dfb14d2a..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/justify-ideograph-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/border-image-vertical-lr-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/border-image-vertical-lr-expected.png
deleted file mode 100644
index f73e19e..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/border-image-vertical-lr-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png
deleted file mode 100644
index bcc3b55..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/broken-ideograph-small-caps-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/broken-ideograph-small-caps-expected.png
deleted file mode 100644
index ba0178e..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/broken-ideograph-small-caps-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/broken-ideographic-font-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/broken-ideographic-font-expected.png
deleted file mode 100644
index 3419f52b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/writing-mode/broken-ideographic-font-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/html/details_summary/details-writing-mode-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/html/details_summary/details-writing-mode-expected.png
deleted file mode 100644
index dc831990..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/html/details_summary/details-writing-mode-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/ietestcenter/css3/text/textshadow-003-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/ietestcenter/css3/text/textshadow-003-expected.png
deleted file mode 100644
index 67266c8..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/ietestcenter/css3/text/textshadow-003-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/ietestcenter/css3/text/textshadow-010-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/ietestcenter/css3/text/textshadow-010-expected.png
deleted file mode 100644
index 9525299..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/ietestcenter/css3/text/textshadow-010-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/images/exif-orientation-image-document-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/images/exif-orientation-image-document-expected.png
deleted file mode 100644
index 1896b5c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/images/exif-orientation-image-document-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-circle-focus-ring-expected.png
deleted file mode 100644
index 60fa273..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-circle-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-focus-ring-expected.png
deleted file mode 100644
index dccc42a..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
deleted file mode 100644
index 083676cb..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-overflowing-polygon-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-overflowing-polygon-focus-ring-expected.png
deleted file mode 100644
index 2112c62d..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/images/imagemap-overflowing-polygon-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/media/video-colorspace-yuv420-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/media/video-colorspace-yuv420-expected.png
deleted file mode 100644
index 446604b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/media/video-colorspace-yuv420-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/plugins/embed-attributes-style-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/plugins/embed-attributes-style-expected.png
deleted file mode 100644
index 14aaa5b9..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/plugins/embed-attributes-style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/clone-element-with-animated-svg-properties-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/clone-element-with-animated-svg-properties-expected.png
deleted file mode 100644
index 2fbd6f6..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/clone-element-with-animated-svg-properties-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/svg-fonts-in-html-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/svg-fonts-in-html-expected.png
deleted file mode 100644
index 42c06bc..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/svg-fonts-in-html-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/text-match-highlight-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/text-match-highlight-expected.png
deleted file mode 100644
index 0e857ef..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/text-match-highlight-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/transformed-text-pattern-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/transformed-text-pattern-expected.png
deleted file mode 100644
index d239172..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/custom/transformed-text-pattern-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/dom/SVGLocatable-getCTM-svg-root-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/dom/SVGLocatable-getCTM-svg-root-expected.png
deleted file mode 100644
index 204e601..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/dom/SVGLocatable-getCTM-svg-root-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/dom/SVGStringList-basics-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/dom/SVGStringList-basics-expected.png
deleted file mode 100644
index 58d94a3..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/dom/SVGStringList-basics-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/hixie/rendering-model/004-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/hixie/rendering-model/004-expected.png
deleted file mode 100644
index 0ee89eec..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/hixie/rendering-model/004-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/wicd/test-rightsizing-a-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/wicd/test-rightsizing-a-expected.png
deleted file mode 100644
index fb648734..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/wicd/test-rightsizing-a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug106158-2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug106158-2-expected.png
deleted file mode 100644
index 209a813..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug106158-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug10633-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug10633-expected.png
deleted file mode 100644
index 7bddf17..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug10633-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug11944-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug11944-expected.png
deleted file mode 100644
index b2b508f1..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug11944-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug1302-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug1302-expected.png
deleted file mode 100644
index 5bc84003..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug1302-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug157890-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug157890-expected.png
deleted file mode 100644
index aec57b469..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug157890-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug17130-2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug17130-2-expected.png
deleted file mode 100644
index a67c6e9..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug17130-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug23235-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug23235-expected.png
deleted file mode 100644
index f286f4df9..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug23235-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug2509-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug2509-expected.png
deleted file mode 100644
index 2454181..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug2509-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug2684-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug2684-expected.png
deleted file mode 100644
index 55eda75fc..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug2684-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug2981-1-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug2981-1-expected.png
deleted file mode 100644
index 398b1b0..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug2981-1-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug38916-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug38916-expected.png
deleted file mode 100644
index 4db8e36..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug38916-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug43039-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug43039-expected.png
deleted file mode 100644
index 64e9fe8..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug43039-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug46368-1-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug46368-1-expected.png
deleted file mode 100644
index b6202ea..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug46368-1-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug46623-1-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug46623-1-expected.png
deleted file mode 100644
index 6ba11656..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug46623-1-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug4849-2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug4849-2-expected.png
deleted file mode 100644
index 4dee9989..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug4849-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug5188-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug5188-expected.png
deleted file mode 100644
index f4a2ccf..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug5188-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug55694-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug55694-expected.png
deleted file mode 100644
index 1933e80..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug55694-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug57828-2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug57828-2-expected.png
deleted file mode 100644
index c1762618..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug57828-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug5838-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug5838-expected.png
deleted file mode 100644
index c234c5c0..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug5838-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug6404-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug6404-expected.png
deleted file mode 100644
index 814436c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug6404-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug650-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug650-expected.png
deleted file mode 100644
index dc2d73d..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug650-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug69382-2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug69382-2-expected.png
deleted file mode 100644
index a6111e5..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug69382-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug7112-2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug7112-2-expected.png
deleted file mode 100644
index 864b5d31..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug7112-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug7342-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug7342-expected.png
deleted file mode 100644
index 221f61b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug7342-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug80762-1-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug80762-1-expected.png
deleted file mode 100644
index 59d9439..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug80762-1-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug88035-2-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug88035-2-expected.png
deleted file mode 100644
index 9c8f4fa..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug88035-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug8950-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug8950-expected.png
deleted file mode 100644
index debe4a01..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/bugs/bug8950-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/core/col_span-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/core/col_span-expected.png
deleted file mode 100644
index da7a94d..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/core/col_span-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/body_tfoot-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/body_tfoot-expected.png
deleted file mode 100644
index df9f750..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/body_tfoot-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/body_thead-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/body_thead-expected.png
deleted file mode 100644
index e10bc6c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/body_thead-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/col_span-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/col_span-expected.png
deleted file mode 100644
index e3a9266..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/col_span-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/colgroup_span-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/colgroup_span-expected.png
deleted file mode 100644
index f7efb55..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/colgroup_span-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/colgroup_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/colgroup_valign_baseline-expected.png
deleted file mode 100644
index ee77669..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/colgroup_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/table_row_align_center-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/table_row_align_center-expected.png
deleted file mode 100644
index c922c0c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/table_row_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/table_rules_all-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/table_rules_all-expected.png
deleted file mode 100644
index 91e4bad..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/table_rules_all-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/table_rules_groups-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/table_rules_groups-expected.png
deleted file mode 100644
index 1b14ad1..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/table_rules_groups-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tables_cellpadding-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tables_cellpadding-expected.png
deleted file mode 100644
index 4a8994f..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tables_cellpadding-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tables_cellpadding_pct-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tables_cellpadding_pct-expected.png
deleted file mode 100644
index 7e5d88c0..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tables_cellpadding_pct-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tables_style-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tables_style-expected.png
deleted file mode 100644
index 697c025..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tables_style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_align_char-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_align_char-expected.png
deleted file mode 100644
index af5b17ee7..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_char-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_char-expected.png
deleted file mode 100644
index b62ee91..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_valign_bottom-expected.png
deleted file mode 100644
index c9ffe04..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_valign_middle-expected.png
deleted file mode 100644
index 9df4c980..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tbody_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/td_valign_top-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/td_valign_top-expected.png
deleted file mode 100644
index 2edd7a2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/td_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tfoot_char-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tfoot_char-expected.png
deleted file mode 100644
index ee40fa51..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tfoot_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tfoot_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tfoot_valign_baseline-expected.png
deleted file mode 100644
index c659acc..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tfoot_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tfoot_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tfoot_valign_bottom-expected.png
deleted file mode 100644
index ec76811..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tfoot_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_align_char-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_align_char-expected.png
deleted file mode 100644
index da9bda8..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_valign_baseline-expected.png
deleted file mode 100644
index 736115e..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_valign_bottom-expected.png
deleted file mode 100644
index 75fa7b3..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_valign_middle-expected.png
deleted file mode 100644
index f942774..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/thead_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tr_bgcolor_white-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tr_bgcolor_white-expected.png
deleted file mode 100644
index de9cb892..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tr_bgcolor_white-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tr_bgcolor_white_rgb-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tr_bgcolor_white_rgb-expected.png
deleted file mode 100644
index de9cb892..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/tr_bgcolor_white_rgb-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_col_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_col_valign_middle-expected.png
deleted file mode 100644
index 0294e57..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_col_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png
deleted file mode 100644
index addca44..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png
deleted file mode 100644
index 96fa500c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_table_border-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_table_border-expected.png
deleted file mode 100644
index 4ab6f9c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_table_border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_table_style-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_table_style-expected.png
deleted file mode 100644
index ac41cb49..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_table_style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tbody_align_char-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tbody_align_char-expected.png
deleted file mode 100644
index 0020a05..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tbody_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png
deleted file mode 100644
index c9204ed..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tbody_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tbody_valign_middle-expected.png
deleted file mode 100644
index cce6a17..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tbody_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_td_align_center-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_td_align_center-expected.png
deleted file mode 100644
index 2088fc9f..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_td_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_td_valign_top-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_td_valign_top-expected.png
deleted file mode 100644
index cfe4af8..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_td_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tfoot_align_char-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tfoot_align_char-expected.png
deleted file mode 100644
index 2407d1f..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tfoot_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tfoot_style-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tfoot_style-expected.png
deleted file mode 100644
index b111410..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tfoot_style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png
deleted file mode 100644
index 6be8bde3..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_th_width-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_th_width-expected.png
deleted file mode 100644
index 3a68794..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla/marvin/x_th_width-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug10140-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug10140-expected.png
deleted file mode 100644
index dff3b0c..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug10140-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug17826-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug17826-expected.png
deleted file mode 100644
index 47fa3b9a..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug17826-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug72393-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug72393-expected.png
deleted file mode 100644
index 5e259c1d..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug72393-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug89315-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug89315-expected.png
deleted file mode 100644
index e5366d18..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/bugs/bug89315-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
deleted file mode 100644
index c578d26..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/marvin/x_colgroup_width_px-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/marvin/x_colgroup_width_px-expected.png
deleted file mode 100644
index 7bfe605..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/tables/mozilla_expected_failures/marvin/x_colgroup_width_px-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/transforms/3d/general/perspective-units-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/transforms/3d/general/perspective-units-expected.png
deleted file mode 100644
index 2f230e2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/transforms/3d/general/perspective-units-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/transforms/diamond-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/transforms/diamond-expected.png
deleted file mode 100644
index fa0eed7..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/transforms/diamond-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/exotic-color-space/images/exif-orientation-css-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/exotic-color-space/images/exif-orientation-css-expected.png
deleted file mode 100644
index 33e5432..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/exotic-color-space/images/exif-orientation-css-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
deleted file mode 100644
index af3c555..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/exif-orientation-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/exif-orientation-expected.png
deleted file mode 100644
index b770984..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/exif-orientation-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/image-map-anchor-children-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/image-map-anchor-children-expected.png
deleted file mode 100644
index 6ebf40b..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/image-map-anchor-children-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
deleted file mode 100644
index bcb4d80..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
deleted file mode 100644
index 749db52..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png
deleted file mode 100644
index 3255bc2..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt
deleted file mode 100644
index b1de4e47..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This tests verifies the hit test regions given to the compositor specifically for continuation case. It can only be run in DumpRenderTree.
-
-continuation: layer(800x600) has hit test rect (13,90 290x12)
-
-
diff --git a/third_party/blink/web_tests/platform/mac-retina/css2.1/t040302-c61-phys-len-00-b-expected.png b/third_party/blink/web_tests/platform/mac-retina/css2.1/t040302-c61-phys-len-00-b-expected.png
deleted file mode 100644
index 3be5493..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/css2.1/t040302-c61-phys-len-00-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/css2.1/t0805-c5522-brdr-02-e-expected.png b/third_party/blink/web_tests/platform/mac-retina/css2.1/t0805-c5522-brdr-02-e-expected.png
deleted file mode 100644
index 1ceacb8..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/css2.1/t0805-c5522-brdr-02-e-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/css2.1/t1202-counter-08-b-expected.png b/third_party/blink/web_tests/platform/mac-retina/css2.1/t1202-counter-08-b-expected.png
deleted file mode 100644
index ad81f6b..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/css2.1/t1202-counter-08-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/css2.1/t1205-c561-list-displ-00-b-expected.png b/third_party/blink/web_tests/platform/mac-retina/css2.1/t1205-c561-list-displ-00-b-expected.png
deleted file mode 100644
index 6e5ac82..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/css2.1/t1205-c561-list-displ-00-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/css3/selectors3/html/css3-modsel-80-expected.png b/third_party/blink/web_tests/platform/mac-retina/css3/selectors3/html/css3-modsel-80-expected.png
deleted file mode 100644
index 9b1940d..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/css3/selectors3/html/css3-modsel-80-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/editing/selection/5232159-expected.png b/third_party/blink/web_tests/platform/mac-retina/editing/selection/5232159-expected.png
deleted file mode 100644
index d399e13..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/editing/selection/5232159-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/basic-inputs-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/basic-inputs-expected.png
deleted file mode 100644
index ea54276..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/basic-inputs-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/button/button-inner-block-reuse-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/button/button-inner-block-reuse-expected.png
deleted file mode 100644
index dfd9bcf..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/button/button-inner-block-reuse-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/formmove2-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/formmove2-expected.png
deleted file mode 100644
index a936e77..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/formmove2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/indeterminate-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/indeterminate-expected.png
deleted file mode 100644
index 12f91d7..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/indeterminate-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/input-appearance-height-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/input-appearance-height-expected.png
deleted file mode 100644
index 223d745..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/input-appearance-height-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/search/search-vertical-alignment-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/search/search-vertical-alignment-expected.png
deleted file mode 100644
index da608b7..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/search/search-vertical-alignment-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/select/option-script-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/select/option-script-expected.png
deleted file mode 100644
index b93343a..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/select/option-script-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/select/select-align-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/select/select-align-expected.png
deleted file mode 100644
index e51e07f2..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/select/select-align-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/select/select-disabled-appearance-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/select/select-disabled-appearance-expected.png
deleted file mode 100644
index 6649cd4..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/select/select-disabled-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/date-suggestion-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/date-suggestion-picker-appearance-expected.png
deleted file mode 100644
index 94726c9..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/date-suggestion-picker-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-locale-hebrew-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-locale-hebrew-expected.png
deleted file mode 100644
index f3fdedf..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-locale-hebrew-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-rtl-expected.png
deleted file mode 100644
index c5914edf..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar-expected.png
deleted file mode 100644
index d253243..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew-expected.png
deleted file mode 100644
index 96969c5..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/targeted-frame-submission-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/targeted-frame-submission-expected.png
deleted file mode 100644
index 30dd729..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/targeted-frame-submission-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/text/textfield-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/text/textfield-focus-ring-expected.png
deleted file mode 100644
index f484194c..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/text/textfield-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/textarea/basic-textareas-quirks-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/textarea/basic-textareas-quirks-expected.png
deleted file mode 100644
index 6ac95d9..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/textarea/basic-textareas-quirks-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
deleted file mode 100644
index 73b0131..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/inline-block/baseline-vertical-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/inline-block/baseline-vertical-expected.png
deleted file mode 100644
index 8ad87dd..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/inline-block/baseline-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/inline/002-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/inline/002-expected.png
deleted file mode 100644
index c1173c0..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/inline/002-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/inline/br-text-decoration-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/inline/br-text-decoration-expected.png
deleted file mode 100644
index 6ce6468..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/inline/br-text-decoration-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/inline/inline-box-background-long-image-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/inline/inline-box-background-long-image-expected.png
deleted file mode 100644
index 37e32737..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/inline/inline-box-background-long-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/invalid/010-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/invalid/010-expected.png
deleted file mode 100644
index 1ea758b..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/invalid/010-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/invalid/021-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/invalid/021-expected.png
deleted file mode 100644
index f56c9a5..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/invalid/021-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/invalid/missing-dt-end-tag-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/invalid/missing-dt-end-tag-expected.png
deleted file mode 100644
index ac99d44..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/invalid/missing-dt-end-tag-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/invalid/nestedh3s-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/invalid/nestedh3s-expected.png
deleted file mode 100644
index 9319f7e..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/invalid/nestedh3s-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/lists/003-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/lists/003-expected.png
deleted file mode 100644
index d84cd1734..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/lists/003-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/lists/003-vertical-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/lists/003-vertical-expected.png
deleted file mode 100644
index 2f957c0..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/lists/003-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/lists/007-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/lists/007-expected.png
deleted file mode 100644
index 96525963..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/lists/007-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/lists/007-vertical-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/lists/007-vertical-expected.png
deleted file mode 100644
index 88541de..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/lists/007-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/multicol/composited-inner-multicol-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/multicol/composited-inner-multicol-expected.png
deleted file mode 100644
index 08346e2..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/multicol/composited-inner-multicol-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/multicol/composited-layer-multiple-fragments-translated-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/multicol/composited-layer-multiple-fragments-translated-expected.png
deleted file mode 100644
index 3ad6d33..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/multicol/composited-layer-multiple-fragments-translated-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/overflow/overflow-auto-table-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/overflow/overflow-auto-table-expected.png
deleted file mode 100644
index 9b92181..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/overflow/overflow-auto-table-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/overflow/table-overflow-float-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/overflow/table-overflow-float-expected.png
deleted file mode 100644
index 125d2fbf..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/overflow/table-overflow-float-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/parser/fonts-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/parser/fonts-expected.png
deleted file mode 100644
index d3f04a50..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/parser/fonts-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/parser/xhtml-alternate-entities-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/parser/xhtml-alternate-entities-expected.png
deleted file mode 100644
index 06638e2..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/parser/xhtml-alternate-entities-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/replaced/max-width-percent-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/replaced/max-width-percent-expected.png
deleted file mode 100644
index a489c39ab..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/replaced/max-width-percent-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/replaced/selection-rect-transform-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/replaced/selection-rect-transform-expected.png
deleted file mode 100644
index 46fb3ae..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/replaced/selection-rect-transform-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/replaced/table-replaced-element-expected.txt b/third_party/blink/web_tests/platform/mac-retina/fast/replaced/table-replaced-element-expected.txt
deleted file mode 100644
index 46faf40..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/replaced/table-replaced-element-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Layout test for WebKit bug 85581.
-
-This tests that the contents of a table do not overflow when the table contains an image with percentage height. For this test to pass, the blue rectangle should be entirely within the table border and/or you should see a 'PASS' message below.
-
-Height of table: 290
-Height of table contents: 280
-PASS: Table contents do not overflow outside of table border.
-
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/020-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/selectors/020-expected.png
deleted file mode 100644
index 2b8682d..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/020-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/040-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/selectors/040-expected.png
deleted file mode 100644
index 997257f..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/040-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/042-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/selectors/042-expected.png
deleted file mode 100644
index fb9a8aa..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/042-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/066-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/selectors/066-expected.png
deleted file mode 100644
index 7cc7061b..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/066-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/078b-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/selectors/078b-expected.png
deleted file mode 100644
index 2509fba8..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/078b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/lang-inheritance-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/selectors/lang-inheritance-expected.png
deleted file mode 100644
index e78ec7ac..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/lang-inheritance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/lang-vs-xml-lang-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/selectors/lang-vs-xml-lang-expected.png
deleted file mode 100644
index a2f5a11..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/selectors/lang-vs-xml-lang-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/040-vertical-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/040-vertical-expected.png
deleted file mode 100644
index b0a85d0..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/040-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/100-percent-cell-width-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/100-percent-cell-width-expected.png
deleted file mode 100644
index d89ea08..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/100-percent-cell-width-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-cell-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-cell-collapsed-border-expected.png
deleted file mode 100644
index 6c713c3..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-cell-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-cell-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-cell-expected.png
deleted file mode 100644
index a0ef5ca..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-cell-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-column-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-column-collapsed-border-expected.png
deleted file mode 100644
index 5d4ebb6..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-column-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-column-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-column-expected.png
deleted file mode 100644
index 5946468..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-column-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-column-group-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-column-group-collapsed-border-expected.png
deleted file mode 100644
index 9ca7d68..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_border-table-column-group-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_fixed-bg-table-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_fixed-bg-table-expected.png
deleted file mode 100644
index a1a5d7a..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_fixed-bg-table-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_layers-show-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_layers-show-collapsed-border-expected.png
deleted file mode 100644
index 873bd40a..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_layers-show-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_layers-show-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_layers-show-expected.png
deleted file mode 100644
index 69a6d521..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_layers-show-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_position-table-row-group-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_position-table-row-group-collapsed-border-expected.png
deleted file mode 100644
index bbdccdb4..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_position-table-row-group-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_position-table-row-group-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_position-table-row-group-expected.png
deleted file mode 100644
index f36219f..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_position-table-row-group-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-cell-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-cell-expected.png
deleted file mode 100644
index 288d4eb4..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-cell-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-collapsed-border-expected.png
deleted file mode 100644
index 1324799..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-column-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-column-collapsed-border-expected.png
deleted file mode 100644
index f5cac25..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-column-collapsed-border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-expected.png
deleted file mode 100644
index 402614c..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/backgr_simple-table-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/form-with-table-style-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/form-with-table-style-expected.png
deleted file mode 100644
index da5d2024..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/form-with-table-style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/insert-row-before-form-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/insert-row-before-form-expected.png
deleted file mode 100644
index ebfbf44..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/insert-row-before-form-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/prepend-in-anonymous-table-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/prepend-in-anonymous-table-expected.png
deleted file mode 100644
index a0caf48..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/prepend-in-anonymous-table-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/rowspan-paint-order-vertical-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/rowspan-paint-order-vertical-expected.png
deleted file mode 100644
index 6c87a0e2..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/rowspan-paint-order-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/split-table-section-before-anonymous-block-3-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/split-table-section-before-anonymous-block-3-expected.png
deleted file mode 100644
index df10010..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/split-table-section-before-anonymous-block-3-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/tbody-background-image-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/tbody-background-image-expected.png
deleted file mode 100644
index 007f4d7..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/tbody-background-image-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/tbody-background-image-repeat-x-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/tbody-background-image-repeat-x-expected.png
deleted file mode 100644
index 383c92b2..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/tbody-background-image-repeat-x-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/table/unused-percent-heights-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/table/unused-percent-heights-expected.png
deleted file mode 100644
index fc0ac13..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/table/unused-percent-heights-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/basic/007-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/basic/007-expected.png
deleted file mode 100644
index cad475db..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/basic/007-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/basic/012-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/basic/012-expected.png
deleted file mode 100644
index 40832ca..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/basic/012-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/basic/generic-family-changes-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/basic/generic-family-changes-expected.png
deleted file mode 100644
index a6a5cca..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/basic/generic-family-changes-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/capitalize-empty-generated-string-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/capitalize-empty-generated-string-expected.png
deleted file mode 100644
index 005c705..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/capitalize-empty-generated-string-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/color-emoji-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/color-emoji-expected.png
deleted file mode 100644
index 6e207549..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/color-emoji-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-in-absolute-block-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-in-absolute-block-expected.png
deleted file mode 100644
index a5d2219..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-in-absolute-block-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-in-justified-text-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-in-justified-text-expected.png
deleted file mode 100644
index 8940f6f..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-in-justified-text-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png
deleted file mode 100644
index 4884770..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-mixed-text-in-ltr-flow-underline-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-mixed-text-in-ltr-flow-underline-expected.png
deleted file mode 100644
index ff2f6d9..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-mixed-text-in-ltr-flow-underline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-mixed-text-in-rtl-flow-underline-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-mixed-text-in-rtl-flow-underline-expected.png
deleted file mode 100644
index d1d7465..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-mixed-text-in-rtl-flow-underline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-platform-font-change-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-platform-font-change-expected.png
deleted file mode 100644
index fa4f132bd..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-platform-font-change-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-with-list-marker-in-ltr-flow-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-with-list-marker-in-ltr-flow-expected.png
deleted file mode 100644
index cf3ca01..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-with-list-marker-in-ltr-flow-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-with-list-marker-in-rtl-flow-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-with-list-marker-in-rtl-flow-expected.png
deleted file mode 100644
index 7debf94..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/ellipsis-with-list-marker-in-rtl-flow-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/font-features/caps-native-synthesis-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/font-features/caps-native-synthesis-expected.png
deleted file mode 100644
index 5c5462f5..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/font-features/caps-native-synthesis-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/font-stretch-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/font-stretch-expected.png
deleted file mode 100644
index a780fd9..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/font-stretch-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/font-stretch-variant-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/font-stretch-variant-expected.png
deleted file mode 100644
index 036d214..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/font-stretch-variant-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/font-weight-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/font-weight-expected.png
deleted file mode 100644
index b74adbd3a..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/font-weight-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/alef-connected-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/international/alef-connected-expected.png
deleted file mode 100644
index 198b7f8..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/alef-connected-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-AN-after-empty-run-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-AN-after-empty-run-expected.png
deleted file mode 100644
index ac68707..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-AN-after-empty-run-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-LDB-2-CSS-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-LDB-2-CSS-expected.png
deleted file mode 100644
index fe6a0223..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-LDB-2-CSS-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-innertext-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-innertext-expected.png
deleted file mode 100644
index 3cc0525..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-innertext-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-linebreak-001-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-linebreak-001-expected.png
deleted file mode 100644
index bc1cc9dd..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-linebreak-001-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-linebreak-003-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-linebreak-003-expected.png
deleted file mode 100644
index 2db34549..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bidi-linebreak-003-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bold-bengali-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bold-bengali-expected.png
deleted file mode 100644
index 1c8a2c6..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/bold-bengali-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/danda-space-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/international/danda-space-expected.png
deleted file mode 100644
index be506a7..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/danda-space-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/shape-across-elements-expected.txt b/third_party/blink/web_tests/platform/mac-retina/fast/text/international/shape-across-elements-expected.txt
deleted file mode 100644
index 2dafceb..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/international/shape-across-elements-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-PASS Width of isolated word does match width of word with markup.
-PASS Width of partial glyph in ligature does not match width of isolated glyph.
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-Shape across element boundary test
-سلام The word by itself.
-سلام Adding a span around a character that forms a ligature. Should render the same as the above, except that half of the middle glyph should be red.
-سل‍ام Same word with a ZWJ character to disallow the ligature.
-Ù„ The letter in red, in isolation.
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/justify-ideograph-vertical-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/justify-ideograph-vertical-expected.png
deleted file mode 100644
index 6dfb14d2a..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/justify-ideograph-vertical-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/midword-break-before-surrogate-pair-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/midword-break-before-surrogate-pair-expected.png
deleted file mode 100644
index 33643c7b..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/midword-break-before-surrogate-pair-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-align-center-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-align-center-2-expected.png
deleted file mode 100644
index cdc2c26..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-align-center-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-align-left-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-align-left-2-expected.png
deleted file mode 100644
index 80abc1b8..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-align-left-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-align-right-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-align-right-2-expected.png
deleted file mode 100644
index ee66585..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-align-right-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-expected.png
deleted file mode 100644
index 6bf2802..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-mixed-ellipsis-in-inline-blocks-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-rtl-ellipsis-in-inline-blocks-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/place-rtl-ellipsis-in-inline-blocks-2-expected.png
deleted file mode 100644
index 05c8a173..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-rtl-ellipsis-in-inline-blocks-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-rtl-ellipsis-in-inline-blocks-align-center-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/place-rtl-ellipsis-in-inline-blocks-align-center-expected.png
deleted file mode 100644
index 40c17255..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-rtl-ellipsis-in-inline-blocks-align-center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-rtl-ellipsis-in-inline-blocks-align-left-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/place-rtl-ellipsis-in-inline-blocks-align-left-expected.png
deleted file mode 100644
index 40c17255..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/place-rtl-ellipsis-in-inline-blocks-align-left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/selection/selection-hard-linebreak-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/selection/selection-hard-linebreak-expected.png
deleted file mode 100644
index 348e693..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/selection/selection-hard-linebreak-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/selection/selection-rect-line-height-too-big-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/selection/selection-rect-line-height-too-big-expected.png
deleted file mode 100644
index f468f7c..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/selection/selection-rect-line-height-too-big-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/vertical-rl-rtl-linebreak-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/vertical-rl-rtl-linebreak-expected.png
deleted file mode 100644
index e452a81..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/vertical-rl-rtl-linebreak-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/wbr-in-pre-crash-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/wbr-in-pre-crash-expected.png
deleted file mode 100644
index b91531f8..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/wbr-in-pre-crash-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/whitespace/pre-wrap-last-char-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/whitespace/pre-wrap-last-char-expected.png
deleted file mode 100644
index 3918454..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/whitespace/pre-wrap-last-char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/text/whitespace/pre-wrap-line-test-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/text/whitespace/pre-wrap-line-test-expected.png
deleted file mode 100644
index 88ab579..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/text/whitespace/pre-wrap-line-test-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/border-image-vertical-lr-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/border-image-vertical-lr-expected.png
deleted file mode 100644
index f73e19e..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/border-image-vertical-lr-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png
deleted file mode 100644
index bcc3b55..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/broken-ideograph-small-caps-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/broken-ideograph-small-caps-expected.png
deleted file mode 100644
index ba0178e..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/broken-ideograph-small-caps-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/broken-ideographic-font-expected.png b/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/broken-ideographic-font-expected.png
deleted file mode 100644
index 3419f52b..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/fast/writing-mode/broken-ideographic-font-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/html/details_summary/details-marker-style-expected.png b/third_party/blink/web_tests/platform/mac-retina/html/details_summary/details-marker-style-expected.png
deleted file mode 100644
index 51c3a44..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/html/details_summary/details-marker-style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/html/details_summary/details-writing-mode-expected.png b/third_party/blink/web_tests/platform/mac-retina/html/details_summary/details-writing-mode-expected.png
deleted file mode 100644
index dc831990..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/html/details_summary/details-writing-mode-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/ietestcenter/css3/text/textshadow-003-expected.png b/third_party/blink/web_tests/platform/mac-retina/ietestcenter/css3/text/textshadow-003-expected.png
deleted file mode 100644
index 67266c8..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/ietestcenter/css3/text/textshadow-003-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/ietestcenter/css3/text/textshadow-010-expected.png b/third_party/blink/web_tests/platform/mac-retina/ietestcenter/css3/text/textshadow-010-expected.png
deleted file mode 100644
index 9525299..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/ietestcenter/css3/text/textshadow-010-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/images/exif-orientation-image-document-expected.png b/third_party/blink/web_tests/platform/mac-retina/images/exif-orientation-image-document-expected.png
deleted file mode 100644
index 1896b5c..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/images/exif-orientation-image-document-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/images/imagemap-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-retina/images/imagemap-circle-focus-ring-expected.png
deleted file mode 100644
index 60fa273..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/images/imagemap-circle-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/images/imagemap-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-retina/images/imagemap-focus-ring-expected.png
deleted file mode 100644
index dccc42a..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/images/imagemap-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png b/third_party/blink/web_tests/platform/mac-retina/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
deleted file mode 100644
index 083676cb..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/images/imagemap-overflowing-polygon-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-retina/images/imagemap-overflowing-polygon-focus-ring-expected.png
deleted file mode 100644
index 2112c62d..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/images/imagemap-overflowing-polygon-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/media/video-colorspace-yuv420-expected.png b/third_party/blink/web_tests/platform/mac-retina/media/video-colorspace-yuv420-expected.png
deleted file mode 100644
index 446604b..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/media/video-colorspace-yuv420-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/media/video-empty-source-expected.png b/third_party/blink/web_tests/platform/mac-retina/media/video-empty-source-expected.png
deleted file mode 100644
index eb8e0daf..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/media/video-empty-source-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/plugins/embed-attributes-style-expected.png b/third_party/blink/web_tests/platform/mac-retina/plugins/embed-attributes-style-expected.png
deleted file mode 100644
index 14aaa5b9..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/plugins/embed-attributes-style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/svg/custom/clone-element-with-animated-svg-properties-expected.png b/third_party/blink/web_tests/platform/mac-retina/svg/custom/clone-element-with-animated-svg-properties-expected.png
deleted file mode 100644
index 2fbd6f6..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/svg/custom/clone-element-with-animated-svg-properties-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/svg/custom/svg-fonts-in-html-expected.png b/third_party/blink/web_tests/platform/mac-retina/svg/custom/svg-fonts-in-html-expected.png
deleted file mode 100644
index 42c06bc..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/svg/custom/svg-fonts-in-html-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/svg/custom/text-match-highlight-expected.png b/third_party/blink/web_tests/platform/mac-retina/svg/custom/text-match-highlight-expected.png
deleted file mode 100644
index 0e857ef..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/svg/custom/text-match-highlight-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/svg/custom/transformed-text-pattern-expected.png b/third_party/blink/web_tests/platform/mac-retina/svg/custom/transformed-text-pattern-expected.png
deleted file mode 100644
index d239172..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/svg/custom/transformed-text-pattern-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/svg/dom/SVGLocatable-getCTM-svg-root-expected.png b/third_party/blink/web_tests/platform/mac-retina/svg/dom/SVGLocatable-getCTM-svg-root-expected.png
deleted file mode 100644
index 204e601..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/svg/dom/SVGLocatable-getCTM-svg-root-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/svg/dom/SVGStringList-basics-expected.png b/third_party/blink/web_tests/platform/mac-retina/svg/dom/SVGStringList-basics-expected.png
deleted file mode 100644
index 58d94a3..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/svg/dom/SVGStringList-basics-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/svg/hixie/rendering-model/004-expected.png b/third_party/blink/web_tests/platform/mac-retina/svg/hixie/rendering-model/004-expected.png
deleted file mode 100644
index 0ee89eec..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/svg/hixie/rendering-model/004-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/svg/wicd/test-rightsizing-a-expected.png b/third_party/blink/web_tests/platform/mac-retina/svg/wicd/test-rightsizing-a-expected.png
deleted file mode 100644
index fb648734..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/svg/wicd/test-rightsizing-a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug106158-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug106158-2-expected.png
deleted file mode 100644
index 209a813..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug106158-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug10633-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug10633-expected.png
deleted file mode 100644
index 7bddf17..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug10633-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug1188-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug1188-expected.png
deleted file mode 100644
index 34af4e1a..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug1188-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug11944-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug11944-expected.png
deleted file mode 100644
index b2b508f1..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug11944-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug1302-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug1302-expected.png
deleted file mode 100644
index 5bc84003..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug1302-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug157890-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug157890-expected.png
deleted file mode 100644
index aec57b469..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug157890-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug17130-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug17130-2-expected.png
deleted file mode 100644
index a67c6e9..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug17130-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug23235-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug23235-expected.png
deleted file mode 100644
index f286f4df9..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug23235-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2479-1-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2479-1-expected.png
deleted file mode 100644
index c0231a6..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2479-1-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2479-3-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2479-3-expected.png
deleted file mode 100644
index 10efd49f..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2479-3-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2509-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2509-expected.png
deleted file mode 100644
index 2454181..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2509-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2684-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2684-expected.png
deleted file mode 100644
index 55eda75fc..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2684-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2981-1-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2981-1-expected.png
deleted file mode 100644
index 398b1b0..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug2981-1-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug38916-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug38916-expected.png
deleted file mode 100644
index 4db8e36..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug38916-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug43039-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug43039-expected.png
deleted file mode 100644
index 64e9fe8..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug43039-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug46368-1-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug46368-1-expected.png
deleted file mode 100644
index b6202ea..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug46368-1-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug46623-1-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug46623-1-expected.png
deleted file mode 100644
index 6ba11656..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug46623-1-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug4849-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug4849-2-expected.png
deleted file mode 100644
index 4dee9989..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug4849-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug5188-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug5188-expected.png
deleted file mode 100644
index f4a2ccf..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug5188-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug55694-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug55694-expected.png
deleted file mode 100644
index 1933e80..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug55694-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug57828-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug57828-2-expected.png
deleted file mode 100644
index c1762618..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug57828-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug5838-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug5838-expected.png
deleted file mode 100644
index c234c5c0..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug5838-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug6404-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug6404-expected.png
deleted file mode 100644
index 814436c..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug6404-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug650-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug650-expected.png
deleted file mode 100644
index dc2d73d..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug650-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug69382-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug69382-2-expected.png
deleted file mode 100644
index a6111e5..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug69382-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug7112-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug7112-2-expected.png
deleted file mode 100644
index 864b5d31..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug7112-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug7342-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug7342-expected.png
deleted file mode 100644
index 221f61b..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug7342-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug80762-1-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug80762-1-expected.png
deleted file mode 100644
index 59d9439..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug80762-1-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug88035-2-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug88035-2-expected.png
deleted file mode 100644
index 9c8f4fa..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug88035-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug8950-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug8950-expected.png
deleted file mode 100644
index debe4a01..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/bugs/bug8950-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/core/col_span-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/core/col_span-expected.png
deleted file mode 100644
index da7a94d..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/core/col_span-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/body_tfoot-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/body_tfoot-expected.png
deleted file mode 100644
index df9f750..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/body_tfoot-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/body_thead-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/body_thead-expected.png
deleted file mode 100644
index e10bc6c..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/body_thead-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/col_span-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/col_span-expected.png
deleted file mode 100644
index e3a9266..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/col_span-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/colgroup_span-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/colgroup_span-expected.png
deleted file mode 100644
index f7efb55..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/colgroup_span-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/colgroup_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/colgroup_valign_baseline-expected.png
deleted file mode 100644
index ee77669..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/colgroup_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/table_row_align_center-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/table_row_align_center-expected.png
deleted file mode 100644
index c922c0c..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/table_row_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/table_rules_all-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/table_rules_all-expected.png
deleted file mode 100644
index 91e4bad..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/table_rules_all-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/table_rules_groups-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/table_rules_groups-expected.png
deleted file mode 100644
index 1b14ad1..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/table_rules_groups-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tables_cellpadding-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tables_cellpadding-expected.png
deleted file mode 100644
index 4a8994f..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tables_cellpadding-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tables_cellpadding_pct-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tables_cellpadding_pct-expected.png
deleted file mode 100644
index 7e5d88c0..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tables_cellpadding_pct-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tables_style-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tables_style-expected.png
deleted file mode 100644
index 697c025..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tables_style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_align_char-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_align_char-expected.png
deleted file mode 100644
index af5b17ee7..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_char-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_char-expected.png
deleted file mode 100644
index b62ee91..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_valign_bottom-expected.png
deleted file mode 100644
index c9ffe04..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_valign_middle-expected.png
deleted file mode 100644
index 9df4c980..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tbody_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/td_valign_top-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/td_valign_top-expected.png
deleted file mode 100644
index 2edd7a2..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/td_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tfoot_char-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tfoot_char-expected.png
deleted file mode 100644
index ee40fa51..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tfoot_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tfoot_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tfoot_valign_baseline-expected.png
deleted file mode 100644
index c659acc..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tfoot_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tfoot_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tfoot_valign_bottom-expected.png
deleted file mode 100644
index ec76811..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tfoot_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_align_char-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_align_char-expected.png
deleted file mode 100644
index da9bda8..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_valign_baseline-expected.png
deleted file mode 100644
index 736115e..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_valign_bottom-expected.png
deleted file mode 100644
index 75fa7b3..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_valign_middle-expected.png
deleted file mode 100644
index f942774..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/thead_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tr_bgcolor_white-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tr_bgcolor_white-expected.png
deleted file mode 100644
index de9cb892..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tr_bgcolor_white-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tr_bgcolor_white_rgb-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tr_bgcolor_white_rgb-expected.png
deleted file mode 100644
index de9cb892..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/tr_bgcolor_white_rgb-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_col_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_col_valign_middle-expected.png
deleted file mode 100644
index 0294e57..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_col_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png
deleted file mode 100644
index addca44..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png
deleted file mode 100644
index 96fa500c..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_table_border-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_table_border-expected.png
deleted file mode 100644
index 4ab6f9c..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_table_border-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_table_style-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_table_style-expected.png
deleted file mode 100644
index ac41cb49..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_table_style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tbody_align_char-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tbody_align_char-expected.png
deleted file mode 100644
index 0020a05..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tbody_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png
deleted file mode 100644
index c9204ed..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tbody_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tbody_valign_middle-expected.png
deleted file mode 100644
index cce6a17..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tbody_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_td_align_center-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_td_align_center-expected.png
deleted file mode 100644
index 2088fc9f..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_td_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_td_valign_top-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_td_valign_top-expected.png
deleted file mode 100644
index cfe4af8..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_td_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tfoot_align_char-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tfoot_align_char-expected.png
deleted file mode 100644
index 2407d1f..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tfoot_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tfoot_style-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tfoot_style-expected.png
deleted file mode 100644
index b111410..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tfoot_style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png
deleted file mode 100644
index 6be8bde3..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_th_width-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_th_width-expected.png
deleted file mode 100644
index 3a68794..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/marvin/x_th_width-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/other/test6-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/other/test6-expected.png
deleted file mode 100644
index acc5886..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla/other/test6-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug10140-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug10140-expected.png
deleted file mode 100644
index dff3b0c..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug10140-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug1725-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug1725-expected.png
deleted file mode 100644
index 6d70945..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug1725-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug17826-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug17826-expected.png
deleted file mode 100644
index 47fa3b9a..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug17826-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug72393-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug72393-expected.png
deleted file mode 100644
index 5e259c1d..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug72393-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug89315-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug89315-expected.png
deleted file mode 100644
index e5366d18..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug89315-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug91057-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug91057-expected.png
deleted file mode 100644
index d24daab..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/bugs/bug91057-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
deleted file mode 100644
index c578d26..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/marvin/x_colgroup_width_px-expected.png b/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/marvin/x_colgroup_width_px-expected.png
deleted file mode 100644
index 7bfe605..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/tables/mozilla_expected_failures/marvin/x_colgroup_width_px-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/transforms/3d/general/perspective-units-expected.png b/third_party/blink/web_tests/platform/mac-retina/transforms/3d/general/perspective-units-expected.png
deleted file mode 100644
index 2f230e2..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/transforms/3d/general/perspective-units-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/transforms/diamond-expected.png b/third_party/blink/web_tests/platform/mac-retina/transforms/diamond-expected.png
deleted file mode 100644
index fa0eed7..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/transforms/diamond-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/exotic-color-space/images/exif-orientation-css-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/exotic-color-space/images/exif-orientation-css-expected.png
deleted file mode 100644
index 33e5432..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/exotic-color-space/images/exif-orientation-css-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
deleted file mode 100644
index af3c555..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/exif-orientation-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/exif-orientation-expected.png
deleted file mode 100644
index b770984..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/exif-orientation-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/image-map-anchor-children-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/image-map-anchor-children-expected.png
deleted file mode 100644
index 6ebf40b..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/image-map-anchor-children-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
deleted file mode 100644
index bcb4d80..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
deleted file mode 100644
index 749db52..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png
deleted file mode 100644
index 3255bc2..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt b/third_party/blink/web_tests/platform/mac-retina/virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt
deleted file mode 100644
index b1de4e47..0000000
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This tests verifies the hit test regions given to the compositor specifically for continuation case. It can only be run in DumpRenderTree.
-
-continuation: layer(800x600) has hit test rect (13,90 290x12)
-
-
diff --git a/third_party/blink/web_tests/platform/mac/css2.1/t040302-c61-phys-len-00-b-expected.png b/third_party/blink/web_tests/platform/mac/css2.1/t040302-c61-phys-len-00-b-expected.png
index 58cb015..3be5493 100644
--- a/third_party/blink/web_tests/platform/mac/css2.1/t040302-c61-phys-len-00-b-expected.png
+++ b/third_party/blink/web_tests/platform/mac/css2.1/t040302-c61-phys-len-00-b-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css2.1/t0805-c5522-brdr-02-e-expected.png b/third_party/blink/web_tests/platform/mac/css2.1/t0805-c5522-brdr-02-e-expected.png
index 33909e8..1ceacb8 100644
--- a/third_party/blink/web_tests/platform/mac/css2.1/t0805-c5522-brdr-02-e-expected.png
+++ b/third_party/blink/web_tests/platform/mac/css2.1/t0805-c5522-brdr-02-e-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css2.1/t1202-counter-08-b-expected.png b/third_party/blink/web_tests/platform/mac/css2.1/t1202-counter-08-b-expected.png
index 719ecc1..ad81f6b 100644
--- a/third_party/blink/web_tests/platform/mac/css2.1/t1202-counter-08-b-expected.png
+++ b/third_party/blink/web_tests/platform/mac/css2.1/t1202-counter-08-b-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css2.1/t1205-c561-list-displ-00-b-expected.png b/third_party/blink/web_tests/platform/mac/css2.1/t1205-c561-list-displ-00-b-expected.png
index 1f81c01..6e5ac82 100644
--- a/third_party/blink/web_tests/platform/mac/css2.1/t1205-c561-list-displ-00-b-expected.png
+++ b/third_party/blink/web_tests/platform/mac/css2.1/t1205-c561-list-displ-00-b-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-80-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-80-expected.png
index f35e115..9b1940d 100644
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-80-expected.png
+++ b/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-80-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/editing/selection/5232159-expected.png b/third_party/blink/web_tests/platform/mac/editing/selection/5232159-expected.png
index 846701e..d399e13 100644
--- a/third_party/blink/web_tests/platform/mac/editing/selection/5232159-expected.png
+++ b/third_party/blink/web_tests/platform/mac/editing/selection/5232159-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/basic-inputs-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/basic-inputs-expected.png
index 6a9ceed..ea54276 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/basic-inputs-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/basic-inputs-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/button/button-inner-block-reuse-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/button/button-inner-block-reuse-expected.png
index 41d31b5..dfd9bcf 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/button/button-inner-block-reuse-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/button/button-inner-block-reuse-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/formmove2-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/formmove2-expected.png
index 6ef55c80..a936e77 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/formmove2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/formmove2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/indeterminate-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/indeterminate-expected.png
index fff01fe..12f91d7 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/indeterminate-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/indeterminate-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/input-appearance-height-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/input-appearance-height-expected.png
index 00abdc1e..223d745 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/input-appearance-height-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/input-appearance-height-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/search/search-vertical-alignment-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/search/search-vertical-alignment-expected.png
index 4e5ae601..da608b7 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/search/search-vertical-alignment-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/search/search-vertical-alignment-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/select/option-script-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/select/option-script-expected.png
index 1bf39cd..b93343a 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/select/option-script-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/select/option-script-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/select/select-align-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/select/select-align-expected.png
index b90757c..e51e07f2 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/select/select-align-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/select/select-align-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/select/select-disabled-appearance-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/select/select-disabled-appearance-expected.png
index 57536631f..6649cd4 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/select/select-disabled-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/select/select-disabled-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/date-suggestion-picker-appearance-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/date-suggestion-picker-appearance-expected.png
index 215ec4e..94726c9 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/date-suggestion-picker-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/date-suggestion-picker-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-locale-hebrew-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-locale-hebrew-expected.png
index 3bcb216d..f3fdedf 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-locale-hebrew-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-locale-hebrew-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-rtl-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-rtl-expected.png
index e1d0139f..c5914edf 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-rtl-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar-expected.png
index 3f00b55..d253243 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew-expected.png
index 6c77b466..96969c5 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/targeted-frame-submission-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/targeted-frame-submission-expected.png
index b4bab71..30dd729 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/targeted-frame-submission-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/targeted-frame-submission-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/text/textfield-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/text/textfield-focus-ring-expected.png
index d376441..f484194c 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/text/textfield-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/text/textfield-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-quirks-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-quirks-expected.png
index 9e71085..6ac95d9 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-quirks-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/textarea/basic-textareas-quirks-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
index 979a887..73b0131 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/inline-block/baseline-vertical-expected.png b/third_party/blink/web_tests/platform/mac/fast/inline-block/baseline-vertical-expected.png
index 9057fdd..8ad87dd 100644
--- a/third_party/blink/web_tests/platform/mac/fast/inline-block/baseline-vertical-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/inline-block/baseline-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/inline/002-expected.png b/third_party/blink/web_tests/platform/mac/fast/inline/002-expected.png
index 24567c5..c1173c0 100644
--- a/third_party/blink/web_tests/platform/mac/fast/inline/002-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/inline/002-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/inline/br-text-decoration-expected.png b/third_party/blink/web_tests/platform/mac/fast/inline/br-text-decoration-expected.png
index 5989a9cf..6ce6468 100644
--- a/third_party/blink/web_tests/platform/mac/fast/inline/br-text-decoration-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/inline/br-text-decoration-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/inline/inline-box-background-long-image-expected.png b/third_party/blink/web_tests/platform/mac/fast/inline/inline-box-background-long-image-expected.png
index 193ba86..37e32737 100644
--- a/third_party/blink/web_tests/platform/mac/fast/inline/inline-box-background-long-image-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/inline/inline-box-background-long-image-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/invalid/010-expected.png b/third_party/blink/web_tests/platform/mac/fast/invalid/010-expected.png
index e2fa3f2..1ea758b 100644
--- a/third_party/blink/web_tests/platform/mac/fast/invalid/010-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/invalid/010-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/invalid/021-expected.png b/third_party/blink/web_tests/platform/mac/fast/invalid/021-expected.png
index e18a9f0..f56c9a5 100644
--- a/third_party/blink/web_tests/platform/mac/fast/invalid/021-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/invalid/021-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/invalid/missing-dt-end-tag-expected.png b/third_party/blink/web_tests/platform/mac/fast/invalid/missing-dt-end-tag-expected.png
index 53b2823..ac99d44 100644
--- a/third_party/blink/web_tests/platform/mac/fast/invalid/missing-dt-end-tag-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/invalid/missing-dt-end-tag-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/invalid/nestedh3s-expected.png b/third_party/blink/web_tests/platform/mac/fast/invalid/nestedh3s-expected.png
index 5d93fc8..9319f7e 100644
--- a/third_party/blink/web_tests/platform/mac/fast/invalid/nestedh3s-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/invalid/nestedh3s-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/lists/003-expected.png b/third_party/blink/web_tests/platform/mac/fast/lists/003-expected.png
index 8810d56..d84cd1734 100644
--- a/third_party/blink/web_tests/platform/mac/fast/lists/003-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/lists/003-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/lists/003-vertical-expected.png b/third_party/blink/web_tests/platform/mac/fast/lists/003-vertical-expected.png
index a2628a0..2f957c0 100644
--- a/third_party/blink/web_tests/platform/mac/fast/lists/003-vertical-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/lists/003-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/lists/007-expected.png b/third_party/blink/web_tests/platform/mac/fast/lists/007-expected.png
index 4e729bdba..96525963 100644
--- a/third_party/blink/web_tests/platform/mac/fast/lists/007-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/lists/007-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/lists/007-vertical-expected.png b/third_party/blink/web_tests/platform/mac/fast/lists/007-vertical-expected.png
index 63a9350c..88541de 100644
--- a/third_party/blink/web_tests/platform/mac/fast/lists/007-vertical-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/lists/007-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/multicol/composited-inner-multicol-expected.png b/third_party/blink/web_tests/platform/mac/fast/multicol/composited-inner-multicol-expected.png
index b94f6c0..08346e2 100644
--- a/third_party/blink/web_tests/platform/mac/fast/multicol/composited-inner-multicol-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/multicol/composited-inner-multicol-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/multicol/composited-layer-multiple-fragments-translated-expected.png b/third_party/blink/web_tests/platform/mac/fast/multicol/composited-layer-multiple-fragments-translated-expected.png
index 3eb4aec..3ad6d33 100644
--- a/third_party/blink/web_tests/platform/mac/fast/multicol/composited-layer-multiple-fragments-translated-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/multicol/composited-layer-multiple-fragments-translated-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-auto-table-expected.png b/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-auto-table-expected.png
index f850436..9b92181 100644
--- a/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-auto-table-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-auto-table-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/overflow/table-overflow-float-expected.png b/third_party/blink/web_tests/platform/mac/fast/overflow/table-overflow-float-expected.png
index 59e9cb9..125d2fbf 100644
--- a/third_party/blink/web_tests/platform/mac/fast/overflow/table-overflow-float-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/overflow/table-overflow-float-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/parser/fonts-expected.png b/third_party/blink/web_tests/platform/mac/fast/parser/fonts-expected.png
index 2589be8..d3f04a50 100644
--- a/third_party/blink/web_tests/platform/mac/fast/parser/fonts-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/parser/fonts-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/parser/xhtml-alternate-entities-expected.png b/third_party/blink/web_tests/platform/mac/fast/parser/xhtml-alternate-entities-expected.png
index 3bec77b..06638e2 100644
--- a/third_party/blink/web_tests/platform/mac/fast/parser/xhtml-alternate-entities-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/parser/xhtml-alternate-entities-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/replaced/max-width-percent-expected.png b/third_party/blink/web_tests/platform/mac/fast/replaced/max-width-percent-expected.png
index e80857e..a489c39ab 100644
--- a/third_party/blink/web_tests/platform/mac/fast/replaced/max-width-percent-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/replaced/max-width-percent-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/replaced/selection-rect-transform-expected.png b/third_party/blink/web_tests/platform/mac/fast/replaced/selection-rect-transform-expected.png
index 537ad07..46fb3ae 100644
--- a/third_party/blink/web_tests/platform/mac/fast/replaced/selection-rect-transform-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/replaced/selection-rect-transform-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/selectors/020-expected.png b/third_party/blink/web_tests/platform/mac/fast/selectors/020-expected.png
index 13a1db3..2b8682d 100644
--- a/third_party/blink/web_tests/platform/mac/fast/selectors/020-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/selectors/020-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/selectors/040-expected.png b/third_party/blink/web_tests/platform/mac/fast/selectors/040-expected.png
index b810e5f..997257f 100644
--- a/third_party/blink/web_tests/platform/mac/fast/selectors/040-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/selectors/040-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/selectors/042-expected.png b/third_party/blink/web_tests/platform/mac/fast/selectors/042-expected.png
index 38a23fd..fb9a8aa 100644
--- a/third_party/blink/web_tests/platform/mac/fast/selectors/042-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/selectors/042-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/selectors/066-expected.png b/third_party/blink/web_tests/platform/mac/fast/selectors/066-expected.png
index 5a984ec0..7cc7061b 100644
--- a/third_party/blink/web_tests/platform/mac/fast/selectors/066-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/selectors/066-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/selectors/078b-expected.png b/third_party/blink/web_tests/platform/mac/fast/selectors/078b-expected.png
index 65b339a9..2509fba8 100644
--- a/third_party/blink/web_tests/platform/mac/fast/selectors/078b-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/selectors/078b-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/selectors/lang-inheritance-expected.png b/third_party/blink/web_tests/platform/mac/fast/selectors/lang-inheritance-expected.png
index c329a3f0..e78ec7ac 100644
--- a/third_party/blink/web_tests/platform/mac/fast/selectors/lang-inheritance-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/selectors/lang-inheritance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/selectors/lang-vs-xml-lang-expected.png b/third_party/blink/web_tests/platform/mac/fast/selectors/lang-vs-xml-lang-expected.png
index fa662d8d..a2f5a11 100644
--- a/third_party/blink/web_tests/platform/mac/fast/selectors/lang-vs-xml-lang-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/selectors/lang-vs-xml-lang-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/040-vertical-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/040-vertical-expected.png
index 11f8aac..b0a85d0 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/040-vertical-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/040-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/100-percent-cell-width-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/100-percent-cell-width-expected.png
index a9a9bb3..d89ea08 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/100-percent-cell-width-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/100-percent-cell-width-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-cell-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-cell-collapsed-border-expected.png
index 1dfd1e86..6c713c3 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-cell-collapsed-border-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-cell-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-cell-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-cell-expected.png
index 467db5f..a0ef5ca 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-cell-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-cell-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-collapsed-border-expected.png
index c2163f2..5d4ebb6 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-collapsed-border-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-expected.png
index 2435c73..5946468 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-group-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-group-collapsed-border-expected.png
index 42780cb..9ca7d68 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-group-collapsed-border-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_border-table-column-group-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_fixed-bg-table-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_fixed-bg-table-expected.png
index bfbf6d0..a1a5d7a 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_fixed-bg-table-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_fixed-bg-table-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_layers-show-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_layers-show-collapsed-border-expected.png
index 3f60086..873bd40a 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_layers-show-collapsed-border-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_layers-show-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_layers-show-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_layers-show-expected.png
index a9d97a4..69a6d521 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_layers-show-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_layers-show-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_position-table-row-group-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_position-table-row-group-collapsed-border-expected.png
index ecfb3af..bbdccdb4 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_position-table-row-group-collapsed-border-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_position-table-row-group-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_position-table-row-group-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_position-table-row-group-expected.png
index 332068d..f36219f 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_position-table-row-group-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_position-table-row-group-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-cell-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-cell-expected.png
index 4b22116..288d4eb4 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-cell-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-cell-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-collapsed-border-expected.png
index 52129c5..1324799 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-collapsed-border-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-column-collapsed-border-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-column-collapsed-border-expected.png
index 02e62ca..f5cac25 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-column-collapsed-border-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-column-collapsed-border-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-expected.png
index 0be3122..402614c 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/backgr_simple-table-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/form-with-table-style-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/form-with-table-style-expected.png
index 6f417df..da5d2024 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/form-with-table-style-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/form-with-table-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/insert-row-before-form-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/insert-row-before-form-expected.png
index 5f1361c..ebfbf44 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/insert-row-before-form-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/insert-row-before-form-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/prepend-in-anonymous-table-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/prepend-in-anonymous-table-expected.png
index cf6b374a..a0caf48 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/prepend-in-anonymous-table-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/prepend-in-anonymous-table-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/rowspan-paint-order-vertical-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/rowspan-paint-order-vertical-expected.png
index 089eea52..6c87a0e2 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/rowspan-paint-order-vertical-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/rowspan-paint-order-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/split-table-section-before-anonymous-block-3-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/split-table-section-before-anonymous-block-3-expected.png
index c56e220..df10010 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/split-table-section-before-anonymous-block-3-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/split-table-section-before-anonymous-block-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/tbody-background-image-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/tbody-background-image-expected.png
index ab1318c..007f4d7 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/tbody-background-image-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/tbody-background-image-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/tbody-background-image-repeat-x-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/tbody-background-image-repeat-x-expected.png
index 476cc880..383c92b2 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/tbody-background-image-repeat-x-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/tbody-background-image-repeat-x-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/table/unused-percent-heights-expected.png b/third_party/blink/web_tests/platform/mac/fast/table/unused-percent-heights-expected.png
index a639af6..fc0ac13 100644
--- a/third_party/blink/web_tests/platform/mac/fast/table/unused-percent-heights-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/table/unused-percent-heights-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/basic/007-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/basic/007-expected.png
index cced7cf..cad475db 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/basic/007-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/basic/007-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/basic/012-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/basic/012-expected.png
index 3b82a8e..40832ca 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/basic/012-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/basic/012-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/basic/generic-family-changes-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/basic/generic-family-changes-expected.png
index a0c8809..a6a5cca 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/basic/generic-family-changes-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/basic/generic-family-changes-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/capitalize-empty-generated-string-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/capitalize-empty-generated-string-expected.png
index 72592e6..005c705 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/capitalize-empty-generated-string-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/capitalize-empty-generated-string-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/color-emoji-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/color-emoji-expected.png
index 0c2179c..6e207549 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/color-emoji-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/color-emoji-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-in-absolute-block-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-in-absolute-block-expected.png
index 3bc73d6a..a5d2219 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-in-absolute-block-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-in-absolute-block-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-in-justified-text-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-in-justified-text-expected.png
index e4b7f1d..8940f6f 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-in-justified-text-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-in-justified-text-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png
index 21afad0..4884770 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-mixed-text-in-ltr-flow-underline-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-mixed-text-in-ltr-flow-underline-expected.png
index 9e94215e..ff2f6d9 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-mixed-text-in-ltr-flow-underline-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-mixed-text-in-ltr-flow-underline-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-mixed-text-in-rtl-flow-underline-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-mixed-text-in-rtl-flow-underline-expected.png
index d51f313..d1d7465 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-mixed-text-in-rtl-flow-underline-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-mixed-text-in-rtl-flow-underline-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-platform-font-change-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-platform-font-change-expected.png
index a034819..fa4f132bd 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-platform-font-change-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-platform-font-change-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-with-list-marker-in-ltr-flow-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-with-list-marker-in-ltr-flow-expected.png
index cc4d83ff..cf3ca01 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-with-list-marker-in-ltr-flow-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-with-list-marker-in-ltr-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-with-list-marker-in-rtl-flow-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-with-list-marker-in-rtl-flow-expected.png
index 0e03b3d..7debf94 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-with-list-marker-in-rtl-flow-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/ellipsis-with-list-marker-in-rtl-flow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/font-features/caps-native-synthesis-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/font-features/caps-native-synthesis-expected.png
index 6e411d6..5c5462f5 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/font-features/caps-native-synthesis-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/font-features/caps-native-synthesis-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/font-stretch-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/font-stretch-expected.png
index 8889ab7f..a780fd9 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/font-stretch-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/font-stretch-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/font-stretch-variant-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/font-stretch-variant-expected.png
index 1a0996b..036d214 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/font-stretch-variant-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/font-stretch-variant-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/font-weight-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/font-weight-expected.png
index 62227cc..b74adbd3a 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/font-weight-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/font-weight-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/international/alef-connected-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/international/alef-connected-expected.png
index c82ad53..198b7f8 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/international/alef-connected-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/international/alef-connected-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-AN-after-empty-run-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-AN-after-empty-run-expected.png
index 1462d7f..ac68707 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-AN-after-empty-run-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-AN-after-empty-run-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-LDB-2-CSS-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-LDB-2-CSS-expected.png
index 72d6562..fe6a0223 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-LDB-2-CSS-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-LDB-2-CSS-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-innertext-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-innertext-expected.png
index 4bd5a016..3cc0525 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-innertext-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-innertext-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-linebreak-001-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-linebreak-001-expected.png
index 5801155..bc1cc9dd 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-linebreak-001-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-linebreak-001-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-linebreak-003-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-linebreak-003-expected.png
index ee62d7f..2db34549 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-linebreak-003-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/international/bidi-linebreak-003-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/international/bold-bengali-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/international/bold-bengali-expected.png
index 0959283..1c8a2c6 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/international/bold-bengali-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/international/bold-bengali-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/international/danda-space-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/international/danda-space-expected.png
index cb26096..be506a7 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/international/danda-space-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/international/danda-space-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/justify-ideograph-vertical-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/justify-ideograph-vertical-expected.png
index 719ccf9..6dfb14d2a 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/justify-ideograph-vertical-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/justify-ideograph-vertical-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/midword-break-before-surrogate-pair-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/midword-break-before-surrogate-pair-expected.png
index c6b85f3f..33643c7b 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/midword-break-before-surrogate-pair-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/midword-break-before-surrogate-pair-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-center-2-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-center-2-expected.png
index aa37fae1..cdc2c26 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-center-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-center-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-left-2-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-left-2-expected.png
index ee309444..80abc1b8 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-left-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-left-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-right-2-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-right-2-expected.png
index c9082b2..ee66585 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-right-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-align-right-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-expected.png
index b62a4f007..6bf2802 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/place-mixed-ellipsis-in-inline-blocks-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-2-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-2-expected.png
index f25b5974..05c8a173 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-align-center-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-align-center-expected.png
index 7864168..40c17255 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-align-center-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-align-center-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-align-left-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-align-left-expected.png
index 7864168..40c17255 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-align-left-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/place-rtl-ellipsis-in-inline-blocks-align-left-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/selection/selection-hard-linebreak-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/selection/selection-hard-linebreak-expected.png
index 08daed4..348e693 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/selection/selection-hard-linebreak-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/selection/selection-hard-linebreak-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/selection/selection-rect-line-height-too-big-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/selection/selection-rect-line-height-too-big-expected.png
index 46d76d0..f468f7c 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/selection/selection-rect-line-height-too-big-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/selection/selection-rect-line-height-too-big-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/vertical-rl-rtl-linebreak-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/vertical-rl-rtl-linebreak-expected.png
index 0a93c2bd..e452a81 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/vertical-rl-rtl-linebreak-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/vertical-rl-rtl-linebreak-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/wbr-in-pre-crash-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/wbr-in-pre-crash-expected.png
index 92aa374..b91531f8 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/wbr-in-pre-crash-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/wbr-in-pre-crash-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/whitespace/pre-wrap-last-char-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/whitespace/pre-wrap-last-char-expected.png
index 896f487..3918454 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/whitespace/pre-wrap-last-char-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/whitespace/pre-wrap-last-char-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/whitespace/pre-wrap-line-test-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/whitespace/pre-wrap-line-test-expected.png
index 02a8af0..88ab579 100644
--- a/third_party/blink/web_tests/platform/mac/fast/text/whitespace/pre-wrap-line-test-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/text/whitespace/pre-wrap-line-test-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/writing-mode/border-image-vertical-lr-expected.png b/third_party/blink/web_tests/platform/mac/fast/writing-mode/border-image-vertical-lr-expected.png
index f67cf93..f73e19e 100644
--- a/third_party/blink/web_tests/platform/mac/fast/writing-mode/border-image-vertical-lr-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/writing-mode/border-image-vertical-lr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png b/third_party/blink/web_tests/platform/mac/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png
index ba589b6..bcc3b55 100644
--- a/third_party/blink/web_tests/platform/mac/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/writing-mode/border-radius-clipping-vertical-lr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/writing-mode/broken-ideograph-small-caps-expected.png b/third_party/blink/web_tests/platform/mac/fast/writing-mode/broken-ideograph-small-caps-expected.png
index d33ee6f..ba0178e 100644
--- a/third_party/blink/web_tests/platform/mac/fast/writing-mode/broken-ideograph-small-caps-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/writing-mode/broken-ideograph-small-caps-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/writing-mode/broken-ideographic-font-expected.png b/third_party/blink/web_tests/platform/mac/fast/writing-mode/broken-ideographic-font-expected.png
index 1bba1ad..3419f52b 100644
--- a/third_party/blink/web_tests/platform/mac/fast/writing-mode/broken-ideographic-font-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/writing-mode/broken-ideographic-font-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/html/details_summary/details-marker-style-expected.png b/third_party/blink/web_tests/platform/mac/html/details_summary/details-marker-style-expected.png
index 9e6373f..51c3a44 100644
--- a/third_party/blink/web_tests/platform/mac/html/details_summary/details-marker-style-expected.png
+++ b/third_party/blink/web_tests/platform/mac/html/details_summary/details-marker-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/html/details_summary/details-writing-mode-expected.png b/third_party/blink/web_tests/platform/mac/html/details_summary/details-writing-mode-expected.png
index 6a27a29..dc831990 100644
--- a/third_party/blink/web_tests/platform/mac/html/details_summary/details-writing-mode-expected.png
+++ b/third_party/blink/web_tests/platform/mac/html/details_summary/details-writing-mode-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/ietestcenter/css3/text/textshadow-003-expected.png b/third_party/blink/web_tests/platform/mac/ietestcenter/css3/text/textshadow-003-expected.png
index 95c5986..67266c8 100644
--- a/third_party/blink/web_tests/platform/mac/ietestcenter/css3/text/textshadow-003-expected.png
+++ b/third_party/blink/web_tests/platform/mac/ietestcenter/css3/text/textshadow-003-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/ietestcenter/css3/text/textshadow-010-expected.png b/third_party/blink/web_tests/platform/mac/ietestcenter/css3/text/textshadow-010-expected.png
index bc37cc1..9525299 100644
--- a/third_party/blink/web_tests/platform/mac/ietestcenter/css3/text/textshadow-010-expected.png
+++ b/third_party/blink/web_tests/platform/mac/ietestcenter/css3/text/textshadow-010-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/exif-orientation-image-document-expected.png b/third_party/blink/web_tests/platform/mac/images/exif-orientation-image-document-expected.png
index d5449e79..1896b5c 100644
--- a/third_party/blink/web_tests/platform/mac/images/exif-orientation-image-document-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/exif-orientation-image-document-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/imagemap-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/images/imagemap-circle-focus-ring-expected.png
index 0c56e8c..60fa273 100644
--- a/third_party/blink/web_tests/platform/mac/images/imagemap-circle-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/imagemap-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/imagemap-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/images/imagemap-focus-ring-expected.png
index 3350e4a..dccc42a 100644
--- a/third_party/blink/web_tests/platform/mac/images/imagemap-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/imagemap-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png b/third_party/blink/web_tests/platform/mac/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
index 2f971df..083676cb 100644
--- a/third_party/blink/web_tests/platform/mac/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/imagemap-focus-ring-outline-color-explicitly-inherited-from-map-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/imagemap-overflowing-polygon-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/images/imagemap-overflowing-polygon-focus-ring-expected.png
index a0f1d64..2112c62d 100644
--- a/third_party/blink/web_tests/platform/mac/images/imagemap-overflowing-polygon-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/images/imagemap-overflowing-polygon-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/video-colorspace-yuv420-expected.png b/third_party/blink/web_tests/platform/mac/media/video-colorspace-yuv420-expected.png
index 74870070..446604b 100644
--- a/third_party/blink/web_tests/platform/mac/media/video-colorspace-yuv420-expected.png
+++ b/third_party/blink/web_tests/platform/mac/media/video-colorspace-yuv420-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/media/video-empty-source-expected.png b/third_party/blink/web_tests/platform/mac/media/video-empty-source-expected.png
index fc52f341..eb8e0daf 100644
--- a/third_party/blink/web_tests/platform/mac/media/video-empty-source-expected.png
+++ b/third_party/blink/web_tests/platform/mac/media/video-empty-source-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/plugins/embed-attributes-style-expected.png b/third_party/blink/web_tests/platform/mac/plugins/embed-attributes-style-expected.png
index 247f0448..14aaa5b9 100644
--- a/third_party/blink/web_tests/platform/mac/plugins/embed-attributes-style-expected.png
+++ b/third_party/blink/web_tests/platform/mac/plugins/embed-attributes-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/custom/clone-element-with-animated-svg-properties-expected.png b/third_party/blink/web_tests/platform/mac/svg/custom/clone-element-with-animated-svg-properties-expected.png
index 600a59437..2fbd6f6 100644
--- a/third_party/blink/web_tests/platform/mac/svg/custom/clone-element-with-animated-svg-properties-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/custom/clone-element-with-animated-svg-properties-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/custom/svg-fonts-in-html-expected.png b/third_party/blink/web_tests/platform/mac/svg/custom/svg-fonts-in-html-expected.png
index 217243d..42c06bc 100644
--- a/third_party/blink/web_tests/platform/mac/svg/custom/svg-fonts-in-html-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/custom/svg-fonts-in-html-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/custom/text-match-highlight-expected.png b/third_party/blink/web_tests/platform/mac/svg/custom/text-match-highlight-expected.png
index 0a321c3..0e857ef 100644
--- a/third_party/blink/web_tests/platform/mac/svg/custom/text-match-highlight-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/custom/text-match-highlight-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/custom/transformed-text-pattern-expected.png b/third_party/blink/web_tests/platform/mac/svg/custom/transformed-text-pattern-expected.png
index 4436f172..d239172 100644
--- a/third_party/blink/web_tests/platform/mac/svg/custom/transformed-text-pattern-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/custom/transformed-text-pattern-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/dom/SVGLocatable-getCTM-svg-root-expected.png b/third_party/blink/web_tests/platform/mac/svg/dom/SVGLocatable-getCTM-svg-root-expected.png
index c66ceb5..204e601 100644
--- a/third_party/blink/web_tests/platform/mac/svg/dom/SVGLocatable-getCTM-svg-root-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/dom/SVGLocatable-getCTM-svg-root-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/dom/SVGStringList-basics-expected.png b/third_party/blink/web_tests/platform/mac/svg/dom/SVGStringList-basics-expected.png
index 46bb6d9..58d94a3 100644
--- a/third_party/blink/web_tests/platform/mac/svg/dom/SVGStringList-basics-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/dom/SVGStringList-basics-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/hixie/rendering-model/004-expected.png b/third_party/blink/web_tests/platform/mac/svg/hixie/rendering-model/004-expected.png
index 8c3a70f..0ee89eec 100644
--- a/third_party/blink/web_tests/platform/mac/svg/hixie/rendering-model/004-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/hixie/rendering-model/004-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/wicd/test-rightsizing-a-expected.png b/third_party/blink/web_tests/platform/mac/svg/wicd/test-rightsizing-a-expected.png
index 0be7084..fb648734 100644
--- a/third_party/blink/web_tests/platform/mac/svg/wicd/test-rightsizing-a-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/wicd/test-rightsizing-a-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug106158-2-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug106158-2-expected.png
index be6aeb3..209a813 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug106158-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug106158-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug10633-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug10633-expected.png
index b958283..7bddf17 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug10633-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug10633-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug1188-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug1188-expected.png
index 9a67ed3..34af4e1a 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug1188-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug1188-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug11944-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug11944-expected.png
index c23bfb4..b2b508f1 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug11944-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug11944-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug1302-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug1302-expected.png
index 63ba50d4..5bc84003 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug1302-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug1302-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug157890-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug157890-expected.png
index f2bbdcd..aec57b469 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug157890-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug157890-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug17130-2-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug17130-2-expected.png
index f48f3c7..a67c6e9 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug17130-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug17130-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug23235-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug23235-expected.png
index fc21778..f286f4df9 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug23235-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug23235-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2479-1-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2479-1-expected.png
index fc82820..c0231a6 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2479-1-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2479-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2479-3-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2479-3-expected.png
index 8f36b9e..10efd49f 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2479-3-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2479-3-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2509-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2509-expected.png
index b66e3025..2454181 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2509-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2509-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2684-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2684-expected.png
index 8648a51b..55eda75fc 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2684-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2684-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2981-1-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2981-1-expected.png
index a7fde5c..398b1b0 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2981-1-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug2981-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug38916-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug38916-expected.png
index 7ee5faa1..4db8e36 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug38916-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug38916-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug43039-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug43039-expected.png
index 3abd045..64e9fe8 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug43039-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug43039-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug46368-1-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug46368-1-expected.png
index 21a87cf..b6202ea 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug46368-1-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug46368-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug46623-1-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug46623-1-expected.png
index 60fae8cf..6ba11656 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug46623-1-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug46623-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug4849-2-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug4849-2-expected.png
index 171632a..4dee9989 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug4849-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug4849-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug5188-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug5188-expected.png
index 94424c4..f4a2ccf 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug5188-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug5188-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug55694-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug55694-expected.png
index 2e94052..1933e80 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug55694-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug55694-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug57828-2-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug57828-2-expected.png
index a7c58ee..c1762618 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug57828-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug57828-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug5838-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug5838-expected.png
index b4e6987..c234c5c0 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug5838-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug5838-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug6404-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug6404-expected.png
index a9cb6da..814436c 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug6404-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug6404-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug650-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug650-expected.png
index 1f5d095c..dc2d73d 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug650-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug650-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug69382-2-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug69382-2-expected.png
index 6bd1d53..a6111e5 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug69382-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug69382-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug7112-2-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug7112-2-expected.png
index b826ce3b..864b5d31 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug7112-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug7112-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug7342-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug7342-expected.png
index c182368..221f61b 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug7342-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug7342-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug80762-1-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug80762-1-expected.png
index 795245c..59d9439 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug80762-1-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug80762-1-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug88035-2-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug88035-2-expected.png
index 1641eb0c..9c8f4fa 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug88035-2-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug88035-2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug8950-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug8950-expected.png
index 0791d75..debe4a01 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug8950-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/bugs/bug8950-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/core/col_span-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/core/col_span-expected.png
index cc91ed41..da7a94d 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/core/col_span-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/core/col_span-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/body_tfoot-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/body_tfoot-expected.png
index 4015279..df9f750 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/body_tfoot-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/body_tfoot-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/body_thead-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/body_thead-expected.png
index 42b7dc0..e10bc6c 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/body_thead-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/body_thead-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/col_span-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/col_span-expected.png
index c470566b..e3a9266 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/col_span-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/col_span-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/colgroup_span-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/colgroup_span-expected.png
index cec976c..f7efb55 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/colgroup_span-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/colgroup_span-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/colgroup_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/colgroup_valign_baseline-expected.png
index e8c7fdbf..ee77669 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/colgroup_valign_baseline-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/colgroup_valign_baseline-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_row_align_center-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_row_align_center-expected.png
index bde4e92..c922c0c 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_row_align_center-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_row_align_center-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_rules_all-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_rules_all-expected.png
index 7d8f5aa..91e4bad 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_rules_all-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_rules_all-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_rules_groups-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_rules_groups-expected.png
index 035b814..1b14ad1 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_rules_groups-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/table_rules_groups-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_cellpadding-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_cellpadding-expected.png
index f0aa79a..4a8994f 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_cellpadding-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_cellpadding-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_cellpadding_pct-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_cellpadding_pct-expected.png
index 1a6ee83..7e5d88c0 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_cellpadding_pct-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_cellpadding_pct-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_style-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_style-expected.png
index d45bf2b..697c025 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_style-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tables_style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_align_char-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_align_char-expected.png
index d451795..af5b17ee7 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_align_char-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_align_char-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_char-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_char-expected.png
index 011fadf..b62ee91 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_char-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_char-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_valign_bottom-expected.png
index d4d78a2..c9ffe04 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_valign_bottom-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_valign_bottom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_valign_middle-expected.png
index bbdbf09..9df4c980 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_valign_middle-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tbody_valign_middle-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/td_valign_top-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/td_valign_top-expected.png
index 51a9dfe..2edd7a2 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/td_valign_top-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/td_valign_top-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_char-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_char-expected.png
index 7785426b..ee40fa51 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_char-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_char-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_valign_baseline-expected.png
index b082d0e..c659acc 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_valign_baseline-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_valign_baseline-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_valign_bottom-expected.png
index 24d0e4f33..ec76811 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_valign_bottom-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tfoot_valign_bottom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_align_char-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_align_char-expected.png
index 389dd33..da9bda8 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_align_char-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_align_char-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_baseline-expected.png
index b55afd4..736115e 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_baseline-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_baseline-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_bottom-expected.png
index 21034be..75fa7b3 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_bottom-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_bottom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_middle-expected.png
index 77efe917..f942774 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_middle-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/thead_valign_middle-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tr_bgcolor_white-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tr_bgcolor_white-expected.png
index 4f83cac..de9cb892 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tr_bgcolor_white-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tr_bgcolor_white-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tr_bgcolor_white_rgb-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tr_bgcolor_white_rgb-expected.png
index 4f83cac..de9cb892 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tr_bgcolor_white_rgb-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/tr_bgcolor_white_rgb-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_col_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_col_valign_middle-expected.png
index 6df4f276..0294e57 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_col_valign_middle-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_col_valign_middle-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png
index 97bd206..addca44 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png
index f0cd136..96fa500c 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_table_border-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_table_border-expected.png
index 5f15dfd..4ab6f9c 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_table_border-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_table_border-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_table_style-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_table_style-expected.png
index 363b92da..ac41cb49 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_table_style-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_table_style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_align_char-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_align_char-expected.png
index 9347209..0020a05 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_align_char-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_align_char-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png
index d3a09fb..c9204ed 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_valign_middle-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_valign_middle-expected.png
index 2208e45..cce6a17 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_valign_middle-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tbody_valign_middle-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_td_align_center-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_td_align_center-expected.png
index 4840d4f..2088fc9f 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_td_align_center-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_td_align_center-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_td_valign_top-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_td_valign_top-expected.png
index d0fae75..cfe4af8 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_td_valign_top-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_td_valign_top-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_align_char-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_align_char-expected.png
index 8c7581b..2407d1f 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_align_char-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_align_char-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_style-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_style-expected.png
index 1a0364cf..b111410 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_style-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png
index 628822fee..6be8bde3 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_th_width-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_th_width-expected.png
index 4eebffa..3a68794 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_th_width-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/marvin/x_th_width-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla/other/test6-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla/other/test6-expected.png
index 777ff2a..acc5886 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla/other/test6-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla/other/test6-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug10140-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug10140-expected.png
index cc83ee8..dff3b0c 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug10140-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug10140-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug1725-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug1725-expected.png
index 6012e3a..6d70945 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug1725-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug1725-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug17826-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug17826-expected.png
index 10f3600..47fa3b9a 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug17826-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug17826-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug72393-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug72393-expected.png
index 145e9ba..5e259c1d 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug72393-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug72393-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug89315-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug89315-expected.png
index 16a8c3e..e5366d18 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug89315-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug89315-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug91057-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug91057-expected.png
index 4908690..d24daab 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug91057-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/bugs/bug91057-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index abb60bc..c578d26 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/marvin/x_colgroup_width_px-expected.png b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/marvin/x_colgroup_width_px-expected.png
index 714261b..7bfe605 100644
--- a/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/marvin/x_colgroup_width_px-expected.png
+++ b/third_party/blink/web_tests/platform/mac/tables/mozilla_expected_failures/marvin/x_colgroup_width_px-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/transforms/3d/general/perspective-units-expected.png b/third_party/blink/web_tests/platform/mac/transforms/3d/general/perspective-units-expected.png
index 1316f4b..2f230e2 100644
--- a/third_party/blink/web_tests/platform/mac/transforms/3d/general/perspective-units-expected.png
+++ b/third_party/blink/web_tests/platform/mac/transforms/3d/general/perspective-units-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/transforms/diamond-expected.png b/third_party/blink/web_tests/platform/mac/transforms/diamond-expected.png
index d17f2e0..fa0eed7 100644
--- a/third_party/blink/web_tests/platform/mac/transforms/diamond-expected.png
+++ b/third_party/blink/web_tests/platform/mac/transforms/diamond-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/exif-orientation-css-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/exif-orientation-css-expected.png
index 6ebe759..33e5432 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/exif-orientation-css-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/exif-orientation-css-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
index a3d58a6..af3c555 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/imagemap-overflowing-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/exif-orientation-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/exif-orientation-expected.png
index ad9974d..b770984 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/exif-orientation-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/exif-orientation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/image-map-anchor-children-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/image-map-anchor-children-expected.png
index b78a734..6ebf40b 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/image-map-anchor-children-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/image-map-anchor-children-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
index 1494523..bcb4d80 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
index 1027048..749db52 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png
index d0a2af1..3255bc2 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/imagemap-overflowing-circle-focus-ring-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/replaced/table-replaced-element-expected.txt b/third_party/blink/web_tests/platform/win/fast/replaced/table-replaced-element-expected.txt
deleted file mode 100644
index 46faf40..0000000
--- a/third_party/blink/web_tests/platform/win/fast/replaced/table-replaced-element-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Layout test for WebKit bug 85581.
-
-This tests that the contents of a table do not overflow when the table contains an image with percentage height. For this test to pass, the blue rectangle should be entirely within the table border and/or you should see a 'PASS' message below.
-
-Height of table: 290
-Height of table contents: 280
-PASS: Table contents do not overflow outside of table border.
-
diff --git a/third_party/blink/web_tests/platform/win/fast/text/international/shape-across-elements-expected.txt b/third_party/blink/web_tests/platform/win/fast/text/international/shape-across-elements-expected.txt
deleted file mode 100644
index 2dafceb..0000000
--- a/third_party/blink/web_tests/platform/win/fast/text/international/shape-across-elements-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-PASS Width of isolated word does match width of word with markup.
-PASS Width of partial glyph in ligature does not match width of isolated glyph.
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-Shape across element boundary test
-سلام The word by itself.
-سلام Adding a span around a character that forms a ligature. Should render the same as the above, except that half of the middle glyph should be red.
-سل‍ام Same word with a ZWJ character to disallow the ligature.
-Ù„ The letter in red, in isolation.
diff --git a/third_party/blink/web_tests/platform/win/virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt b/third_party/blink/web_tests/virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/win/virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt
rename to third_party/blink/web_tests/virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-continuation-expected.txt
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/README.txt b/third_party/blink/web_tests/virtual/stable/compositing/README.txt
deleted file mode 100644
index 73f914f..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/README.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-# This suite runs the compositing/ directory without test or experimental
-# features enabled. This is primarily in support of the BlinkGenPropertyTrees
-# launch.
-# See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png
deleted file mode 100644
index 446aa85..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png
deleted file mode 100644
index 5393c95..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/direct-image-compositing-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/direct-image-compositing-expected.png
deleted file mode 100644
index bb3c623..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/direct-image-compositing-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/fixed-body-background-positioned-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/fixed-body-background-positioned-expected.txt
deleted file mode 100644
index a9d5368..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/fixed-body-background-positioned-expected.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Root Transform Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "Inner Viewport Container Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Overscroll Elasticity Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "Page Scale Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "Inner Viewport Scroll Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [785, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [785, 3700],
-      "backgroundColor": "#FFFFFF",
-      "transform": 1
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [785, 0],
-      "bounds": [15, 600],
-      "contentsOpaque": true,
-      "drawsContent": false
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -200, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/geometry/clip-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/geometry/clip-expected.txt
deleted file mode 100644
index 100aca1..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/geometry/clip-expected.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-Test CSS clip with composited layers. Left and right sides should look the same.
-
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='composited box'",
-      "bounds": [110, 110],
-      "backgroundColor": "#808080",
-      "transform": 2
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [215, 15],
-      "bounds": [110, 110],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'",
-      "bounds": [120, 120],
-      "backgroundColor": "#00000033",
-      "transform": 4
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [15, 15, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [210, 10, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ],
-      "flattenInheritedTransform": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/geometry/clip-inside-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/geometry/clip-inside-expected.txt
deleted file mode 100644
index 3566aba2..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/geometry/clip-inside-expected.txt
+++ /dev/null
@@ -1,85 +0,0 @@
-Test CSS clip with composited layers. Left and right sides should look the same.
-
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='composited box'",
-      "bounds": [90, 80],
-      "contentsOpaque": true,
-      "backgroundColor": "#808080",
-      "transform": 2
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [225, 35],
-      "bounds": [90, 80],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'",
-      "bounds": [120, 120],
-      "backgroundColor": "#00000033",
-      "transform": 4
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [25, 35, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [210, 10, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ],
-      "flattenInheritedTransform": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/geometry/clip-with-shadow-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/geometry/clip-with-shadow-expected.txt
deleted file mode 100644
index 3a44c3e..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/geometry/clip-with-shadow-expected.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='composited box'",
-      "bounds": [110, 110],
-      "backgroundColor": "#808080",
-      "transform": 2
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [215, 15],
-      "bounds": [110, 110],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'",
-      "bounds": [120, 120],
-      "backgroundColor": "#00000033",
-      "transform": 4
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [15, 15, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [210, 10, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ],
-      "flattenInheritedTransform": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/geometry/foreground-layer-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/geometry/foreground-layer-expected.txt
deleted file mode 100644
index 1617299..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/geometry/foreground-layer-expected.txt
+++ /dev/null
@@ -1,125 +0,0 @@
- 
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='main box'",
-      "bounds": [318, 318],
-      "backgroundColor": "#FF0000",
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='negative child'",
-      "bounds": [50, 50],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='main box' (foreground) Layer",
-      "bounds": [318, 318],
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='main box'",
-      "bounds": [318, 318],
-      "backgroundColor": "#FF0000",
-      "transform": 4
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [59, 59],
-      "bounds": [200, 200],
-      "drawsContent": false,
-      "transform": 4
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='negative child'",
-      "bounds": [50, 50],
-      "drawsContent": false,
-      "transform": 6
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='main box' (foreground) Layer",
-      "position": [59, 59],
-      "bounds": [200, 200],
-      "transform": 4
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [19, 89, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [59, 59, 0, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "parent": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [363, 19, 0, 1]
-      ]
-    },
-    {
-      "id": 5,
-      "parent": 4,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [59, 59, 0, 1]
-      ]
-    },
-    {
-      "id": 6,
-      "parent": 5,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/geometry/layer-due-to-layer-children-expected.png
deleted file mode 100644
index 59e6267..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/geometry/layer-due-to-layer-children-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/iframes/become-composited-nested-iframes-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/iframes/become-composited-nested-iframes-expected.txt
deleted file mode 100644
index 2021656..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/iframes/become-composited-nested-iframes-expected.txt
+++ /dev/null
@@ -1,128 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [785, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [785, 1500],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutIFrame IFRAME",
-      "position": [20, 120],
-      "bounds": [284, 204]
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [22, 122],
-      "bounds": [280, 200]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [22, 122],
-      "bounds": [280, 200],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutIFrame IFRAME",
-      "position": [30, 130],
-      "bounds": [252, 172]
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [31, 131],
-      "bounds": [250, 170],
-      "backgroundColor": "#C0C0C0"
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [31, 131],
-      "bounds": [250, 170],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='iframe-content' class='box'",
-      "bounds": [210, 210],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 1
-    },
-    {
-      "name": "LayoutIFrame IFRAME",
-      "position": [20, 344],
-      "bounds": [284, 204]
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [22, 346],
-      "bounds": [280, 200]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [22, 346],
-      "bounds": [280, 200],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutIFrame IFRAME",
-      "position": [30, 354],
-      "bounds": [252, 172]
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [31, 355],
-      "bounds": [250, 170],
-      "backgroundColor": "#C0C0C0"
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [31, 355],
-      "bounds": [250, 170],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='iframe-content' class='box'",
-      "bounds": [210, 210],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='box' class='composited'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [49, 141, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [49, 365, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/iframes/invisible-nested-iframe-show-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/iframes/invisible-nested-iframe-show-expected.txt
deleted file mode 100644
index 392b2cc1..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/iframes/invisible-nested-iframe-show-expected.txt
+++ /dev/null
@@ -1,117 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutIFrame IFRAME",
-      "position": [-11, -11],
-      "bounds": [368, 218]
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [23, 23],
-      "bounds": [300, 150],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [23, 23],
-      "bounds": [285, 150],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "position": [23, 23],
-      "bounds": [285, 193]
-    },
-    {
-      "name": "LayoutIFrame IFRAME",
-      "position": [31, 31],
-      "bounds": [252, 172]
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [32, 32],
-      "bounds": [250, 170],
-      "backgroundColor": "#C0C0C0"
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [32, 32],
-      "bounds": [250, 170],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='iframe-content' class='box'",
-      "bounds": [210, 210],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 1
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [23, 23],
-      "bounds": [300, 150],
-      "drawsContent": false
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [308, 23],
-      "bounds": [15, 150],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='box'",
-      "bounds": [210, 210],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 3
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [50, 42, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [18, 203, 0, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "parent": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/iframes/overlapped-iframe-iframe-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/iframes/overlapped-iframe-iframe-expected.txt
deleted file mode 100644
index c3c1d6f8..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/iframes/overlapped-iframe-iframe-expected.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutIFrame (positioned) IFRAME",
-      "bounds": [304, 304]
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [2, 2],
-      "bounds": [300, 300],
-      "backgroundColor": "#C0C0C0"
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [2, 2],
-      "bounds": [300, 300],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='iframe-content' class='box'",
-      "bounds": [210, 210],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 1
-    },
-    {
-      "name": "LayoutIFrame (positioned) IFRAME id='overlap'",
-      "position": [250, 0],
-      "bounds": [304, 304]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [20, 12, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/iframes/overlapped-nested-iframes-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/iframes/overlapped-nested-iframes-expected.txt
deleted file mode 100644
index 368814d..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/iframes/overlapped-nested-iframes-expected.txt
+++ /dev/null
@@ -1,154 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [785, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [785, 1650],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "transform": 1
-    },
-    {
-      "name": "LayoutIFrame IFRAME",
-      "position": [20, 150],
-      "bounds": [284, 204],
-      "transform": 1
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [22, 152],
-      "bounds": [280, 200],
-      "transform": 1
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [22, 152],
-      "bounds": [280, 200],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutIFrame IFRAME",
-      "position": [30, 160],
-      "bounds": [252, 172],
-      "transform": 1
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [31, 161],
-      "bounds": [250, 170],
-      "backgroundColor": "#C0C0C0",
-      "transform": 1
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [31, 161],
-      "bounds": [250, 170],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='iframe-content' class='box'",
-      "bounds": [210, 210],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 2
-    },
-    {
-      "name": "LayoutIFrame IFRAME",
-      "position": [20, 374],
-      "bounds": [284, 204],
-      "transform": 1
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [22, 376],
-      "bounds": [280, 200],
-      "transform": 1
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [22, 376],
-      "bounds": [280, 200],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutIFrame IFRAME",
-      "position": [30, 384],
-      "bounds": [252, 172],
-      "transform": 1
-    },
-    {
-      "name": "LayoutView #document",
-      "position": [31, 385],
-      "bounds": [250, 170],
-      "backgroundColor": "#C0C0C0",
-      "transform": 1
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [31, 385],
-      "bounds": [250, 170],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='iframe-content' class='box'",
-      "bounds": [210, 210],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 3
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='banner'",
-      "position": [0, 100],
-      "bounds": [785, 120],
-      "backgroundColor": "#00000080",
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -100, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [49, 171, 0, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [49, 395, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overflow-scroll-overlap-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overflow-scroll-overlap-expected.txt
deleted file mode 100644
index 0bc9060..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overflow-scroll-overlap-expected.txt
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Squashing Containment Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='composited'",
-      "bounds": [30, 30],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='scroller' class='overflow')",
-      "position": [20, 20],
-      "bounds": [306, 206]
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [23, 23],
-      "bounds": [285, 200],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='box'",
-      "position": [43, 29],
-      "bounds": [200, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='box')",
-      "position": [43, 184],
-      "bounds": [210, 100]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-animation-clipping-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-animation-clipping-expected.txt
deleted file mode 100644
index 1d92058..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-animation-clipping-expected.txt
+++ /dev/null
@@ -1,129 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [785, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [785, 812],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='to-animate1' class='box animating1'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='container'",
-      "position": [58, 230],
-      "bounds": [122, 462],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [59, 231],
-      "bounds": [120, 460],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='box gray force-layer'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#808080",
-      "transform": 4
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='to-animate2' class='box animating2'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 6
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='box yellow'",
-      "position": [69, 571],
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFF00"
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='box yellow'",
-      "position": [18, 702],
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFF00"
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [...],
-        [...],
-        [...],
-        [...]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [...],
-        [...],
-        [...],
-        [...]
-      ]
-    },
-    {
-      "id": 3,
-      "transform": [
-        [...],
-        [...],
-        [...],
-        [...]
-      ]
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [...],
-        [...],
-        [...],
-        [...]
-      ]
-    },
-    {
-      "id": 5,
-      "transform": [
-        [...],
-        [...],
-        [...],
-        [...]
-      ]
-    },
-    {
-      "id": 6,
-      "parent": 5,
-      "transform": [
-        [...],
-        [...],
-        [...],
-        [...]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-animation-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-animation-expected.txt
deleted file mode 100644
index 0f1c74b..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-animation-expected.txt
+++ /dev/null
@@ -1,69 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='container'",
-      "position": [8, 8],
-      "bounds": [122, 242]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [9, 9],
-      "bounds": [120, 240],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='to-animate' class='animating box'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='box'",
-      "position": [19, 129],
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [...],
-        [...],
-        [...],
-        [...]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [...],
-        [...],
-        [...],
-        [...]
-      ],
-      "origin": [50, 50]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-clipping-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-clipping-expected.txt
deleted file mode 100644
index f2c359c09..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-clipping-expected.txt
+++ /dev/null
@@ -1,73 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [50, 50],
-      "bounds": [100, 100],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='child'",
-      "bounds": [500, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 1
-    },
-    {
-      "name": "Squashing Containment Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='child'",
-      "bounds": [500, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 2
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='overlap')",
-      "position": [450, 200],
-      "bounds": [100, 100]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [50, 50, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [50, 200, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt
deleted file mode 100644
index 7f07d31..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container clips'",
-      "bounds": [100, 100],
-      "transform": 1
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Squashing Containment Layer",
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='under composited'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
-      "transform": 1
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='over')",
-      "bounds": [100, 100],
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [110, 0, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-transforms-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-transforms-expected.txt
deleted file mode 100644
index 6d2c9d99..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/overlap-transforms-expected.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='container'",
-      "position": [8, 8],
-      "bounds": [122, 242]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [9, 9],
-      "bounds": [120, 240],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='transformed box'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 2
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [19, 19, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
deleted file mode 100644
index 623ad00..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [8, 8],
-      "bounds": [100, 100],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='composited'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#FA8072",
-      "transform": 1
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='squashed')",
-      "position": [8, 58],
-      "bounds": [100, 100]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 58, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/layer-tree-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/layer-tree-expected.txt
deleted file mode 100644
index 18acd2b..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/layer-tree-expected.txt
+++ /dev/null
@@ -1,146 +0,0 @@
-Layer tree:
-{
-  "name": "Root Transform Layer",
-  "drawsContent": false,
-  "children": [
-    {
-      "name": "Inner Viewport Container Layer",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "children": [
-        {
-          "name": "Overscroll Elasticity Layer",
-          "drawsContent": false,
-          "children": [
-            {
-              "name": "Page Scale Layer",
-              "drawsContent": false,
-              "children": [
-                {
-                  "name": "Inner Viewport Scroll Layer",
-                  "bounds": [800, 600],
-                  "drawsContent": false,
-                  "children": [
-                    {
-                      "name": "LayoutView #document",
-                      "bounds": [800, 600],
-                      "drawsContent": false,
-                      "backgroundColor": "#FFFFFF",
-                      "shouldFlattenTransform": false,
-                      "children": [
-                        {
-                          "name": "Scrolling Layer",
-                          "bounds": [780, 580],
-                          "drawsContent": false,
-                          "flattenInheritedTransform": false,
-                          "shouldFlattenTransform": false,
-                          "children": [
-                            {
-                              "name": "Scrolling Contents Layer",
-                              "bounds": [1200, 900],
-                              "contentsOpaque": true,
-                              "backgroundColor": "#FFFFFF",
-                              "flattenInheritedTransform": false
-                            }
-                          ]
-                        }
-                      ]
-                    }
-                  ]
-                }
-              ]
-            }
-          ]
-        },
-        {
-          "name": "Overflow Controls Host Layer",
-          "bounds": [800, 600],
-          "drawsContent": false,
-          "children": [
-            {
-              "name": "Horizontal Scrollbar Layer",
-              "position": [0, 580],
-              "bounds": [780, 20]
-            },
-            {
-              "name": "Vertical Scrollbar Layer",
-              "position": [780, 0],
-              "bounds": [20, 580]
-            },
-            {
-              "name": "Scroll Corner Layer",
-              "position": [780, 580],
-              "bounds": [20, 20]
-            }
-          ]
-        }
-      ]
-    }
-  ]
-}
-
-Layer list
-{
-  "layers": [
-    {
-      "name": "Root Transform Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "Inner Viewport Container Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Overscroll Elasticity Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "Page Scale Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "Inner Viewport Scroll Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [780, 580],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [1200, 900],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 580],
-      "bounds": [780, 20]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [780, 0],
-      "bounds": [20, 580]
-    },
-    {
-      "name": "Scroll Corner Layer",
-      "position": [780, 580],
-      "bounds": [20, 20]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/lots-of-img-layers-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/lots-of-img-layers-expected.png
deleted file mode 100644
index 312bcf9..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/lots-of-img-layers-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/lots-of-img-layers-with-opacity-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/lots-of-img-layers-with-opacity-expected.png
deleted file mode 100644
index a88d0274c..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/lots-of-img-layers-with-opacity-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/masks/direct-image-mask-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/masks/direct-image-mask-expected.png
deleted file mode 100644
index 187bc849..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/masks/direct-image-mask-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/masks/mask-with-removed-filters-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/masks/mask-with-removed-filters-expected.png
deleted file mode 100644
index bf05d030..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/masks/mask-with-removed-filters-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/masks/masked-ancestor-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/masks/masked-ancestor-expected.png
deleted file mode 100644
index 2893d5c6..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/masks/masked-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/masks/multiple-masks-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/masks/multiple-masks-expected.png
deleted file mode 100644
index 50633eb..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/masks/multiple-masks-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/masks/simple-composited-mask-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/masks/simple-composited-mask-expected.png
deleted file mode 100644
index a4ea481..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/masks/simple-composited-mask-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/opacity-with-mask-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/opacity-with-mask-expected.png
deleted file mode 100644
index b39d0c8..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/opacity-with-mask-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-above-composited-subframe-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-above-composited-subframe-expected.png
deleted file mode 100644
index 3c73dc0..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-above-composited-subframe-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-composited-subframe-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-composited-subframe-expected.png
deleted file mode 100644
index 8540490..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-composited-subframe-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png
deleted file mode 100644
index f4b4fff8..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png
deleted file mode 100644
index f380d7a..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png
deleted file mode 100644
index 61743f1..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-styles-with-composited-child-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-styles-with-composited-child-expected.png
deleted file mode 100644
index 969f416..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/border-radius-styles-with-composited-child-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/clip-descendents-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/clip-descendents-expected.txt
deleted file mode 100644
index 048aec8..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/clip-descendents-expected.txt
+++ /dev/null
@@ -1,166 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [48, 38],
-      "bounds": [60, 70],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='box'",
-      "bounds": [100, 150],
-      "contentsOpaque": true,
-      "backgroundColor": "#808080",
-      "transform": 2
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [240, 38],
-      "bounds": [60, 70],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='box'",
-      "bounds": [100, 150],
-      "contentsOpaque": true,
-      "backgroundColor": "#808080",
-      "transform": 4
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "position": [48, 230],
-      "bounds": [60, 70]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [48, 230],
-      "bounds": [60, 70],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='box'",
-      "bounds": [100, 150],
-      "contentsOpaque": true,
-      "backgroundColor": "#808080",
-      "transform": 6
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "position": [240, 230],
-      "bounds": [60, 70]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [240, 230],
-      "bounds": [60, 70],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='box'",
-      "bounds": [100, 150],
-      "contentsOpaque": true,
-      "backgroundColor": "#808080",
-      "transform": 8
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [50, 50, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [242, 50, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 5,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [50, 242, 0, 1]
-      ]
-    },
-    {
-      "id": 6,
-      "parent": 5,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ]
-    },
-    {
-      "id": 7,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [242, 242, 0, 1]
-      ]
-    },
-    {
-      "id": 8,
-      "parent": 7,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 1, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/content-gains-scrollbars-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/content-gains-scrollbars-expected.txt
deleted file mode 100644
index 285f901d..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/content-gains-scrollbars-expected.txt
+++ /dev/null
@@ -1,210 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "bounds": [100, 100],
-      "transform": 1
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [85, 100],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [85, 200],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='vertical' class='content tall'",
-      "bounds": [10, 200],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [85, 0],
-      "bounds": [15, 100],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "bounds": [100, 100],
-      "transform": 2
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [100, 85],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [200, 85],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='horizontal' class='content wide'",
-      "bounds": [200, 10],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 85],
-      "bounds": [100, 15],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "bounds": [100, 100],
-      "transform": 3
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [200, 200],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='both' class='content wide tall'",
-      "bounds": [200, 200],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 85],
-      "bounds": [85, 15],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [85, 0],
-      "bounds": [15, 85],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Scroll Corner Layer",
-      "position": [85, 85],
-      "bounds": [15, 15],
-      "transform": 3
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='corner' class='container resizeWidget'",
-      "bounds": [100, 100],
-      "transform": 4
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 4
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='content'",
-      "bounds": [10, 10],
-      "drawsContent": false,
-      "transform": 4
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 4
-    },
-    {
-      "name": "Scroll Corner Layer",
-      "position": [85, 85],
-      "bounds": [15, 15],
-      "transform": 4
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/content-loses-scrollbars-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/content-loses-scrollbars-expected.txt
deleted file mode 100644
index 28e47b8..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/content-loses-scrollbars-expected.txt
+++ /dev/null
@@ -1,132 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='vertical' class='content'",
-      "bounds": [10, 10],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='horizontal' class='content'",
-      "bounds": [10, 10],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='both' class='content'",
-      "bounds": [10, 10],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='corner' class='container'",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 4
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 4
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='content'",
-      "bounds": [10, 10],
-      "drawsContent": false,
-      "transform": 4
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png
deleted file mode 100644
index b219e48..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png
deleted file mode 100644
index b219e48..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
deleted file mode 100644
index 1600edb..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/nested-render-surfaces-with-rotation-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/overflow-scrollbar-layers-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/overflow-scrollbar-layers-expected.txt
deleted file mode 100644
index f679344..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/overflow-scrollbar-layers-expected.txt
+++ /dev/null
@@ -1,210 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "bounds": [100, 100],
-      "transform": 1
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [85, 100],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [85, 200],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='content tall'",
-      "bounds": [10, 200],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [85, 0],
-      "bounds": [15, 100],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "bounds": [100, 100],
-      "transform": 2
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [100, 85],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [200, 85],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='content wide'",
-      "bounds": [200, 10],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 85],
-      "bounds": [100, 15],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "bounds": [100, 100],
-      "transform": 3
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [200, 200],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='content wide tall'",
-      "bounds": [200, 200],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [0, 85],
-      "bounds": [85, 15],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [85, 0],
-      "bounds": [15, 85],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Scroll Corner Layer",
-      "position": [85, 85],
-      "bounds": [15, 15],
-      "transform": 3
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container resizeWidget'",
-      "bounds": [100, 100],
-      "transform": 4
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 4
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='content'",
-      "bounds": [10, 10],
-      "drawsContent": false,
-      "transform": 4
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 4
-    },
-    {
-      "name": "Scroll Corner Layer",
-      "position": [85, 85],
-      "bounds": [15, 15],
-      "transform": 4
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 13, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
deleted file mode 100644
index c8f192a..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
+++ /dev/null
@@ -1,85 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [1208, 821],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [8, 8],
-      "bounds": [1200, 800],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='positioned'",
-      "position": [8, 8],
-      "bounds": [1200, 800]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [8, 8],
-      "bounds": [1200, 800],
-      "drawsContent": false
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [8, 8],
-      "bounds": [1200, 1000],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='scroller'",
-      "position": [8, 8],
-      "bounds": [1200, 1000]
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [8, 8],
-      "bounds": [1200, 1000],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "position": [8, 8],
-      "bounds": [1200, 10000]
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='foreground'",
-      "position": [8, 10008],
-      "contentsOpaque": true,
-      "drawsContent": false
-    },
-    {
-      "name": "Overflow Controls Ancestor Clipping Layer",
-      "position": [8, 8],
-      "bounds": [1200, 1000],
-      "drawsContent": false
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [8, 8],
-      "bounds": [1200, 1000],
-      "drawsContent": false
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [1201, 8],
-      "bounds": [7, 1000],
-      "drawsContent": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-clip-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-clip-expected.txt
deleted file mode 100644
index 9801d91..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-clip-expected.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV",
-      "bounds": [240, 240],
-      "transform": 2
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [20, 20],
-      "bounds": [200, 200],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow DIV",
-      "position": [20, 20],
-      "bounds": [400, 400],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 2
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [108, 100, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [0.707106781186548, 0.707106781186548, 0, 0],
-        [-0.707106781186548, 0.707106781186548, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 0, 1]
-      ],
-      "origin": [120, 120]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-effect-interleave-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-effect-interleave-expected.txt
deleted file mode 100644
index a390599f..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-effect-interleave-expected.txt
+++ /dev/null
@@ -1,94 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV",
-      "bounds": [240, 240],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow DIV",
-      "bounds": [240, 240],
-      "opacity": 0.899999976158142,
-      "transform": 2
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [20, 20],
-      "bounds": [200, 200],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow DIV",
-      "position": [20, 20],
-      "bounds": [400, 400],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV",
-      "position": [20, 0],
-      "bounds": [400, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#00FFFF",
-      "transform": 2
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [20, 20],
-      "bounds": [200, 200],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV",
-      "position": [20, 20],
-      "bounds": [100, 400],
-      "contentsOpaque": true,
-      "backgroundColor": "#FF00FF",
-      "transform": 2
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [108, 100, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [0.707106781186548, 0.707106781186548, 0, 0],
-        [-0.707106781186548, 0.707106781186548, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 0, 1]
-      ],
-      "origin": [120, 120]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-expected.txt
deleted file mode 100644
index fbb4681..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-expected.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV",
-      "bounds": [240, 240],
-      "transform": 2
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [20, 20],
-      "bounds": [200, 200],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow DIV",
-      "position": [20, 20],
-      "bounds": [400, 400],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF",
-      "transform": 2
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [108, 100, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [0.707106781186548, 0.707106781186548, 0, 0],
-        [-0.707106781186548, 0.707106781186548, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 0, 1]
-      ],
-      "origin": [120, 120]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
deleted file mode 100644
index 0edab25..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-z-order-interleave-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-z-order-interleave-expected.txt
deleted file mode 100644
index f97eb4f..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/rotate-then-clip-z-order-interleave-expected.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV",
-      "bounds": [300, 100],
-      "transform": 2
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV",
-      "bounds": [200, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV",
-      "bounds": [200, 22],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFF00",
-      "transform": 2
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "bounds": [100, 100],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV",
-      "bounds": [50, 200],
-      "contentsOpaque": true,
-      "backgroundColor": "#FF0000",
-      "transform": 2
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [108, 100, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [0.707106781186548, 0.707106781186548, 0, 0],
-        [-0.707106781186548, 0.707106781186548, 0, 0],
-        [0, 0, 1, 0],
-        [0, 0, 0, 1]
-      ],
-      "origin": [150, 50]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt
deleted file mode 100644
index 15c58a53..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='intervening'",
-      "position": [98, 90],
-      "bounds": [300, 300],
-      "contentsOpaque": true,
-      "backfaceVisibility": "hidden",
-      "backgroundColor": "#FFEFD5"
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='scroller'",
-      "position": [98, 90],
-      "bounds": [102, 102]
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [99, 91],
-      "bounds": [100, 100],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "position": [99, 91],
-      "bounds": [100, 180],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='fixed'",
-      "position": [60, 60],
-      "bounds": [80, 80],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000"
-    },
-    {
-      "name": "Squashing Containment Layer",
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='scrolled'",
-      "position": [103, 95],
-      "bounds": [60, 40],
-      "contentsOpaque": true,
-      "backgroundColor": "#0000FF"
-    },
-    {
-      "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='scrolled')",
-      "position": [103, 139],
-      "bounds": [60, 128]
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [98, 90],
-      "bounds": [102, 102],
-      "drawsContent": false
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [192, 91],
-      "bounds": [7, 100],
-      "drawsContent": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/scrollbar-layer-placement-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/overflow/scrollbar-layer-placement-expected.txt
deleted file mode 100644
index 7be354a..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/scrollbar-layer-placement-expected.txt
+++ /dev/null
@@ -1,218 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer A'",
-      "position": [6, 6],
-      "bounds": [340, 282]
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='scroller'",
-      "position": [38, 38],
-      "bounds": [278, 218],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [67, 67],
-      "bounds": [220, 160],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "position": [67, 67],
-      "bounds": [220, 236],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [62, 62],
-      "bounds": [230, 170],
-      "drawsContent": false
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [280, 67],
-      "bounds": [7, 160],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer B'",
-      "position": [355, 6],
-      "bounds": [340, 282]
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [387, 38],
-      "bounds": [278, 218],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [416, 67],
-      "bounds": [220, 160],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "position": [416, 67],
-      "bounds": [220, 236],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [428, 79],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [411, 62],
-      "bounds": [230, 170],
-      "drawsContent": false
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [629, 67],
-      "bounds": [7, 160],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer C'",
-      "position": [6, 297],
-      "bounds": [340, 282]
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [46, 337],
-      "bounds": [260, 100],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [37, 328],
-      "bounds": [278, 218],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [66, 357],
-      "bounds": [220, 160],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "position": [66, 357],
-      "bounds": [220, 236],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [78, 369],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Ancestor Clipping Layer",
-      "position": [46, 337],
-      "bounds": [260, 100],
-      "drawsContent": false
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [61, 352],
-      "bounds": [230, 170],
-      "drawsContent": false
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [279, 357],
-      "bounds": [7, 160],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='outer D'",
-      "position": [355, 297],
-      "bounds": [340, 282]
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='clipper'",
-      "position": [379, 321],
-      "bounds": [292, 200]
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [389, 331],
-      "bounds": [272, 180],
-      "drawsContent": false
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [395, 337],
-      "bounds": [260, 100],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "position": [386, 328],
-      "bounds": [278, 218],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [415, 357],
-      "bounds": [220, 160],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "position": [415, 357],
-      "bounds": [220, 236],
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV class='content'",
-      "position": [427, 369],
-      "bounds": [196, 212],
-      "contentsOpaque": true,
-      "backgroundColor": "#DDDDDD"
-    },
-    {
-      "name": "Overflow Controls Ancestor Clipping Layer",
-      "position": [395, 337],
-      "bounds": [260, 100],
-      "drawsContent": false
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [410, 352],
-      "bounds": [230, 170],
-      "drawsContent": false
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [628, 357],
-      "bounds": [7, 160],
-      "drawsContent": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png
deleted file mode 100644
index b219e48..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png
deleted file mode 100644
index ef41de3..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/siblings-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/siblings-with-border-radius-ancestor-expected.png
deleted file mode 100644
index fa893ed..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/siblings-with-border-radius-ancestor-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/overflow/tiled-mask-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/overflow/tiled-mask-expected.png
deleted file mode 100644
index 49e4d2e8..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/overflow/tiled-mask-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/perpendicular-layer-sorting-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/perpendicular-layer-sorting-expected.png
deleted file mode 100644
index fa252db..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/perpendicular-layer-sorting-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/perspective-interest-rect-expected.png b/third_party/blink/web_tests/virtual/stable/compositing/perspective-interest-rect-expected.png
deleted file mode 100644
index 6beffe7..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/perspective-interest-rect-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/rtl/rtl-iframe-absolute-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/rtl/rtl-iframe-absolute-expected.txt
deleted file mode 100644
index 11a5e14..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/rtl/rtl-iframe-absolute-expected.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutIFrame (positioned) IFRAME",
-      "bounds": [400, 400]
-    },
-    {
-      "name": "LayoutView #document",
-      "bounds": [400, 400],
-      "backgroundColor": "#FF0000"
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [400, 400],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='positioned layer'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [50, 50, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/rtl/rtl-iframe-fixed-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/rtl/rtl-iframe-fixed-expected.txt
deleted file mode 100644
index 11a5e14..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/rtl/rtl-iframe-fixed-expected.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutIFrame (positioned) IFRAME",
-      "bounds": [400, 400]
-    },
-    {
-      "name": "LayoutView #document",
-      "bounds": [400, 400],
-      "backgroundColor": "#FF0000"
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [400, 400],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='positioned layer'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [50, 50, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/rtl/rtl-iframe-relative-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/rtl/rtl-iframe-relative-expected.txt
deleted file mode 100644
index 7d4fc5b..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/rtl/rtl-iframe-relative-expected.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutIFrame (positioned) IFRAME",
-      "bounds": [400, 400]
-    },
-    {
-      "name": "LayoutView #document",
-      "bounds": [400, 400]
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [400, 400],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='layer'",
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [242, 58, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/squashing/clipping-ancestor-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/squashing/clipping-ancestor-expected.txt
deleted file mode 100644
index 7298b1c..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/squashing/clipping-ancestor-expected.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Ancestor Clipping Layer",
-      "position": [8, 8],
-      "bounds": [200, 10],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner'",
-      "bounds": [200, 10],
-      "contentsOpaque": true,
-      "backgroundColor": "#F5F5F5",
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='hoverable'",
-      "position": [8, 0],
-      "bounds": [100, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#90EE90"
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt
deleted file mode 100644
index 4a56b34..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt
+++ /dev/null
@@ -1,59 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV",
-      "bounds": [784, 10],
-      "contentsOpaque": true,
-      "backgroundColor": "#ADD8E6",
-      "transform": 1
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [784, 10],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='inner'",
-      "bounds": [784, 10],
-      "contentsOpaque": true,
-      "backgroundColor": "#F5F5F5",
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='hoverable'",
-      "position": [8, 0],
-      "bounds": [216, 100],
-      "backgroundColor": "#90EE90"
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt
deleted file mode 100644
index f13b579..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt
+++ /dev/null
@@ -1,59 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='fixedpos'",
-      "position": [0, 50],
-      "bounds": [800, 550],
-      "contentsOpaque": true,
-      "backgroundColor": "#ADD8E6"
-    },
-    {
-      "name": "Child Containment Layer",
-      "position": [0, 50],
-      "bounds": [800, 550],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='compositedlayer'",
-      "bounds": [24, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#D3D3D3",
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='notsquashedelement'",
-      "bounds": [800, 60],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000"
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [400, 40, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/compositing/visibility/layer-visible-content-expected.txt b/third_party/blink/web_tests/virtual/stable/compositing/visibility/layer-visible-content-expected.txt
deleted file mode 100644
index 0b05974b..0000000
--- a/third_party/blink/web_tests/virtual/stable/compositing/visibility/layer-visible-content-expected.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "bounds": [200, 200]
-    },
-    {
-      "name": "Child Containment Layer",
-      "bounds": [200, 200],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow DIV class='composited box'",
-      "bounds": [10, 10],
-      "drawsContent": false
-    },
-    {
-      "name": "LayoutBlockFlow PRE id='layer-tree'",
-      "bounds": [800, 16],
-      "opacity": 0
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/paint/README.txt b/third_party/blink/web_tests/virtual/stable/paint/README.txt
deleted file mode 100644
index ca5b430..0000000
--- a/third_party/blink/web_tests/virtual/stable/paint/README.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-# This suite runs the paint/ directory without test or experimental features
-# enabled. This is primarily in support of the BlinkGenPropertyTrees launch.
-# See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/blink/web_tests/virtual/stable/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt b/third_party/blink/web_tests/virtual/stable/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt
deleted file mode 100644
index e24b05c..0000000
--- a/third_party/blink/web_tests/virtual/stable/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "Scrolling Layer",
-      "bounds": [800, 600],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "drawsContent": false,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow HTML",
-      "bounds": [800, 318]
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='neg-z'",
-      "position": [9, -81],
-      "bounds": [100, 410]
-    },
-    {
-      "name": "LayoutBlockFlow HTML (foreground) Layer",
-      "bounds": [800, 318]
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='container'",
-      "position": [8, 8],
-      "bounds": [102, 302],
-      "backfaceVisibility": "hidden"
-    },
-    {
-      "name": "Scrolling Layer",
-      "position": [9, 9],
-      "bounds": [100, 300],
-      "drawsContent": false
-    },
-    {
-      "name": "Scrolling Contents Layer",
-      "position": [9, 9],
-      "bounds": [100, 430],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Overflow Controls Host Layer",
-      "position": [8, 8],
-      "bounds": [102, 302],
-      "drawsContent": false,
-      "backfaceVisibility": "hidden"
-    },
-    {
-      "name": "Horizontal Scrollbar Layer",
-      "position": [9, 309],
-      "bounds": [100, 0]
-    },
-    {
-      "name": "Vertical Scrollbar Layer",
-      "position": [109, 9],
-      "bounds": [0, 300]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -100, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/paint/invalidation/iframe-display-block-to-display-none-expected.txt b/third_party/blink/web_tests/virtual/stable/paint/invalidation/iframe-display-block-to-display-none-expected.txt
deleted file mode 100644
index 941dd7bd..0000000
--- a/third_party/blink/web_tests/virtual/stable/paint/invalidation/iframe-display-block-to-display-none-expected.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "paintInvalidations": [
-        {
-          "object": "LayoutIFrame IFRAME id='iframe'",
-          "rect": [8, 68, 732, 94],
-          "reason": "layoutObject removal"
-        },
-        {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [10, 70, 728, 90],
-          "reason": "layoutObject removal"
-        },
-        {
-          "object": "LayoutBlockFlow BODY",
-          "rect": [18, 78, 712, 74],
-          "reason": "layoutObject removal"
-        }
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/paint/invalidation/iframe-display-none-to-display-block-expected.txt b/third_party/blink/web_tests/virtual/stable/paint/invalidation/iframe-display-none-to-display-block-expected.txt
deleted file mode 100644
index 884e4f6..0000000
--- a/third_party/blink/web_tests/virtual/stable/paint/invalidation/iframe-display-none-to-display-block-expected.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [800, 600],
-      "drawsContent": false,
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "paintInvalidations": [
-        {
-          "object": "LayoutIFrame IFRAME id='iframe'",
-          "rect": [8, 68, 732, 94],
-          "reason": "layoutObject insertion"
-        },
-        {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [10, 70, 728, 90],
-          "reason": "layoutObject insertion"
-        },
-        {
-          "object": "LayoutView #document",
-          "rect": [10, 70, 728, 90],
-          "reason": "full"
-        },
-        {
-          "object": "LayoutBlockFlow BODY",
-          "rect": [18, 78, 712, 74],
-          "reason": "layoutObject insertion"
-        }
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/stable/paint/invalidation/shift-relative-positioned-container-with-image-removal-expected.txt b/third_party/blink/web_tests/virtual/stable/paint/invalidation/shift-relative-positioned-container-with-image-removal-expected.txt
deleted file mode 100644
index c7e3965a..0000000
--- a/third_party/blink/web_tests/virtual/stable/paint/invalidation/shift-relative-positioned-container-with-image-removal-expected.txt
+++ /dev/null
@@ -1,59 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "LayoutView #document",
-      "bounds": [785, 735],
-      "drawsContent": false,
-      "contentsOpaque": true,
-      "drawsContent": true,
-      "paintInvalidations": [
-        {
-          "object": "LayoutView #document",
-          "rect": [0, 735, 785, 98],
-          "reason": "incremental"
-        },
-        {
-          "object": "LayoutBlockFlow (relative positioned) DIV class='relative paddingTop'",
-          "rect": [8, 184, 769, 641],
-          "reason": "bounds change"
-        },
-        {
-          "object": "LayoutBlockFlow (relative positioned) DIV class='relative paddingTop'",
-          "rect": [8, 86, 769, 641],
-          "reason": "bounds change"
-        },
-        {
-          "object": "LayoutBlockFlow (anonymous)",
-          "rect": [8, 86, 769, 98],
-          "reason": "layoutObject removal"
-        },
-        {
-          "object": "LayoutIFrame IFRAME id='iframe'",
-          "rect": [8, 86, 732, 94],
-          "reason": "layoutObject removal"
-        },
-        {
-          "object": "LayoutBlockFlow HTML",
-          "rect": [10, 88, 728, 90],
-          "reason": "layoutObject removal"
-        },
-        {
-          "object": "LayoutBlockFlow BODY",
-          "rect": [18, 96, 712, 74],
-          "reason": "layoutObject removal"
-        },
-        {
-          "object": "LayoutImage IMG",
-          "rect": [58, 234, 489, 537],
-          "reason": "bounds change"
-        },
-        {
-          "object": "LayoutImage IMG",
-          "rect": [58, 136, 489, 537],
-          "reason": "bounds change"
-        }
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt
index 5e43679..aeafc16 100644
--- a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt
+++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 514 tests; 406 PASS, 108 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 516 tests; 404 PASS, 112 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS idl_test validation
 PASS Test driver for asyncInitCertificate
@@ -206,13 +206,15 @@
 PASS RTCPeerConnectionIceErrorEvent interface: existence and properties of interface prototype object
 PASS RTCPeerConnectionIceErrorEvent interface: existence and properties of interface prototype object's "constructor" property
 PASS RTCPeerConnectionIceErrorEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCPeerConnectionIceErrorEvent interface: attribute hostCandidate
+FAIL RTCPeerConnectionIceErrorEvent interface: attribute address assert_true: The prototype object must have a property "address" expected true got false
+FAIL RTCPeerConnectionIceErrorEvent interface: attribute port assert_true: The prototype object must have a property "port" expected true got false
 PASS RTCPeerConnectionIceErrorEvent interface: attribute url
 PASS RTCPeerConnectionIceErrorEvent interface: attribute errorCode
 PASS RTCPeerConnectionIceErrorEvent interface: attribute errorText
 PASS RTCPeerConnectionIceErrorEvent must be primary interface of new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 });
 PASS Stringification of new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 });
-PASS RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "hostCandidate" with the proper type
+FAIL RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "address" with the proper type assert_inherits: property "address" not found in prototype chain
+FAIL RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "port" with the proper type assert_inherits: property "port" not found in prototype chain
 PASS RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "url" with the proper type
 PASS RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "errorCode" with the proper type
 PASS RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "errorText" with the proper type
diff --git a/third_party/sfntly/BUILD.gn b/third_party/sfntly/BUILD.gn
index 8f312543..0596ca1 100644
--- a/third_party/sfntly/BUILD.gn
+++ b/third_party/sfntly/BUILD.gn
@@ -2,8 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//testing/libfuzzer/fuzzer_test.gni")
-
 declare_args() {
   # Flip to true to build sfntly sample programs.
   build_sfntly_samples = false
@@ -165,17 +163,6 @@
   ]
 }
 
-fuzzer_test("sfntly_fuzzer") {
-  sources = [
-    "fuzzers/subset_font_fuzzer.cc",
-  ]
-  deps = [
-    ":sfntly",
-    "//base/test:test_support",
-  ]
-  seed_corpus = "fuzzers/corpora/sfntly_fuzzer"
-}
-
 if (build_sfntly_samples) {
   source_set("sfntly_subtly") {
     sources = [
diff --git a/third_party/sfntly/fuzzers/DEPS b/third_party/sfntly/fuzzers/DEPS
deleted file mode 100644
index ad3256b..0000000
--- a/third_party/sfntly/fuzzers/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  "+base",
-]
-
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Ahem.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Ahem.ttf
deleted file mode 100644
index ac81cb0..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Ahem.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Distortable.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Distortable.ttf
deleted file mode 100644
index 95f30c33..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Distortable.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/DroidSans-Regular.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/DroidSans-Regular.ttf
deleted file mode 100644
index 767c63a..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/DroidSans-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Em.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Em.ttf
deleted file mode 100644
index 2e44097..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Em.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Funkster.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Funkster.ttf
deleted file mode 100644
index 6fc6110..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Funkster.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/HangingS.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/HangingS.ttf
deleted file mode 100644
index bb30114..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/HangingS.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/OpenSans-Regular.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/OpenSans-Regular.ttf
deleted file mode 100644
index db433349..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/OpenSans-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/ReallyBigA.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/ReallyBigA.ttf
deleted file mode 100644
index 088a560..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/ReallyBigA.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Roboto-Regular.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Roboto-Regular.ttf
deleted file mode 100644
index 7d9a6c4..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Roboto-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Roboto2-Regular_NoEmbed.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Roboto2-Regular_NoEmbed.ttf
deleted file mode 100644
index 08928623..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/Roboto2-Regular_NoEmbed.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/SpiderSymbol.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/SpiderSymbol.ttf
deleted file mode 100644
index ed651ea..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/SpiderSymbol.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/hintgasp.ttf b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/hintgasp.ttf
deleted file mode 100644
index ce1771e..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/hintgasp.ttf
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/test.ttc b/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/test.ttc
deleted file mode 100644
index fb6729d..0000000
--- a/third_party/sfntly/fuzzers/corpora/sfntly_fuzzer/test.ttc
+++ /dev/null
Binary files differ
diff --git a/third_party/sfntly/fuzzers/subset_font_fuzzer.cc b/third_party/sfntly/fuzzers/subset_font_fuzzer.cc
deleted file mode 100644
index aaa1c5d..0000000
--- a/third_party/sfntly/fuzzers/subset_font_fuzzer.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2016 The Chromimum 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 <stddef.h>
-#include <stdint.h>
-
-#include <fuzzer/FuzzedDataProvider.h>
-
-#include <string>
-#include <vector>
-
-#include "third_party/sfntly/src/cpp/src/sample/chromium/font_subsetter.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  constexpr int kMaxFontNameSize = 128;
-  constexpr int kMaxFontSize = 50 * 1024 * 1024;
-  FuzzedDataProvider fuzzed_data(data, size);
-
-  size_t font_name_size =
-      fuzzed_data.ConsumeIntegralInRange(0, kMaxFontNameSize);
-  std::string font_name = fuzzed_data.ConsumeBytesAsString(font_name_size);
-
-  size_t font_str_size = fuzzed_data.ConsumeIntegralInRange(0, kMaxFontSize);
-  std::vector<unsigned char> font_str =
-      fuzzed_data.ConsumeBytes<unsigned char>(font_str_size);
-
-  std::vector<uint8_t> glyph_ids_str =
-      fuzzed_data.ConsumeRemainingBytes<uint8_t>();
-  const unsigned int* glyph_ids =
-      reinterpret_cast<const unsigned int*>(glyph_ids_str.data());
-  size_t glyph_ids_size = glyph_ids_str.size() *
-                          sizeof(decltype(glyph_ids_str)::value_type) /
-                          sizeof(*glyph_ids);
-
-  unsigned char* output = nullptr;
-  SfntlyWrapper::SubsetFont(font_name.c_str(), font_str.data(), font_str.size(),
-                            glyph_ids, glyph_ids_size, &output);
-  delete[] output;
-  return 0;
-}
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index beb15a7..35f4c1c 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -649,6 +649,7 @@
     },
 
     'tryserver.chromium.android': {
+      'android-opus-kitkat-arm-rel': 'android_release_trybot',
       # TODO(crbug/597596): Switch this back to debug_trybot when cronet's
       # shared library loading is fixed.
       'android-cronet-arm-dbg': 'android_cronet_debug_static_bot_arm_no_neon',
@@ -899,6 +900,7 @@
       'gpu-fyi-try-win10-nvidia-exp-64': 'gpu_fyi_tests_release_trybot',
       'gpu-fyi-try-win10-nvidia-rel-32': 'gpu_tests_release_trybot_x86_resource_whitelisting',
       'gpu-fyi-try-win10-nvidia-rel-64': 'gpu_fyi_tests_release_trybot',
+      'gpu-fyi-try-win10-nvidia-skgl-64': 'gpu_fyi_tests_release_trybot',
       'win10_chromium_x64_dbg_ng': 'gpu_tests_debug_trybot',
       'win10_chromium_x64_rel_ng': 'gpu_tests_release_trybot_resource_whitelisting',
       'win10_chromium_x64_rel_ng_exp': 'release_trybot',
@@ -2138,11 +2140,15 @@
 
     # Settings used by the codesearch builders to generate cross-references.
     'codesearch': {
-      'gn_args': 'clang_use_chrome_plugins=false enable_kythe_annotations=true',
+      'gn_args': ('clang_use_chrome_plugins=false '
+                  'enable_kythe_annotations=true '
+                  'is_chrome_branded=true'),
       'mixins': ['goma', 'clang', 'shared', 'debug', 'minimal_symbols'],
     },
     'codesearch_release': {
-      'gn_args': 'clang_use_chrome_plugins=false enable_kythe_annotations=true',
+      'gn_args': ('clang_use_chrome_plugins=false '
+                  'enable_kythe_annotations=true '
+                  'is_chrome_branded=true'),
       'mixins': ['release', 'static', 'goma'],
     },
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index b97b95f..f454ecd7 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -1738,6 +1738,20 @@
   <int value="2" label="Search engine changed"/>
 </enum>
 
+<enum name="AndroidSearchEngineChoiceEventsV2">
+  <summary>Events related to Search Engine Choice V2 feature.</summary>
+  <int value="0" label="Request recieved from play"/>
+  <int value="1"
+      label="User skipped (didn't complete) Search Engine Choice flow"/>
+  <int value="2" label="Play API returned empty list of providers"/>
+  <int value="3" label="User selected valid search provider"/>
+  <int value="4" label="Search engine metadata value was null"/>
+  <int value="5" label="Failed to parse search engine metadata JSON"/>
+  <int value="6"
+      label="Previous attempt to persist search engine metadata failed"/>
+  <int value="7" label="Request success"/>
+</enum>
+
 <enum name="AndroidSeccompSandboxStatus">
   <int value="0" label="Not Supported"/>
   <int value="1" label="Detection Failed"/>
@@ -18241,6 +18255,7 @@
   <int value="624" label="LegacySameSiteCookieBehaviorEnabledForDomainList"/>
   <int value="625" label="PrintJobHistoryExpirationPeriod"/>
   <int value="626" label="TLS13HardeningForLocalAnchorsEnabled"/>
+  <int value="627" label="ForceDisableAudioSandbox"/>
 </enum>
 
 <enum name="EnterprisePolicyInvalidations">
@@ -35203,6 +35218,7 @@
   <int value="-1833149810" label="enable-accessibility-tab-switcher"/>
   <int value="-1832575380" label="show-saved-copy"/>
   <int value="-1832221649" label="disable-out-of-process-pac"/>
+  <int value="-1830472348" label="CryptAuthV2DeviceSync:enabled"/>
   <int value="-1826649921" label="ContextualSuggestionsButton:disabled"/>
   <int value="-1826309726" label="ArcCustomTabsExperiment:disabled"/>
   <int value="-1823193038" label="QuietNotificationPrompts:disabled"/>
@@ -36263,6 +36279,7 @@
   <int value="-468697885" label="ArcInputMethod:enabled"/>
   <int value="-462554210"
       label="OminboxUIExperimentUseGenericSearchEngineIcon:enabled"/>
+  <int value="-462404204" label="CryptAuthV2DeviceSync:disabled"/>
   <int value="-462205750" label="enable-service-worker-sync"/>
   <int value="-461292699" label="ContentSuggestionsCategoryOrder:enabled"/>
   <int value="-460313418" label="ProgressBarThrottle:enabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 4b0fc46..b62a0e9 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -3624,6 +3624,18 @@
   </summary>
 </histogram>
 
+<histogram name="Android.SearchEngineChoice.EventsV2"
+    enum="AndroidSearchEngineChoiceEventsV2" expires_after="2020-10-07">
+  <owner>fgorski@chromium.org</owner>
+  <owner>pavely@chromium.org</owner>
+  <owner>wylieb@chromium.org</owner>
+  <owner>lzbylut@chromium.org</owner>
+  <summary>
+    Counts occurences of various events related to Search Engine Choice V2
+    feature.
+  </summary>
+</histogram>
+
 <histogram name="Android.SearchEngineChoice.SearchEngineBeforeChoicePrompt"
     enum="OmniboxSearchEngineType" expires_after="2020-04-01">
   <owner>fgorski@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index f345143..b61ff2cb 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -7742,47 +7742,47 @@
     Collects information about when and why a lifecycle state change was
     attempted, and information about the outcome of the attempt.
   </summary>
-  <metric name="FailureGlobalBlacklist">
+  <metric name="FailureGlobalBlacklist" enum="Boolean">
     <summary>
       Boolean indicating that the tab was explicitly opted out of the
       intervention via the global blacklist.
     </summary>
   </metric>
-  <metric name="FailureHeuristicAudio">
+  <metric name="FailureHeuristicAudio" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the origin
       has historically been observed emitting audio while in the background.
     </summary>
   </metric>
-  <metric name="FailureHeuristicFavicon">
+  <metric name="FailureHeuristicFavicon" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the origin
       has historically been observed updating its favicon while in the
       background.
     </summary>
   </metric>
-  <metric name="FailureHeuristicInsufficientObservation">
+  <metric name="FailureHeuristicInsufficientObservation" enum="Boolean">
     <summary>
       Boolean indicating that the site is still being observed locally in order
       to determine which features are in use. In the meantime, it is protected
       from this intervention.
     </summary>
   </metric>
-  <metric name="FailureHeuristicNotifications">
+  <metric name="FailureHeuristicNotifications" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the origin
       has historically been observed making use of notifications while in the
       background.
     </summary>
   </metric>
-  <metric name="FailureHeuristicTitle">
+  <metric name="FailureHeuristicTitle" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the origin
       has historically been observed updating its tab title while in the
       background.
     </summary>
   </metric>
-  <metric name="FailureLifecyclesEnterprisePolicyOptOut">
+  <metric name="FailureLifecyclesEnterprisePolicyOptOut" enum="Boolean">
     <summary>
       Boolean indicating that the browser was explicitly opted out of the
       intervention via enterprise policy.
@@ -7797,91 +7797,103 @@
       via feature policy.
     </summary>
   </metric>
-  <metric name="FailureLiveStateCapturing">
+  <metric name="FailureLiveStateCapturing" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
       currently capturing user media (making use of webcam or microphone, for
       example).
     </summary>
   </metric>
-  <metric name="FailureLiveStateDesktopCapture">
+  <metric name="FailureLiveStateDesktopCapture" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
       currently capturing a window or screen.
     </summary>
   </metric>
-  <metric name="FailureLiveStateDevToolsOpen">
+  <metric name="FailureLiveStateDevToolsOpen" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
       currently using DevTools.
     </summary>
   </metric>
-  <metric name="FailureLiveStateExtensionDisallowed">
+  <metric name="FailureLiveStateExtensionDisallowed" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed by an extension.
     </summary>
   </metric>
-  <metric name="FailureLiveStateFormEntry">
+  <metric name="FailureLiveStateFormEntry" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab
       currently contains text form entry.
     </summary>
   </metric>
-  <metric name="FailureLiveStateIsPDF">
+  <metric name="FailureLiveStateIsPDF" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
       currently hosting a PDF.
     </summary>
   </metric>
-  <metric name="FailureLiveStateMirroring">
+  <metric name="FailureLiveStateMirroring" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
       currently being mirrored (casting its contents, for example).
     </summary>
   </metric>
-  <metric name="FailureLiveStatePlayingAudio">
+  <metric name="FailureLiveStatePlayingAudio" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
       currently playing audio.
     </summary>
   </metric>
-  <metric name="FailureLiveStateSharingBrowsingInstance">
+  <metric name="FailureLiveStateSharingBrowsingInstance" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
       sharing its BrowsingInstance with at least one other tab.
     </summary>
   </metric>
-  <metric name="FailureLiveStateUsingBluetooth">
+  <metric name="FailureLiveStateUsingBluetooth" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
-      currently connnected to at least one bluetooth device.
+      currently connected to at least one bluetooth device.
     </summary>
   </metric>
-  <metric name="FailureLiveStateUsingWebSockets">
+  <metric name="FailureLiveStateUsingIndexedDBLock" enum="Boolean">
+    <summary>
+      Boolean indicating that the intervention was disallowed because the tab is
+      currently holding at least one IndexedDB lock.
+    </summary>
+  </metric>
+  <metric name="FailureLiveStateUsingWebLock" enum="Boolean">
+    <summary>
+      Boolean indicating that the intervention was disallowed because the tab is
+      currently holding at least one WebLock.
+    </summary>
+  </metric>
+  <metric name="FailureLiveStateUsingWebSockets" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
       currently using WebSockets.
     </summary>
   </metric>
-  <metric name="FailureLiveStateUsingWebUSB">
+  <metric name="FailureLiveStateUsingWebUSB" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
       currently using WebUSB.
     </summary>
   </metric>
-  <metric name="FailureLiveStateVisible">
+  <metric name="FailureLiveStateVisible" enum="Boolean">
     <summary>
       Boolean indicating that the intervention was disallowed because the tab is
       currently visible.
     </summary>
   </metric>
-  <metric name="FailureOriginTrialOptOut">
+  <metric name="FailureOriginTrialOptOut" enum="Boolean">
     <summary>
       Boolean indicating that the tab explicitly opted out of the intervention
       via origin trial.
     </summary>
   </metric>
-  <metric name="FailureOriginTrialUnknown">
+  <metric name="FailureOriginTrialUnknown" enum="Boolean">
     <summary>
       Boolean indicating that the tab did not report its origin trial
       opt-in/opt-out yet.
@@ -7907,7 +7919,7 @@
       lifecycle_unit_state.mojom.
     </summary>
   </metric>
-  <metric name="Outcome">
+  <metric name="Outcome" enum="Boolean">
     <summary>
       Whether or not the state change was successful. The various Failure and
       Success booleans encode the actual reasons for this outcome. Note that
@@ -7916,13 +7928,13 @@
       success bits are present the outcome is positive.
     </summary>
   </metric>
-  <metric name="SuccessGlobalWhitelist">
+  <metric name="SuccessGlobalWhitelist" enum="Boolean">
     <summary>
       Boolean indicating that the tab was explicitly opted in to the
       intervention via the global whitelist.
     </summary>
   </metric>
-  <metric name="SuccessHeuristic">
+  <metric name="SuccessHeuristic" enum="Boolean">
     <summary>
       Boolean indicating that the tab was deemed safe for the intervention via
       local observations and heuristics.
@@ -7937,7 +7949,7 @@
       via feature policy.
     </summary>
   </metric>
-  <metric name="SuccessOriginTrialOptIn">
+  <metric name="SuccessOriginTrialOptIn" enum="Boolean">
     <summary>
       Boolean indicating that the tab explicitly opted in to the intervention
       via origin trial.
@@ -7955,7 +7967,7 @@
       visibility state change.
     </summary>
   </metric>
-  <metric name="TransitionForced">
+  <metric name="TransitionForced" enum="Boolean">
     <summary>
       This is set if the transition to the new lifecycle state was forced by the
       browser because the content took too long to respond to the lifecycle
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 2473e9d3..431b17ac 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -762,11 +762,6 @@
         'num_shards': 1,
         'type': TEST_TYPES.GTEST,
       },
-      {
-        'isolate': 'dawn_perf_tests',
-        'num_shards': 1,
-        'type': TEST_TYPES.GTEST,
-      },
     ],
     'platform': 'linux',
     'dimension': {
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 1d05e78..6ba2b78 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -308,6 +308,8 @@
 crbug.com/1009838 [ mac ] system_health.common_desktop/browse:tools:maps:2019 [ Skip ]
 
 # Benchmark: system_health.common_mobile
+crbug.com/1013317 [ android ] system_health.common_mobile/load:news:nytimes [ Skip ]
+crbug.com/1013317 [ android ] system_health.common_mobile/background:news:nytimes [ Skip ]
 crbug.com/1007355 [ android-go android-webview ] system_health.common_mobile/load:media:imgur:2018 [ Skip ]
 crbug.com/914390 [ android-nexus-5 ] system_health.common_mobile/browse:chrome:newtab [ Skip ]
 crbug.com/714650 [ android ] system_health.common_mobile/browse:news:globo [ Skip ]
@@ -356,6 +358,7 @@
 crbug.com/1009838 [ mac ] system_health.memory_desktop/browse:tools:maps:2019 [ Skip ]
 
 # Benchmark: system_health.memory_mobile
+crbug.com/1013317 [ android ] system_health.memory_mobile/load:news:nytimes [ Skip ]
 crbug.com/1007355 [ android-go android-webview ] system_health.memory_mobile/load:media:imgur:2018 [ Skip ]
 crbug.com/914390 [ android-nexus-5 ] system_health.memory_mobile/browse:chrome:newtab [ Skip ]
 crbug.com/714650 [ android ] system_health.memory_mobile/browse:news:globo [ Skip ]
diff --git a/ui/file_manager/base/js/mock_chrome.js b/ui/file_manager/base/js/mock_chrome.js
index db2ce98..8ab2f4a4 100644
--- a/ui/file_manager/base/js/mock_chrome.js
+++ b/ui/file_manager/base/js/mock_chrome.js
@@ -22,7 +22,7 @@
     }
 
     if (!chrome.commandLinePrivate) {
-      /** @suppress {checkTypes} */
+      /** @suppress {checkTypes, const} */
       chrome.commandLinePrivate = {};
     }
     chrome.commandLinePrivate.hasSwitch = (name, callback) => {
@@ -53,7 +53,7 @@
     window.chrome = window.chrome || {};
     /** @suppress {const} */
     window.chrome.runtime = window.chrome.runtime || {};  // For lastError.
-    /** @suppress {checkTypes} */
+    /** @suppress {checkTypes, const} */
     window.chrome.storage = {
       local: {
         get: this.get_.bind(this),
diff --git a/ui/file_manager/externs/background/import_history.js b/ui/file_manager/externs/background/import_history.js
index 07ec0b4..e17c958 100644
--- a/ui/file_manager/externs/background/import_history.js
+++ b/ui/file_manager/externs/background/import_history.js
@@ -78,7 +78,10 @@
 /**
  * @enum {string} Import history changed event |state| values.
  */
-importer.ImportHistoryState = {};
+importer.ImportHistoryState = {
+  'COPIED': 'copied',
+  'IMPORTED': 'imported'
+};
 
 /**
  * Import history changed event (sent to ImportHistory.Observer's).
diff --git a/ui/file_manager/externs/entry_location.js b/ui/file_manager/externs/entry_location.js
index 7174733..427ffc54 100644
--- a/ui/file_manager/externs/entry_location.js
+++ b/ui/file_manager/externs/entry_location.js
@@ -11,7 +11,7 @@
   constructor() {
     /**
      * Volume information.
-     * @type {!VolumeInfo}
+     * @type {VolumeInfo}
      */
     this.volumeInfo;
 
diff --git a/ui/file_manager/externs/volume_manager.js b/ui/file_manager/externs/volume_manager.js
index 53ff207a..3bbc5a7 100644
--- a/ui/file_manager/externs/volume_manager.js
+++ b/ui/file_manager/externs/volume_manager.js
@@ -25,7 +25,7 @@
    * Obtains a volume info containing the passed entry.
    * @param {!Entry|!FilesAppEntry} entry Entry on the volume to be
    *     returned. Can be fake.
-   * @return {VolumeInfo} The VolumeInfo instance or null if not found.
+   * @return {?VolumeInfo} The VolumeInfo instance or null if not found.
    */
   getVolumeInfo(entry) {}
 
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js
index 4896230f..ebe1e5df 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -19,9 +19,9 @@
 
     /**
      * Volume manager.
-     * @private {?FilteredVolumeManager}
+     * @private {!FilteredVolumeManager}
      */
-    this.volumeManager_ = null;
+    this.volumeManager_;
 
     /** @private {?importer.HistoryLoader} */
     this.historyLoader_ = null;
@@ -438,7 +438,7 @@
   }
 
   /**
-   * @return {FilteredVolumeManager}
+   * @return {!FilteredVolumeManager}
    */
   get volumeManager() {
     return this.volumeManager_;
diff --git a/ui/file_manager/file_manager/foreground/js/mock_thumbnail_loader.js b/ui/file_manager/file_manager/foreground/js/mock_thumbnail_loader.js
index a2c1542a..b7f76ec 100644
--- a/ui/file_manager/file_manager/foreground/js/mock_thumbnail_loader.js
+++ b/ui/file_manager/file_manager/foreground/js/mock_thumbnail_loader.js
@@ -47,18 +47,18 @@
 
 /**
  * Width of test image.
- * @private {number}
+ * @type {number}
  */
 MockThumbnailLoader.testImageWidth = 0;
 
 /**
  * Height of test image.
- * @private {number}
+ * @type {number}
  */
 MockThumbnailLoader.testImageHeight = 0;
 
 /**
  * Error urls.
- * @private {Array<string>}
+ * @type {Array<string>}
  */
 MockThumbnailLoader.errorUrls = [];
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
index 778565b..b545e06 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -265,9 +265,9 @@
 
     /**
      * List container.
-     * @type {ListContainer}
+     * @type {!ListContainer}
      */
-    this.listContainer = null;
+    this.listContainer;
 
     /**
      * @type {!HTMLElement}
diff --git a/ui/ozone/public/ozone_platform.cc b/ui/ozone/public/ozone_platform.cc
index 767d82f..e075ecc 100644
--- a/ui/ozone/public/ozone_platform.cc
+++ b/ui/ozone/public/ozone_platform.cc
@@ -18,7 +18,23 @@
 namespace ui {
 
 namespace {
+
 OzonePlatform* g_instance = nullptr;
+
+void EnsureInstance() {
+  if (g_instance)
+    return;
+
+  TRACE_EVENT1("ozone", "OzonePlatform::Initialize", "platform",
+               GetOzonePlatformName());
+  std::unique_ptr<OzonePlatform> platform =
+      PlatformObject<OzonePlatform>::Create();
+
+  // TODO(spang): Currently need to leak this object.
+  OzonePlatform* pl = platform.release();
+  DCHECK_EQ(g_instance, pl);
+}
+
 }  // namespace
 
 OzonePlatform::OzonePlatform() {
@@ -62,23 +78,6 @@
   return GetOzonePlatformName();
 }
 
-// static
-OzonePlatform* OzonePlatform::EnsureInstance() {
-  if (!g_instance) {
-    TRACE_EVENT1("ozone",
-                 "OzonePlatform::Initialize",
-                 "platform",
-                 GetOzonePlatformName());
-    std::unique_ptr<OzonePlatform> platform =
-        PlatformObject<OzonePlatform>::Create();
-
-    // TODO(spang): Currently need to leak this object.
-    OzonePlatform* pl = platform.release();
-    DCHECK_EQ(g_instance, pl);
-  }
-  return g_instance;
-}
-
 IPC::MessageFilter* OzonePlatform::GetGpuMessageFilter() {
   return nullptr;
 }
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index d57e8287..69e250c 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -120,12 +120,6 @@
     bool supports_overlays = false;
   };
 
-  // Ensures that the OzonePlatform instance exists, without doing any
-  // initialization. No-op in case the instance is already created. This is
-  // useful in order to call virtual methods that depend on the Ozone platform
-  // selected at runtime, e.g. IsNativePixmapConfigSupported().
-  static OzonePlatform* EnsureInstance();
-
   // Initializes the subsystems/resources necessary for the UI process (e.g.
   // events) with additional properties to customize the ozone platform
   // implementation. Ozone will not retain InitParams after returning from