diff --git a/.gn b/.gn
index 375c60c..eaff26d 100644
--- a/.gn
+++ b/.gn
@@ -111,8 +111,7 @@
   "//extensions/browser:unit_tests",
   "//extensions/common:unit_tests",
   "//extensions/renderer:unit_tests",
-  "//extensions/shell:browser_tests",
-  "//extensions/shell:unit_tests",
+  "//extensions/shell/*",
   "//gin/*",
   "//google_apis/*",
   "//google_update/*",
diff --git a/BUILD.gn b/BUILD.gn
index 23947a30..30dd5e3 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -481,6 +481,9 @@
         "//extensions/shell:app_shell",
         "//extensions/shell/installer:app_shell_installer",
       ]
+      if (is_desktop_linux && is_official_build) {
+        deps += [ "//extensions/shell:app_shell_linux_symbols" ]
+      }
     }
 
     if (enable_nacl) {
diff --git a/DEPS b/DEPS
index ddc8b63b8..991002e 100644
--- a/DEPS
+++ b/DEPS
@@ -79,11 +79,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': 'bcc00b2a612c3cc7a15fe708ca481e6e572c2085',
+  'skia_revision': '16c1196ea6bae60be684f6c37f97348666ceaf2f',
   # 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': '386975ac9a68cd5857557b0a9452f8b1f13e10f7',
+  'v8_revision': '2d6bcd7991435f28f7ef0e3fa32386b4d60cc7ce',
   # 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.
@@ -91,7 +91,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': '5ae6ee457860f95fb813891bd2cec963c1154f0a',
+  'angle_revision': '6f5444da73ae14c45a1357c3714122665f18dd92',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -135,7 +135,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': '6733f341991f62fa7b3e51182121d2eaa3ea5d62',
+  'catapult_revision': '16322a374abb6c805d8d3fd7ed2daf11a2579292',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -657,7 +657,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '3c1cb0203b6cfc10389e85a350b2ea6ca29d01ce',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '8870f553f3d0f771502a6d8a04bcb932096149d9', # commit position 21742
+    Var('webrtc_git') + '/src.git' + '@' + 'bf3dbb4a692f4be31d4dd025fcf57b8c0a88c547', # commit position 21742
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py
index b83d58ad..5aa17a1 100755
--- a/PRESUBMIT_test.py
+++ b/PRESUBMIT_test.py
@@ -1009,11 +1009,11 @@
           'public class IncorrectTest extends TestCase {',
           '}',
         ]),
-        MockAffectedFile('IncorrectTestWithInterface.java', [
+        MockAffectedFile('IncorrectWithInterfaceTest.java', [
           'public class Test implements X extends BaseClass {',
           '}',
         ]),
-        MockAffectedFile('IncorrectTestMultiLine.java', [
+        MockAffectedFile('IncorrectMultiLineTest.java', [
           'public class Test implements X, Y, Z',
           '        extends TestBase {',
           '}',
@@ -1029,11 +1029,11 @@
                      % (3, len(msgs[0].items), msgs[0].items))
     self.assertTrue('IncorrectTest.java:1' in msgs[0].items,
                     'IncorrectTest not found in errors')
-    self.assertTrue('IncorrectTestWithInterface.java:1'
+    self.assertTrue('IncorrectWithInterfaceTest.java:1'
                     in msgs[0].items,
-                    'IncorrectTestWithInterface not found in errors')
-    self.assertTrue('IncorrectTestMultiLine.java:2' in msgs[0].items,
-                    'IncorrectTestMultiLine not found in errors')
+                    'IncorrectWithInterfaceTest not found in errors')
+    self.assertTrue('IncorrectMultiLineTest.java:2' in msgs[0].items,
+                    'IncorrectMultiLineTest not found in errors')
 
 class LogUsageTest(unittest.TestCase):
 
@@ -1488,5 +1488,38 @@
     self.assertTrue('some/mac/file.mm' not in errors[0].message)
 
 
+class NoProductionCodeUsingTestOnlyFunctions(unittest.TestCase):
+  def testTruePositives(self):
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+      MockFile('some/path/foo.cc', ['foo_for_testing();']),
+      MockFile('some/path/foo.mm', ['FooForTesting();']),
+      MockFile('some/path/foo.cxx', ['FooForTests();']),
+      MockFile('some/path/foo.cpp', ['foo_for_test();']),
+    ]
+
+    results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
+        mock_input_api, MockOutputApi())
+    self.assertEqual(1, len(results))
+    self.assertEqual(4, len(results[0].items))
+    self.assertTrue('foo.cc' in results[0].items[0])
+    self.assertTrue('foo.mm' in results[0].items[1])
+    self.assertTrue('foo.cxx' in results[0].items[2])
+    self.assertTrue('foo.cpp' in results[0].items[3])
+
+  def testFalsePositives(self):
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+      MockFile('some/path/foo.h', ['foo_for_testing();']),
+      MockFile('some/path/foo.mm', ['FooForTesting() {']),
+      MockFile('some/path/foo.cc', ['::FooForTests();']),
+      MockFile('some/path/foo.cpp', ['// foo_for_test();']),
+    ]
+
+    results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions(
+        mock_input_api, MockOutputApi())
+    self.assertEqual(0, len(results))
+
+
 if __name__ == '__main__':
   unittest.main()
diff --git a/PRESUBMIT_test_mocks.py b/PRESUBMIT_test_mocks.py
index 846f8413..3b491d9 100644
--- a/PRESUBMIT_test_mocks.py
+++ b/PRESUBMIT_test_mocks.py
@@ -92,17 +92,19 @@
 
   def FilterSourceFile(self, file, white_list=(), black_list=()):
     local_path = file.LocalPath()
+    found_in_white_list = not white_list
     if white_list:
       for pattern in white_list:
         compiled_pattern = re.compile(pattern)
         if compiled_pattern.search(local_path):
-          return True
+          found_in_white_list = True
+          break
     if black_list:
       for pattern in black_list:
         compiled_pattern = re.compile(pattern)
         if compiled_pattern.search(local_path):
           return False
-    return True
+    return found_in_white_list
 
   def LocalPaths(self):
     return self.files
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
index 0d59697..fc732a62 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
@@ -46,6 +46,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.InMemorySharedPreferences;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.components.safe_browsing.SafeBrowsingApiBridge;
@@ -656,6 +657,7 @@
     @Test
     @SmallTest
     @Feature({"AndroidWebView"})
+    @FlakyTest(message = "crbug/822753")
     public void testSafeBrowsingDontProceedNavigatesBackForSubResource() throws Throwable {
         loadGreenPage();
         final String originalTitle = mActivityTestRule.getTitleOnUiThread(mAwContents);
diff --git a/ash/shelf/shelf_controller.cc b/ash/shelf/shelf_controller.cc
index 44278c4b..48e566e 100644
--- a/ash/shelf/shelf_controller.cc
+++ b/ash/shelf/shelf_controller.cc
@@ -86,9 +86,11 @@
 void SetShelfBehaviorsFromPrefs() {
   // The shelf should always be bottom-aligned and not hidden in tablet mode;
   // alignment and auto-hide are assigned from prefs when tablet mode is exited.
-  if (Shell::Get()
-          ->tablet_mode_controller()
-          ->IsTabletModeWindowManagerEnabled()) {
+  // ShelfController outlives TabletModeController, hence the null check.
+  // https://crbug.com/817522
+  Shell* shell = Shell::Get();
+  if (shell->tablet_mode_controller() &&
+      shell->tablet_mode_controller()->IsTabletModeWindowManagerEnabled()) {
     return;
   }
 
diff --git a/ash/shell.cc b/ash/shell.cc
index 5ebe7ff..061684d5 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -818,6 +818,7 @@
   shelf_window_watcher_.reset();
 
   // Removes itself as an observer of |pref_service_|.
+  // TODO(jamescook): Uses tablet_mode_controller_. Add separate shutdown pass.
   shelf_controller_.reset();
 
   // NightLightController depends on the PrefService as well as the window tree
diff --git a/base/android/java/src/org/chromium/base/ContextUtils.java b/base/android/java/src/org/chromium/base/ContextUtils.java
index 09401466..c74a77bd 100644
--- a/base/android/java/src/org/chromium/base/ContextUtils.java
+++ b/base/android/java/src/org/chromium/base/ContextUtils.java
@@ -25,6 +25,8 @@
 public class ContextUtils {
     private static final String TAG = "ContextUtils";
     private static Context sApplicationContext;
+    // TODO(agrieve): Remove sProcessName caching when we stop supporting JB.
+    private static String sProcessName;
 
     /**
      * Initialization-on-demand holder. This exists for thread-safe lazy initialization.
@@ -132,6 +134,9 @@
             throw new RuntimeException("Global application context cannot be set to null.");
         }
         sApplicationContext = appContext;
+
+        // TODO(agrieve): Remove when we stop supporting JB.
+        getProcessName(); // Prime the cache for getProcessName().
     }
 
     /**
@@ -166,13 +171,20 @@
 
     /** @return The name of the current process. E.g. "org.chromium.chrome:privileged_process0". */
     public static String getProcessName() {
+        if (sProcessName != null) {
+            return sProcessName;
+        }
         try {
             // An even more convenient ActivityThread.currentProcessName() exists, but was not added
             // until JB MR2.
             Class<?> activityThreadClazz = Class.forName("android.app.ActivityThread");
             Object activityThread =
                     activityThreadClazz.getMethod("currentActivityThread").invoke(null);
-            return (String) activityThreadClazz.getMethod("getProcessName").invoke(activityThread);
+            // Before JB MR2, currentActivityThread() returns null when called on a non-UI thread.
+            // Cache the name to allow other threads to access it.
+            sProcessName =
+                    (String) activityThreadClazz.getMethod("getProcessName").invoke(activityThread);
+            return sProcessName;
         } catch (Exception e) { // No multi-catch below API level 19 for reflection exceptions.
             // If fallback logic is ever needed, refer to:
             // https://chromium-review.googlesource.com/c/chromium/src/+/905563/1
diff --git a/build/android/pylib/base/output_manager.py b/build/android/pylib/base/output_manager.py
index b4dd018f..60b8123b 100644
--- a/build/android/pylib/base/output_manager.py
+++ b/build/android/pylib/base/output_manager.py
@@ -11,10 +11,10 @@
 
 
 class Datatype(object):
-  HTML = 'html'
-  IMAGE = 'image'
-  TEXT = 'text'
-  JSON = 'json'
+  HTML = 'text/html'
+  JSON = 'application/json'
+  PNG = 'image/png'
+  TEXT = 'text/plain'
 
 
 class OutputManager(object):
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index b3517ba..8d126be 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -538,7 +538,7 @@
       json_data = json.loads(device.ReadFile(json_path))
       image_file_path = posixpath.join(source_dir, json_data['location'])
       with self._env.output_manager.ArchivedTempfile(
-          json_data['location'], 'ui_capture', output_manager.Datatype.IMAGE
+          json_data['location'], 'ui_capture', output_manager.Datatype.PNG
           ) as image_archive:
         device.PullFile(image_file_path, image_archive.name)
       json_data['image_link'] = image_archive.Link()
@@ -764,7 +764,7 @@
       if device.FileExists(screenshot_device_file.name):
         with self._env.output_manager.ArchivedTempfile(
             screenshot_filename, 'screenshot',
-            output_manager.Datatype.IMAGE) as screenshot_host_file:
+            output_manager.Datatype.PNG) as screenshot_host_file:
           try:
             device.PullFile(screenshot_device_file.name,
                             screenshot_host_file.name)
@@ -791,7 +791,7 @@
 
       with self._env.output_manager.ArchivedTempfile(
           'fail_%s' % failure_filename, 'render_tests',
-          output_manager.Datatype.IMAGE) as failure_image_host_file:
+          output_manager.Datatype.PNG) as failure_image_host_file:
         device.PullFile(
             posixpath.join(failure_images_device_dir, failure_filename),
             failure_image_host_file.name)
@@ -802,7 +802,7 @@
       if device.PathExists(golden_image_device_file):
         with self._env.output_manager.ArchivedTempfile(
             'golden_%s' % failure_filename, 'render_tests',
-            output_manager.Datatype.IMAGE) as golden_image_host_file:
+            output_manager.Datatype.PNG) as golden_image_host_file:
           device.PullFile(
               golden_image_device_file, golden_image_host_file.name)
         golden_link = golden_image_host_file.Link()
@@ -814,7 +814,7 @@
       if device.PathExists(diff_image_device_file):
         with self._env.output_manager.ArchivedTempfile(
             'diff_%s' % failure_filename, 'render_tests',
-            output_manager.Datatype.IMAGE) as diff_image_host_file:
+            output_manager.Datatype.PNG) as diff_image_host_file:
           device.PullFile(
               diff_image_device_file, diff_image_host_file.name)
         diff_link = diff_image_host_file.Link()
diff --git a/build/android/pylib/output/remote_output_manager.py b/build/android/pylib/output/remote_output_manager.py
index b726cb0..9fdb4bf6 100644
--- a/build/android/pylib/output/remote_output_manager.py
+++ b/build/android/pylib/output/remote_output_manager.py
@@ -66,7 +66,7 @@
   def _PrepareArchive(self):
     self._content_addressed = (self._datatype in (
         output_manager.Datatype.HTML,
-        output_manager.Datatype.IMAGE,
+        output_manager.Datatype.PNG,
         output_manager.Datatype.JSON))
     if self._content_addressed:
       sha1 = hashlib.sha1()
@@ -85,10 +85,5 @@
         google_storage_helper.exists(self._upload_path, self._bucket)):
       return
 
-    content_type = None
-    if self._datatype == output_manager.Datatype.HTML:
-      content_type = 'text/html'
-    elif self._datatype == output_manager.Datatype.JSON:
-      content_type = 'application/json'
     google_storage_helper.upload(
-        self._upload_path, self.name, self._bucket, content_type=content_type)
+        self._upload_path, self.name, self._bucket, content_type=self._datatype)
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 100c121..adf78cbb 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1968,8 +1968,11 @@
       cflags = [ "/Zi" ]  # Produce PDB file, no edit and continue.
     }
 
-    if (is_win_fastlink) {
-      assert(!use_lld, "is_win_fastlink=true cannot be used with use_lld=true.")
+    if (is_win_fastlink && !use_lld) {
+      # TODO(hans): is_win_fastlink=true is incompatible with use_lld. However,
+      # some developers might have enabled it manually, so to ease the
+      # transition to lld, just ignore it rather than asserting. Eventually we
+      # want to assert instead.
 
       # Tell VS 2015+ to create a PDB that references debug
       # information in .obj and .lib files instead of copying
@@ -1982,7 +1985,7 @@
     if (is_clang) {
       # /DEBUG:FASTLINK requires every object file to have standalone debug
       # information.
-      if (is_win_fastlink) {
+      if (is_win_fastlink && !use_lld) {
         cflags += [ "-fstandalone-debug" ]
       } else {
         cflags += [ "-fno-standalone-debug" ]
diff --git a/build/config/fuchsia/BUILD.gn b/build/config/fuchsia/BUILD.gn
index 14c5b21..ac57038 100644
--- a/build/config/fuchsia/BUILD.gn
+++ b/build/config/fuchsia/BUILD.gn
@@ -55,5 +55,9 @@
     "-Wl,--as-needed",
   ]
 
+  # TODO(crbug.com/821951): Clang enables SafeStack by default when targeting
+  # Fuchsia, but it breaks some tests, notably in V8.
+  cflags += [ "-fno-sanitize=safe-stack" ]
+
   libs = [ "zircon" ]
 }
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index 68906fe3..b5719de3 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -105,7 +105,7 @@
     ldflags = [ "/PROFILE" ]
   } else {
     if (!is_debug && !is_component_build) {
-      if (is_win_fastlink) {
+      if (is_win_fastlink && !use_lld) {
         # /PROFILE implies the following linker flags. Therefore if we are
         # skipping /PROFILE because it is incompatible with /DEBUG:FASTLINK
         # we should explicitly add these flags in order to avoid unintended
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index 5412332..e5da816 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -1341,7 +1341,7 @@
 
 void Layer::SetScrollbarsHiddenFromImplSide(bool hidden) {
   if (inputs_.client)
-    inputs_.client->didChangeScrollbarsHidden(hidden);
+    inputs_.client->didChangeScrollbarsHiddenIfOverlay(hidden);
 }
 
 // On<Property>Animated is called due to an ongoing accelerated animation.
diff --git a/cc/layers/layer_client.h b/cc/layers/layer_client.h
index 85c9772..10ded49b 100644
--- a/cc/layers/layer_client.h
+++ b/cc/layers/layer_client.h
@@ -31,7 +31,7 @@
   virtual std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
   TakeDebugInfo(Layer* layer) = 0;
   virtual void didUpdateMainThreadScrollingReasons() = 0;
-  virtual void didChangeScrollbarsHidden(bool) = 0;
+  virtual void didChangeScrollbarsHiddenIfOverlay(bool) = 0;
 
  protected:
   virtual ~LayerClient() {}
diff --git a/cc/test/mock_layer_client.h b/cc/test/mock_layer_client.h
index 5737213..56c953d1 100644
--- a/cc/test/mock_layer_client.h
+++ b/cc/test/mock_layer_client.h
@@ -21,7 +21,7 @@
       TakeDebugInfo,
       std::unique_ptr<base::trace_event::ConvertableToTraceFormat>(Layer*));
   MOCK_METHOD0(didUpdateMainThreadScrollingReasons, void());
-  MOCK_METHOD1(didChangeScrollbarsHidden, void(bool));
+  MOCK_METHOD1(didChangeScrollbarsHiddenIfOverlay, void(bool));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockLayerClient);
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index be3c78f..12d3713 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2939,8 +2939,10 @@
   InputHandler::ScrollStatus scroll_status;
   scroll_status.main_thread_scrolling_reasons =
       MainThreadScrollingReason::kNotScrollingOnMain;
-  if (!!scroll_node->main_thread_scrolling_reasons) {
-    TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
+  if (scroll_node->main_thread_scrolling_reasons) {
+    TRACE_EVENT1("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread",
+                 "MainThreadScrollingReason",
+                 scroll_node->main_thread_scrolling_reasons);
     scroll_status.thread = InputHandler::SCROLL_ON_MAIN_THREAD;
     scroll_status.main_thread_scrolling_reasons =
         scroll_node->main_thread_scrolling_reasons;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
index 4e2e55c..f9d5bd1d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
@@ -144,7 +144,9 @@
                         mWasSearchContentViewSeen, wasAnySuppressionHeuristicSatisfied);
                 ContextualSearchUma.logSelectionLengthResultsSeen(
                         mWasSearchContentViewSeen, mSelectionLength);
+                ContextualSearchUma.logTapResultsSeen(mWasSearchContentViewSeen);
             }
+            ContextualSearchUma.logAllResultsSeen(mWasSearchContentViewSeen);
 
             // Notifications to Feature Engagement.
             ContextualSearchIPH.doSearchFinishedNotifications(profile, mWasSearchContentViewSeen,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
index 5153513..12af884 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
@@ -695,6 +695,24 @@
     }
 
     /**
+     * Logs whether search results were seen for a Tap gesture.  Recorded for all users.
+     * @param wasPanelSeen Whether the panel was seen.
+     */
+    public static void logTapResultsSeen(boolean wasPanelSeen) {
+        RecordHistogram.recordBooleanHistogram(
+                "Search.ContextualSearch.Tap.ResultsSeen", wasPanelSeen);
+    }
+
+    /**
+     * Logs whether search results were seen for all gestures.  Recorded for all users.
+     * @param wasPanelSeen Whether the panel was seen.
+     */
+    public static void logAllResultsSeen(boolean wasPanelSeen) {
+        RecordHistogram.recordBooleanHistogram(
+                "Search.ContextualSearch.All.ResultsSeen", wasPanelSeen);
+    }
+
+    /**
      * Logs the whether the panel was seen and the type of the trigger and if Bar nearly overlapped.
      * If the panel was seen, logs the duration of the panel view into a BarOverlap or BarNoOverlap
      * duration histogram.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDialog.java
index 0455e06..1251076 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDialog.java
@@ -65,7 +65,19 @@
             if (view instanceof ViewGroup) {
                 disableSoftKeyboard((ViewGroup) view);
             } else if (view instanceof TextView) {
-                ((TextView) view).setInputType(InputType.TYPE_NULL);
+                TextView text = (TextView) view;
+                // It is important to avoid setting InputType to NULL again. Otherwise, it will
+                // change the TextView to single line mode and cause other unexpected issues(such as
+                // text in button is not captiablized).
+                int type = text.getInputType();
+                if (type != InputType.TYPE_NULL) {
+                    text.setInputType(InputType.TYPE_NULL);
+                    // If the TextView has multi line flag, reset line mode to multi line.
+                    if ((type & (InputType.TYPE_MASK_CLASS | InputType.TYPE_TEXT_FLAG_MULTI_LINE))
+                            == (InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE)) {
+                        text.setSingleLine(false);
+                    }
+                }
             }
         }
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
index d77bee1..0e76087 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -171,6 +171,7 @@
     private ContextualSearchPolicy mPolicy;
     private ContextualSearchSelectionController mSelectionController;
     private EmbeddedTestServer mTestServer;
+    private boolean mPollInstrumentationThread;
 
     private float mDpToPx;
 
@@ -801,10 +802,11 @@
 
     /**
      * Waits for the Search Panel to enter the given {@code PanelState} and assert.
+     * Waits on the UI thread unless mPollInstrumentationThread is set.
      * @param state The {@link PanelState} to wait for.
      */
     private void waitForPanelToEnterState(final PanelState state) {
-        CriteriaHelper.pollUiThread(new Criteria() {
+        final Criteria panelStateCriteria = new Criteria() {
             @Override
             public boolean isSatisfied() {
                 if (mPanel == null) return false;
@@ -812,7 +814,12 @@
                         + "Instead, the current state is " + mPanel.getPanelState() + ".");
                 return mPanel.getPanelState() == state && !mPanel.isHeightAnimationRunning();
             }
-        }, TEST_TIMEOUT, DEFAULT_POLLING_INTERVAL);
+        };
+        if (mPollInstrumentationThread) {
+            CriteriaHelper.pollInstrumentationThread(panelStateCriteria);
+        } else {
+            CriteriaHelper.pollUiThread(panelStateCriteria);
+        }
     }
 
     /**
@@ -854,18 +861,24 @@
 
     /**
      * Waits for the selection to be empty.
+     * Waits on the UI thread unless mPollInstrumentationThread is set.
      * Use this method any time a test repeatedly establishes and dissolves a selection to ensure
      * that the selection has been completely dissolved before simulating the next selection event.
      * This is needed because the renderer's notification of a selection going away is async,
      * and a subsequent tap may think there's a current selection until it has been dissolved.
      */
     private void waitForSelectionEmpty() {
-        CriteriaHelper.pollUiThread(new Criteria("Selection never empty.") {
+        final Criteria selectionEmptyCriteria = new Criteria("Selection never empty.") {
             @Override
             public boolean isSatisfied() {
                 return mSelectionController.isSelectionEmpty();
             }
-        }, TEST_TIMEOUT, DEFAULT_POLLING_INTERVAL);
+        };
+        if (mPollInstrumentationThread) {
+            CriteriaHelper.pollInstrumentationThread(selectionEmptyCriteria);
+        } else {
+            CriteriaHelper.pollUiThread(selectionEmptyCriteria);
+        }
     }
 
     /**
@@ -1031,7 +1044,6 @@
     private void clickToTriggerPrefetch() throws InterruptedException, TimeoutException {
         mFakeServer.reset();
         simulateTapSearch("search");
-        waitForPanelToPeek();
         closePanel();
         waitForPanelToCloseAndSelectionEmpty();
     }
@@ -2196,6 +2208,19 @@
     }
 
     /**
+     * Tests a bunch of taps in a row, with the variation that we wait on the instrumentation
+     * thread instead of the UI thread for some wait sequences.
+     */
+    @Test
+    @LargeTest
+    @Feature({"ContextualSearch"})
+    @DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.LOLLIPOP, message = "crbug.com/818897")
+    public void testTapALotInstrumentation() throws InterruptedException, TimeoutException {
+        mPollInstrumentationThread = true;
+        testTapALot();
+    }
+
+    /**
      * Tests ContextualSearchManager#shouldInterceptNavigation for a case that an external
      * navigation has a user gesture.
      */
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 06828487..06f568b4 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -3006,18 +3006,9 @@
           <message name="IDS_TASK_MANAGER_CPU_TIME_COLUMN" desc="The text of the CPU time usage column">
             CPU Time
           </message>
-          <message name="IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN" desc="Task manager process memory column. This is the similar to the process 'working set' reported by the Windows Task Manager">
-            Memory
-          </message>
           <message name="IDS_TASK_MANAGER_MEM_FOOTPRINT_COLUMN" desc="Task manager process memory footprint column. This is the amount of memory used by the process.">
             Memory footprint
           </message>
-          <message name="IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN" desc="Task manager process private memory column. This is the allocated size that cannot be shared with other processes">
-            Private memory
-          </message>
-          <message name="IDS_TASK_MANAGER_SHARED_MEM_COLUMN" desc="Task manager process shared memory column. Shows the size of the memory used by the process which is shared with other processes">
-            Shared memory
-          </message>
           <message name="IDS_TASK_MANAGER_SWAPPED_MEM_COLUMN" desc="Task manager process swapped memory column. Shows the size of the memory that lives in the swap space.">
             Swapped memory
           </message>
@@ -3095,15 +3086,6 @@
           <message name="IDS_TASK_MANAGER_MEM_FOOTPRINT_COLUMN" desc="Task manager process memory footprint column. This is the amount of memory used by the process.">
             Memory Footprint
           </message>
-          <message name="IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN" desc="Task manager process memory column. This is the similar to the process 'working set' reported by the Windows Task Manager">
-            Memory
-          </message>
-          <message name="IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN" desc="Task manager process private memory column. This is the allocated size that cannot be shared with other processes">
-            Private Memory
-          </message>
-          <message name="IDS_TASK_MANAGER_SHARED_MEM_COLUMN" desc="Task manager process shared memory column. Shows the size of the memory used by the process which is shared with other processes">
-            Shared Memory
-          </message>
           <message name="IDS_TASK_MANAGER_SWAPPED_MEM_COLUMN" desc="Task manager process swapped memory column. Shows the size of the memory that lives in the swap space.">
             Swapped Memory
           </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 40ada5b..916d452 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -730,11 +730,11 @@
     "mod_pagespeed/mod_pagespeed_metrics.cc",
     "mod_pagespeed/mod_pagespeed_metrics.h",
     "native_window_notification_source.h",
+    "net/chrome_accept_language_settings.cc",
+    "net/chrome_accept_language_settings.h",
     "net/chrome_cookie_notification_details.h",
     "net/chrome_extensions_network_delegate.cc",
     "net/chrome_extensions_network_delegate.h",
-    "net/chrome_http_user_agent_settings.cc",
-    "net/chrome_http_user_agent_settings.h",
     "net/chrome_mojo_proxy_resolver_factory.cc",
     "net/chrome_mojo_proxy_resolver_factory.h",
     "net/chrome_net_log_helper.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b10fcf9..280d6c7 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -467,7 +467,9 @@
     {flag_descriptions::kTopChromeMdMaterialAuto, switches::kTopChromeMD,
      switches::kTopChromeMDMaterialAuto},
     {flag_descriptions::kTopChromeMdMaterialTouchOptimized,
-     switches::kTopChromeMD, switches::kTopChromeMDMaterialTouchOptimized}};
+     switches::kTopChromeMD, switches::kTopChromeMDMaterialTouchOptimized},
+    {flag_descriptions::kTopChromeMdMaterialRefresh, switches::kTopChromeMD,
+     switches::kTopChromeMDMaterialRefresh}};
 
 #if defined(OS_CHROMEOS)
 const FeatureEntry::Choice kAshShelfColorChoices[] = {
diff --git a/chrome/browser/android/vr/vr_gl_thread.cc b/chrome/browser/android/vr/vr_gl_thread.cc
index 76f27f2d..2899455 100644
--- a/chrome/browser/android/vr/vr_gl_thread.cc
+++ b/chrome/browser/android/vr/vr_gl_thread.cc
@@ -209,10 +209,11 @@
       base::BindOnce(&VrShell::OnContentPaused, weak_vr_shell_, enabled));
 }
 
-void VrGLThread::Navigate(GURL gurl) {
+void VrGLThread::Navigate(GURL gurl, NavigationMethod method) {
   DCHECK(OnGlThread());
   main_thread_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&VrShell::Navigate, weak_vr_shell_, gurl));
+      FROM_HERE,
+      base::BindOnce(&VrShell::Navigate, weak_vr_shell_, gurl, method));
 }
 
 void VrGLThread::NavigateBack() {
diff --git a/chrome/browser/android/vr/vr_gl_thread.h b/chrome/browser/android/vr/vr_gl_thread.h
index 24315371..f3b0a63f 100644
--- a/chrome/browser/android/vr/vr_gl_thread.h
+++ b/chrome/browser/android/vr/vr_gl_thread.h
@@ -79,7 +79,7 @@
   // UiBrowserInterface implementation (UI calling to VrShell).
   void ExitPresent() override;
   void ExitFullscreen() override;
-  void Navigate(GURL gurl) override;
+  void Navigate(GURL gurl, NavigationMethod method) override;
   void NavigateBack() override;
   void ExitCct() override;
   void CloseHostedDialog() override;
diff --git a/chrome/browser/android/vr/vr_shell.cc b/chrome/browser/android/vr/vr_shell.cc
index 8184fab..cc0690b1 100644
--- a/chrome/browser/android/vr/vr_shell.cc
+++ b/chrome/browser/android/vr/vr_shell.cc
@@ -331,8 +331,18 @@
     device->Focus();
 }
 
-void VrShell::Navigate(GURL url) {
+void VrShell::Navigate(GURL url, NavigationMethod method) {
   JNIEnv* env = base::android::AttachCurrentThread();
+
+  // Record metrics.
+  if (method == NavigationMethod::kOmniboxSuggestionSelected ||
+      method == NavigationMethod::kOmniboxUrlEntry) {
+    SessionMetricsHelper* metrics_helper =
+        SessionMetricsHelper::FromWebContents(web_contents_);
+    if (metrics_helper)
+      metrics_helper->RecordUrlRequested(url, method);
+  }
+
   Java_VrShellImpl_loadUrl(
       env, j_vr_shell_,
       base::android::ConvertUTF8ToJavaString(env, url.spec()));
@@ -1016,7 +1026,7 @@
   SessionMetricsHelper* metrics_helper =
       SessionMetricsHelper::FromWebContents(web_contents_);
   if (metrics_helper && input_was_url)
-    metrics_helper->RecordUrlRequestedByVoice(url);
+    metrics_helper->RecordUrlRequested(url, NavigationMethod::kVoiceSearch);
 
   Java_VrShellImpl_loadUrl(
       env, j_vr_shell_,
diff --git a/chrome/browser/android/vr/vr_shell.h b/chrome/browser/android/vr/vr_shell.h
index 2f1e504..99c6fc5 100644
--- a/chrome/browser/android/vr/vr_shell.h
+++ b/chrome/browser/android/vr/vr_shell.h
@@ -21,6 +21,7 @@
 #include "chrome/browser/vr/exit_vr_prompt_choice.h"
 #include "chrome/browser/vr/speech_recognizer.h"
 #include "chrome/browser/vr/ui.h"
+#include "chrome/browser/vr/ui_browser_interface.h"
 #include "chrome/browser/vr/ui_unsupported_mode.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "device/vr/android/gvr/cardboard_gamepad_data_provider.h"
@@ -122,7 +123,7 @@
                     jboolean incognito,
                     jint id);
   void OnContentPaused(bool paused);
-  void Navigate(GURL url);
+  void Navigate(GURL url, NavigationMethod method);
   void NavigateBack();
   void ExitCct();
   void CloseHostedDialog();
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
index 1f6c3a2..643dbc40 100644
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -393,11 +393,11 @@
 bool ChromeAutocompleteProviderClient::StrippedURLsAreEqual(
     const GURL& url1,
     const GURL& url2,
-    const AutocompleteInput* input) {
+    const AutocompleteInput* input) const {
   AutocompleteInput empty_input;
   if (!input)
     input = &empty_input;
-  TemplateURLService* template_url_service = GetTemplateURLService();
+  const TemplateURLService* template_url_service = GetTemplateURLService();
   return AutocompleteMatch::GURLToStrippedGURL(url1, AutocompleteInput(),
                                                template_url_service,
                                                base::string16()) ==
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
index 9465c0d..4ba760aa 100644
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
@@ -76,7 +76,7 @@
 
   bool StrippedURLsAreEqual(const GURL& url1,
                             const GURL& url2,
-                            const AutocompleteInput* input);
+                            const AutocompleteInput* input) const;
 
  private:
   Profile* profile_;
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc
index 7332100..b7cc65d3 100644
--- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc
+++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service.cc
@@ -318,10 +318,12 @@
                        ->GetHost()
                        ->GetRootTransform();
   float scale_factor = ash::GetScaleFactorForTransform(transform);
-  web_contents->RequestAXTreeSnapshot(base::BindOnce(
-      &RequestVoiceInteractionStructureCallback, std::move(callback),
-      gfx::ConvertRectToPixel(scale_factor, browser->window()->GetBounds()),
-      web_contents->GetLastCommittedURL().spec(), web_contents->GetTitle()));
+  web_contents->RequestAXTreeSnapshot(
+      base::BindOnce(
+          &RequestVoiceInteractionStructureCallback, std::move(callback),
+          gfx::ConvertRectToPixel(scale_factor, browser->window()->GetBounds()),
+          web_contents->GetLastCommittedURL().spec(), web_contents->GetTitle()),
+      ui::kAXModeComplete);
 }
 
 void ArcVoiceInteractionArcHomeService::OnVoiceInteractionOobeSetupComplete() {
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service_browsertest.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service_browsertest.cc
index d86144c..9a68ae0 100644
--- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service_browsertest.cc
+++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service_browsertest.cc
@@ -58,8 +58,10 @@
     ui_test_utils::NavigateToURL(browser(), url);
     auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
     AXTreeSnapshotWaiter waiter;
-    web_contents->RequestAXTreeSnapshot(base::BindOnce(
-        &AXTreeSnapshotWaiter::ReceiveSnapshot, base::Unretained(&waiter)));
+    web_contents->RequestAXTreeSnapshot(
+        base::BindOnce(&AXTreeSnapshotWaiter::ReceiveSnapshot,
+                       base::Unretained(&waiter)),
+        ui::kAXModeComplete);
     waiter.Wait();
     auto node = ui::AXSnapshotNodeAndroid::Create(waiter.snapshot(), false);
     return ArcVoiceInteractionArcHomeService::
diff --git a/chrome/browser/chromeos/resource_reporter/resource_reporter.cc b/chrome/browser/chromeos/resource_reporter/resource_reporter.cc
index cc5e033..815f1e69 100644
--- a/chrome/browser/chromeos/resource_reporter/resource_reporter.cc
+++ b/chrome/browser/chromeos/resource_reporter/resource_reporter.cc
@@ -148,7 +148,7 @@
         (observed_task_manager()->GetPlatformIndependentCPUUsage(id) /
          base::SysInfo::NumberOfProcessors());
     const int64_t memory_usage =
-        observed_task_manager()->GetPhysicalMemoryUsage(id);
+        observed_task_manager()->GetMemoryFootprintUsage(id);
 
     // Browser and GPU processes are reported later using UMA histograms as they
     // don't have any privacy issues.
@@ -203,7 +203,7 @@
 ResourceReporter::ResourceReporter()
     : TaskManagerObserver(base::TimeDelta::FromSeconds(kRefreshIntervalSeconds),
                           task_manager::REFRESH_TYPE_CPU |
-                              task_manager::REFRESH_TYPE_MEMORY |
+                              task_manager::REFRESH_TYPE_MEMORY_FOOTPRINT |
                               task_manager::REFRESH_TYPE_PRIORITY),
       task_manager_to_observe_(nullptr),
       system_cpu_cores_range_(GetCurrentSystemCpuCoresRange()),
diff --git a/chrome/browser/chromeos/resource_reporter/resource_reporter.h b/chrome/browser/chromeos/resource_reporter/resource_reporter.h
index e33992a..9046317 100644
--- a/chrome/browser/chromeos/resource_reporter/resource_reporter.h
+++ b/chrome/browser/chromeos/resource_reporter/resource_reporter.h
@@ -53,10 +53,10 @@
     // percentage [0.0, 100.0].
     double cpu_percent;
 
-    // The physical memory usage of the task from the most recent task manager
+    // The memory footprint of the task from the most recent task manager
     // refresh in bytes. It doesn't include shared memory. A value of -1 is
     // invalid and means that the memory usage measurement for this task is not
-    // ready yet. See TaskManagerInterface::GetPhysicalMemoryUsage().
+    // ready yet. See TaskManagerInterface::GetMemoryFootprintUsage().
     int64_t memory_bytes;
 
     // True if the task is running on a process at background priority.
diff --git a/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc b/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc
index 89ca2a00..aa1dd5c0 100644
--- a/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc
+++ b/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc
@@ -76,7 +76,7 @@
     return tasks_.at(task_id)->cpu_percent *
            base::SysInfo::NumberOfProcessors();
   }
-  int64_t GetPhysicalMemoryUsage(TaskId task_id) const override {
+  int64_t GetMemoryFootprintUsage(TaskId task_id) const override {
     return tasks_.at(task_id)->memory_bytes;
   }
   const std::string& GetTaskNameForRappor(TaskId task_id) const override {
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index b96c11b..8c36b90 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -633,6 +633,10 @@
       ->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS, std::string(),
                               &host_settings);
   EXPECT_EQ(1u, host_settings.size());
+
+  // Clear settings.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
 }
 
 // Ensure that when the JavaScript is blocked, persisted client hints are not
@@ -753,6 +757,10 @@
   EXPECT_EQ(2u, count_client_hints_headers_seen());
   EXPECT_EQ(3u, third_party_request_count_seen());
   EXPECT_EQ(0u, third_party_client_hints_count_seen());
+
+  // Clear settings.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
 }
 
 // Ensure that when the cookies is blocked, client hints are not attached to the
@@ -809,6 +817,10 @@
   EXPECT_EQ(2u, count_client_hints_headers_seen());
   EXPECT_EQ(3u, third_party_request_count_seen());
   EXPECT_EQ(0u, third_party_client_hints_count_seen());
+
+  // Clear settings.
+  HostContentSettingsMapFactory::GetForProfile(browser()->profile())
+      ->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_COOKIES);
 }
 
 // Check the client hints for the given URL in an incognito window.
diff --git a/chrome/browser/content_settings/content_settings_browsertest.cc b/chrome/browser/content_settings/content_settings_browsertest.cc
index 88059c0..8a61a5f 100644
--- a/chrome/browser/content_settings/content_settings_browsertest.cc
+++ b/chrome/browser/content_settings/content_settings_browsertest.cc
@@ -473,6 +473,19 @@
     content_settings_map->SetDefaultContentSetting(
         CONTENT_SETTINGS_TYPE_JAVASCRIPT, CONTENT_SETTING_BLOCK);
   }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    PepperContentSettingsSpecialCasesTest::SetUpCommandLine(command_line);
+    // ClientHintsPersistent feature queries the status of JavaScript content
+    // setting on every page load. When JavaScript is blocked, this results in
+    // tab_settings->IsContentBlocked(CONTENT_SETTINGS_TYPE_JAVASCRIPT) always
+    // returning true in RunJavaScriptBlockedTest() method. This interferes with
+    // the execution of the test.
+    // TODO: https://crbug.com/822553: Make these tests compatible with the
+    // client hints feature.
+    command_line->AppendSwitchASCII("disable-blink-features",
+                                    "ClientHintsPersistent");
+  }
 };
 
 // A sanity check to verify that the plugin that is used as a baseline below
diff --git a/chrome/browser/extensions/api/processes/processes_api.cc b/chrome/browser/extensions/api/processes/processes_api.cc
index 4ec343e..38041677 100644
--- a/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chrome/browser/extensions/api/processes/processes_api.cc
@@ -276,11 +276,11 @@
                     &process);
 
     if (has_on_updated_with_memory_listeners) {
-      // Append the private memory usage to the process data.
-      const int64_t private_memory =
-          observed_task_manager()->GetPrivateMemoryUsage(task_id);
-      process.private_memory.reset(new double(static_cast<double>(
-          private_memory)));
+      // Append the memory footprint to the process data.
+      const int64_t memory_footprint =
+          observed_task_manager()->GetMemoryFootprintUsage(task_id);
+      process.private_memory =
+          std::make_unique<double>(static_cast<double>(memory_footprint));
     }
 
     // Store each process indexed by the string version of its ChildProcessHost
@@ -376,8 +376,10 @@
   if (HasEventListeners(api::processes::OnUpdated::kEventName))
     refresh_types |= on_updated_types;
 
-  if (HasEventListeners(api::processes::OnUpdatedWithMemory::kEventName))
-    refresh_types |= (on_updated_types | task_manager::REFRESH_TYPE_MEMORY);
+  if (HasEventListeners(api::processes::OnUpdatedWithMemory::kEventName)) {
+    refresh_types |=
+        (on_updated_types | task_manager::REFRESH_TYPE_MEMORY_FOOTPRINT);
+  }
 
   SetRefreshTypesFlags(refresh_types);
 }
@@ -581,7 +583,7 @@
 
   include_memory_ = params->include_memory;
   if (include_memory_)
-    AddRefreshType(task_manager::REFRESH_TYPE_MEMORY);
+    AddRefreshType(task_manager::REFRESH_TYPE_MEMORY_FOOTPRINT);
 
   // Keep this object alive until the first of either OnTasksRefreshed() or
   // OnTasksRefreshedWithBackgroundCalculations() is received depending on
@@ -663,11 +665,11 @@
                     &process);
 
     if (include_memory_) {
-      // Append the private memory usage to the process data.
-      const int64_t private_memory =
-          observed_task_manager()->GetPrivateMemoryUsage(task_id);
-      process.private_memory.reset(new double(static_cast<double>(
-          private_memory)));
+      // Append the memory footprint to the process data.
+      const int64_t memory_footprint =
+          observed_task_manager()->GetMemoryFootprintUsage(task_id);
+      process.private_memory =
+          std::make_unique<double>(static_cast<double>(memory_footprint));
     }
 
     // Store each process indexed by the string version of its
diff --git a/chrome/browser/extensions/api/processes/processes_apitest.cc b/chrome/browser/extensions/api/processes/processes_apitest.cc
index 42668f26..da8e064 100644
--- a/chrome/browser/extensions/api/processes/processes_apitest.cc
+++ b/chrome/browser/extensions/api/processes/processes_apitest.cc
@@ -61,7 +61,7 @@
       task_manager::TaskManagerInterface::GetTaskManager();
   EXPECT_EQ(2, GetListenersCount());
   EXPECT_TRUE(task_manager->IsResourceRefreshEnabled(
-      task_manager::REFRESH_TYPE_MEMORY));
+      task_manager::REFRESH_TYPE_MEMORY_FOOTPRINT));
 
   // Unload the extensions and make sure the listeners count is updated.
   UnloadExtension(extension2->id());
@@ -92,7 +92,7 @@
   EXPECT_FALSE(event_router->HasEventListener(
       extensions::api::processes::OnUpdated::kEventName));
   EXPECT_TRUE(task_manager->IsResourceRefreshEnabled(
-      task_manager::REFRESH_TYPE_MEMORY));
+      task_manager::REFRESH_TYPE_MEMORY_FOOTPRINT));
 
   // Despite the fact that there are no onUpdated listeners, refresh types for
   // CPU, Network, SQLite, V8 memory, and webcache stats should be enabled.
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc
index c51d496..acf90c0 100644
--- a/chrome/browser/extensions/process_manager_browsertest.cc
+++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -1081,8 +1081,9 @@
 
 // Test that a web frame can't navigate a proxy for an extension frame to a
 // blob/filesystem extension URL.  See https://crbug.com/656752.
+// Disabled due to flake, see http://crbug.com/822635.
 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest,
-                       NestedURLNavigationsViaProxyBlocked) {
+                       DISABLED_NestedURLNavigationsViaProxyBlocked) {
   // Create a simple extension without a background page.
   const Extension* extension = CreateExtension("Extension", false);
   embedded_test_server()->ServeFilesFromDirectory(extension->path());
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 5140521f..a6128bc 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1520,12 +1520,14 @@
 const char kTopChromeMd[] = "UI Layout for the browser's top chrome";
 const char kTopChromeMdDescription[] =
     "Toggles between 1) Normal - for clamshell devices, 2) Hybrid (previously "
-    "touch) - middle point for devices with a touch screen, and 3) Touchable "
-    "- new unified interface for touch and convertibles (Chrome OS).";
+    "touch) - middle point for devices with a touch screen, 3) Touchable "
+    "- new unified interface for touch and convertibles (Chrome OS) and 4) "
+    "Material Design refresh.";
 const char kTopChromeMdMaterial[] = "Normal";
 const char kTopChromeMdMaterialAuto[] = "Auto";
 const char kTopChromeMdMaterialHybrid[] = "Hybrid";
 const char kTopChromeMdMaterialTouchOptimized[] = "Touchable";
+const char kTopChromeMdMaterialRefresh[] = "Refresh";
 
 const char kThreadedScrollingName[] = "Threaded scrolling";
 const char kThreadedScrollingDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 5c15acd0..035cee2 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -939,6 +939,7 @@
 extern const char kTopChromeMdMaterialAuto[];
 extern const char kTopChromeMdMaterialHybrid[];
 extern const char kTopChromeMdMaterialTouchOptimized[];
+extern const char kTopChromeMdMaterialRefresh[];
 
 extern const char kThreadedScrollingName[];
 extern const char kThreadedScrollingDescription[];
diff --git a/chrome/browser/media/router/discovery/dial/dial_service.cc b/chrome/browser/media/router/discovery/dial/dial_service.cc
index c8ede26..2437070 100644
--- a/chrome/browser/media/router/discovery/dial/dial_service.cc
+++ b/chrome/browser/media/router/discovery/dial/dial_service.cc
@@ -13,7 +13,6 @@
 #include "base/callback.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/task_scheduler/post_task.h"
@@ -182,9 +181,8 @@
   DCHECK(!socket_);
   DCHECK(bind_ip_address.IsIPv4());
 
-  net::RandIntCallback rand_cb = base::Bind(&base::RandInt);
   socket_ = std::make_unique<UDPSocket>(net::DatagramSocket::RANDOM_BIND,
-                                        rand_cb, net_log, net::NetLogSource());
+                                        net_log, net::NetLogSource());
 
   // 0 means bind a random port
   net::IPEndPoint address(bind_ip_address, 0);
diff --git a/chrome/browser/net/chrome_http_user_agent_settings.cc b/chrome/browser/net/chrome_accept_language_settings.cc
similarity index 60%
rename from chrome/browser/net/chrome_http_user_agent_settings.cc
rename to chrome/browser/net/chrome_accept_language_settings.cc
index c8e79bf2..cf96988 100644
--- a/chrome/browser/net/chrome_http_user_agent_settings.cc
+++ b/chrome/browser/net/chrome_accept_language_settings.cc
@@ -2,20 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/net/chrome_http_user_agent_settings.h"
+#include "chrome/browser/net/chrome_accept_language_settings.h"
+
+#include <unordered_set>
 
 #include "base/feature_list.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/common/chrome_content_client.h"
 #include "chrome/common/chrome_features.h"
-#include "chrome/common/pref_names.h"
-#include "components/prefs/pref_service.h"
-#include "content/public/browser/browser_thread.h"
 #include "net/http/http_util.h"
 
+namespace chrome_accept_language_settings {
 namespace {
 
 // Helper class that builds the list of languages for the Accept-Language
@@ -57,24 +56,7 @@
 
 }  // namespace
 
-ChromeHttpUserAgentSettings::ChromeHttpUserAgentSettings(PrefService* prefs) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  pref_accept_language_.Init(prefs::kAcceptLanguages, prefs);
-  last_pref_accept_language_ = *pref_accept_language_;
-  last_http_accept_language_ =
-      ComputeAcceptLanguageFromPref(last_pref_accept_language_);
-
-  pref_accept_language_.MoveToThread(
-      content::BrowserThread::GetTaskRunnerForThread(
-          content::BrowserThread::IO));
-}
-
-ChromeHttpUserAgentSettings::~ChromeHttpUserAgentSettings() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-}
-
-std::string ChromeHttpUserAgentSettings::ComputeAcceptLanguageFromPref(
-    const std::string& language_pref) {
+std::string ComputeAcceptLanguageFromPref(const std::string& language_pref) {
   std::string accept_languages_str =
       base::FeatureList::IsEnabled(features::kUseNewAcceptLanguageHeader)
           ? ExpandLanguageList(language_pref)
@@ -82,8 +64,7 @@
   return net::HttpUtil::GenerateAcceptLanguageHeader(accept_languages_str);
 }
 
-std::string ChromeHttpUserAgentSettings::ExpandLanguageList(
-    const std::string& language_prefs) {
+std::string ExpandLanguageList(const std::string& language_prefs) {
   const std::vector<std::string> languages = base::SplitString(
       language_prefs, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
 
@@ -111,26 +92,4 @@
   return builder.GetString();
 }
 
-void ChromeHttpUserAgentSettings::CleanupOnUIThread() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  pref_accept_language_.Destroy();
-}
-
-std::string ChromeHttpUserAgentSettings::GetAcceptLanguage() const {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  std::string new_pref_accept_language = *pref_accept_language_;
-
-  if (new_pref_accept_language != last_pref_accept_language_) {
-    last_http_accept_language_ =
-        ComputeAcceptLanguageFromPref(new_pref_accept_language);
-    last_pref_accept_language_ = new_pref_accept_language;
-  }
-
-  return last_http_accept_language_;
-}
-
-std::string ChromeHttpUserAgentSettings::GetUserAgent() const {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  return ::GetUserAgent();
-}
-
+}  // namespace chrome_accept_language_settings
diff --git a/chrome/browser/net/chrome_accept_language_settings.h b/chrome/browser/net/chrome_accept_language_settings.h
new file mode 100644
index 0000000..470d1575
--- /dev/null
+++ b/chrome/browser/net/chrome_accept_language_settings.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NET_CHROME_ACCEPT_LANGUAGE_SETTINGS_H_
+#define CHROME_BROWSER_NET_CHROME_ACCEPT_LANGUAGE_SETTINGS_H_
+
+#include <string>
+
+namespace chrome_accept_language_settings {
+
+// Given value of prefs::kAcceptLanguages pref, computes the corresponding
+// Accept-Language header to send.
+std::string ComputeAcceptLanguageFromPref(const std::string& language_pref);
+
+// Adds the base language if a corresponding language+region code is present.
+std::string ExpandLanguageList(const std::string& language_prefs);
+
+}  // namespace chrome_accept_language_settings
+
+#endif  // CHROME_BROWSER_NET_CHROME_ACCEPT_LANGUAGE_SETTINGS_H_
diff --git a/chrome/browser/net/chrome_accept_language_settings_unittest.cc b/chrome/browser/net/chrome_accept_language_settings_unittest.cc
new file mode 100644
index 0000000..53ab1f30
--- /dev/null
+++ b/chrome/browser/net/chrome_accept_language_settings_unittest.cc
@@ -0,0 +1,41 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/net/chrome_accept_language_settings.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Test the expansion of the Language List.
+TEST(ChromeAcceptLanguageSettings, ExpandLanguageList) {
+  std::string output = chrome_accept_language_settings::ExpandLanguageList("");
+  EXPECT_EQ("", output);
+
+  output = chrome_accept_language_settings::ExpandLanguageList("en-US");
+  EXPECT_EQ("en-US,en", output);
+
+  output = chrome_accept_language_settings::ExpandLanguageList("fr");
+  EXPECT_EQ("fr", output);
+
+  // The base language is added after all regional codes...
+  output = chrome_accept_language_settings::ExpandLanguageList("en-US,en-CA");
+  EXPECT_EQ("en-US,en-CA,en", output);
+
+  // ... but before other language families.
+  output =
+      chrome_accept_language_settings::ExpandLanguageList("en-US,en-CA,fr");
+  EXPECT_EQ("en-US,en-CA,en,fr", output);
+
+  output = chrome_accept_language_settings::ExpandLanguageList(
+      "en-US,en-CA,fr,en-AU");
+  EXPECT_EQ("en-US,en-CA,en,fr,en-AU", output);
+
+  output =
+      chrome_accept_language_settings::ExpandLanguageList("en-US,en-CA,fr-CA");
+  EXPECT_EQ("en-US,en-CA,en,fr-CA,fr", output);
+
+  // Add a base language even if it's already in the list.
+  output = chrome_accept_language_settings::ExpandLanguageList(
+      "en-US,fr-CA,it,fr,es-AR,it-IT");
+  EXPECT_EQ("en-US,en,fr-CA,fr,it,es-AR,es,it-IT", output);
+}
diff --git a/chrome/browser/net/chrome_http_user_agent_settings.h b/chrome/browser/net/chrome_http_user_agent_settings.h
deleted file mode 100644
index a13d881..0000000
--- a/chrome/browser/net/chrome_http_user_agent_settings.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_NET_CHROME_HTTP_USER_AGENT_SETTINGS_H_
-#define CHROME_BROWSER_NET_CHROME_HTTP_USER_AGENT_SETTINGS_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "components/prefs/pref_member.h"
-#include "net/url_request/http_user_agent_settings.h"
-
-class PrefService;
-
-// An implementation of |HttpUserAgentSettings| that provides HTTP header
-// Accept-Language value that tracks Pref settings.
-class ChromeHttpUserAgentSettings : public net::HttpUserAgentSettings {
- public:
-  // Must be called on the UI thread.
-  explicit ChromeHttpUserAgentSettings(PrefService* prefs);
-  // Must be called on the IO thread.
-  ~ChromeHttpUserAgentSettings() override;
-
-  // Given the language setting in the Prefs::kAcceptLanguages setting, returns
-  // the appropriate value of Accept-Language header to send.
-  static std::string ComputeAcceptLanguageFromPref(
-      const std::string& language_pref);
-
-  // Adds the base language if a corresponding language+region code is present.
-  static std::string ExpandLanguageList(const std::string& language_prefs);
-
-  void CleanupOnUIThread();
-
-  // net::HttpUserAgentSettings implementation
-  std::string GetAcceptLanguage() const override;
-  std::string GetUserAgent() const override;
-
- private:
-  StringPrefMember pref_accept_language_;
-
-  // Avoid re-processing by caching the last value from the preferences and the
-  // last result of processing via net::HttpUtil::GenerateAccept*Header().
-  mutable std::string last_pref_accept_language_;
-  mutable std::string last_http_accept_language_;
-
-  DISALLOW_COPY_AND_ASSIGN(ChromeHttpUserAgentSettings);
-};
-
-#endif  // CHROME_BROWSER_NET_CHROME_HTTP_USER_AGENT_SETTINGS_H_
-
diff --git a/chrome/browser/net/chrome_http_user_agent_settings_unittest.cc b/chrome/browser/net/chrome_http_user_agent_settings_unittest.cc
deleted file mode 100644
index 5f4f65f..0000000
--- a/chrome/browser/net/chrome_http_user_agent_settings_unittest.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/net/chrome_http_user_agent_settings.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-// Test the expansion of the Language List.
-TEST(ChromeHttpUserAgentSettings, ExpandLanguageList) {
-  std::string output = ChromeHttpUserAgentSettings::ExpandLanguageList("");
-  EXPECT_EQ("", output);
-
-  output = ChromeHttpUserAgentSettings::ExpandLanguageList("en-US");
-  EXPECT_EQ("en-US,en", output);
-
-  output = ChromeHttpUserAgentSettings::ExpandLanguageList("fr");
-  EXPECT_EQ("fr", output);
-
-  // The base language is added after all regional codes...
-  output = ChromeHttpUserAgentSettings::ExpandLanguageList("en-US,en-CA");
-  EXPECT_EQ("en-US,en-CA,en", output);
-
-  // ... but before other language families.
-  output = ChromeHttpUserAgentSettings::ExpandLanguageList("en-US,en-CA,fr");
-  EXPECT_EQ("en-US,en-CA,en,fr", output);
-
-  output =
-      ChromeHttpUserAgentSettings::ExpandLanguageList("en-US,en-CA,fr,en-AU");
-  EXPECT_EQ("en-US,en-CA,en,fr,en-AU", output);
-
-  output = ChromeHttpUserAgentSettings::ExpandLanguageList("en-US,en-CA,fr-CA");
-  EXPECT_EQ("en-US,en-CA,en,fr-CA,fr", output);
-
-  // Add a base language even if it's already in the list.
-  output = ChromeHttpUserAgentSettings::ExpandLanguageList(
-      "en-US,fr-CA,it,fr,es-AR,it-IT");
-  EXPECT_EQ("en-US,en,fr-CA,fr,it,es-AR,es,it-IT", output);
-}
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc
index 2130cdc7..5e9f503 100644
--- a/chrome/browser/net/profile_network_context_service.cc
+++ b/chrome/browser/net/profile_network_context_service.cc
@@ -12,7 +12,7 @@
 #include "base/logging.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/net/chrome_http_user_agent_settings.h"
+#include "chrome/browser/net/chrome_accept_language_settings.h"
 #include "chrome/browser/net/default_network_context_params.h"
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
@@ -115,7 +115,7 @@
 }
 
 std::string ProfileNetworkContextService::ComputeAcceptLanguage() const {
-  return ChromeHttpUserAgentSettings::ComputeAcceptLanguageFromPref(
+  return chrome_accept_language_settings::ComputeAcceptLanguageFromPref(
       pref_accept_language_.GetValue());
 }
 
diff --git a/chrome/browser/task_manager/sampling/shared_sampler.h b/chrome/browser/task_manager/sampling/shared_sampler.h
index c2c8506..2849c6c13 100644
--- a/chrome/browser/task_manager/sampling/shared_sampler.h
+++ b/chrome/browser/task_manager/sampling/shared_sampler.h
@@ -42,7 +42,6 @@
     base::TimeDelta cpu_time;
     int64_t hard_faults_per_second;
     int idle_wakeups_per_second;
-    int64_t physical_bytes;
     base::Time start_time;
   };
   using OnSamplingCompleteCallback =
diff --git a/chrome/browser/task_manager/sampling/shared_sampler_win.cc b/chrome/browser/task_manager/sampling/shared_sampler_win.cc
index e1b9c3f9..e57d4a31 100644
--- a/chrome/browser/task_manager/sampling/shared_sampler_win.cc
+++ b/chrome/browser/task_manager/sampling/shared_sampler_win.cc
@@ -142,7 +142,6 @@
   ProcessData(ProcessData&&) = default;
 
   int64_t hard_fault_count;
-  int64_t physical_bytes;
   base::Time start_time;
   base::TimeDelta cpu_time;
   std::vector<ThreadData> threads;
@@ -249,9 +248,8 @@
 SharedSampler::~SharedSampler() {}
 
 int64_t SharedSampler::GetSupportedFlags() const {
-  return REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_PHYSICAL_MEMORY |
-         REFRESH_TYPE_START_TIME | REFRESH_TYPE_CPU_TIME |
-         REFRESH_TYPE_HARD_FAULTS;
+  return REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_START_TIME |
+         REFRESH_TYPE_CPU_TIME | REFRESH_TYPE_HARD_FAULTS;
 }
 
 void SharedSampler::RegisterCallback(
@@ -414,8 +412,6 @@
         // recent snapshot.
         ProcessData process_data;
         process_data.hard_fault_count = pi->HardFaultCount;
-        process_data.physical_bytes =
-            static_cast<int64_t>(pi->WorkingSetPrivateSize);
         process_data.start_time = ConvertTicksToTime(pi->CreateTime);
         process_data.cpu_time =
             ConvertTicksToTimeDelta(pi->KernelTime + pi->UserTime);
@@ -502,7 +498,6 @@
         static_cast<int>(round(hard_faults_delta / time_delta));
     result.data.idle_wakeups_per_second =
         static_cast<int>(round(idle_wakeups_delta / time_delta));
-    result.data.physical_bytes = process.physical_bytes;
     result.data.start_time = process.start_time;
     result.data.cpu_time = process.cpu_time;
     results.push_back(result);
@@ -522,7 +517,6 @@
     // ProcessMetrics::CalculateIdleWakeupsPerSecond implementation.
     result.data.hard_faults_per_second = 0;
     result.data.idle_wakeups_per_second = 0;
-    result.data.physical_bytes = pair.second.physical_bytes;
     result.data.start_time = pair.second.start_time;
     result.data.cpu_time = pair.second.cpu_time;
     results.push_back(result);
diff --git a/chrome/browser/task_manager/sampling/shared_sampler_win_unittest.cc b/chrome/browser/task_manager/sampling/shared_sampler_win_unittest.cc
index 5814200..78348437 100644
--- a/chrome/browser/task_manager/sampling/shared_sampler_win_unittest.cc
+++ b/chrome/browser/task_manager/sampling/shared_sampler_win_unittest.cc
@@ -41,8 +41,6 @@
   ~SharedSamplerTest() override {}
 
  protected:
-  int64_t physical_bytes() const { return physical_bytes_; }
-
   base::Time start_time() const { return start_time_; }
 
   base::TimeDelta cpu_time() const { return cpu_time_; }
@@ -77,14 +75,12 @@
   void OnSamplerRefreshDone(
       base::Optional<SharedSampler::SamplingResult> results) {
     if (results) {
-      physical_bytes_ = results->physical_bytes;
       idle_wakeups_per_second_ = results->idle_wakeups_per_second;
       start_time_ = results->start_time;
       cpu_time_ = results->cpu_time;
     }
     OnRefreshTypeFinished(expected_refresh_type_ &
-                          (REFRESH_TYPE_PHYSICAL_MEMORY |
-                           REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_START_TIME |
+                          (REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_START_TIME |
                            REFRESH_TYPE_CPU_TIME));
   }
 
@@ -92,7 +88,6 @@
   int64_t finished_refresh_type_ = 0;
   base::Closure quit_closure_;
 
-  int64_t physical_bytes_ = 0;
   int idle_wakeups_per_second_ = -1;
   base::Time start_time_;
   base::TimeDelta cpu_time_;
@@ -126,32 +121,6 @@
   EXPECT_GT(idle_wakeups_per_second(), 0);
 }
 
-// Verifies that Memory (Private WS) value can be obtained from Shared Sampler.
-TEST_F(SharedSamplerTest, PhysicalMemory) {
-  StartRefresh(REFRESH_TYPE_PHYSICAL_MEMORY);
-  WaitUntilRefreshDone();
-  EXPECT_EQ(REFRESH_TYPE_PHYSICAL_MEMORY, finished_refresh_type());
-
-  int64_t initial_value = physical_bytes();
-
-  // Allocate a large continuous block of memory.
-  const int allocated_size = 4 * 1024 * 1024;
-  std::vector<uint8_t> memory_block(allocated_size);
-
-  // It appears the allocation is not counted when allocated, but when actually
-  // accessed. vector's constructor does access the memory to initialize it,
-  // but if the memory then isn't read the compiler might optimize away the
-  // initialization. So read the memory to prevent that.
-  uint8_t sum = std::accumulate(memory_block.begin(), memory_block.end(), 0);
-  EXPECT_EQ(0, sum);
-
-  StartRefresh(REFRESH_TYPE_PHYSICAL_MEMORY);
-  WaitUntilRefreshDone();
-
-  // Verify that physical bytes has increased accordingly.
-  EXPECT_GE(physical_bytes(), initial_value + allocated_size);
-}
-
 // Tests that process start time can be obtained from SharedSampler.
 TEST_F(SharedSamplerTest, StartTime) {
   StartRefresh(REFRESH_TYPE_START_TIME);
@@ -188,11 +157,11 @@
 
 // Verifies that multiple refresh types can be refreshed at the same time.
 TEST_F(SharedSamplerTest, MultipleRefreshTypes) {
-  StartRefresh(REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_PHYSICAL_MEMORY |
-               REFRESH_TYPE_START_TIME | REFRESH_TYPE_CPU_TIME);
+  StartRefresh(REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_START_TIME |
+               REFRESH_TYPE_CPU_TIME);
   WaitUntilRefreshDone();
-  EXPECT_EQ(REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_PHYSICAL_MEMORY |
-                REFRESH_TYPE_START_TIME | REFRESH_TYPE_CPU_TIME,
+  EXPECT_EQ(REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_START_TIME |
+                REFRESH_TYPE_CPU_TIME,
             finished_refresh_type());
 }
 
@@ -235,15 +204,13 @@
   SharedSampler::SetQuerySystemInformationForTest(
       ReturnZeroThreadProcessInformation);
 
-  StartRefresh(REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_PHYSICAL_MEMORY |
-               REFRESH_TYPE_START_TIME | REFRESH_TYPE_CPU_TIME);
+  StartRefresh(REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_START_TIME |
+               REFRESH_TYPE_CPU_TIME);
   WaitUntilRefreshDone();
-  EXPECT_EQ(REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_PHYSICAL_MEMORY |
-                REFRESH_TYPE_START_TIME | REFRESH_TYPE_CPU_TIME,
+  EXPECT_EQ(REFRESH_TYPE_IDLE_WAKEUPS | REFRESH_TYPE_START_TIME |
+                REFRESH_TYPE_CPU_TIME,
             finished_refresh_type());
 
-  EXPECT_EQ(1024ll, physical_bytes());
-
   SharedSampler::SetQuerySystemInformationForTest(nullptr);
 }
 
diff --git a/chrome/browser/task_manager/sampling/task_group.cc b/chrome/browser/task_manager/sampling/task_group.cc
index 5fb10b7d..3e7e18ab 100644
--- a/chrome/browser/task_manager/sampling/task_group.cc
+++ b/chrome/browser/task_manager/sampling/task_group.cc
@@ -28,8 +28,7 @@
 
 // A mask for the refresh types that are done in the background thread.
 const int kBackgroundRefreshTypesMask =
-    REFRESH_TYPE_CPU | REFRESH_TYPE_PHYSICAL_MEMORY |
-    REFRESH_TYPE_MEMORY_DETAILS | REFRESH_TYPE_IDLE_WAKEUPS |
+    REFRESH_TYPE_CPU | REFRESH_TYPE_MEMORY_DETAILS | REFRESH_TYPE_IDLE_WAKEUPS |
 #if defined(OS_WIN)
     REFRESH_TYPE_START_TIME | REFRESH_TYPE_CPU_TIME |
 #endif  // defined(OS_WIN)
@@ -307,15 +306,8 @@
 void TaskGroup::OnMemoryUsageRefreshDone(MemoryUsageStats memory_usage) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-#if defined(OS_WIN)
-  memory_usage_.private_bytes = memory_usage.private_bytes;
-  memory_usage_.shared_bytes = memory_usage.shared_bytes;
-  OnBackgroundRefreshTypeFinished(REFRESH_TYPE_MEMORY_DETAILS);
-#else
   memory_usage_ = memory_usage;
-  OnBackgroundRefreshTypeFinished(REFRESH_TYPE_PHYSICAL_MEMORY |
-                                  REFRESH_TYPE_MEMORY_DETAILS);
-#endif // OS_WIN
+  OnBackgroundRefreshTypeFinished(REFRESH_TYPE_MEMORY_DETAILS);
 }
 
 void TaskGroup::OnProcessPriorityDone(bool is_backgrounded) {
@@ -345,7 +337,6 @@
     idle_wakeups_per_second_ = results->idle_wakeups_per_second;
 #if defined(OS_WIN)
     hard_faults_per_second_ = results->hard_faults_per_second;
-    memory_usage_.physical_bytes = results->physical_bytes;
 #endif
     start_time_ = results->start_time;
   } else {
@@ -353,7 +344,6 @@
     idle_wakeups_per_second_ = -1;
 #if defined(OS_WIN)
     hard_faults_per_second_ = 0;
-    memory_usage_.physical_bytes = -1;
 #endif
     start_time_ = base::Time();
   }
diff --git a/chrome/browser/task_manager/sampling/task_group.h b/chrome/browser/task_manager/sampling/task_group.h
index 9e3716d..0ed31d50 100644
--- a/chrome/browser/task_manager/sampling/task_group.h
+++ b/chrome/browser/task_manager/sampling/task_group.h
@@ -77,9 +77,6 @@
   base::TimeDelta cpu_time() const { return cpu_time_; }
   void set_footprint_bytes(int64_t footprint) { memory_footprint_ = footprint; }
   int64_t footprint_bytes() const { return memory_footprint_; }
-  int64_t private_bytes() const { return memory_usage_.private_bytes; }
-  int64_t shared_bytes() const { return memory_usage_.shared_bytes; }
-  int64_t physical_bytes() const { return memory_usage_.physical_bytes; }
 #if defined(OS_CHROMEOS)
   int64_t swapped_bytes() const { return memory_usage_.swapped_bytes; }
 #endif
diff --git a/chrome/browser/task_manager/sampling/task_group_sampler.cc b/chrome/browser/task_manager/sampling/task_group_sampler.cc
index d1769be..0fa7b1e7 100644
--- a/chrome/browser/task_manager/sampling/task_group_sampler.cc
+++ b/chrome/browser/task_manager/sampling/task_group_sampler.cc
@@ -77,8 +77,8 @@
         on_cpu_refresh_callback_);
   }
 
-  if (TaskManagerObserver::IsResourceRefreshEnabled(
-          REFRESH_TYPE_MEMORY_NON_MEMORY_INSTRUMENTATION, refresh_flags)) {
+  if (TaskManagerObserver::IsResourceRefreshEnabled(REFRESH_TYPE_MEMORY_DETAILS,
+                                                    refresh_flags)) {
     base::PostTaskAndReplyWithResult(
         blocking_pool_runner_.get(),
         FROM_HERE,
@@ -131,47 +131,13 @@
   DCHECK(worker_pool_sequenced_checker_.CalledOnValidSequence());
 
   MemoryUsageStats memory_usage;
-#if defined(OS_MACOSX)
-  size_t private_bytes = 0;
-  size_t shared_bytes = 0;
-  size_t resident_bytes = 0;
-  if (process_metrics_->GetMemoryBytes(&private_bytes, &shared_bytes,
-                                       &resident_bytes, nullptr)) {
-    memory_usage.private_bytes = static_cast<int64_t>(private_bytes);
-    memory_usage.shared_bytes = static_cast<int64_t>(shared_bytes);
-    memory_usage.physical_bytes = resident_bytes;
-  }
-#else
-  // Refreshing the physical/private/shared memory at one shot.
-  base::WorkingSetKBytes ws_usage;
-  if (process_metrics_->GetWorkingSetKBytes(&ws_usage)) {
-    memory_usage.private_bytes = static_cast<int64_t>(ws_usage.priv * 1024);
-    memory_usage.shared_bytes = static_cast<int64_t>(ws_usage.shared * 1024);
-#if defined(OS_LINUX)
-    // On Linux private memory is also resident. Just use it.
-    memory_usage.physical_bytes = memory_usage.private_bytes;
-#else
-    PROCESS_MEMORY_COUNTERS pmc;
-    if (::GetProcessMemoryInfo(process_.Handle(), &pmc, sizeof(pmc))) {
-      memory_usage.physical_bytes = static_cast<int64_t>(pmc.WorkingSetSize);
-    } else {
-      memory_usage.physical_bytes = 0;
-    }
-
-    // Memory = working_set.private which is working set minus shareable. This
-    // avoids the unpredictable counting that occurs when calculating memory as
-    // working set minus shared (renderer code counted when one tab is open and
-    // not counted when two or more are open) and it is much more efficient to
-    // calculate on Windows.
-    memory_usage.physical_bytes -=
-        static_cast<int64_t>(ws_usage.shareable * 1024);
-#endif  // defined(OS_LINUX)
 
 #if defined(OS_CHROMEOS)
+  base::WorkingSetKBytes ws_usage;
+  if (process_metrics_->GetWorkingSetKBytes(&ws_usage)) {
     memory_usage.swapped_bytes = ws_usage.swapped * 1024;
-#endif  // defined(OS_CHROMEOS)
   }
-#endif  // defined(OS_MACOSX)
+#endif  // defined(OS_CHROMEOS)
 
   return memory_usage;
 }
diff --git a/chrome/browser/task_manager/sampling/task_group_sampler.h b/chrome/browser/task_manager/sampling/task_group_sampler.h
index b8deb6f7..40cfb648 100644
--- a/chrome/browser/task_manager/sampling/task_group_sampler.h
+++ b/chrome/browser/task_manager/sampling/task_group_sampler.h
@@ -24,9 +24,6 @@
 // Wraps the memory usage stats values together so that it can be sent between
 // the UI and the worker threads.
 struct MemoryUsageStats {
-  int64_t private_bytes = -1;
-  int64_t shared_bytes = -1;
-  int64_t physical_bytes = -1;
 #if defined(OS_CHROMEOS)
   int64_t swapped_bytes = -1;
 #endif
diff --git a/chrome/browser/task_manager/sampling/task_group_unittest.cc b/chrome/browser/task_manager/sampling/task_group_unittest.cc
index 3cabbaf1..ac6e0d7 100644
--- a/chrome/browser/task_manager/sampling/task_group_unittest.cc
+++ b/chrome/browser/task_manager/sampling/task_group_unittest.cc
@@ -114,11 +114,11 @@
 }
 
 // Some fields are refreshed on a per-TaskGroup basis, but require asynchronous
-// work (e.g. on another thread) to complete. Memory is such a field, so verify
+// work (e.g. on another thread) to complete. Cpu is such a field, so verify
 // that it is correctly reported as requiring background calculations.
 TEST_F(TaskGroupTest, AsyncRefresh) {
   task_group_.Refresh(gpu::VideoMemoryUsageStats(), base::TimeDelta(),
-                      REFRESH_TYPE_MEMORY);
+                      REFRESH_TYPE_CPU);
   EXPECT_FALSE(task_group_.AreBackgroundCalculationsDone());
 
   ASSERT_FALSE(background_refresh_complete_);
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.cc b/chrome/browser/task_manager/sampling/task_manager_impl.cc
index 4dcaa66..c9315271 100644
--- a/chrome/browser/task_manager/sampling/task_manager_impl.cc
+++ b/chrome/browser/task_manager/sampling/task_manager_impl.cc
@@ -125,18 +125,6 @@
   return GetTaskGroupByTaskId(task_id)->footprint_bytes();
 }
 
-int64_t TaskManagerImpl::GetPhysicalMemoryUsage(TaskId task_id) const {
-  return GetTaskGroupByTaskId(task_id)->physical_bytes();
-}
-
-int64_t TaskManagerImpl::GetPrivateMemoryUsage(TaskId task_id) const {
-  return GetTaskGroupByTaskId(task_id)->private_bytes();
-}
-
-int64_t TaskManagerImpl::GetSharedMemoryUsage(TaskId task_id) const {
-  return GetTaskGroupByTaskId(task_id)->shared_bytes();
-}
-
 int64_t TaskManagerImpl::GetSwappedMemoryUsage(TaskId task_id) const {
 #if defined(OS_CHROMEOS)
   return GetTaskGroupByTaskId(task_id)->swapped_bytes();
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.h b/chrome/browser/task_manager/sampling/task_manager_impl.h
index e0b46b4..7e31f64 100644
--- a/chrome/browser/task_manager/sampling/task_manager_impl.h
+++ b/chrome/browser/task_manager/sampling/task_manager_impl.h
@@ -46,9 +46,6 @@
   base::Time GetStartTime(TaskId task_id) const override;
   base::TimeDelta GetCpuTime(TaskId task_id) const override;
   int64_t GetMemoryFootprintUsage(TaskId task_id) const override;
-  int64_t GetPhysicalMemoryUsage(TaskId task_id) const override;
-  int64_t GetPrivateMemoryUsage(TaskId task_id) const override;
-  int64_t GetSharedMemoryUsage(TaskId task_id) const override;
   int64_t GetSwappedMemoryUsage(TaskId task_id) const override;
   int64_t GetGpuMemoryUsage(TaskId task_id,
                             bool* has_duplicates) const override;
diff --git a/chrome/browser/task_manager/task_manager_browsertest_util.cc b/chrome/browser/task_manager/task_manager_browsertest_util.cc
index 22abfea..1227df1 100644
--- a/chrome/browser/task_manager/task_manager_browsertest_util.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest_util.cc
@@ -110,8 +110,6 @@
         return "Process ID";
       case ColumnSpecifier::MEMORY_FOOTPRINT:
         return "Memory Footprint";
-      case ColumnSpecifier::PHYSICAL_MEMORY:
-        return "Physical Memory";
       case ColumnSpecifier::V8_MEMORY:
         return "V8 Memory";
       case ColumnSpecifier::V8_MEMORY_USED:
diff --git a/chrome/browser/task_manager/task_manager_browsertest_util.h b/chrome/browser/task_manager/task_manager_browsertest_util.h
index ad93a3b..b818afb 100644
--- a/chrome/browser/task_manager/task_manager_browsertest_util.h
+++ b/chrome/browser/task_manager/task_manager_browsertest_util.h
@@ -23,7 +23,6 @@
 enum class ColumnSpecifier {
   PROCESS_ID,
   MEMORY_FOOTPRINT,
-  PHYSICAL_MEMORY,
   V8_MEMORY,
   V8_MEMORY_USED,
   SQLITE_MEMORY_USED,
diff --git a/chrome/browser/task_manager/task_manager_interface.h b/chrome/browser/task_manager/task_manager_interface.h
index eca5238..5893811 100644
--- a/chrome/browser/task_manager/task_manager_interface.h
+++ b/chrome/browser/task_manager/task_manager_interface.h
@@ -87,13 +87,10 @@
   // Only implemented in Windows now.
   virtual base::TimeDelta GetCpuTime(TaskId task_id) const = 0;
 
-  // Returns the current footprint/physical/private/shared memory usage of the
-  // task with |task_id| in bytes. A value of -1 means no valid value is
-  // currently available.
+  // Returns the current memory footprint/swapped memory of the task with
+  // |task_id| in bytes. A value of -1 means no valid value is currently
+  // available.
   virtual int64_t GetMemoryFootprintUsage(TaskId task_id) const = 0;
-  virtual int64_t GetPhysicalMemoryUsage(TaskId task_id) const = 0;
-  virtual int64_t GetPrivateMemoryUsage(TaskId task_id) const = 0;
-  virtual int64_t GetSharedMemoryUsage(TaskId task_id) const = 0;
   virtual int64_t GetSwappedMemoryUsage(TaskId task_id) const = 0;
 
   // Returns the GPU memory usage of the task with |task_id| in bytes. A value
diff --git a/chrome/browser/task_manager/task_manager_observer.h b/chrome/browser/task_manager/task_manager_observer.h
index 1debc43..1d700f6 100644
--- a/chrome/browser/task_manager/task_manager_observer.h
+++ b/chrome/browser/task_manager/task_manager_observer.h
@@ -25,7 +25,8 @@
 enum RefreshType {
   REFRESH_TYPE_NONE = 0,
   REFRESH_TYPE_CPU = 1,
-  REFRESH_TYPE_PHYSICAL_MEMORY = 1 << 1,
+
+  // Memory details currently only includes "swapped memory" on CrOS.
   REFRESH_TYPE_MEMORY_DETAILS = 1 << 2,
   REFRESH_TYPE_GPU_MEMORY = 1 << 3,
   REFRESH_TYPE_V8_MEMORY = 1 << 4,
@@ -52,12 +53,6 @@
   REFRESH_TYPE_KEEPALIVE_COUNT = 1 << 16,
   REFRESH_TYPE_MEMORY_FOOTPRINT = 1 << 17,
   REFRESH_TYPE_HARD_FAULTS = 1 << 18,
-
-  REFRESH_TYPE_MEMORY = REFRESH_TYPE_PHYSICAL_MEMORY |
-                        REFRESH_TYPE_MEMORY_FOOTPRINT |
-                        REFRESH_TYPE_MEMORY_DETAILS,
-  REFRESH_TYPE_MEMORY_NON_MEMORY_INSTRUMENTATION =
-      REFRESH_TYPE_PHYSICAL_MEMORY | REFRESH_TYPE_MEMORY_DETAILS,
 };
 
 // Defines the interface for observers of the task manager.
diff --git a/chrome/browser/task_manager/task_manager_observer_unittest.cc b/chrome/browser/task_manager/task_manager_observer_unittest.cc
index fdd46d4..d11fd94 100644
--- a/chrome/browser/task_manager/task_manager_observer_unittest.cc
+++ b/chrome/browser/task_manager/task_manager_observer_unittest.cc
@@ -54,8 +54,8 @@
   int64_t flags1 = RefreshType::REFRESH_TYPE_CPU |
                    RefreshType::REFRESH_TYPE_WEBCACHE_STATS |
                    RefreshType::REFRESH_TYPE_HANDLES;
-  int64_t flags2 =
-      RefreshType::REFRESH_TYPE_MEMORY | RefreshType::REFRESH_TYPE_NACL;
+  int64_t flags2 = RefreshType::REFRESH_TYPE_MEMORY_FOOTPRINT |
+                   RefreshType::REFRESH_TYPE_NACL;
 
   TestObserver observer1(refresh_time1, flags1);
   TestObserver observer2(refresh_time2, flags2);
@@ -80,10 +80,10 @@
   int64_t flags1 = RefreshType::REFRESH_TYPE_CPU |
                    RefreshType::REFRESH_TYPE_WEBCACHE_STATS |
                    RefreshType::REFRESH_TYPE_HANDLES;
-  int64_t flags2 =
-      RefreshType::REFRESH_TYPE_MEMORY | RefreshType::REFRESH_TYPE_NACL;
-  int64_t flags3 =
-      RefreshType::REFRESH_TYPE_MEMORY | RefreshType::REFRESH_TYPE_CPU;
+  int64_t flags2 = RefreshType::REFRESH_TYPE_MEMORY_FOOTPRINT |
+                   RefreshType::REFRESH_TYPE_NACL;
+  int64_t flags3 = RefreshType::REFRESH_TYPE_MEMORY_FOOTPRINT |
+                   RefreshType::REFRESH_TYPE_CPU;
   int64_t flags4 = RefreshType::REFRESH_TYPE_GPU_MEMORY;
 
   TestObserver observer1(refresh_time1, flags1);
diff --git a/chrome/browser/task_manager/task_manager_tester.cc b/chrome/browser/task_manager/task_manager_tester.cc
index bdb2c9a8..4bd243ce 100644
--- a/chrome/browser/task_manager/task_manager_tester.cc
+++ b/chrome/browser/task_manager/task_manager_tester.cc
@@ -105,9 +105,6 @@
     case ColumnSpecifier::MEMORY_FOOTPRINT:
       column_id = IDS_TASK_MANAGER_MEM_FOOTPRINT_COLUMN;
       break;
-    case ColumnSpecifier::PHYSICAL_MEMORY:
-      column_id = IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN;
-      break;
     case ColumnSpecifier::SQLITE_MEMORY_USED:
       column_id = IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN;
       break;
@@ -143,10 +140,6 @@
       value = task_manager()->GetMemoryFootprintUsage(task_id);
       success = true;
       break;
-    case ColumnSpecifier::PHYSICAL_MEMORY:
-      value = task_manager()->GetPhysicalMemoryUsage(task_id);
-      success = true;
-      break;
     case ColumnSpecifier::PROCESS_ID:
       value = static_cast<int64_t>(task_manager()->GetProcessId(task_id));
       success = true;
diff --git a/chrome/browser/task_manager/test_task_manager.cc b/chrome/browser/task_manager/test_task_manager.cc
index 9f64b10..4ff357b 100644
--- a/chrome/browser/task_manager/test_task_manager.cc
+++ b/chrome/browser/task_manager/test_task_manager.cc
@@ -42,18 +42,6 @@
   return -1;
 }
 
-int64_t TestTaskManager::GetPhysicalMemoryUsage(TaskId task_id) const {
-  return -1;
-}
-
-int64_t TestTaskManager::GetPrivateMemoryUsage(TaskId task_id) const {
-  return -1;
-}
-
-int64_t TestTaskManager::GetSharedMemoryUsage(TaskId task_id) const {
-  return -1;
-}
-
 int64_t TestTaskManager::GetSwappedMemoryUsage(TaskId task_id) const {
   return -1;
 }
diff --git a/chrome/browser/task_manager/test_task_manager.h b/chrome/browser/task_manager/test_task_manager.h
index f4edab4..f99892a 100644
--- a/chrome/browser/task_manager/test_task_manager.h
+++ b/chrome/browser/task_manager/test_task_manager.h
@@ -30,9 +30,6 @@
   base::Time GetStartTime(TaskId task_id) const override;
   base::TimeDelta GetCpuTime(TaskId task_id) const override;
   int64_t GetMemoryFootprintUsage(TaskId task_id) const override;
-  int64_t GetPhysicalMemoryUsage(TaskId task_id) const override;
-  int64_t GetPrivateMemoryUsage(TaskId task_id) const override;
-  int64_t GetSharedMemoryUsage(TaskId task_id) const override;
   int64_t GetSwappedMemoryUsage(TaskId task_id) const override;
   int64_t GetGpuMemoryUsage(TaskId task_id,
                             bool* has_duplicates) const override;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 93e76d15..25159fbd 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -507,7 +507,6 @@
       "cocoa/screen_capture_notification_ui_cocoa.mm",
       "cocoa/separate_fullscreen_window.h",
       "cocoa/separate_fullscreen_window.mm",
-      "cocoa/session_crashed_bubble.mm",
       "cocoa/simple_message_box_bridge_views.mm",
       "cocoa/simple_message_box_cocoa.h",
       "cocoa/simple_message_box_cocoa.mm",
@@ -2521,7 +2520,6 @@
         "cocoa/password_reuse_warning_view_controller.h",
         "cocoa/password_reuse_warning_view_controller.mm",
         "cocoa/passwords/password_prompt_views_mac.mm",
-        "cocoa/session_crashed_bubble.mm",
         "cocoa/simple_message_box_bridge_views.mm",
         "cocoa/simple_message_box_cocoa.h",
         "cocoa/simple_message_box_cocoa.mm",
@@ -2926,6 +2924,8 @@
       "views/permission_bubble/permission_prompt_impl.h",
       "views/safe_browsing/password_reuse_modal_warning_dialog.cc",
       "views/safe_browsing/password_reuse_modal_warning_dialog.h",
+      "views/session_crashed_bubble_view.cc",
+      "views/session_crashed_bubble_view.h",
       "views/simple_message_box_views.cc",
       "views/simple_message_box_views.h",
       "views/subtle_notification_view.cc",
@@ -3163,8 +3163,6 @@
         "views/proximity_auth/proximity_auth_error_bubble_view.h",
         "views/sad_tab_view.cc",
         "views/sad_tab_view.h",
-        "views/session_crashed_bubble_view.cc",
-        "views/session_crashed_bubble_view.h",
         "views/ssl_client_certificate_selector.cc",
         "views/ssl_client_certificate_selector.h",
         "views/status_bubble_views.cc",
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
index b848ace24..566b43d 100644
--- a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
+++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
@@ -703,6 +703,26 @@
   auto* site_engagement_service = SiteEngagementService::Get(profile());
   site_engagement_service->AddPointsForTesting(blocked_url, 1);
 
+  EXPECT_TRUE(NavigateAndCommitWithoutGesture(blocked_url));
+  ExpectUIShown(false);
+  histogram_tester()->ExpectTotalCount(kEngagementScore, 1);
+  auto samples = histogram_tester()->GetAllSamples(kEngagementScore);
+  EXPECT_LT(0, samples[0].min);
+}
+
+TEST_F(BlockTabUnderTest, SiteEngagementNoThreshold_Blocks) {
+  base::test::ScopedFeatureList scoped_features;
+  scoped_features.InitAndEnableFeatureWithParameters(
+      TabUnderNavigationThrottle::kBlockTabUnders,
+      {{"engagement_threshold", "-1"}});
+
+  EXPECT_TRUE(NavigateAndCommitWithoutGesture(GURL("https://first.test/")));
+  SimulatePopup();
+  const GURL blocked_url("https://example.test/");
+
+  auto* site_engagement_service = SiteEngagementService::Get(profile());
+  site_engagement_service->AddPointsForTesting(blocked_url, 1);
+
   EXPECT_FALSE(NavigateAndCommitWithoutGesture(blocked_url));
   ExpectUIShown(true);
   histogram_tester()->ExpectTotalCount(kEngagementScore, 1);
diff --git a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
index b1a5e8a..334fc4e 100644
--- a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
+++ b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
@@ -12,6 +12,7 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
@@ -41,6 +42,8 @@
 
 namespace {
 
+constexpr char kEngagementThreshold[] = "engagement_threshold";
+
 void LogAction(TabUnderNavigationThrottle::Action action, bool off_the_record) {
   UMA_HISTOGRAM_ENUMERATION("Tab.TabUnderAction", action,
                             TabUnderNavigationThrottle::Action::kCount);
@@ -83,7 +86,6 @@
 
 void LogTabUnderAttempt(content::NavigationHandle* handle,
                         base::Optional<ukm::SourceId> opener_source_id,
-                        double engagement_score,
                         bool off_the_record) {
   LogAction(TabUnderNavigationThrottle::Action::kDidTabUnder, off_the_record);
 
@@ -96,9 +98,6 @@
         .SetDidTabUnder(true)
         .Record(ukm_recorder);
   }
-  DCHECK_EQ(100, SiteEngagementService::GetMaxPoints());
-  UMA_HISTOGRAM_COUNTS_100("Tab.TabUnder.EngagementScore",
-                           std::ceil(engagement_score));
 }
 
 }  // namespace
@@ -119,48 +118,64 @@
 TabUnderNavigationThrottle::TabUnderNavigationThrottle(
     content::NavigationHandle* handle)
     : content::NavigationThrottle(handle),
+      engagement_threshold_(
+          base::GetFieldTrialParamByFeatureAsInt(kBlockTabUnders,
+                                                 kEngagementThreshold,
+                                                 0 /* default_value */)),
       off_the_record_(
           handle->GetWebContents()->GetBrowserContext()->IsOffTheRecord()),
       block_(base::FeatureList::IsEnabled(kBlockTabUnders)),
       has_opened_popup_since_last_user_gesture_at_start_(
           HasOpenedPopupSinceLastUserGesture()) {}
 
-// static
-bool TabUnderNavigationThrottle::IsSuspiciousClientRedirect(
-    content::NavigationHandle* navigation_handle) {
+bool TabUnderNavigationThrottle::IsSuspiciousClientRedirect() const {
   // Some browser initiated navigations have HasUserGesture set to false. This
   // should eventually be fixed in crbug.com/617904. In the meantime, just dont
   // block browser initiated ones.
-  if (!navigation_handle->IsInMainFrame() ||
-      navigation_handle->HasUserGesture() ||
-      !navigation_handle->IsRendererInitiated()) {
+  if (!navigation_handle()->IsInMainFrame() ||
+      navigation_handle()->HasUserGesture() ||
+      !navigation_handle()->IsRendererInitiated()) {
     return false;
   }
 
   // An empty previous URL indicates this was the first load. We filter these
   // out because we're primarily interested in sites which navigate themselves
   // away while in the background.
+  content::WebContents* contents = navigation_handle()->GetWebContents();
   const GURL& previous_main_frame_url =
-      navigation_handle->HasCommitted()
-          ? navigation_handle->GetPreviousURL()
-          : navigation_handle->GetWebContents()->GetLastCommittedURL();
+      navigation_handle()->HasCommitted()
+          ? navigation_handle()->GetPreviousURL()
+          : contents->GetLastCommittedURL();
   if (previous_main_frame_url.is_empty())
     return false;
 
   // Same-site navigations are exempt from tab-under protection.
+  const GURL& target_url = navigation_handle()->GetURL();
   if (net::registry_controlled_domains::SameDomainOrHost(
-          previous_main_frame_url, navigation_handle->GetURL(),
+          previous_main_frame_url, target_url,
           net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
     return false;
   }
 
+  // This metric should be logged as the last check before a site would be
+  // blocked, to give an accurate sense of what scores tab-under destinations
+  // typically have.
+  DCHECK_EQ(100, SiteEngagementService::GetMaxPoints());
+  auto* site_engagement_service = SiteEngagementService::Get(
+      Profile::FromBrowserContext(contents->GetBrowserContext()));
+  double engagement_score = site_engagement_service->GetScore(target_url);
+  UMA_HISTOGRAM_COUNTS_100("Tab.TabUnder.EngagementScore",
+                           std::ceil(engagement_score));
+  if (engagement_score > engagement_threshold_ && engagement_threshold_ != -1)
+    return false;
+
   return true;
 }
 
 content::NavigationThrottle::ThrottleCheckResult
 TabUnderNavigationThrottle::MaybeBlockNavigation() {
   if (seen_tab_under_ || !has_opened_popup_since_last_user_gesture_at_start_ ||
-      !IsSuspiciousClientRedirect(navigation_handle())) {
+      !IsSuspiciousClientRedirect()) {
     return content::NavigationThrottle::PROCEED;
   }
 
@@ -170,17 +185,13 @@
   DCHECK(popup_opener);
   popup_opener->OnDidTabUnder();
 
-  auto* site_engagement_service = SiteEngagementService::Get(
-      Profile::FromBrowserContext(contents->GetBrowserContext()));
-  const GURL& url = navigation_handle()->GetURL();
-  double engagement_score = site_engagement_service->GetScore(url);
   LogTabUnderAttempt(navigation_handle(),
-                     popup_opener->last_committed_source_id(), engagement_score,
-                     off_the_record_);
+                     popup_opener->last_committed_source_id(), off_the_record_);
 
   if (block_) {
     const std::string error =
-        base::StringPrintf(kBlockTabUnderFormatMessage, url.spec().c_str());
+        base::StringPrintf(kBlockTabUnderFormatMessage,
+                           navigation_handle()->GetURL().spec().c_str());
     contents->GetMainFrame()->AddMessageToConsole(
         content::CONSOLE_MESSAGE_LEVEL_ERROR, error.c_str());
     LogAction(Action::kBlocked, off_the_record_);
diff --git a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h
index 749b72a9..699b7e7 100644
--- a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h
+++ b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h
@@ -29,6 +29,8 @@
 //    a. It has no user gesture.
 //    b. It is renderer-initiated.
 //    c. It is cross site to the last committed URL in the tab.
+//    d. The target site has a Site Engagement score below some threshold (by
+//       default, a score of 0).
 // 2. The tab has opened a popup and hasn't received a user gesture since then.
 //    This information is tracked by the PopupOpenerTabHelper.
 class TabUnderNavigationThrottle : public content::NavigationThrottle {
@@ -70,8 +72,7 @@
   // This method is described at the top of this file.
   //
   // Note: This method should be robust to navigations at any stage.
-  static bool IsSuspiciousClientRedirect(
-      content::NavigationHandle* navigation_handle);
+  bool IsSuspiciousClientRedirect() const;
 
   content::NavigationThrottle::ThrottleCheckResult MaybeBlockNavigation();
   void ShowUI();
@@ -84,6 +85,12 @@
       override;
   const char* GetNameForLogging() override;
 
+  // Threshold for a site's engagement score to be considered non-suspicious.
+  // Any tab-under target URL with engagement > |engagement_threshold_| will not
+  // be considered a suspicious redirect. If this member is -1, this threshold
+  // will not apply and all sites will be candidates for blocking.
+  const int engagement_threshold_ = 0;
+
   // Store whether we're off the record as a member to avoid looking it up all
   // the time.
   const bool off_the_record_ = false;
diff --git a/chrome/browser/ui/browser_navigator_browsertest.cc b/chrome/browser/ui/browser_navigator_browsertest.cc
index ad7b6d9..ca7470b5 100644
--- a/chrome/browser/ui/browser_navigator_browsertest.cc
+++ b/chrome/browser/ui/browser_navigator_browsertest.cc
@@ -250,10 +250,10 @@
   std::unique_ptr<content::NavigationUIData> last_navigation_ui_data_ = nullptr;
 };
 
-Browser* BrowserNavigatorTest::NavigateHelper(
-    const GURL& url,
-    Browser* browser,
-    WindowOpenDisposition disposition) {
+Browser* BrowserNavigatorTest::NavigateHelper(const GURL& url,
+                                              Browser* browser,
+                                              WindowOpenDisposition disposition,
+                                              bool wait_for_navigation) {
   content::WindowedNotificationObserver observer(
       content::NOTIFICATION_LOAD_STOP,
       content::NotificationService::AllSources());
@@ -264,7 +264,7 @@
   params.window_action = NavigateParams::SHOW_WINDOW;
   Navigate(&params);
 
-  if (params.disposition != WindowOpenDisposition::SWITCH_TO_TAB)
+  if (wait_for_navigation)
     observer.Wait();
 
   return params.browser;
@@ -642,12 +642,12 @@
   GURL singleton_url("http://maps.google.com/");
 
   NavigateHelper(singleton_url, browser(),
-                 WindowOpenDisposition::NEW_FOREGROUND_TAB);
+                 WindowOpenDisposition::NEW_FOREGROUND_TAB, true);
 
   browser()->tab_strip_model()->ActivateTabAt(0, true);
 
-  NavigateHelper(singleton_url, browser(),
-                 WindowOpenDisposition::SWITCH_TO_TAB);
+  NavigateHelper(singleton_url, browser(), WindowOpenDisposition::SWITCH_TO_TAB,
+                 false);
 }
 
 // This test verifies that IsTabOpenWithURL() and GetIndexOfExistingTab()
@@ -658,10 +658,10 @@
 
   // Generate history so the tab isn't closed.
   NavigateHelper(GURL("chrome://dino/"), browser(),
-                 WindowOpenDisposition::CURRENT_TAB);
+                 WindowOpenDisposition::CURRENT_TAB, true);
 
   NavigateHelper(navigate_url, browser(),
-                 WindowOpenDisposition::NEW_BACKGROUND_TAB);
+                 WindowOpenDisposition::NEW_BACKGROUND_TAB, true);
 
   // We must be on another tab than the target for it to be found and
   // switched to.
@@ -670,7 +670,8 @@
   ChromeAutocompleteProviderClient client(browser()->profile());
   EXPECT_TRUE(client.IsTabOpenWithURL(search_url, nullptr));
 
-  NavigateHelper(search_url, browser(), WindowOpenDisposition::SWITCH_TO_TAB);
+  NavigateHelper(search_url, browser(), WindowOpenDisposition::SWITCH_TO_TAB,
+                 false);
 
   EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
 }
@@ -682,13 +683,13 @@
   GURL singleton_url("http://maps.google.com/");
 
   // Make singleton tab.
-  Browser* orig_browser = NavigateHelper(singleton_url, browser(),
-                                         WindowOpenDisposition::CURRENT_TAB);
+  Browser* orig_browser = NavigateHelper(
+      singleton_url, browser(), WindowOpenDisposition::CURRENT_TAB, true);
 
   // Make a new window with different URL.
   Browser* middle_browser =
       NavigateHelper(GURL("http://www.google.com/"), orig_browser,
-                     WindowOpenDisposition::NEW_WINDOW);
+                     WindowOpenDisposition::NEW_WINDOW, true);
   EXPECT_NE(orig_browser, middle_browser);
 
   ChromeAutocompleteProviderClient client(browser()->profile());
@@ -699,8 +700,9 @@
   EXPECT_TRUE(client.IsTabOpenWithURL(singleton_url, nullptr));
 
   // Navigate to the singleton again.
-  Browser* test_browser = NavigateHelper(singleton_url, middle_browser,
-                                         WindowOpenDisposition::SWITCH_TO_TAB);
+  Browser* test_browser =
+      NavigateHelper(singleton_url, middle_browser,
+                     WindowOpenDisposition::SWITCH_TO_TAB, false);
 
   // Make sure we chose the browser with the tab, not simply the current
   // browser.
@@ -715,21 +717,21 @@
 IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, SwitchToTabLatestWindow) {
   // Navigate to a site.
   NavigateHelper(GURL("http://maps.google.com/"), browser(),
-                 WindowOpenDisposition::CURRENT_TAB);
+                 WindowOpenDisposition::CURRENT_TAB, true);
 
   // Navigate to a new window.
   Browser* browser1 = NavigateHelper(GURL("http://maps.google.com/"), browser(),
-                                     WindowOpenDisposition::NEW_WINDOW);
+                                     WindowOpenDisposition::NEW_WINDOW, true);
 
   // Make yet another window.
   Browser* browser2 = NavigateHelper(GURL("http://maps.google.com/"), browser(),
-                                     WindowOpenDisposition::NEW_WINDOW);
+                                     WindowOpenDisposition::NEW_WINDOW, true);
 
   // Navigate to the latest copy of the URL, in spite of specifying
   // the previous browser.
   Browser* test_browser =
       NavigateHelper(GURL("http://maps.google.com/"), browser1,
-                     WindowOpenDisposition::SWITCH_TO_TAB);
+                     WindowOpenDisposition::SWITCH_TO_TAB, false);
 
   EXPECT_EQ(browser2, test_browser);
 }
@@ -741,49 +743,37 @@
 
   // Navigate to a site.
   browser1 = NavigateHelper(GURL("chrome://dino"), browser(),
-                            WindowOpenDisposition::CURRENT_TAB);
+                            WindowOpenDisposition::CURRENT_TAB, true);
 
   // Navigate to a new window.
   Browser* browser2 = NavigateHelper(GURL("chrome://about"), browser(),
-                                     WindowOpenDisposition::NEW_WINDOW);
+                                     WindowOpenDisposition::NEW_WINDOW, true);
 
   // Make sure we open non-special URL here.
   Browser* test_browser =
       NavigateHelper(GURL("chrome://dino"), browser2,
-                     WindowOpenDisposition::NEW_FOREGROUND_TAB);
+                     WindowOpenDisposition::NEW_FOREGROUND_TAB, true);
   EXPECT_EQ(browser2, test_browser);
 }
 
-// Tests that a disposition of SINGLETON_TAB cannot see outside its
-// window, and that a disposition of SWITCH_TO_TAB can't see outside
-// its profile, except for certain non-incognito affinity URLs.
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-// https://crbug.com/822033
-#define MAYBE_SingletonProfileLeak DISABLED_SingletonProfileLeak
-#else
-#define MAYBE_SingletonProfileLeak SingletonProfileLeak
-#endif
-IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, MAYBE_SingletonProfileLeak) {
+// Tests that a disposition of SINGLETON_TAB cannot see across anonymity,
+// except for certain non-incognito affinity URLs (e.g. settings).
+IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, SingletonIncognitoLeak) {
   Browser* orig_browser;
 
   // Navigate to a site.
   orig_browser = NavigateHelper(GURL("http://maps.google.com/"), browser(),
-                                WindowOpenDisposition::CURRENT_TAB);
+                                WindowOpenDisposition::CURRENT_TAB, true);
 
-  // Open dino for finding later.
-  NavigateHelper(GURL("chrome://dino"), orig_browser,
-                 WindowOpenDisposition::NEW_FOREGROUND_TAB);
+  // Open about for (not) finding later.
+  NavigateHelper(GURL("chrome://about"), orig_browser,
+                 WindowOpenDisposition::NEW_FOREGROUND_TAB, true);
 
   // Also open settings for finding later.
   NavigateHelper(GURL("chrome://settings"), orig_browser,
-                 WindowOpenDisposition::NEW_FOREGROUND_TAB);
+                 WindowOpenDisposition::NEW_FOREGROUND_TAB, true);
 
-  // Also open about for searching too.
-  NavigateHelper(GURL("chrome://about"), orig_browser,
-                 WindowOpenDisposition::NEW_FOREGROUND_TAB);
-
-  // Sanity check that the above created 4 separate tabs.
-  EXPECT_EQ(4, browser()->tab_strip_model()->count());
+  EXPECT_EQ(3, browser()->tab_strip_model()->count());
 
   Browser* test_browser;
 
@@ -791,45 +781,80 @@
     Browser* incognito_browser = CreateIncognitoBrowser();
 
     test_browser = NavigateHelper(GURL("chrome://downloads"), incognito_browser,
-                                  WindowOpenDisposition::OFF_THE_RECORD);
+                                  WindowOpenDisposition::OFF_THE_RECORD, true);
     // Sanity check where OTR tab landed.
     EXPECT_EQ(incognito_browser, test_browser);
 
     // Sanity check that browser() always returns original.
     EXPECT_EQ(orig_browser, browser());
 
-    // Make another for switch-to-tab to try and find.
-    NavigateHelper(GURL("chrome://history"), incognito_browser,
-                   WindowOpenDisposition::NEW_FOREGROUND_TAB);
-
-    // Try to open the original chrome://about via switch-to-tab. Should not
-    // find copy in regular browser, and open new tab in incognito.
-    test_browser = NavigateHelper(GURL("chrome://about"), incognito_browser,
-                                  WindowOpenDisposition::SWITCH_TO_TAB);
-    EXPECT_EQ(incognito_browser, test_browser);
-
-    // Open dino singleton. Should not find in regular browser and
+    // Open about singleton. Should not find in regular browser and
     // open locally.
-    test_browser = NavigateHelper(GURL("chrome://dino"), incognito_browser,
-                                  WindowOpenDisposition::SINGLETON_TAB);
+    test_browser = NavigateHelper(GURL("chrome://about"), incognito_browser,
+                                  WindowOpenDisposition::SINGLETON_TAB, true);
     EXPECT_NE(orig_browser, test_browser);
 
     // Open settings. Should switch to non-incognito profile to do so.
     test_browser = NavigateHelper(GURL("chrome://settings"), incognito_browser,
-                                  WindowOpenDisposition::SINGLETON_TAB);
+                                  WindowOpenDisposition::SINGLETON_TAB, false);
     EXPECT_EQ(orig_browser, test_browser);
   }
 
   // Open downloads singleton. Should not search OTR browser and
   // should open in regular browser.
   test_browser = NavigateHelper(GURL("chrome://downloads"), orig_browser,
-                                WindowOpenDisposition::SINGLETON_TAB);
+                                WindowOpenDisposition::SINGLETON_TAB, true);
   EXPECT_EQ(browser(), test_browser);
+}
 
-  // Likewise, switch-to-tab shouldn't find the incognito tab either,
-  // and open new one in current browser.
-  test_browser = NavigateHelper(GURL("chrome://history"), orig_browser,
-                                WindowOpenDisposition::SWITCH_TO_TAB);
+// Tests that a disposition of SWITCH_TAB cannot see across anonymity,
+// except for certain non-incognito affinity URLs (e.g. settings).
+IN_PROC_BROWSER_TEST_F(BrowserNavigatorTest, SwitchToTabIncognitoLeak) {
+  Browser* orig_browser;
+
+  // Navigate to a site.
+  orig_browser = NavigateHelper(GURL("http://maps.google.com/"), browser(),
+                                WindowOpenDisposition::CURRENT_TAB, true);
+
+  // Also open settings for finding later.
+  NavigateHelper(GURL("chrome://settings"), orig_browser,
+                 WindowOpenDisposition::NEW_FOREGROUND_TAB, true);
+
+  // Also open about for searching too.
+  NavigateHelper(GURL("chrome://about"), orig_browser,
+                 WindowOpenDisposition::NEW_FOREGROUND_TAB, true);
+
+  EXPECT_EQ(3, browser()->tab_strip_model()->count());
+
+  Browser* test_browser;
+
+  {
+    Browser* incognito_browser = CreateIncognitoBrowser();
+
+    test_browser = NavigateHelper(GURL("chrome://downloads"), incognito_browser,
+                                  WindowOpenDisposition::OFF_THE_RECORD, true);
+    // Sanity check where OTR tab landed.
+    EXPECT_EQ(incognito_browser, test_browser);
+
+    // Sanity check that browser() always returns original.
+    EXPECT_EQ(orig_browser, browser());
+
+    // Try to open the original chrome://about via switch-to-tab. Should not
+    // find copy in regular browser, and open new tab in incognito.
+    test_browser = NavigateHelper(GURL("chrome://about"), incognito_browser,
+                                  WindowOpenDisposition::SWITCH_TO_TAB, true);
+    EXPECT_EQ(incognito_browser, test_browser);
+
+    // Open settings. Should switch to non-incognito profile to do so.
+    test_browser = NavigateHelper(GURL("chrome://settings"), incognito_browser,
+                                  WindowOpenDisposition::SWITCH_TO_TAB, false);
+    EXPECT_EQ(orig_browser, test_browser);
+  }
+
+  // Switch-to-tab shouldn't find the incognito tab, and open new one in
+  // current browser.
+  test_browser = NavigateHelper(GURL("chrome://downloads"), orig_browser,
+                                WindowOpenDisposition::SWITCH_TO_TAB, true);
   EXPECT_EQ(browser(), test_browser);
 }
 
diff --git a/chrome/browser/ui/browser_navigator_browsertest.h b/chrome/browser/ui/browser_navigator_browsertest.h
index 732a1ab5..4660b4c 100644
--- a/chrome/browser/ui/browser_navigator_browsertest.h
+++ b/chrome/browser/ui/browser_navigator_browsertest.h
@@ -50,7 +50,8 @@
 
   Browser* NavigateHelper(const GURL& url,
                           Browser* browser,
-                          WindowOpenDisposition disposition);
+                          WindowOpenDisposition disposition,
+                          bool wait_for_navigation);
 
   size_t created_tab_contents_count_;
 };
diff --git a/chrome/browser/ui/bubble_anchor_util.h b/chrome/browser/ui/bubble_anchor_util.h
index 2210c98..47b5e4d8b1 100644
--- a/chrome/browser/ui/bubble_anchor_util.h
+++ b/chrome/browser/ui/bubble_anchor_util.h
@@ -47,6 +47,10 @@
 gfx::Point GetExtensionInstalledAnchorPointCocoa(
     gfx::NativeWindow window,
     const ExtensionInstalledBubble* bubble);
+
+// Returns the app menu anchor rect for |browser|, which is assumed to have a
+// Cocoa browser window.
+gfx::Rect GetAppMenuAnchorRectCocoa(Browser* browser);
 #endif
 
 }  // namespace bubble_anchor_util
diff --git a/chrome/browser/ui/cocoa/bubble_anchor_util_views_mac.mm b/chrome/browser/ui/cocoa/bubble_anchor_util_views_mac.mm
index 994273a..8fd14c4 100644
--- a/chrome/browser/ui/cocoa/bubble_anchor_util_views_mac.mm
+++ b/chrome/browser/ui/cocoa/bubble_anchor_util_views_mac.mm
@@ -6,13 +6,16 @@
 
 #import <Cocoa/Cocoa.h>
 
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
+#include "chrome/browser/ui/cocoa/browser_window_views_mac.h"
 #import "chrome/browser/ui/cocoa/bubble_anchor_helper.h"
 #import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #include "chrome/browser/ui/extensions/extension_installed_bubble.h"
-#include "ui/base/cocoa/cocoa_base_utils.h"
+#import "ui/base/cocoa/cocoa_base_utils.h"
 #include "ui/base/ui_features.h"
 #include "ui/gfx/geometry/rect.h"
 #import "ui/gfx/mac/coordinate_conversion.h"
@@ -64,6 +67,15 @@
   return gfx::ScreenPointFromNSPoint(arrow_point);
 }
 
+gfx::Rect GetAppMenuAnchorRectCocoa(Browser* browser) {
+  NSWindow* window = browser->window()->GetNativeWindow();
+  BrowserWindowController* bwc = BrowserWindowControllerForWindow(window);
+  NSPoint point = [[bwc toolbarController] appMenuBubblePoint];
+  return gfx::Rect(gfx::ScreenPointFromNSPoint(
+                       ui::ConvertPointFromWindowToScreen(window, point)),
+                   gfx::Size());
+}
+
 #if !BUILDFLAG(MAC_VIEWS_BROWSER)
 gfx::Rect GetPageInfoAnchorRect(Browser* browser) {
   return GetPageInfoAnchorRectCocoa(browser);
diff --git a/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_views_mac.mm b/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_views_mac.mm
index 0bb822d1..e8d1a46 100644
--- a/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_views_mac.mm
+++ b/chrome/browser/ui/cocoa/permission_bubble/chooser_bubble_ui_views_mac.mm
@@ -17,14 +17,6 @@
 #include "chrome/browser/ui/permission_bubble/chooser_bubble_delegate.h"
 #include "ui/views/bubble/bubble_dialog_delegate.h"
 
-std::unique_ptr<BubbleUi> ChooserBubbleDelegate::BuildBubbleUi() {
-  if (!chrome::ShowAllDialogsWithViewsToolkit()) {
-    return std::make_unique<ChooserBubbleUiCocoa>(
-        browser_, std::move(chooser_controller_));
-  }
-  return std::make_unique<ChooserBubbleUi>(browser_,
-                                           std::move(chooser_controller_));
-}
 
 void ChooserBubbleUi::CreateAndShowCocoa(
     views::BubbleDialogDelegateView* delegate) {
@@ -41,4 +33,13 @@
 void ChooserBubbleUi::CreateAndShow(views::BubbleDialogDelegateView* delegate) {
   CreateAndShowCocoa(delegate);
 }
+
+std::unique_ptr<BubbleUi> ChooserBubbleDelegate::BuildBubbleUi() {
+  if (!chrome::ShowAllDialogsWithViewsToolkit()) {
+    return std::make_unique<ChooserBubbleUiCocoa>(
+        browser_, std::move(chooser_controller_));
+  }
+  return std::make_unique<ChooserBubbleUi>(browser_,
+                                           std::move(chooser_controller_));
+}
 #endif
diff --git a/chrome/browser/ui/cocoa/session_crashed_bubble.mm b/chrome/browser/ui/cocoa/session_crashed_bubble.mm
deleted file mode 100644
index 3563bc17..0000000
--- a/chrome/browser/ui/cocoa/session_crashed_bubble.mm
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/session_crashed_bubble.h"
-
-bool SessionCrashedBubble::Show(Browser* /* browser */) {
-  return false;
-}
diff --git a/chrome/browser/ui/search_engines/search_engine_tab_helper.cc b/chrome/browser/ui/search_engines/search_engine_tab_helper.cc
index 0762096c..829959fe 100644
--- a/chrome/browser/ui/search_engines/search_engine_tab_helper.cc
+++ b/chrome/browser/ui/search_engines/search_engine_tab_helper.cc
@@ -178,7 +178,7 @@
     return;
   }
 
-  TemplateURL* current_url;
+  const TemplateURL* current_url;
   GURL url = handle->GetSearchableFormURL();
   if (!url_service->CanAddAutogeneratedKeyword(keyword, url, &current_url))
     return;
diff --git a/chrome/browser/ui/task_manager/task_manager_columns.cc b/chrome/browser/ui/task_manager/task_manager_columns.cc
index 940d2f7..1b46063f 100644
--- a/chrome/browser/ui/task_manager/task_manager_columns.cc
+++ b/chrome/browser/ui/task_manager/task_manager_columns.cc
@@ -29,12 +29,6 @@
     {IDS_TASK_MANAGER_MEM_FOOTPRINT_COLUMN, ui::TableColumn::RIGHT, -1, 0,
      arraysize("800 MiB") * kCharWidth,
      arraysize("Memory Footprint") * 1.5 * kCharWidth, true, false, true},
-    {IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN, ui::TableColumn::RIGHT, -1, 0,
-     arraysize("800 MiB") * kCharWidth, -1, true, false, false},
-    {IDS_TASK_MANAGER_SHARED_MEM_COLUMN, ui::TableColumn::RIGHT, -1, 0,
-     arraysize("800 MiB") * kCharWidth, -1, true, false, false},
-    {IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN, ui::TableColumn::RIGHT, -1, 0,
-     arraysize("800 MiB") * kCharWidth, -1, true, false, false},
 
 #if defined(OS_CHROMEOS)
     {IDS_TASK_MANAGER_SWAPPED_MEM_COLUMN, ui::TableColumn::RIGHT, -1, 0,
@@ -131,9 +125,6 @@
     COLUMN_CASE(IDS_TASK_MANAGER_TASK_COLUMN);
     COLUMN_CASE(IDS_TASK_MANAGER_PROFILE_NAME_COLUMN);
     COLUMN_CASE(IDS_TASK_MANAGER_MEM_FOOTPRINT_COLUMN);
-    COLUMN_CASE(IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN);
-    COLUMN_CASE(IDS_TASK_MANAGER_SHARED_MEM_COLUMN);
-    COLUMN_CASE(IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN);
     COLUMN_CASE(IDS_TASK_MANAGER_SWAPPED_MEM_COLUMN);
     COLUMN_CASE(IDS_TASK_MANAGER_CPU_COLUMN);
     COLUMN_CASE(IDS_TASK_MANAGER_START_TIME_COLUMN);
diff --git a/chrome/browser/ui/task_manager/task_manager_table_model.cc b/chrome/browser/ui/task_manager/task_manager_table_model.cc
index d61ab19..1424dcf 100644
--- a/chrome/browser/ui/task_manager/task_manager_table_model.cc
+++ b/chrome/browser/ui/task_manager/task_manager_table_model.cc
@@ -49,9 +49,6 @@
 bool IsSharedByGroup(int column_id) {
   switch (column_id) {
     case IDS_TASK_MANAGER_MEM_FOOTPRINT_COLUMN:
-    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
-    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
-    case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
     case IDS_TASK_MANAGER_SWAPPED_MEM_COLUMN:
     case IDS_TASK_MANAGER_CPU_COLUMN:
     case IDS_TASK_MANAGER_START_TIME_COLUMN:
@@ -376,18 +373,6 @@
       return stringifier_->GetMemoryUsageText(
           observed_task_manager()->GetMemoryFootprintUsage(tasks_[row]), false);
 
-    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
-      return stringifier_->GetMemoryUsageText(
-          observed_task_manager()->GetPrivateMemoryUsage(tasks_[row]), false);
-
-    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
-      return stringifier_->GetMemoryUsageText(
-          observed_task_manager()->GetSharedMemoryUsage(tasks_[row]), false);
-
-    case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
-      return stringifier_->GetMemoryUsageText(
-          observed_task_manager()->GetPhysicalMemoryUsage(tasks_[row]), false);
-
     case IDS_TASK_MANAGER_SWAPPED_MEM_COLUMN:
       return stringifier_->GetMemoryUsageText(
           observed_task_manager()->GetSwappedMemoryUsage(tasks_[row]), false);
@@ -538,21 +523,6 @@
           observed_task_manager()->GetMemoryFootprintUsage(tasks_[row1]),
           observed_task_manager()->GetMemoryFootprintUsage(tasks_[row2]));
 
-    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
-      return ValueCompare(
-          observed_task_manager()->GetPrivateMemoryUsage(tasks_[row1]),
-          observed_task_manager()->GetPrivateMemoryUsage(tasks_[row2]));
-
-    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
-      return ValueCompare(
-          observed_task_manager()->GetSharedMemoryUsage(tasks_[row1]),
-          observed_task_manager()->GetSharedMemoryUsage(tasks_[row2]));
-
-    case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
-      return ValueCompare(
-          observed_task_manager()->GetPhysicalMemoryUsage(tasks_[row1]),
-          observed_task_manager()->GetPhysicalMemoryUsage(tasks_[row2]));
-
     case IDS_TASK_MANAGER_SWAPPED_MEM_COLUMN:
       return ValueCompare(
           observed_task_manager()->GetSwappedMemoryUsage(tasks_[row1]),
@@ -757,20 +727,9 @@
       type = REFRESH_TYPE_MEMORY_FOOTPRINT;
       break;
 
-    case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
-      type = REFRESH_TYPE_PHYSICAL_MEMORY;
-      break;
-    case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
-    case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
     case IDS_TASK_MANAGER_SWAPPED_MEM_COLUMN:
       type = REFRESH_TYPE_MEMORY_DETAILS;
       if (table_view_delegate_->IsColumnVisible(
-              IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN) ||
-          table_view_delegate_->IsColumnVisible(
-              IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN) ||
-          table_view_delegate_->IsColumnVisible(
-              IDS_TASK_MANAGER_SHARED_MEM_COLUMN) ||
-          table_view_delegate_->IsColumnVisible(
               IDS_TASK_MANAGER_SWAPPED_MEM_COLUMN)) {
         needs_refresh = true;
       }
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.cc b/chrome/browser/ui/views/session_crashed_bubble_view.cc
index 18989e5c3..ddd08d1c 100644
--- a/chrome/browser/ui/views/session_crashed_bubble_view.cc
+++ b/chrome/browser/ui/views/session_crashed_bubble_view.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_list_observer.h"
+#include "chrome/browser/ui/bubble_anchor_util.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/browser_view_button_provider.h"
@@ -36,6 +37,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/ui_features.h"
 #include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/label.h"
@@ -45,6 +47,11 @@
 #include "ui/views/layout/grid_layout.h"
 #include "ui/views/widget/widget.h"
 
+#if defined(OS_MACOSX)
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/ui/cocoa/browser_dialogs_views_mac.h"
+#endif
+
 using views::GridLayout;
 
 namespace {
@@ -75,6 +82,35 @@
 #endif
 }
 
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
+// Returns the app menu view, except when the browser window is Cocoa; Cocoa
+// browser windows always have a null anchor view and use GetBubbleAnchorRect()
+// instead.
+views::View* GetBubbleAnchorView(Browser* browser) {
+#if BUILDFLAG(MAC_VIEWS_BROWSER)
+  if (views_mode_controller::IsViewsBrowserCocoa())
+    return nullptr;
+#endif
+  return BrowserView::GetBrowserViewForBrowser(browser)
+      ->button_provider()
+      ->GetAppMenuButton();
+}
+#else  // OS_MACOSX && !MAC_VIEWS_BROWSER
+views::View* GetBubbleAnchorView(Browser* browser) {
+  return nullptr;
+}
+#endif
+
+gfx::Rect GetBubbleAnchorRect(Browser* browser) {
+#if BUILDFLAG(MAC_VIEWS_BROWSER)
+  if (views_mode_controller::IsViewsBrowserCocoa())
+    return bubble_anchor_util::GetAppMenuAnchorRectCocoa(browser);
+#elif defined(OS_MACOSX)
+  return bubble_anchor_util::GetAppMenuAnchorRectCocoa(browser);
+#endif
+  return gfx::Rect();
+}
+
 }  // namespace
 
 // A helper class that listens to browser removal event.
@@ -104,6 +140,11 @@
 
 // static
 bool SessionCrashedBubble::Show(Browser* browser) {
+#if defined(OS_MACOSX)
+  if (!chrome::ShowAllDialogsWithViewsToolkit())
+    return false;
+#endif
+
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (browser->profile()->IsOffTheRecord())
     return true;
@@ -120,14 +161,6 @@
         base::Bind(&SessionCrashedBubbleView::ShowForReal,
                    base::Passed(&browser_observer)));
   } else {
-#if defined(OS_MACOSX)
-    // SessionCrashedBubbleView doesn't support being hosted by a Cocoa browser
-    // window, so return false here so StartupBrowserCreator will fall back to
-    // the infobar.
-    // TODO(ellyjones): Make SessionCrashedBubbleView support a Cocoa host.
-    if (views_mode_controller::IsViewsBrowserCocoa())
-      return false;
-#endif
     SessionCrashedBubbleView::ShowForReal(std::move(browser_observer), false);
   }
   return true;
@@ -152,11 +185,9 @@
     return;
   }
 
-  views::View* anchor_view = BrowserView::GetBrowserViewForBrowser(browser)
-                                 ->button_provider()
-                                 ->GetAppMenuButton();
-  SessionCrashedBubbleView* crash_bubble =
-      new SessionCrashedBubbleView(anchor_view, browser, offer_uma_optin);
+  SessionCrashedBubbleView* crash_bubble = new SessionCrashedBubbleView(
+      GetBubbleAnchorView(browser), GetBubbleAnchorRect(browser), browser,
+      offer_uma_optin);
   views::BubbleDialogDelegateView::CreateBubble(crash_bubble)->Show();
 
   RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_SHOWN);
@@ -165,6 +196,7 @@
 }
 
 SessionCrashedBubbleView::SessionCrashedBubbleView(views::View* anchor_view,
+                                                   const gfx::Rect& anchor_rect,
                                                    Browser* browser,
                                                    bool offer_uma_optin)
     : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
@@ -174,6 +206,12 @@
       ignored_(true) {
   set_close_on_deactivate(false);
   chrome::RecordDialogCreation(chrome::DialogIdentifier::SESSION_CRASHED);
+
+  if (!anchor_view) {
+    SetAnchorRect(anchor_rect);
+    set_parent_window(
+        platform_util::GetViewForWindow(browser->window()->GetNativeWindow()));
+  }
 }
 
 SessionCrashedBubbleView::~SessionCrashedBubbleView() {
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.h b/chrome/browser/ui/views/session_crashed_bubble_view.h
index dc2b862a4..3232336f 100644
--- a/chrome/browser/ui/views/session_crashed_bubble_view.h
+++ b/chrome/browser/ui/views/session_crashed_bubble_view.h
@@ -40,6 +40,7 @@
   friend class SessionCrashedBubbleViewTest;
 
   SessionCrashedBubbleView(views::View* anchor_view,
+                           const gfx::Rect& anchor_rect,
                            Browser* browser,
                            bool offer_uma_optin);
   ~SessionCrashedBubbleView() override;
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view_browsertest.cc b/chrome/browser/ui/views/session_crashed_bubble_view_browsertest.cc
index 86ad100..26d7cbf 100644
--- a/chrome/browser/ui/views/session_crashed_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/session_crashed_bubble_view_browsertest.cc
@@ -6,11 +6,15 @@
 
 #include <string>
 
+#include "build/buildflag.h"
+#include "chrome/browser/ui/bubble_anchor_util.h"
 #include "chrome/browser/ui/test/test_browser_dialog.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/toolbar/app_menu_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/browser/ui/views_mode_controller.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "ui/base/ui_features.h"
 #include "ui/views/view.h"
 
 class SessionCrashedBubbleViewTest : public DialogBrowserTest {
@@ -19,11 +23,20 @@
   ~SessionCrashedBubbleViewTest() override {}
 
   void ShowUi(const std::string& name) override {
-    views::View* anchor_view = BrowserView::GetBrowserViewForBrowser(browser())
-                                   ->toolbar()
-                                   ->app_menu_button();
-    SessionCrashedBubbleView* crash_bubble = new SessionCrashedBubbleView(
-        anchor_view, browser(), name == "SessionCrashedBubbleOfferUma");
+    gfx::Rect anchor_rect = gfx::Rect();
+    views::View* anchor_view = nullptr;
+#if BUILDFLAG(MAC_VIEWS_BROWSER)
+    if (views_mode_controller::IsViewsBrowserCocoa())
+      anchor_rect = bubble_anchor_util::GetAppMenuAnchorRectCocoa(browser());
+#endif
+    if (anchor_rect == gfx::Rect()) {
+      anchor_view = BrowserView::GetBrowserViewForBrowser(browser())
+                        ->toolbar()
+                        ->app_menu_button();
+    }
+    SessionCrashedBubbleView* crash_bubble =
+        new SessionCrashedBubbleView(anchor_view, anchor_rect, browser(),
+                                     name == "SessionCrashedBubbleOfferUma");
     views::BubbleDialogDelegateView::CreateBubble(crash_bubble)->Show();
   }
 
diff --git a/chrome/browser/vr/metrics/session_metrics_helper.cc b/chrome/browser/vr/metrics/session_metrics_helper.cc
index 18ea95e..7ed38a33 100644
--- a/chrome/browser/vr/metrics/session_metrics_helper.cc
+++ b/chrome/browser/vr/metrics/session_metrics_helper.cc
@@ -300,8 +300,10 @@
   num_voice_search_started_++;
 }
 
-void SessionMetricsHelper::RecordUrlRequestedByVoice(GURL url) {
-  url_requested_by_voice_ = url;
+void SessionMetricsHelper::RecordUrlRequested(GURL url,
+                                              NavigationMethod method) {
+  last_requested_url_ = url;
+  last_url_request_method_ = method;
 }
 
 void SessionMetricsHelper::SetVrMode(Mode new_mode) {
@@ -558,13 +560,21 @@
                 ukm::GetSourceIdForWebContentsDocument(web_contents())));
 
     // Check that the completed navigation is indeed the one that was requested
-    // by voice, in case that one was incomplete and another was begun. Check
-    // against the first entry for the navigation, as redirects might have
-    // changed what the URL looks like.
-    if (url_requested_by_voice_ == handle->GetRedirectChain().front()) {
-      page_session_tracker_->ukm_entry()->SetWasVoiceSearchNavigation(1);
+    // by either voice or omnibox entry, in case the requested navigation was
+    // incomplete when another was begun. Check against the first entry for the
+    // navigation, as redirects might have changed what the URL looks like.
+    if (last_requested_url_ == handle->GetRedirectChain().front()) {
+      switch (last_url_request_method_) {
+        case kOmniboxUrlEntry:
+        case kOmniboxSuggestionSelected:
+          page_session_tracker_->ukm_entry()->SetWasOmniboxNavigation(1);
+          break;
+        case kVoiceSearch:
+          page_session_tracker_->ukm_entry()->SetWasVoiceSearchNavigation(1);
+          break;
+      }
     }
-    url_requested_by_voice_ = GURL();
+    last_requested_url_ = GURL();
 
     if (mode_ == Mode::kWebXrVrPresentation) {
       presentation_session_tracker_ = std::make_unique<
diff --git a/chrome/browser/vr/metrics/session_metrics_helper.h b/chrome/browser/vr/metrics/session_metrics_helper.h
index a951445..346f487 100644
--- a/chrome/browser/vr/metrics/session_metrics_helper.h
+++ b/chrome/browser/vr/metrics/session_metrics_helper.h
@@ -9,6 +9,7 @@
 
 #include "base/time/time.h"
 #include "chrome/browser/vr/mode.h"
+#include "chrome/browser/vr/ui_browser_interface.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
@@ -118,7 +119,7 @@
   void SetWebVREnabled(bool is_webvr_presenting);
   void SetVRActive(bool is_vr_enabled);
   void RecordVoiceSearchStarted();
-  void RecordUrlRequestedByVoice(GURL url);
+  void RecordUrlRequested(GURL url, NavigationMethod method);
 
  private:
   SessionMetricsHelper(content::WebContents* contents,
@@ -165,7 +166,8 @@
   bool is_vr_enabled_ = false;
   bool started_with_autopresentation_ = false;
 
-  GURL url_requested_by_voice_;
+  GURL last_requested_url_;
+  NavigationMethod last_url_request_method_;
 
   int num_videos_playing_ = 0;
   int num_session_navigation_ = 0;
diff --git a/chrome/browser/vr/test/mock_ui_browser_interface.h b/chrome/browser/vr/test/mock_ui_browser_interface.h
index 42114d7..33ca3be9 100644
--- a/chrome/browser/vr/test/mock_ui_browser_interface.h
+++ b/chrome/browser/vr/test/mock_ui_browser_interface.h
@@ -18,7 +18,7 @@
 
   MOCK_METHOD0(ExitPresent, void());
   MOCK_METHOD0(ExitFullscreen, void());
-  MOCK_METHOD1(Navigate, void(GURL gurl));
+  MOCK_METHOD2(Navigate, void(GURL gurl, NavigationMethod method));
   MOCK_METHOD0(NavigateBack, void());
   MOCK_METHOD0(ExitCct, void());
   MOCK_METHOD0(CloseHostedDialog, void());
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc
index 1b25a21..f315467 100644
--- a/chrome/browser/vr/testapp/vr_test_context.cc
+++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -459,7 +459,7 @@
 void VrTestContext::ExitPresent() {}
 void VrTestContext::ExitFullscreen() {}
 
-void VrTestContext::Navigate(GURL gurl) {
+void VrTestContext::Navigate(GURL gurl, NavigationMethod method) {
   ToolbarState state(gurl, security_state::SecurityLevel::HTTP_SHOW_WARNING,
                      &toolbar::kHttpIcon, base::string16(), true, false);
   ui_->SetToolbarState(state);
diff --git a/chrome/browser/vr/testapp/vr_test_context.h b/chrome/browser/vr/testapp/vr_test_context.h
index 0aa8e97..68db23f 100644
--- a/chrome/browser/vr/testapp/vr_test_context.h
+++ b/chrome/browser/vr/testapp/vr_test_context.h
@@ -53,7 +53,7 @@
   void SetVoiceSearchActive(bool active) override;
   void StartAutocomplete(const AutocompleteRequest& request) override;
   void StopAutocomplete() override;
-  void Navigate(GURL gurl) override;
+  void Navigate(GURL gurl, NavigationMethod method) override;
 
   void set_window_size(const gfx::Size& size) { window_size_ = size; }
 
diff --git a/chrome/browser/vr/ui_browser_interface.h b/chrome/browser/vr/ui_browser_interface.h
index ad0ec29..fc6d59e 100644
--- a/chrome/browser/vr/ui_browser_interface.h
+++ b/chrome/browser/vr/ui_browser_interface.h
@@ -13,6 +13,13 @@
 
 namespace vr {
 
+// A actions which can trigger the navigate function.
+enum NavigationMethod {
+  kOmniboxUrlEntry,
+  kOmniboxSuggestionSelected,
+  kVoiceSearch,
+};
+
 // An interface for the VR UI to communicate with VrShell. Many of the functions
 // in this interface are proxies to methods on VrShell.
 class UiBrowserInterface {
@@ -21,7 +28,7 @@
 
   virtual void ExitPresent() = 0;
   virtual void ExitFullscreen() = 0;
-  virtual void Navigate(GURL gurl) = 0;
+  virtual void Navigate(GURL gurl, NavigationMethod method) = 0;
   virtual void NavigateBack() = 0;
   virtual void ExitCct() = 0;
   virtual void CloseHostedDialog() = 0;
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc
index a921d4166..88e747a 100644
--- a/chrome/browser/vr/ui_scene_creator.cc
+++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -188,7 +188,8 @@
       kNone, kPhaseForeground,
       base::BindRepeating(
           [](UiBrowserInterface* b, Ui* ui, Model* m, SuggestionBinding* e) {
-            b->Navigate(e->model()->destination);
+            b->Navigate(e->model()->destination,
+                        NavigationMethod::kOmniboxSuggestionSelected);
             ui->OnUiRequestedNavigation();
           },
           base::Unretained(browser), base::Unretained(ui),
@@ -1998,7 +1999,8 @@
       [](Model* model, UiBrowserInterface* browser, Ui* ui,
          const EditedText& text) {
         if (!model->omnibox_suggestions.empty()) {
-          browser->Navigate(model->omnibox_suggestions.front().destination);
+          browser->Navigate(model->omnibox_suggestions.front().destination,
+                            NavigationMethod::kOmniboxUrlEntry);
           ui->OnUiRequestedNavigation();
         }
       },
diff --git a/chrome/browser/vr/ui_unittest.cc b/chrome/browser/vr/ui_unittest.cc
index 6594260a..d679fbf 100644
--- a/chrome/browser/vr/ui_unittest.cc
+++ b/chrome/browser/vr/ui_unittest.cc
@@ -997,7 +997,9 @@
   ASSERT_NE(suggestions, nullptr);
   UiElement* suggestion = suggestions->children().front().get();
   ASSERT_NE(suggestion, nullptr);
-  EXPECT_CALL(*browser_, Navigate(gurl)).Times(1);
+  EXPECT_CALL(*browser_,
+              Navigate(gurl, NavigationMethod::kOmniboxSuggestionSelected))
+      .Times(1);
   suggestion->OnHoverEnter({0, 0});
   suggestion->OnButtonDown({0, 0});
   suggestion->OnButtonUp({0, 0});
diff --git a/chrome/browser/webshare/share_service_impl.cc b/chrome/browser/webshare/share_service_impl.cc
index d785f94..a6d9bd9 100644
--- a/chrome/browser/webshare/share_service_impl.cc
+++ b/chrome/browser/webshare/share_service_impl.cc
@@ -126,9 +126,8 @@
   if (!content::ReplaceWebShareUrlPlaceholders(result->url_template(), title,
                                                text, share_url,
                                                &url_template_filled)) {
-    // TODO(mgiuca): This error should not be possible at share time, because
-    // targets with invalid templates should not be chooseable. Fix
-    // https://crbug.com/694380 and replace this with a DCHECK.
+    // This error should not be possible at share time. content::ManifestParser
+    // should have filtered out invalid targets at manifest parse time.
     std::move(callback).Run(blink::mojom::ShareError::INTERNAL_ERROR);
     return;
   }
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/background.js b/chrome/common/extensions/docs/examples/extensions/mappy/background.js
index 9796f8c..959e7bd 100644
--- a/chrome/common/extensions/docs/examples/extensions/mappy/background.js
+++ b/chrome/common/extensions/docs/examples/extensions/mappy/background.js
@@ -2,43 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Global accessor that the popup uses.
-var addresses = {};
-var selectedAddress = null;
-var selectedId = null;
+'use strict'
 
-function updateAddress(tabId) {
-  chrome.tabs.sendRequest(tabId, {}, function(address) {
-    addresses[tabId] = address;
-    if (!address) {
-      chrome.pageAction.hide(tabId);
-    } else {
-      chrome.pageAction.show(tabId);
-      if (selectedId == tabId) {
-        updateSelected(tabId);
-      }
-    }
-  });
-}
-
-function updateSelected(tabId) {
-  selectedAddress = addresses[tabId];
-  if (selectedAddress)
-    chrome.pageAction.setTitle({tabId:tabId, title:selectedAddress});
-}
-
-chrome.tabs.onUpdated.addListener(function(tabId, change, tab) {
-  if (change.status == "complete") {
-    updateAddress(tabId);
-  }
-});
-
-chrome.tabs.onSelectionChanged.addListener(function(tabId, info) {
-  selectedId = tabId;
-  updateSelected(tabId);
-});
-
-// Ensure the current selected tab is set up.
-chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
-  updateAddress(tabs[0].id);
+chrome.runtime.onMessage.addListener(function(req, sender) {
+  chrome.storage.local.set({address: req.address})
+  chrome.pageAction.show(sender.tab.id);
+  chrome.pageAction.setTitle({tabId: sender.tab.id, title: req.address});
 });
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/manifest.json b/chrome/common/extensions/docs/examples/extensions/mappy/manifest.json
index c0e8462..2cacda9 100644
--- a/chrome/common/extensions/docs/examples/extensions/mappy/manifest.json
+++ b/chrome/common/extensions/docs/examples/extensions/mappy/manifest.json
@@ -1,14 +1,20 @@
 {
   "name": "Mappy",
-  "version": "0.6.1",
+  "version": "1.0",
   "description": "Finds addresses in the web page you're on and pops up a map window.",
   "icons": { "128": "icon.png" },
-  "background": { "scripts": ["background.js"] },
+  "background": {
+    "scripts": ["background.js"],
+    "persistent": false
+  },
   "content_scripts": [
-    { "matches": ["http://*/*"], "js": ["mappy_content_script.js"] }
+    {
+      "matches": ["http://*/*"],
+      "js": ["mappy_content_script.js"]
+    }
   ],
   "permissions": [
-    "tabs",
+    "storage",
     "https://maps.google.com/*",
     "https://maps.googleapis.com/*"
   ],
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/mappy_content_script.js b/chrome/common/extensions/docs/examples/extensions/mappy/mappy_content_script.js
index 990a27f..8bdf56ee 100644
--- a/chrome/common/extensions/docs/examples/extensions/mappy/mappy_content_script.js
+++ b/chrome/common/extensions/docs/examples/extensions/mappy/mappy_content_script.js
@@ -2,50 +2,28 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// The background page is asking us to find an address on the page.
-if (window == top) {
-  chrome.extension.onRequest.addListener(function(req, sender, sendResponse) {
-    sendResponse(findAddress());
-  });
-}
-
 // Search the text nodes for a US-style mailing address.
-// Return null if none is found.
-var findAddress = function() {
-  var found;
-  var re = /(\d+\s+[':.,\s\w]*,\s*[A-Za-z]+\s*\d{5}(-\d{4})?)/m;
-  var node = document.body;
-  var done = false;
-  while (!done) {
-    done = true;
-    for (var i = 0; i < node.childNodes.length; ++i) {
-      var child = node.childNodes[i];
-      if (child.textContent.match(re)) {
-        node = child;
-        found = node;
-        done = false;
-        break;
-      }
-    }
+
+let findAddress = function() {
+  let found;
+  let re = /(\d+\s+[':.,\s\w]*,\s*[A-Za-z]+\s*\d{5}(-\d{4})?)/m;
+  let node = document.body.textContent.match(re);
+  if (document.body.textContent.match(re)) {
+    found = node;
   }
   if (found) {
-    var text = "";
-    if (found.childNodes.length) {
-      for (var i = 0; i < found.childNodes.length; ++i) {
-        text += found.childNodes[i].textContent + " ";
-      }
-    } else {
-      text = found.textContent;
-    }
-    var match = re.exec(text);
+    let text = node;
+    let match = re.exec(text);
     if (match && match.length) {
-      console.log("found: " + match[0]);
-      var trim = /\s{2,}/g;
-      return match[0].replace(trim, " ");
+      console.log('found: ' + match[0]);
+      let trim = /\s{2,}/g;
+      let address = match[0].replace(trim, ' ')
+      chrome.runtime.sendMessage({'address': address})
     } else {
-      console.log("bad initial match: " + found.textContent);
-      console.log("no match in: " + text);
+      console.log('bad initial match: ' + found.textContent);
+      console.log('no match in: ' + text);
     }
   }
-  return null;
 }
+
+findAddress();
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/popup.js b/chrome/common/extensions/docs/examples/extensions/mappy/popup.js
index 10b4e74..20486956 100644
--- a/chrome/common/extensions/docs/examples/extensions/mappy/popup.js
+++ b/chrome/common/extensions/docs/examples/extensions/mappy/popup.js
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var maps_key = "AIzaSyBa5aieunaIp3Obco-dNVYMdbnTZGAVkKQ";
+'use strict'
+
+const kMaps_key = 'AIzaSyBa5aieunaIp3Obco-dNVYMdbnTZGAVkKQ';
 
 function gclient_geocode(address) {
-  var url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' +
+  let url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' +
             encodeURIComponent(address) + '&sensor=false';
-  var request = new XMLHttpRequest();
+  let request = new XMLHttpRequest();
 
   request.open('GET', url, true);
   console.log(url);
@@ -15,13 +17,13 @@
     console.log(request, e);
     if (request.readyState == 4) {
       if (request.status == 200) {
-        var json = JSON.parse(request.responseText);
-        var latlng = json.results[0].geometry.location;
+        let json = JSON.parse(request.responseText);
+        let latlng = json.results[0].geometry.location;
         latlng = latlng.lat + ',' + latlng.lng;
-        var src = 'https://maps.googleapis.com/maps/api/staticmap?center=' +
+        let src = 'https://maps.googleapis.com/maps/api/staticmap?center=' +
             latlng + '&markers=' + latlng + '&zoom=14' +
-            '&size=512x512&sensor=false&key=' + maps_key;
-        var map = document.getElementById('map');
+            '&size=512x512&sensor=false&key=' + kMaps_key;
+        let map = document.getElementById('map');
         map.src = src;
         map.addEventListener('click', function () {
           window.close();
@@ -35,9 +37,9 @@
 }
 
 function map() {
-  var address = chrome.extension.getBackgroundPage().selectedAddress;
-  if (address)
-    gclient_geocode(address);
+  chrome.storage.local.get(['address'], function(value){
+    gclient_geocode(value.address);
+  })
 }
 
 window.onload = map;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 0024435..12a69367 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2375,7 +2375,7 @@
     "../browser/metrics/thread_watcher_android_unittest.cc",
     "../browser/metrics/thread_watcher_unittest.cc",
     "../browser/mod_pagespeed/mod_pagespeed_metrics_unittest.cc",
-    "../browser/net/chrome_http_user_agent_settings_unittest.cc",
+    "../browser/net/chrome_accept_language_settings_unittest.cc",
     "../browser/net/chrome_network_delegate_unittest.cc",
     "../browser/net/dns_probe_runner_unittest.cc",
     "../browser/net/dns_probe_service_unittest.cc",
diff --git a/chrome/test/chromedriver/chrome/chrome_finder.cc b/chrome/test/chromedriver/chrome/chrome_finder.cc
index ecdbbb47..2554ed60 100644
--- a/chrome/test/chromedriver/chrome/chrome_finder.cc
+++ b/chrome/test/chromedriver/chrome/chrome_finder.cc
@@ -47,13 +47,16 @@
 }
 #elif defined(OS_LINUX)
 void GetApplicationDirs(std::vector<base::FilePath>* locations) {
-  locations->push_back(base::FilePath("/opt/google/chrome"));
-  locations->push_back(base::FilePath("/usr/local/bin"));
+  // TODO: Respect users' PATH variables.
+  // Until then, we use an approximation of the most common defaults.
   locations->push_back(base::FilePath("/usr/local/sbin"));
-  locations->push_back(base::FilePath("/usr/bin"));
+  locations->push_back(base::FilePath("/usr/local/bin"));
   locations->push_back(base::FilePath("/usr/sbin"));
-  locations->push_back(base::FilePath("/bin"));
+  locations->push_back(base::FilePath("/usr/bin"));
   locations->push_back(base::FilePath("/sbin"));
+  locations->push_back(base::FilePath("/bin"));
+  // Lastly, try the default installation location.
+  locations->push_back(base::FilePath("/opt/google/chrome"));
 }
 #elif defined(OS_ANDROID)
 void GetApplicationDirs(std::vector<base::FilePath>* locations) {
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index a115c7c8..b73d974 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -195,6 +195,7 @@
         'ChromeDriverTest.testWindowPosition',
         'ChromeDriverTest.testWindowSize',
         'ChromeDriverTest.testWindowMaximize',
+        'ChromeDriverTest.testWindowMinimize',
         'ChromeLogPathCapabilityTest.testChromeLogPath',
         'RemoteBrowserTest.*',
         # Don't enable perf testing on Android yet.
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc
index 7281872e..8bf1f43 100644
--- a/chrome/test/media_router/media_router_integration_browsertest.cc
+++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -827,7 +827,9 @@
   CheckStartFailed(web_contents, "UnknownError", "Unknown sink");
 }
 
-IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, ReconnectSession) {
+// TODO(crbug.com/822231): Flaky in Chromium waterfall.
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
+                       MANUAL_ReconnectSession) {
   RunReconnectSessionTest();
 }
 
diff --git a/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc b/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc
index e5d96d21..f9cf7ab 100644
--- a/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc
+++ b/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc
@@ -99,6 +99,7 @@
   RunFailToSendMessageTest();
 }
 
+// TODO(crbug.com/822231): Flaky in Chromium waterfall.
 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUANoReceiverBrowserTest,
                        ReconnectSession) {
   RunReconnectSessionTest();
diff --git a/chrome/test/mini_installer/uninstall_chrome.py b/chrome/test/mini_installer/uninstall_chrome.py
index 3ce22e4..e0979d7 100644
--- a/chrome/test/mini_installer/uninstall_chrome.py
+++ b/chrome/test/mini_installer/uninstall_chrome.py
@@ -38,7 +38,8 @@
              options.chrome_long_name)
   # Query the key. It will throw a WindowsError if the key doesn't exist.
   try:
-    key = _winreg.OpenKey(root_key, sub_key, 0, _winreg.KEY_QUERY_VALUE)
+    key = _winreg.OpenKey(root_key, sub_key, 0,
+                          _winreg.KEY_QUERY_VALUE | _winreg.KEY_WOW64_32KEY)
   except WindowsError:
     if options.no_error_if_absent:
       return 0
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc
index 8228612..86fd83d 100644
--- a/components/omnibox/browser/autocomplete_match.cc
+++ b/components/omnibox/browser/autocomplete_match.cc
@@ -438,9 +438,19 @@
     TemplateURLService* template_url_service,
     const base::string16& keyword,
     const std::string& host) {
+  return const_cast<TemplateURL*>(GetTemplateURLWithKeyword(
+      static_cast<const TemplateURLService*>(template_url_service), keyword,
+      host));
+}
+
+// static
+const TemplateURL* AutocompleteMatch::GetTemplateURLWithKeyword(
+    const TemplateURLService* template_url_service,
+    const base::string16& keyword,
+    const std::string& host) {
   if (template_url_service == nullptr)
     return nullptr;
-  TemplateURL* template_url =
+  const TemplateURL* template_url =
       keyword.empty() ? nullptr
                       : template_url_service->GetTemplateURLForKeyword(keyword);
   return (template_url || host.empty()) ?
@@ -451,7 +461,7 @@
 GURL AutocompleteMatch::GURLToStrippedGURL(
     const GURL& url,
     const AutocompleteInput& input,
-    TemplateURLService* template_url_service,
+    const TemplateURLService* template_url_service,
     const base::string16& keyword) {
   if (!url.is_valid())
     return url;
diff --git a/components/omnibox/browser/autocomplete_match.h b/components/omnibox/browser/autocomplete_match.h
index 92fc24c..b245b7fd 100644
--- a/components/omnibox/browser/autocomplete_match.h
+++ b/components/omnibox/browser/autocomplete_match.h
@@ -194,6 +194,10 @@
       TemplateURLService* template_url_service,
       const base::string16& keyword,
       const std::string& host);
+  static const TemplateURL* GetTemplateURLWithKeyword(
+      const TemplateURLService* template_url_service,
+      const base::string16& keyword,
+      const std::string& host);
 
   // Returns |url| altered by stripping off "www.", converting https protocol
   // to http, and stripping excess query parameters.  These conversions are
@@ -212,7 +216,7 @@
   // seems to matter to the user.
   static GURL GURLToStrippedGURL(const GURL& url,
                                  const AutocompleteInput& input,
-                                 TemplateURLService* template_url_service,
+                                 const TemplateURLService* template_url_service,
                                  const base::string16& keyword);
 
   // Sets the |match_in_scheme|, |match_in_subdomain|, and |match_after_host|
diff --git a/components/safe_browsing/db/v4_store.cc b/components/safe_browsing/db/v4_store.cc
index 5911ca1..c03f22c 100644
--- a/components/safe_browsing/db/v4_store.cc
+++ b/components/safe_browsing/db/v4_store.cc
@@ -777,6 +777,10 @@
 }
 
 HashPrefix V4Store::GetMatchingHashPrefix(const FullHash& full_hash) {
+  return GetMatchingHashPrefix(base::StringPiece(full_hash));
+}
+
+HashPrefix V4Store::GetMatchingHashPrefix(base::StringPiece full_hash) {
   // It should never be the case that more than one hash prefixes match a given
   // full hash. However, if that happens, this method returns any one of them.
   // It does not guarantee which one of those will be returned.
@@ -784,8 +788,7 @@
   checks_attempted_++;
   for (const auto& pair : hash_prefix_map_) {
     const PrefixSize& prefix_size = pair.first;
-    base::StringPiece hash_prefix =
-        base::StringPiece(full_hash).substr(0, prefix_size);
+    base::StringPiece hash_prefix = full_hash.substr(0, prefix_size);
     if (HashPrefixMatches(hash_prefix, pair.second, prefix_size))
       return hash_prefix.as_string();
   }
diff --git a/components/safe_browsing/db/v4_store.h b/components/safe_browsing/db/v4_store.h
index 6db059f..3812af0 100644
--- a/components/safe_browsing/db/v4_store.h
+++ b/components/safe_browsing/db/v4_store.h
@@ -293,6 +293,8 @@
   FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestChecksumErrorOnStartup);
   FRIEND_TEST_ALL_PREFIXES(V4StoreTest, WriteToDiskFails);
   FRIEND_TEST_ALL_PREFIXES(V4StoreTest, FullUpdateFailsChecksumSynchronously);
+  FRIEND_TEST_ALL_PREFIXES(V4StorePerftest, StressTest);
+
   friend class V4StoreTest;
 
   // If |prefix_size| is within expected range, and |raw_hashes_length| is a
@@ -338,6 +340,10 @@
   static void ReserveSpaceInPrefixMap(const HashPrefixMap& other_prefixes_map,
                                       HashPrefixMap* prefix_map_to_update);
 
+  // Same as the public GetMatchingHashPrefix method, but takes a StringPiece,
+  // for performance reasons.
+  HashPrefix GetMatchingHashPrefix(base::StringPiece full_hash);
+
   // Merges the prefix map from the old store (|old_hash_prefix_map|) and the
   // update (additions_map) to populate the prefix map for the current store.
   // The indices in the |raw_removals| list, which may be NULL, are not merged.
diff --git a/components/safe_browsing/db/v4_store_perftest.cc b/components/safe_browsing/db/v4_store_perftest.cc
index e187dc4..4db3783c 100644
--- a/components/safe_browsing/db/v4_store_perftest.cc
+++ b/components/safe_browsing/db/v4_store_perftest.cc
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/numerics/checked_math.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/timer/elapsed_timer.h"
@@ -23,14 +24,28 @@
 class V4StorePerftest : public testing::Test {};
 
 TEST_F(V4StorePerftest, StressTest) {
-  const int kNumPrefixes = 2000000;
+// Debug builds can be quite slow. Use a smaller number of prefixes to test.
+#if defined(NDEBUG)
+  const size_t kNumPrefixes = 2000000;
+#else
+  const size_t kNumPrefixes = 20000;
+#endif
+
+  static_assert(kMaxHashPrefixLength == crypto::kSHA256Length,
+                "SHA256 produces a valid FullHash");
+  CHECK(base::IsValidForType<size_t>(
+      base::CheckMul(kNumPrefixes, kMaxHashPrefixLength)));
+
+  // Keep the full hashes as one big string to avoid tons of allocations /
+  // deallocations in the test.
+  std::string full_hashes(kNumPrefixes * kMaxHashPrefixLength, 0);
+  base::StringPiece full_hashes_piece = base::StringPiece(full_hashes);
   std::vector<std::string> prefixes;
-  std::vector<std::string> full_hashes;
   for (size_t i = 0; i < kNumPrefixes; i++) {
-    std::string sha256 = crypto::SHA256HashString(base::StringPrintf("%zu", i));
-    DCHECK_EQ(crypto::kSHA256Length, kMaxHashPrefixLength);
-    full_hashes.push_back(sha256);
-    prefixes.push_back(sha256.substr(0, kMinHashPrefixLength));
+    size_t index = i * kMaxHashPrefixLength;
+    crypto::SHA256HashString(base::StringPrintf("%zu", i), &full_hashes[index],
+                             kMaxHashPrefixLength);
+    prefixes.push_back(full_hashes.substr(index, kMinHashPrefixLength));
   }
 
   auto store = std::make_unique<TestV4Store>(
@@ -39,13 +54,16 @@
 
   size_t matches = 0;
   base::ElapsedTimer timer;
-  for (const auto& full_hash : full_hashes) {
+  for (size_t i = 0; i < kNumPrefixes; i++) {
+    size_t index = i * kMaxHashPrefixLength;
+    base::StringPiece full_hash =
+        full_hashes_piece.substr(index, kMaxHashPrefixLength);
     matches += !store->GetMatchingHashPrefix(full_hash).empty();
   }
-  perf_test::PrintResult("GetMachingHashPrefix", "", "",
+  perf_test::PrintResult("GetMatchingHashPrefix", "", "",
                          timer.Elapsed().InMillisecondsF(), "ms", true);
 
-  EXPECT_EQ(matches, full_hashes.size());
+  EXPECT_EQ(kNumPrefixes, matches);
 }
 
 }  // namespace safe_browsing
diff --git a/components/search_engines/search_host_to_urls_map.cc b/components/search_engines/search_host_to_urls_map.cc
index 0fec21ec..581974b 100644
--- a/components/search_engines/search_host_to_urls_map.cc
+++ b/components/search_engines/search_host_to_urls_map.cc
@@ -36,7 +36,7 @@
   host_to_urls_map_[url.host()].insert(template_url);
 }
 
-void SearchHostToURLsMap::Remove(TemplateURL* template_url) {
+void SearchHostToURLsMap::Remove(const TemplateURL* template_url) {
   DCHECK(initialized_);
   DCHECK(template_url);
   DCHECK_NE(TemplateURL::OMNIBOX_API_EXTENSION, template_url->type());
@@ -45,7 +45,8 @@
   auto set_with_url =
       std::find_if(host_to_urls_map_.begin(), host_to_urls_map_.end(),
                    [&](std::pair<const std::string, TemplateURLSet>& entry) {
-                     return entry.second.erase(template_url);
+                     return entry.second.erase(
+                         const_cast<TemplateURL*>(template_url));
                    });
 
   if (set_with_url != host_to_urls_map_.end() && set_with_url->second.empty())
diff --git a/components/search_engines/search_host_to_urls_map.h b/components/search_engines/search_host_to_urls_map.h
index 041f7754..6a25d5c 100644
--- a/components/search_engines/search_host_to_urls_map.h
+++ b/components/search_engines/search_host_to_urls_map.h
@@ -34,7 +34,7 @@
            const SearchTermsData& search_terms_data);
 
   // Removes the TemplateURL from the lookup.
-  void Remove(TemplateURL* template_url);
+  void Remove(const TemplateURL* template_url);
 
   // Returns the first TemplateURL found with a URL using the specified |host|,
   // or NULL if there are no such TemplateURLs
diff --git a/components/search_engines/template_url_fetcher.cc b/components/search_engines/template_url_fetcher.cc
index abb6005..211e69f9 100644
--- a/components/search_engines/template_url_fetcher.cc
+++ b/components/search_engines/template_url_fetcher.cc
@@ -168,7 +168,7 @@
   DCHECK(model);
   DCHECK(model->loaded());
 
-  TemplateURL* existing_url = nullptr;
+  const TemplateURL* existing_url = nullptr;
   if (!model->CanAddAutogeneratedKeyword(keyword_, GURL(template_url_->url()),
                                          &existing_url)) {
     fetcher_->RequestCompleted(this);  // WARNING: Deletes us!
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc
index 1854524..d5aad0b 100644
--- a/components/search_engines/template_url_service.cc
+++ b/components/search_engines/template_url_service.cc
@@ -183,7 +183,7 @@
 }
 
 bool Contains(TemplateURLService::OwnedTemplateURLVector* template_urls,
-              TemplateURL* turl) {
+              const TemplateURL* turl) {
   return FindTemplateURL(template_urls, turl) != template_urls->end();
 }
 
@@ -304,11 +304,11 @@
 bool TemplateURLService::CanAddAutogeneratedKeyword(
     const base::string16& keyword,
     const GURL& url,
-    TemplateURL** template_url_to_replace) {
+    const TemplateURL** template_url_to_replace) {
   DCHECK(!keyword.empty());  // This should only be called for non-empty
                              // keywords. If we need to support empty kewords
                              // the code needs to change slightly.
-  TemplateURL* existing_url = GetTemplateURLForKeyword(keyword);
+  const TemplateURL* existing_url = GetTemplateURLForKeyword(keyword);
   if (template_url_to_replace)
     *template_url_to_replace = existing_url;
   if (existing_url) {
@@ -441,7 +441,7 @@
   return Add(std::move(template_url));
 }
 
-void TemplateURLService::Remove(TemplateURL* template_url) {
+void TemplateURLService::Remove(const TemplateURL* template_url) {
   RemoveNoNotify(template_url);
   NotifyObservers();
 }
@@ -1370,7 +1370,7 @@
                                                                : engine1;
 }
 
-void TemplateURLService::RemoveFromMaps(TemplateURL* template_url) {
+void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) {
   const base::string16& keyword = template_url->keyword();
   DCHECK_NE(0U, keyword_to_turl_and_length_.count(keyword));
   if (keyword_to_turl_and_length_[keyword].first == template_url) {
@@ -1562,7 +1562,7 @@
   // functions.
   // Search for conflicting keyword turl before updating values of
   // existing_turl.
-  TemplateURL* conflicting_keyword_turl =
+  const TemplateURL* conflicting_keyword_turl =
       FindNonExtensionTemplateURLForKeyword(new_values.keyword());
 
   // Update existing turl with new values.
@@ -1956,7 +1956,7 @@
   return template_url_ptr;
 }
 
-void TemplateURLService::RemoveNoNotify(TemplateURL* template_url) {
+void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) {
   DCHECK(template_url != default_search_provider_);
 
   auto i = FindTemplateURL(&template_urls_, template_url);
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h
index 3e5ff00..45501fb 100644
--- a/components/search_engines/template_url_service.h
+++ b/components/search_engines/template_url_service.h
@@ -128,7 +128,7 @@
   // a keyword for hosts already associated with a manually-edited keyword.
   bool CanAddAutogeneratedKeyword(const base::string16& keyword,
                                   const GURL& url,
-                                  TemplateURL** template_url_to_replace);
+                                  const TemplateURL** template_url_to_replace);
 
   // Returns whether the engine is a "pre-existing" engine, either from the
   // prepopulate list or created by policy.
@@ -192,7 +192,7 @@
 
   // Removes the keyword from the model. This deletes the supplied TemplateURL.
   // This fails if the supplied template_url is the default search provider.
-  void Remove(TemplateURL* template_url);
+  void Remove(const TemplateURL* template_url);
 
   // Removes any TemplateURL of the specified |type| associated with
   // |extension_id|. Unlike with Remove(), this can be called when the
@@ -494,7 +494,7 @@
   // Removes |template_url| from various internal maps
   // (|keyword_to_turl_and_length_|, |keyword_domain_to_turl_and_length_|,
   // |guid_to_turl_|, |provider_map_|).
-  void RemoveFromMaps(TemplateURL* template_url);
+  void RemoveFromMaps(const TemplateURL* template_url);
 
   // Adds |template_url| to various internal maps
   // (|keyword_to_turl_and_length_|, |keyword_domain_to_turl_and_length_|,
@@ -613,7 +613,7 @@
   // Removes the keyword from the model. This deletes the supplied TemplateURL.
   // This fails if the supplied template_url is the default search provider.
   // Caller is responsible for notifying observers.
-  void RemoveNoNotify(TemplateURL* template_url);
+  void RemoveNoNotify(const TemplateURL* template_url);
 
   // Like ResetTemplateURL(), but instead of notifying observers, returns
   // whether anything has changed.
diff --git a/components/sync/driver/about_sync_util.cc b/components/sync/driver/about_sync_util.cc
index 23921e0..6333744f 100644
--- a/components/sync/driver/about_sync_util.cc
+++ b/components/sync/driver/about_sync_util.cc
@@ -464,8 +464,10 @@
 
   // Status from Last Completed Session.
   if (snapshot.is_initialized()) {
-    if (snapshot.get_updates_origin() != sync_pb::SyncEnums::UNKNOWN_ORIGIN) {
-      session_source->Set(ProtoEnumToString(snapshot.get_updates_origin()));
+    if (snapshot.legacy_updates_source() !=
+        sync_pb::GetUpdatesCallerInfo::UNKNOWN) {
+      session_source->Set(
+          ProtoEnumToString(snapshot.legacy_updates_source()));
     }
     get_key_result->Set(GetSyncerErrorString(
         snapshot.model_neutral_state().last_get_key_result));
diff --git a/components/sync/engine/cycle/sync_cycle_snapshot.cc b/components/sync/engine/cycle/sync_cycle_snapshot.cc
index 20823b51..fab6c65 100644
--- a/components/sync/engine/cycle/sync_cycle_snapshot.cc
+++ b/components/sync/engine/cycle/sync_cycle_snapshot.cc
@@ -36,7 +36,7 @@
     base::Time poll_finish_time,
     const std::vector<int>& num_entries_by_type,
     const std::vector<int>& num_to_delete_entries_by_type,
-    sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin)
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource legacy_updates_source)
     : model_neutral_state_(model_neutral_state),
       download_progress_markers_(download_progress_markers),
       is_silenced_(is_silenced),
@@ -49,7 +49,7 @@
       poll_finish_time_(poll_finish_time),
       num_entries_by_type_(num_entries_by_type),
       num_to_delete_entries_by_type_(num_to_delete_entries_by_type),
-      get_updates_origin_(get_updates_origin),
+      legacy_updates_source_(legacy_updates_source),
       is_initialized_(true) {}
 
 SyncCycleSnapshot::SyncCycleSnapshot(const SyncCycleSnapshot& other) = default;
@@ -82,7 +82,7 @@
   value->SetInteger("numHierarchyConflicts", num_hierarchy_conflicts_);
   value->SetInteger("numServerConflicts", num_server_conflicts_);
   value->SetInteger("numEntries", num_entries_);
-  value->SetString("getUpdatesOrigin", ProtoEnumToString(get_updates_origin_));
+  value->SetString("legacySource", ProtoEnumToString(legacy_updates_source_));
   value->SetBoolean("notificationsEnabled", notifications_enabled_);
 
   std::unique_ptr<base::DictionaryValue> counter_entries(
@@ -157,9 +157,9 @@
   return num_to_delete_entries_by_type_;
 }
 
-sync_pb::SyncEnums::GetUpdatesOrigin SyncCycleSnapshot::get_updates_origin()
-    const {
-  return get_updates_origin_;
+sync_pb::GetUpdatesCallerInfo::GetUpdatesSource
+SyncCycleSnapshot::legacy_updates_source() const {
+  return legacy_updates_source_;
 }
 
 }  // namespace syncer
diff --git a/components/sync/engine/cycle/sync_cycle_snapshot.h b/components/sync/engine/cycle/sync_cycle_snapshot.h
index 62aee7e..1897af2 100644
--- a/components/sync/engine/cycle/sync_cycle_snapshot.h
+++ b/components/sync/engine/cycle/sync_cycle_snapshot.h
@@ -30,19 +30,20 @@
 class SyncCycleSnapshot {
  public:
   SyncCycleSnapshot();
-  SyncCycleSnapshot(const ModelNeutralState& model_neutral_state,
-                    const ProgressMarkerMap& download_progress_markers,
-                    bool is_silenced,
-                    int num_encryption_conflicts,
-                    int num_hierarchy_conflicts,
-                    int num_server_conflicts,
-                    bool notifications_enabled,
-                    size_t num_entries,
-                    base::Time sync_start_time,
-                    base::Time poll_finish_time,
-                    const std::vector<int>& num_entries_by_type,
-                    const std::vector<int>& num_to_delete_entries_by_type,
-                    sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin);
+  SyncCycleSnapshot(
+      const ModelNeutralState& model_neutral_state,
+      const ProgressMarkerMap& download_progress_markers,
+      bool is_silenced,
+      int num_encryption_conflicts,
+      int num_hierarchy_conflicts,
+      int num_server_conflicts,
+      bool notifications_enabled,
+      size_t num_entries,
+      base::Time sync_start_time,
+      base::Time poll_finish_time,
+      const std::vector<int>& num_entries_by_type,
+      const std::vector<int>& num_to_delete_entries_by_type,
+      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource legacy_updates_source);
   SyncCycleSnapshot(const SyncCycleSnapshot& other);
   ~SyncCycleSnapshot();
 
@@ -62,7 +63,7 @@
   base::Time poll_finish_time() const;
   const std::vector<int>& num_entries_by_type() const;
   const std::vector<int>& num_to_delete_entries_by_type() const;
-  sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin() const;
+  sync_pb::GetUpdatesCallerInfo::GetUpdatesSource legacy_updates_source() const;
 
   // Set iff this snapshot was not built using the default constructor.
   bool is_initialized() const;
@@ -82,7 +83,10 @@
   std::vector<int> num_entries_by_type_;
   std::vector<int> num_to_delete_entries_by_type_;
 
-  sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin_;
+  // This enum value used to be an important part of the sync protocol, but is
+  // now deprecated.  We continue to use it in the snapshot because there is
+  // still some value in displaying it on the about:sync page.
+  sync_pb::GetUpdatesCallerInfo::GetUpdatesSource legacy_updates_source_;
 
   bool is_initialized_;
 };
diff --git a/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc b/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc
index ca0f243..2e7c2b9 100644
--- a/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc
+++ b/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc
@@ -47,7 +47,7 @@
                              0, base::Time::Now(), base::Time::Now(),
                              std::vector<int>(MODEL_TYPE_COUNT, 0),
                              std::vector<int>(MODEL_TYPE_COUNT, 0),
-                             sync_pb::SyncEnums::UNKNOWN_ORIGIN);
+                             sync_pb::GetUpdatesCallerInfo::UNKNOWN);
   std::unique_ptr<base::DictionaryValue> value(snapshot.ToValue());
   EXPECT_EQ(16u, value->size());
   ExpectDictIntegerValue(model_neutral.num_successful_commits, *value,
diff --git a/components/sync/engine_impl/cycle/nudge_tracker.cc b/components/sync/engine_impl/cycle/nudge_tracker.cc
index 8b327e6..40d26e5 100644
--- a/components/sync/engine_impl/cycle/nudge_tracker.cc
+++ b/components/sync/engine_impl/cycle/nudge_tracker.cc
@@ -299,22 +299,53 @@
   type_trackers_.find(type)->second->SetLegacyNotificationHint(progress);
 }
 
-sync_pb::SyncEnums::GetUpdatesOrigin NudgeTracker::GetOrigin() const {
-  for (const auto& type_and_tracker : type_trackers_) {
-    const DataTypeTracker& tracker = *type_and_tracker.second;
-    if (!tracker.IsBlocked() &&
-        (tracker.HasPendingInvalidation() ||
-         tracker.HasRefreshRequestPending() ||
-         tracker.HasLocalChangePending() || tracker.IsInitialSyncRequired())) {
-      return sync_pb::SyncEnums::GU_TRIGGER;
+sync_pb::GetUpdatesCallerInfo::GetUpdatesSource NudgeTracker::GetLegacySource()
+    const {
+  // There's an order to these sources: NOTIFICATION, DATATYPE_REFRESH, LOCAL,
+  // RETRY.  The server makes optimization decisions based on this field, so
+  // it's important to get this right.  Setting it wrong could lead to missed
+  // updates.
+  //
+  // This complexity is part of the reason why we're deprecating 'source' in
+  // favor of 'origin'.
+  bool has_invalidation_pending = false;
+  bool has_refresh_request_pending = false;
+  bool has_commit_pending = false;
+  bool is_initial_sync_required = false;
+  bool has_retry = IsRetryRequired();
+
+  for (TypeTrackerMap::const_iterator it = type_trackers_.begin();
+       it != type_trackers_.end(); ++it) {
+    const DataTypeTracker& tracker = *it->second;
+    if (!tracker.IsBlocked() && tracker.HasPendingInvalidation()) {
+      has_invalidation_pending = true;
+    }
+    if (!tracker.IsBlocked() && tracker.HasRefreshRequestPending()) {
+      has_refresh_request_pending = true;
+    }
+    if (!tracker.IsBlocked() && tracker.HasLocalChangePending()) {
+      has_commit_pending = true;
+    }
+    if (!tracker.IsBlocked() && tracker.IsInitialSyncRequired()) {
+      is_initial_sync_required = true;
     }
   }
 
-  if (IsRetryRequired()) {
-    return sync_pb::SyncEnums::RETRY;
+  if (has_invalidation_pending) {
+    return sync_pb::GetUpdatesCallerInfo::NOTIFICATION;
+  } else if (has_refresh_request_pending) {
+    return sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH;
+  } else if (is_initial_sync_required) {
+    // Not quite accurate, but good enough for our purposes.  This setting of
+    // SOURCE is just a backward-compatibility hack anyway.
+    return sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH;
+  } else if (has_commit_pending) {
+    return sync_pb::GetUpdatesCallerInfo::LOCAL;
+  } else if (has_retry) {
+    return sync_pb::GetUpdatesCallerInfo::RETRY;
+  } else {
+    return sync_pb::GetUpdatesCallerInfo::UNKNOWN;
   }
-
-  return sync_pb::SyncEnums::UNKNOWN_ORIGIN;
 }
 
 void NudgeTracker::FillProtoMessage(ModelType type,
diff --git a/components/sync/engine_impl/cycle/nudge_tracker.h b/components/sync/engine_impl/cycle/nudge_tracker.h
index 57fd37c..f63923e 100644
--- a/components/sync/engine_impl/cycle/nudge_tracker.h
+++ b/components/sync/engine_impl/cycle/nudge_tracker.h
@@ -117,8 +117,15 @@
   // Returns the set of types that have pending refresh requests.
   ModelTypeSet GetRefreshRequestedTypes() const;
 
-  // Returns the 'origin' of the GetUpdate request.
-  sync_pb::SyncEnums::GetUpdatesOrigin GetOrigin() const;
+  // Returns the 'source' of the GetUpdate request.
+  //
+  // This flag is deprecated, but still used by the server.  There can be more
+  // than one reason to perform a particular sync cycle.  The GetUpdatesTrigger
+  // message will contain more reliable information about the reasons for
+  // performing a sync.
+  //
+  // See the implementation for important information about the coalesce logic.
+  sync_pb::GetUpdatesCallerInfo::GetUpdatesSource GetLegacySource() const;
 
   // Fills a GetUpdatesTrigger message for the next GetUpdates request.  This is
   // used by the DownloadUpdatesCommand to dump lots of useful per-type state
diff --git a/components/sync/engine_impl/cycle/nudge_tracker_unittest.cc b/components/sync/engine_impl/cycle/nudge_tracker_unittest.cc
index cab1d19..f3dbf35 100644
--- a/components/sync/engine_impl/cycle/nudge_tracker_unittest.cc
+++ b/components/sync/engine_impl/cycle/nudge_tracker_unittest.cc
@@ -97,43 +97,76 @@
   // Now we're at the normal, "idle" state.
   EXPECT_FALSE(nudge_tracker_.IsSyncRequired());
   EXPECT_FALSE(nudge_tracker_.IsGetUpdatesRequired());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
+            nudge_tracker_.GetLegacySource());
 
   sync_pb::GetUpdateTriggers gu_trigger;
   nudge_tracker_.FillProtoMessage(BOOKMARKS, &gu_trigger);
+
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN,
+            nudge_tracker_.GetLegacySource());
 }
 
 // Verify that nudges override each other based on a priority order.
-// RETRY < all variants of GU_TRIGGER
+// RETRY < LOCAL < DATATYPE_REFRESH < NOTIFICATION
 TEST_F(NudgeTrackerTest, SourcePriorities) {
   // Start with a retry request.
   const base::TimeTicks t0 = base::TimeTicks::FromInternalValue(1234);
   const base::TimeTicks t1 = t0 + base::TimeDelta::FromSeconds(10);
   nudge_tracker_.SetNextRetryTime(t0);
   nudge_tracker_.SetSyncCycleStartTime(t1);
-  EXPECT_EQ(sync_pb::SyncEnums::RETRY, nudge_tracker_.GetOrigin());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RETRY,
+            nudge_tracker_.GetLegacySource());
 
   // Track a local nudge.
   nudge_tracker_.RecordLocalChange(ModelTypeSet(BOOKMARKS));
-  EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, nudge_tracker_.GetOrigin());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::LOCAL,
+            nudge_tracker_.GetLegacySource());
 
   // A refresh request will override it.
   nudge_tracker_.RecordLocalRefreshRequest(ModelTypeSet(TYPED_URLS));
-  EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, nudge_tracker_.GetOrigin());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH,
+            nudge_tracker_.GetLegacySource());
 
   // Another local nudge will not be enough to change it.
   nudge_tracker_.RecordLocalChange(ModelTypeSet(BOOKMARKS));
-  EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, nudge_tracker_.GetOrigin());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH,
+            nudge_tracker_.GetLegacySource());
 
   // An invalidation will override the refresh request source.
   nudge_tracker_.RecordRemoteInvalidation(PREFERENCES,
                                           BuildInvalidation(1, "hint"));
-  EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, nudge_tracker_.GetOrigin());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION,
+            nudge_tracker_.GetLegacySource());
 
   // Neither local nudges nor refresh requests will override it.
   nudge_tracker_.RecordLocalChange(ModelTypeSet(BOOKMARKS));
-  EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, nudge_tracker_.GetOrigin());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION,
+            nudge_tracker_.GetLegacySource());
   nudge_tracker_.RecordLocalRefreshRequest(ModelTypeSet(TYPED_URLS));
-  EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, nudge_tracker_.GetOrigin());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION,
+            nudge_tracker_.GetLegacySource());
+}
+
+TEST_F(NudgeTrackerTest, SourcePriority_InitialSyncRequest) {
+  nudge_tracker_.RecordInitialSyncRequired(BOOKMARKS);
+
+  // For lack of a better source, we describe an initial sync request as having
+  // source DATATYPE_REFRESH.
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH,
+            nudge_tracker_.GetLegacySource());
+
+  // This should never happen in practice.  But, if it did, we'd want the
+  // initial sync required to keep the source set to DATATYPE_REFRESH.
+  nudge_tracker_.RecordLocalChange(ModelTypeSet(BOOKMARKS));
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH,
+            nudge_tracker_.GetLegacySource());
+
+  // It should be safe to let NOTIFICATIONs override it.
+  nudge_tracker_.RecordRemoteInvalidation(BOOKMARKS,
+                                          BuildInvalidation(1, "hint"));
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION,
+            nudge_tracker_.GetLegacySource());
 }
 
 // Verifies the management of invalidation hints and GU trigger fields.
diff --git a/components/sync/engine_impl/cycle/sync_cycle.cc b/components/sync/engine_impl/cycle/sync_cycle.cc
index 7127f036..fd30097 100644
--- a/components/sync/engine_impl/cycle/sync_cycle.cc
+++ b/components/sync/engine_impl/cycle/sync_cycle.cc
@@ -20,11 +20,12 @@
 SyncCycle::~SyncCycle() {}
 
 SyncCycleSnapshot SyncCycle::TakeSnapshot() const {
-  return TakeSnapshotWithOrigin(sync_pb::SyncEnums::UNKNOWN_ORIGIN);
+  return TakeSnapshotWithSource(sync_pb::GetUpdatesCallerInfo::UNKNOWN);
 }
 
-SyncCycleSnapshot SyncCycle::TakeSnapshotWithOrigin(
-    sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin) const {
+SyncCycleSnapshot SyncCycle::TakeSnapshotWithSource(
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource legacy_updates_source)
+    const {
   syncable::Directory* dir = context_->directory();
 
   ProgressMarkerMap download_progress_markers;
@@ -47,15 +48,15 @@
       context_->notifications_enabled(), dir->GetEntriesCount(),
       status_controller_->sync_start_time(),
       status_controller_->poll_finish_time(), num_entries_by_type,
-      num_to_delete_entries_by_type, get_updates_origin);
+      num_to_delete_entries_by_type, legacy_updates_source);
 
   return snapshot;
 }
 
 void SyncCycle::SendSyncCycleEndEventNotification(
-    sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin) {
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source) {
   SyncCycleEvent event(SyncCycleEvent::SYNC_CYCLE_ENDED);
-  event.snapshot = TakeSnapshotWithOrigin(get_updates_origin);
+  event.snapshot = TakeSnapshotWithSource(source);
 
   DVLOG(1) << "Sending cycle end event with snapshot: "
            << event.snapshot.ToString();
diff --git a/components/sync/engine_impl/cycle/sync_cycle.h b/components/sync/engine_impl/cycle/sync_cycle.h
index b41478d..11201dd 100644
--- a/components/sync/engine_impl/cycle/sync_cycle.h
+++ b/components/sync/engine_impl/cycle/sync_cycle.h
@@ -93,12 +93,13 @@
 
   // Builds a thread-safe and read-only copy of the current cycle state.
   SyncCycleSnapshot TakeSnapshot() const;
-  SyncCycleSnapshot TakeSnapshotWithOrigin(
-      sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin) const;
+  SyncCycleSnapshot TakeSnapshotWithSource(
+      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource legacy_updates_source)
+      const;
 
   // Builds and sends a snapshot to the cycle context's listeners.
   void SendSyncCycleEndEventNotification(
-      sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin);
+      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source);
   void SendEventNotification(SyncCycleEvent::EventCause cause);
 
   void SendProtocolEvent(const ProtocolEvent& event);
diff --git a/components/sync/engine_impl/cycle/test_util.cc b/components/sync/engine_impl/cycle/test_util.cc
index 5c8939b..92947fde3 100644
--- a/components/sync/engine_impl/cycle/test_util.cc
+++ b/components/sync/engine_impl/cycle/test_util.cc
@@ -7,26 +7,29 @@
 namespace syncer {
 namespace test_util {
 
-void SimulateGetEncryptionKeyFailed(ModelTypeSet requsted_types,
-                                    sync_pb::SyncEnums::GetUpdatesOrigin origin,
-                                    SyncCycle* cycle) {
+void SimulateGetEncryptionKeyFailed(
+    ModelTypeSet requsted_types,
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+    SyncCycle* cycle) {
   cycle->mutable_status_controller()->set_last_get_key_result(
       SERVER_RESPONSE_VALIDATION_FAILED);
   cycle->mutable_status_controller()->set_last_download_updates_result(
       SYNCER_OK);
 }
 
-void SimulateConfigureSuccess(ModelTypeSet requsted_types,
-                              sync_pb::SyncEnums::GetUpdatesOrigin origin,
-                              SyncCycle* cycle) {
+void SimulateConfigureSuccess(
+    ModelTypeSet requsted_types,
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+    SyncCycle* cycle) {
   cycle->mutable_status_controller()->set_last_get_key_result(SYNCER_OK);
   cycle->mutable_status_controller()->set_last_download_updates_result(
       SYNCER_OK);
 }
 
-void SimulateConfigureFailed(ModelTypeSet requsted_types,
-                             sync_pb::SyncEnums::GetUpdatesOrigin origin,
-                             SyncCycle* cycle) {
+void SimulateConfigureFailed(
+    ModelTypeSet requsted_types,
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+    SyncCycle* cycle) {
   cycle->mutable_status_controller()->set_last_get_key_result(SYNCER_OK);
   cycle->mutable_status_controller()->set_last_download_updates_result(
       SERVER_RETURN_TRANSIENT_ERROR);
@@ -34,7 +37,7 @@
 
 void SimulateConfigureConnectionFailure(
     ModelTypeSet requsted_types,
-    sync_pb::SyncEnums::GetUpdatesOrigin origin,
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
     SyncCycle* cycle) {
   cycle->mutable_status_controller()->set_last_get_key_result(SYNCER_OK);
   cycle->mutable_status_controller()->set_last_download_updates_result(
diff --git a/components/sync/engine_impl/cycle/test_util.h b/components/sync/engine_impl/cycle/test_util.h
index 2f17712b..77b111d 100644
--- a/components/sync/engine_impl/cycle/test_util.h
+++ b/components/sync/engine_impl/cycle/test_util.h
@@ -16,18 +16,21 @@
 // Utils to simulate various outcomes of a sync cycle.
 
 // Configure sync cycle successes and failures.
-void SimulateGetEncryptionKeyFailed(ModelTypeSet requested_types,
-                                    sync_pb::SyncEnums::GetUpdatesOrigin origin,
-                                    SyncCycle* cycle);
-void SimulateConfigureSuccess(ModelTypeSet requested_types,
-                              sync_pb::SyncEnums::GetUpdatesOrigin origin,
-                              SyncCycle* cycle);
-void SimulateConfigureFailed(ModelTypeSet requested_types,
-                             sync_pb::SyncEnums::GetUpdatesOrigin origin,
-                             SyncCycle* cycle);
+void SimulateGetEncryptionKeyFailed(
+    ModelTypeSet requested_types,
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+    SyncCycle* cycle);
+void SimulateConfigureSuccess(
+    ModelTypeSet requested_types,
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+    SyncCycle* cycle);
+void SimulateConfigureFailed(
+    ModelTypeSet requested_types,
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+    SyncCycle* cycle);
 void SimulateConfigureConnectionFailure(
     ModelTypeSet requested_types,
-    sync_pb::SyncEnums::GetUpdatesOrigin origin,
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
     SyncCycle* cycle);
 
 // Normal mode sync cycle successes and failures.
diff --git a/components/sync/engine_impl/debug_info_event_listener.cc b/components/sync/engine_impl/debug_info_event_listener.cc
index 820f08b..511e584 100644
--- a/components/sync/engine_impl/debug_info_event_listener.cc
+++ b/components/sync/engine_impl/debug_info_event_listener.cc
@@ -36,16 +36,11 @@
       snapshot.model_neutral_state().num_updates_downloaded_total);
   sync_completed_event_info->set_num_reflected_updates_downloaded(
       snapshot.model_neutral_state().num_reflected_updates_downloaded_total);
-  sync_completed_event_info->set_get_updates_origin(
-      snapshot.get_updates_origin());
+  sync_completed_event_info->mutable_caller_info()->set_source(
+      snapshot.legacy_updates_source());
   sync_completed_event_info->mutable_caller_info()->set_notifications_enabled(
       snapshot.notifications_enabled());
 
-  // Fill the legacy GetUpdatesSource field. This is not used anymore, but it's
-  // a required field so we still have to fill it with something.
-  sync_completed_event_info->mutable_caller_info()->set_source(
-      sync_pb::GetUpdatesCallerInfo::UNKNOWN);
-
   AddEventToQueue(event_info);
 }
 
diff --git a/components/sync/engine_impl/get_updates_delegate.cc b/components/sync/engine_impl/get_updates_delegate.cc
index c5d493be..2e54b54 100644
--- a/components/sync/engine_impl/get_updates_delegate.cc
+++ b/components/sync/engine_impl/get_updates_delegate.cc
@@ -49,18 +49,17 @@
 // This function assumes the progress markers have already been populated.
 void NormalGetUpdatesDelegate::HelpPopulateGuMessage(
     sync_pb::GetUpdatesMessage* get_updates) const {
-  // Fill the legacy GetUpdatesSource field. This is not used anymore, but it's
-  // a required field so we still have to fill it with something.
+  // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
   get_updates->mutable_caller_info()->set_source(
-      sync_pb::GetUpdatesCallerInfo::UNKNOWN);
+      nudge_tracker_.GetLegacySource());
 
-  // Set the origin.
+  // Set the new and improved version of source, too.
   get_updates->set_get_updates_origin(sync_pb::SyncEnums::GU_TRIGGER);
   get_updates->set_is_retry(nudge_tracker_.IsRetryRequired());
 
   // Special case: A GU performed for no other reason than retry will have its
   // origin set to RETRY.
-  if (nudge_tracker_.GetOrigin() == sync_pb::SyncEnums::RETRY)
+  if (nudge_tracker_.GetLegacySource() == sync_pb::GetUpdatesCallerInfo::RETRY)
     get_updates->set_get_updates_origin(sync_pb::SyncEnums::RETRY);
 
   // Fill in the notification hints.
@@ -94,19 +93,15 @@
 }
 
 ConfigureGetUpdatesDelegate::ConfigureGetUpdatesDelegate(
-    sync_pb::SyncEnums::GetUpdatesOrigin origin)
-    : origin_(origin) {}
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source)
+    : source_(source) {}
 
 ConfigureGetUpdatesDelegate::~ConfigureGetUpdatesDelegate() {}
 
 void ConfigureGetUpdatesDelegate::HelpPopulateGuMessage(
     sync_pb::GetUpdatesMessage* get_updates) const {
-  // Fill the legacy GetUpdatesSource field. This is not used anymore, but it's
-  // a required field so we still have to fill it with something.
-  get_updates->mutable_caller_info()->set_source(
-      sync_pb::GetUpdatesCallerInfo::UNKNOWN);
-
-  get_updates->set_get_updates_origin(origin_);
+  get_updates->mutable_caller_info()->set_source(source_);
+  get_updates->set_get_updates_origin(ConvertConfigureSourceToOrigin(source_));
 }
 
 void ConfigureGetUpdatesDelegate::ApplyUpdates(
@@ -120,8 +115,29 @@
 ConfigureGetUpdatesDelegate::GetNetworkRequestEvent(
     base::Time timestamp,
     const sync_pb::ClientToServerMessage& request) const {
-  return std::unique_ptr<ProtocolEvent>(
-      new ConfigureGetUpdatesRequestEvent(timestamp, origin_, request));
+  return std::unique_ptr<ProtocolEvent>(new ConfigureGetUpdatesRequestEvent(
+      timestamp, ConvertConfigureSourceToOrigin(source_), request));
+}
+
+sync_pb::SyncEnums::GetUpdatesOrigin
+ConfigureGetUpdatesDelegate::ConvertConfigureSourceToOrigin(
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source) {
+  switch (source) {
+    // Configurations:
+    case sync_pb::GetUpdatesCallerInfo::NEWLY_SUPPORTED_DATATYPE:
+      return sync_pb::SyncEnums::NEWLY_SUPPORTED_DATATYPE;
+    case sync_pb::GetUpdatesCallerInfo::MIGRATION:
+      return sync_pb::SyncEnums::MIGRATION;
+    case sync_pb::GetUpdatesCallerInfo::RECONFIGURATION:
+      return sync_pb::SyncEnums::RECONFIGURATION;
+    case sync_pb::GetUpdatesCallerInfo::NEW_CLIENT:
+      return sync_pb::SyncEnums::NEW_CLIENT;
+    case sync_pb::GetUpdatesCallerInfo::PROGRAMMATIC:
+      return sync_pb::SyncEnums::PROGRAMMATIC;
+    default:
+      NOTREACHED();
+      return sync_pb::SyncEnums::UNKNOWN_ORIGIN;
+  }
 }
 
 PollGetUpdatesDelegate::PollGetUpdatesDelegate() {}
@@ -130,11 +146,11 @@
 
 void PollGetUpdatesDelegate::HelpPopulateGuMessage(
     sync_pb::GetUpdatesMessage* get_updates) const {
-  // Fill the legacy GetUpdatesSource field. This is not used anymore, but it's
-  // a required field so we still have to fill it with something.
+  // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
   get_updates->mutable_caller_info()->set_source(
-      sync_pb::GetUpdatesCallerInfo::UNKNOWN);
+      sync_pb::GetUpdatesCallerInfo::PERIODIC);
 
+  // Set the new and improved version of source, too.
   get_updates->set_get_updates_origin(sync_pb::SyncEnums::PERIODIC);
 }
 
diff --git a/components/sync/engine_impl/get_updates_delegate.h b/components/sync/engine_impl/get_updates_delegate.h
index 88e3d601..f02829e 100644
--- a/components/sync/engine_impl/get_updates_delegate.h
+++ b/components/sync/engine_impl/get_updates_delegate.h
@@ -69,8 +69,8 @@
 // Functionality specific to the configure GetUpdate request.
 class ConfigureGetUpdatesDelegate : public GetUpdatesDelegate {
  public:
-  explicit ConfigureGetUpdatesDelegate(
-      sync_pb::SyncEnums::GetUpdatesOrigin origin);
+  ConfigureGetUpdatesDelegate(
+      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source);
   ~ConfigureGetUpdatesDelegate() override;
 
   // Sets the 'source' and 'origin' fields for this request.
@@ -90,7 +90,10 @@
       const sync_pb::ClientToServerMessage& request) const override;
 
  private:
-  const sync_pb::SyncEnums::GetUpdatesOrigin origin_;
+  static sync_pb::SyncEnums::GetUpdatesOrigin ConvertConfigureSourceToOrigin(
+      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source);
+
+  const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source_;
 
   DISALLOW_COPY_AND_ASSIGN(ConfigureGetUpdatesDelegate);
 };
diff --git a/components/sync/engine_impl/get_updates_processor.cc b/components/sync/engine_impl/get_updates_processor.cc
index 5ac5d88..85e4542 100644
--- a/components/sync/engine_impl/get_updates_processor.cc
+++ b/components/sync/engine_impl/get_updates_processor.cc
@@ -152,6 +152,7 @@
   bool need_encryption_key = ShouldRequestEncryptionKey(cycle->context());
   get_updates->set_need_encryption_key(need_encryption_key);
 
+  // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
   get_updates->mutable_caller_info()->set_notifications_enabled(
       cycle->context()->notifications_enabled());
 }
diff --git a/components/sync/engine_impl/get_updates_processor_unittest.cc b/components/sync/engine_impl/get_updates_processor_unittest.cc
index 34fe0b48..e45eb3f 100644
--- a/components/sync/engine_impl/get_updates_processor_unittest.cc
+++ b/components/sync/engine_impl/get_updates_processor_unittest.cc
@@ -108,6 +108,8 @@
   processor->PrepareGetUpdates(enabled_types(), &message);
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::LOCAL,
+            gu_msg.caller_info().source());
   EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin());
   for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
     ModelType type = GetModelTypeFromSpecificsFieldNumber(
@@ -154,6 +156,8 @@
   processor->PrepareGetUpdates(enabled_types(), &message);
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION,
+            gu_msg.caller_info().source());
   EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin());
   for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
     ModelType type = GetModelTypeFromSpecificsFieldNumber(
@@ -192,6 +196,8 @@
   processor->PrepareGetUpdates(enabled_types(), &message);
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::DATATYPE_REFRESH,
+            gu_msg.caller_info().source());
   EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin());
   for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
     ModelType type = GetModelTypeFromSpecificsFieldNumber(
@@ -216,13 +222,15 @@
 TEST_F(GetUpdatesProcessorTest, ConfigureTest) {
   sync_pb::ClientToServerMessage message;
   ConfigureGetUpdatesDelegate configure_delegate(
-      sync_pb::SyncEnums::RECONFIGURATION);
+      sync_pb::GetUpdatesCallerInfo::RECONFIGURATION);
   std::unique_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(configure_delegate));
   processor->PrepareGetUpdates(enabled_types(), &message);
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
   EXPECT_EQ(sync_pb::SyncEnums::RECONFIGURATION, gu_msg.get_updates_origin());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RECONFIGURATION,
+            gu_msg.caller_info().source());
 
   ModelTypeSet progress_types;
   for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
@@ -242,6 +250,8 @@
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
   EXPECT_EQ(sync_pb::SyncEnums::PERIODIC, gu_msg.get_updates_origin());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::PERIODIC,
+            gu_msg.caller_info().source());
 
   ModelTypeSet progress_types;
   for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) {
@@ -270,6 +280,8 @@
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
   EXPECT_EQ(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin());
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RETRY,
+            gu_msg.caller_info().source());
   EXPECT_TRUE(gu_msg.is_retry());
 
   ModelTypeSet progress_types;
@@ -302,6 +314,8 @@
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
   EXPECT_NE(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin());
+  EXPECT_NE(sync_pb::GetUpdatesCallerInfo::RETRY,
+            gu_msg.caller_info().source());
 
   EXPECT_TRUE(gu_msg.is_retry());
 }
@@ -409,7 +423,7 @@
 // types.
 TEST_F(GetUpdatesProcessorApplyUpdatesTest, Configure) {
   ConfigureGetUpdatesDelegate configure_delegate(
-      sync_pb::SyncEnums::RECONFIGURATION);
+      sync_pb::GetUpdatesCallerInfo::RECONFIGURATION);
   std::unique_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(configure_delegate));
 
diff --git a/components/sync/engine_impl/js_sync_manager_observer_unittest.cc b/components/sync/engine_impl/js_sync_manager_observer_unittest.cc
index 8dc6370f..52774eeb 100644
--- a/components/sync/engine_impl/js_sync_manager_observer_unittest.cc
+++ b/components/sync/engine_impl/js_sync_manager_observer_unittest.cc
@@ -66,7 +66,7 @@
                              base::Time::Now(),
                              std::vector<int>(MODEL_TYPE_COUNT, 0),
                              std::vector<int>(MODEL_TYPE_COUNT, 0),
-                             sync_pb::SyncEnums::UNKNOWN_ORIGIN);
+                             sync_pb::GetUpdatesCallerInfo::UNKNOWN);
   base::DictionaryValue expected_details;
   expected_details.Set("snapshot", snapshot.ToValue());
 
diff --git a/components/sync/engine_impl/sync_manager_impl.cc b/components/sync/engine_impl/sync_manager_impl.cc
index 2f3a289..80ad5e1 100644
--- a/components/sync/engine_impl/sync_manager_impl.cc
+++ b/components/sync/engine_impl/sync_manager_impl.cc
@@ -49,6 +49,7 @@
 
 
 using base::TimeDelta;
+using sync_pb::GetUpdatesCallerInfo;
 
 class GURL;
 
@@ -60,25 +61,25 @@
 
 namespace {
 
-sync_pb::SyncEnums::GetUpdatesOrigin GetOriginFromReason(
+GetUpdatesCallerInfo::GetUpdatesSource GetSourceFromReason(
     ConfigureReason reason) {
   switch (reason) {
     case CONFIGURE_REASON_RECONFIGURATION:
-      return sync_pb::SyncEnums::RECONFIGURATION;
+      return GetUpdatesCallerInfo::RECONFIGURATION;
     case CONFIGURE_REASON_MIGRATION:
-      return sync_pb::SyncEnums::MIGRATION;
+      return GetUpdatesCallerInfo::MIGRATION;
     case CONFIGURE_REASON_NEW_CLIENT:
-      return sync_pb::SyncEnums::NEW_CLIENT;
+      return GetUpdatesCallerInfo::NEW_CLIENT;
     case CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE:
     case CONFIGURE_REASON_CRYPTO:
     case CONFIGURE_REASON_CATCH_UP:
-      return sync_pb::SyncEnums::NEWLY_SUPPORTED_DATATYPE;
+      return GetUpdatesCallerInfo::NEWLY_SUPPORTED_DATATYPE;
     case CONFIGURE_REASON_PROGRAMMATIC:
-      return sync_pb::SyncEnums::PROGRAMMATIC;
+      return GetUpdatesCallerInfo::PROGRAMMATIC;
     case CONFIGURE_REASON_UNKNOWN:
       NOTREACHED();
   }
-  return sync_pb::SyncEnums::UNKNOWN_ORIGIN;
+  return GetUpdatesCallerInfo::UNKNOWN;
 }
 
 }  // namespace
@@ -189,7 +190,7 @@
   DVLOG(1) << "Configuring -"
            << "\n\t"
            << "types to download: " << ModelTypeSetToString(to_download);
-  ConfigurationParams params(GetOriginFromReason(reason), to_download,
+  ConfigurationParams params(GetSourceFromReason(reason), to_download,
                              ready_task, retry_task);
 
   scheduler_->Start(SyncScheduler::CONFIGURATION_MODE, base::Time());
diff --git a/components/sync/engine_impl/sync_manager_impl_unittest.cc b/components/sync/engine_impl/sync_manager_impl_unittest.cc
index ef1a524..d349dd9 100644
--- a/components/sync/engine_impl/sync_manager_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_manager_impl_unittest.cc
@@ -2710,7 +2710,7 @@
                  base::Unretained(&retry_task_counter)));
   EXPECT_EQ(0, ready_task_counter.times_called());
   EXPECT_EQ(0, retry_task_counter.times_called());
-  EXPECT_EQ(sync_pb::SyncEnums::RECONFIGURATION, params.origin);
+  EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::RECONFIGURATION, params.source);
   EXPECT_EQ(types_to_download, params.types_to_download);
 }
 
diff --git a/components/sync/engine_impl/sync_scheduler.h b/components/sync/engine_impl/sync_scheduler.h
index 423bec9..d3229e14 100644
--- a/components/sync/engine_impl/sync_scheduler.h
+++ b/components/sync/engine_impl/sync_scheduler.h
@@ -24,15 +24,16 @@
 
 struct ConfigurationParams {
   ConfigurationParams();
-  ConfigurationParams(sync_pb::SyncEnums::GetUpdatesOrigin origin,
-                      ModelTypeSet types_to_download,
-                      const base::Closure& ready_task,
-                      const base::Closure& retry_task);
+  ConfigurationParams(
+      const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource& source,
+      ModelTypeSet types_to_download,
+      const base::Closure& ready_task,
+      const base::Closure& retry_task);
   ConfigurationParams(const ConfigurationParams& other);
   ~ConfigurationParams();
 
-  // Origin for the configuration.
-  sync_pb::SyncEnums::GetUpdatesOrigin origin;
+  // Source for the configuration.
+  sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source;
   // The types that should be downloaded.
   ModelTypeSet types_to_download;
   // Callback to invoke on configuration completion.
diff --git a/components/sync/engine_impl/sync_scheduler_impl.cc b/components/sync/engine_impl/sync_scheduler_impl.cc
index e5e45d47..935fc8ac 100644
--- a/components/sync/engine_impl/sync_scheduler_impl.cc
+++ b/components/sync/engine_impl/sync_scheduler_impl.cc
@@ -23,19 +23,20 @@
 
 using base::TimeDelta;
 using base::TimeTicks;
+using sync_pb::GetUpdatesCallerInfo;
 
 namespace syncer {
 
 namespace {
 
-bool IsConfigRelatedUpdateOriginValue(
-    sync_pb::SyncEnums::GetUpdatesOrigin origin) {
-  switch (origin) {
-    case sync_pb::SyncEnums::RECONFIGURATION:
-    case sync_pb::SyncEnums::MIGRATION:
-    case sync_pb::SyncEnums::NEW_CLIENT:
-    case sync_pb::SyncEnums::NEWLY_SUPPORTED_DATATYPE:
-    case sync_pb::SyncEnums::PROGRAMMATIC:
+bool IsConfigRelatedUpdateSourceValue(
+    GetUpdatesCallerInfo::GetUpdatesSource source) {
+  switch (source) {
+    case GetUpdatesCallerInfo::RECONFIGURATION:
+    case GetUpdatesCallerInfo::MIGRATION:
+    case GetUpdatesCallerInfo::NEW_CLIENT:
+    case GetUpdatesCallerInfo::NEWLY_SUPPORTED_DATATYPE:
+    case GetUpdatesCallerInfo::PROGRAMMATIC:
       return true;
     default:
       return false;
@@ -93,13 +94,13 @@
 }  // namespace
 
 ConfigurationParams::ConfigurationParams()
-    : origin(sync_pb::SyncEnums::UNKNOWN_ORIGIN) {}
+    : source(GetUpdatesCallerInfo::UNKNOWN) {}
 ConfigurationParams::ConfigurationParams(
-    sync_pb::SyncEnums::GetUpdatesOrigin origin,
+    const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource& source,
     ModelTypeSet types_to_download,
     const base::Closure& ready_task,
     const base::Closure& retry_task)
-    : origin(origin),
+    : source(source),
       types_to_download(types_to_download),
       ready_task(ready_task),
       retry_task(retry_task) {
@@ -253,7 +254,7 @@
 void SyncSchedulerImpl::ScheduleConfiguration(
     const ConfigurationParams& params) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(IsConfigRelatedUpdateOriginValue(params.origin));
+  DCHECK(IsConfigRelatedUpdateSourceValue(params.source));
   DCHECK_EQ(CONFIGURATION_MODE, mode_);
   DCHECK(!params.ready_task.is_null());
   DCHECK(started_) << "Scheduler must be running to configure.";
@@ -472,7 +473,7 @@
   SyncCycle cycle(cycle_context_, this);
   bool success =
       syncer_->ConfigureSyncShare(pending_configure_params_->types_to_download,
-                                  pending_configure_params_->origin, &cycle);
+                                  pending_configure_params_->source, &cycle);
 
   if (success) {
     SDVLOG(2) << "Configure succeeded.";
diff --git a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
index d309241..3c9bbc4 100644
--- a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
@@ -44,13 +44,15 @@
 
 namespace syncer {
 
+using sync_pb::GetUpdatesCallerInfo;
+
 class MockSyncer : public Syncer {
  public:
   MockSyncer();
   MOCK_METHOD3(NormalSyncShare, bool(ModelTypeSet, NudgeTracker*, SyncCycle*));
   MOCK_METHOD3(ConfigureSyncShare,
                bool(const ModelTypeSet&,
-                    sync_pb::SyncEnums::GetUpdatesOrigin,
+                    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource,
                     SyncCycle*));
   MOCK_METHOD2(PollSyncShare, bool(ModelTypeSet, SyncCycle*));
 };
@@ -386,7 +388,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, model_types,
+      GetUpdatesCallerInfo::RECONFIGURATION, model_types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -414,7 +416,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, model_types,
+      GetUpdatesCallerInfo::RECONFIGURATION, model_types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -459,7 +461,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, model_types,
+      GetUpdatesCallerInfo::RECONFIGURATION, model_types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -480,7 +482,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, model_types,
+      GetUpdatesCallerInfo::RECONFIGURATION, model_types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -507,7 +509,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, model_types,
+      GetUpdatesCallerInfo::RECONFIGURATION, model_types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -534,7 +536,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, model_types,
+      GetUpdatesCallerInfo::RECONFIGURATION, model_types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -795,7 +797,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, types,
+      GetUpdatesCallerInfo::RECONFIGURATION, types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -879,7 +881,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, types,
+      GetUpdatesCallerInfo::RECONFIGURATION, types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -1212,7 +1214,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, config_types,
+      GetUpdatesCallerInfo::RECONFIGURATION, config_types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -1304,7 +1306,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, types,
+      GetUpdatesCallerInfo::RECONFIGURATION, types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -1353,7 +1355,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, types,
+      GetUpdatesCallerInfo::RECONFIGURATION, types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
@@ -1612,7 +1614,7 @@
   CallbackCounter ready_counter;
   CallbackCounter retry_counter;
   ConfigurationParams params(
-      sync_pb::SyncEnums::RECONFIGURATION, model_types,
+      GetUpdatesCallerInfo::RECONFIGURATION, model_types,
       base::Bind(&CallbackCounter::Callback, base::Unretained(&ready_counter)),
       base::Bind(&CallbackCounter::Callback, base::Unretained(&retry_counter)));
   scheduler()->ScheduleConfiguration(params);
diff --git a/components/sync/engine_impl/syncer.cc b/components/sync/engine_impl/syncer.cc
index 6a81698..158652ce 100644
--- a/components/sync/engine_impl/syncer.cc
+++ b/components/sync/engine_impl/syncer.cc
@@ -60,7 +60,7 @@
     if (!DownloadAndApplyUpdates(&request_types, cycle,
                                  NormalGetUpdatesDelegate(*nudge_tracker),
                                  kCreateMobileBookmarksFolder)) {
-      return HandleCycleEnd(cycle, nudge_tracker->GetOrigin());
+      return HandleCycleEnd(cycle, nudge_tracker->GetLegacySource());
     }
   }
 
@@ -70,12 +70,13 @@
                                                   cycle, &commit_processor);
   cycle->mutable_status_controller()->set_commit_result(commit_result);
 
-  return HandleCycleEnd(cycle, nudge_tracker->GetOrigin());
+  return HandleCycleEnd(cycle, nudge_tracker->GetLegacySource());
 }
 
-bool Syncer::ConfigureSyncShare(const ModelTypeSet& request_types,
-                                sync_pb::SyncEnums::GetUpdatesOrigin origin,
-                                SyncCycle* cycle) {
+bool Syncer::ConfigureSyncShare(
+    const ModelTypeSet& request_types,
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+    SyncCycle* cycle) {
   base::AutoReset<bool> is_syncing(&is_syncing_, true);
 
   // It is possible during configuration that datatypes get unregistered from
@@ -89,9 +90,9 @@
   VLOG(1) << "Configuring types " << ModelTypeSetToString(still_enabled_types);
   HandleCycleBegin(cycle);
   DownloadAndApplyUpdates(&still_enabled_types, cycle,
-                          ConfigureGetUpdatesDelegate(origin),
+                          ConfigureGetUpdatesDelegate(source),
                           kCreateMobileBookmarksFolder);
-  return HandleCycleEnd(cycle, origin);
+  return HandleCycleEnd(cycle, source);
 }
 
 bool Syncer::PollSyncShare(ModelTypeSet request_types, SyncCycle* cycle) {
@@ -100,7 +101,7 @@
   HandleCycleBegin(cycle);
   DownloadAndApplyUpdates(&request_types, cycle, PollGetUpdatesDelegate(),
                           kCreateMobileBookmarksFolder);
-  return HandleCycleEnd(cycle, sync_pb::SyncEnums::PERIODIC);
+  return HandleCycleEnd(cycle, sync_pb::GetUpdatesCallerInfo::PERIODIC);
 }
 
 bool Syncer::PostClearServerData(SyncCycle* cycle) {
@@ -195,15 +196,16 @@
   return cancelation_signal_->IsSignalled();
 }
 
-bool Syncer::HandleCycleEnd(SyncCycle* cycle,
-                            sync_pb::SyncEnums::GetUpdatesOrigin origin) {
+bool Syncer::HandleCycleEnd(
+    SyncCycle* cycle,
+    sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source) {
   if (ExitRequested())
     return false;
 
-  cycle->SendSyncCycleEndEventNotification(origin);
+  cycle->SendSyncCycleEndEventNotification(source);
   bool success =
       !HasSyncerError(cycle->status_controller().model_neutral_state());
-  if (success && origin == sync_pb::SyncEnums::PERIODIC) {
+  if (success && source == sync_pb::GetUpdatesCallerInfo::PERIODIC) {
     cycle->mutable_status_controller()->UpdatePollTime();
   }
 
diff --git a/components/sync/engine_impl/syncer.h b/components/sync/engine_impl/syncer.h
index 2aac6af..455c7590 100644
--- a/components/sync/engine_impl/syncer.h
+++ b/components/sync/engine_impl/syncer.h
@@ -57,9 +57,10 @@
   // purposes.  It describes the reson for performing this initial download.
   // Returns: false if an error occurred and retries should backoff, true
   // otherwise.
-  virtual bool ConfigureSyncShare(const ModelTypeSet& request_types,
-                                  sync_pb::SyncEnums::GetUpdatesOrigin origin,
-                                  SyncCycle* cycle);
+  virtual bool ConfigureSyncShare(
+      const ModelTypeSet& request_types,
+      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source,
+      SyncCycle* cycle);
 
   // Requests to download updates for the |request_types|.  For a well-behaved
   // client with a working connection to the invalidations server, this should
@@ -93,7 +94,7 @@
   bool ExitRequested();
 
   bool HandleCycleEnd(SyncCycle* cycle,
-                      sync_pb::SyncEnums::GetUpdatesOrigin origin);
+                      sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source);
 
   CancelationSignal* const cancelation_signal_;
 
diff --git a/components/sync/engine_impl/syncer_unittest.cc b/components/sync/engine_impl/syncer_unittest.cc
index c95fb2c..310abd7d 100644
--- a/components/sync/engine_impl/syncer_unittest.cc
+++ b/components/sync/engine_impl/syncer_unittest.cc
@@ -259,7 +259,7 @@
   bool SyncShareConfigureTypes(ModelTypeSet types) {
     ResetCycle();
     return syncer_->ConfigureSyncShare(
-        types, sync_pb::SyncEnums::RECONFIGURATION, cycle_.get());
+        types, sync_pb::GetUpdatesCallerInfo::RECONFIGURATION, cycle_.get());
   }
 
   void SetUp() override {
diff --git a/components/sync/protocol/client_debug_info.proto b/components/sync/protocol/client_debug_info.proto
index b10cb4e..d2446e03 100644
--- a/components/sync/protocol/client_debug_info.proto
+++ b/components/sync/protocol/client_debug_info.proto
@@ -22,7 +22,14 @@
   optional bool has_valid_hint = 2;
 }
 
-message DeprecatedSourceInfo {}
+// Information about the source that triggered a sync.
+message SourceInfo {
+  // An enum indicating the reason for the nudge.
+  optional GetUpdatesCallerInfo.GetUpdatesSource source = 1;
+
+  // The per-type hint information associated with the nudge.
+  repeated TypeHint type_hint = 2;
+}
 
 // The additional info here is from the StatusController. They get sent when
 // the event SYNC_CYCLE_COMPLETED  is sent.
@@ -48,15 +55,13 @@
   // Counts to track the effective usefulness of our GetUpdate requests.
   optional int32 num_updates_downloaded = 8;
   optional int32 num_reflected_updates_downloaded = 9;
-
-  // |caller_info| was mostly replaced by |get_updates_origin|; now it only
-  // contains the |notifications_enabled| flag.
   optional GetUpdatesCallerInfo caller_info = 10;
 
-  // |source_info| was unused and marked deprecated in M66.
-  repeated DeprecatedSourceInfo source_info = 11 [deprecated = true];
-
-  optional SyncEnums.GetUpdatesOrigin get_updates_origin = 12;
+  // A list of all the sources that were merged into this cycle.
+  //
+  // Some scenarios, notably mode switches and canary jobs, can spuriously add
+  // back-to-back duplicate sources to this list.
+  repeated SourceInfo source_info = 11;
 }
 
 // Datatype specifics statistics gathered at association time.
diff --git a/components/sync/protocol/get_updates_caller_info.proto b/components/sync/protocol/get_updates_caller_info.proto
index f035864..bfc092d 100644
--- a/components/sync/protocol/get_updates_caller_info.proto
+++ b/components/sync/protocol/get_updates_caller_info.proto
@@ -9,15 +9,45 @@
 package sync_pb;
 
 message GetUpdatesCallerInfo {
-  // This enum was deprecated in M28.  The preferred represenation of this
+  // This message was deprecated in M28.  The preferred represenation of this
   // information is now the GetUpdatesOrigin enum, which is defined in
-  // sync_enums.proto.  However, since |source| is a required field, both the
-  // field and the enum have to be kept around.
-  enum GetUpdatesSource { UNKNOWN = 0; }
-  required GetUpdatesSource source = 1 [deprecated = true];
+  // sync_enums.proto.
+  enum GetUpdatesSource {
+    UNKNOWN = 0;       // The source was not set by the caller.
+    FIRST_UPDATE = 1;  // First request after browser restart.  Not to
+                       // be confused with "NEW_CLIENT".
+    LOCAL = 2;         // The source of the update was a local change.
+    NOTIFICATION = 3;  // The source of the update was a p2p notification.
+    PERIODIC = 4;      // The source of the update was periodic polling.
+    SYNC_CYCLE_CONTINUATION = 5;  // The source of the update was a
+                                  // continuation of a previous sync cycle.
+                                  // No longer sent as of M24.
+
+    // This value is deprecated and was never used in production.
+    // CLEAR_PRIVATE_DATA = 6;
+
+    NEWLY_SUPPORTED_DATATYPE = 7;  // The client is in configuration mode
+                                   // because it's syncing all datatypes, and
+                                   // support for a new datatype was recently
+                                   // released via a software auto-update.
+    MIGRATION = 8;          // The client is in configuration mode because a
+                            // MIGRATION_DONE error previously returned by the
+                            // server necessitated resynchronization.
+    NEW_CLIENT = 9;         // The client is in configuration mode because the
+                            // user enabled sync for the first time.  Not to be
+                            // confused with FIRST_UPDATE.
+    RECONFIGURATION = 10;   // The client is in configuration mode because the
+                            // user opted to sync a different set of datatypes.
+    DATATYPE_REFRESH = 11;  // A datatype has requested a refresh. This is
+                            // typically used when datatype's have custom
+                            // sync UI, e.g. sessions.
+    RETRY = 13;  // A follow-up GU to pick up updates missed by previous GU.
+    PROGRAMMATIC = 14;  // The client is programmatically enabling/disabling
+                        // a type, typically for error handling purposes.
+  }
+
+  required GetUpdatesSource source = 1;
 
   // True only if notifications were enabled for this GetUpdateMessage.
-  // TODO(crbug.com/510165): Move this bool out of GetUpdatesCallerInfo so that
-  // GetUpdatesCallerInfo can be removed.
   optional bool notifications_enabled = 2;
 };
diff --git a/components/sync/protocol/proto_enum_conversions.cc b/components/sync/protocol/proto_enum_conversions.cc
index 0de51225..24dc909 100644
--- a/components/sync/protocol/proto_enum_conversions.cc
+++ b/components/sync/protocol/proto_enum_conversions.cc
@@ -75,11 +75,24 @@
 
 const char* ProtoEnumToString(
     sync_pb::GetUpdatesCallerInfo::GetUpdatesSource updates_source) {
+  ASSERT_ENUM_BOUNDS(sync_pb::GetUpdatesCallerInfo, GetUpdatesSource, UNKNOWN,
+                     PROGRAMMATIC);
   switch (updates_source) {
     ENUM_CASE(sync_pb::GetUpdatesCallerInfo, UNKNOWN);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, FIRST_UPDATE);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, LOCAL);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, NOTIFICATION);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, PERIODIC);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, SYNC_CYCLE_CONTINUATION);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, NEWLY_SUPPORTED_DATATYPE);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, MIGRATION);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, NEW_CLIENT);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, RECONFIGURATION);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, DATATYPE_REFRESH);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, RETRY);
+    ENUM_CASE(sync_pb::GetUpdatesCallerInfo, PROGRAMMATIC);
   }
-  // Note: No "NOTREACHED()" here - this enum used to have more entries, but it
-  // has been deprecated so we don't need to handle them anymore.
+  NOTREACHED();
   return "";
 }
 
diff --git a/components/sync/protocol/proto_enum_conversions_unittest.cc b/components/sync/protocol/proto_enum_conversions_unittest.cc
index 5ce5fe7..71370dc 100644
--- a/components/sync/protocol/proto_enum_conversions_unittest.cc
+++ b/components/sync/protocol/proto_enum_conversions_unittest.cc
@@ -49,21 +49,11 @@
 
 TEST_F(ProtoEnumConversionsTest, GetUpdatesSourceString) {
   TestEnumStringFunction(sync_pb::GetUpdatesCallerInfo::GetUpdatesSource_MIN,
+                         sync_pb::GetUpdatesCallerInfo::PERIODIC);
+  TestEnumStringFunction(sync_pb::GetUpdatesCallerInfo::RETRY,
                          sync_pb::GetUpdatesCallerInfo::GetUpdatesSource_MAX);
 }
 
-TEST_F(ProtoEnumConversionsTest, GetUpdatesOriginString) {
-  // This enum has rather scattered values, so we need multiple ranges.
-  TestEnumStringFunction(sync_pb::SyncEnums::GetUpdatesOrigin_MIN,
-                         sync_pb::SyncEnums::UNKNOWN_ORIGIN);
-  TestEnumStringFunction(sync_pb::SyncEnums::PERIODIC,
-                         sync_pb::SyncEnums::PERIODIC);
-  TestEnumStringFunction(sync_pb::SyncEnums::NEWLY_SUPPORTED_DATATYPE,
-                         sync_pb::SyncEnums::RECONFIGURATION);
-  TestEnumStringFunction(sync_pb::SyncEnums::GU_TRIGGER,
-                         sync_pb::SyncEnums::GetUpdatesOrigin_MAX);
-}
-
 TEST_F(ProtoEnumConversionsTest, GetResponseTypeString) {
   TestEnumStringFunction(sync_pb::CommitResponse::ResponseType_MIN,
                          sync_pb::CommitResponse::ResponseType_MAX);
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h
index 97c28db4d..8c79ab221 100644
--- a/components/sync/protocol/proto_visitors.h
+++ b/components/sync/protocol/proto_visitors.h
@@ -744,6 +744,11 @@
   VISIT_ENUM(browser_type);
 }
 
+VISIT_PROTO_FIELDS(const sync_pb::SourceInfo& proto) {
+  VISIT_ENUM(source);
+  VISIT_REP(type_hint);
+}
+
 VISIT_PROTO_FIELDS(const sync_pb::SyncCycleCompletedEventInfo& proto) {
   VISIT(num_encryption_conflicts);
   VISIT(num_hierarchy_conflicts);
@@ -751,7 +756,7 @@
   VISIT(num_updates_downloaded);
   VISIT(num_reflected_updates_downloaded);
   VISIT(caller_info);
-  VISIT_ENUM(get_updates_origin);
+  VISIT_REP(source_info);
 }
 
 VISIT_PROTO_FIELDS(const sync_pb::SyncEntity& proto) {
diff --git a/components/sync/protocol/sync.proto b/components/sync/protocol/sync.proto
index 0e0b7bd..4d3001a 100644
--- a/components/sync/protocol/sync.proto
+++ b/components/sync/protocol/sync.proto
@@ -618,9 +618,8 @@
   optional int64 from_timestamp = 1;
 
   // Indicates the reason for the GetUpdatesMessage.
-  // This was *mostly* deprecated in M29.  We now rely on GetUpdatesOrigin
-  // instead to encode the reason for the GetUpdates request.  Now this field
-  // only contains the "notifications_enabled" flag.
+  // Deprecated in M29.  We should eventually rely on GetUpdatesOrigin instead.
+  // Newer clients will support both systems during the transition period.
   optional GetUpdatesCallerInfo caller_info = 2;
 
   // Indicates whether related folders should be fetched.
diff --git a/components/sync/test/engine/mock_connection_manager.cc b/components/sync/test/engine/mock_connection_manager.cc
index 753f89b..02e29bab 100644
--- a/components/sync/test/engine/mock_connection_manager.cc
+++ b/components/sync/test/engine/mock_connection_manager.cc
@@ -547,7 +547,8 @@
   EXPECT_FALSE(gu.has_requested_types());
 
   if (fail_non_periodic_get_updates_) {
-    EXPECT_EQ(sync_pb::SyncEnums::PERIODIC, gu.get_updates_origin());
+    EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::PERIODIC,
+              gu.caller_info().source());
   }
 
   // Verify that the items we're about to send back to the client are of
diff --git a/components/sync/tools/testserver/chromiumsync.py b/components/sync/tools/testserver/chromiumsync.py
index fe1c0ff..e6f1991 100644
--- a/components/sync/tools/testserver/chromiumsync.py
+++ b/components/sync/tools/testserver/chromiumsync.py
@@ -33,6 +33,7 @@
 import bookmark_specifics_pb2
 import client_commands_pb2
 import dictionary_specifics_pb2
+import get_updates_caller_info_pb2
 import extension_setting_specifics_pb2
 import extension_specifics_pb2
 import favicon_image_specifics_pb2
@@ -301,10 +302,11 @@
   return SYNC_TYPE_TO_DESCRIPTOR[data_type].name
 
 
-def GetUpdatesOriginToString(origin):
-  """Formats a GetUpdatesOrigin enum value to a readable string."""
-  return sync_enums_pb2.SyncEnums.DESCRIPTOR \
-      .enum_types_by_name['GetUpdatesOrigin'].values_by_number[origin].name
+def CallerInfoToString(caller_info_source):
+  """Formats a GetUpdatesSource enum value to a readable string."""
+  return get_updates_caller_info_pb2.GetUpdatesCallerInfo \
+      .DESCRIPTOR.enum_types_by_name['GetUpdatesSource'] \
+      .values_by_number[caller_info_source].name
 
 
 def ShortDatatypeListSummary(data_types):
@@ -1579,7 +1581,7 @@
     update_response.SetInParent()
     update_sieve = UpdateSieve(update_request, self.account.migration_history)
 
-    print GetUpdatesOriginToString(update_request.get_updates_origin),
+    print CallerInfoToString(update_request.caller_info.source),
     print update_sieve.SummarizeRequest()
 
     update_sieve.CheckMigrationState()
diff --git a/components/viz/client/hit_test_data_provider_draw_quad.cc b/components/viz/client/hit_test_data_provider_draw_quad.cc
index f571fa89..7131e17c 100644
--- a/components/viz/client/hit_test_data_provider_draw_quad.cc
+++ b/components/viz/client/hit_test_data_provider_draw_quad.cc
@@ -33,6 +33,18 @@
 
     for (const DrawQuad* quad : render_pass->quad_list) {
       if (quad->material == DrawQuad::SURFACE_CONTENT) {
+        const SurfaceDrawQuad* surface_quad =
+            SurfaceDrawQuad::MaterialCast(quad);
+
+        // Skip the quad if the FrameSinkId between fallback and primary is not
+        // the same, because we don't know which FrameSinkId would be used to
+        // draw this quad.
+        if (surface_quad->fallback_surface_id.has_value() &&
+            surface_quad->fallback_surface_id->frame_sink_id() !=
+                surface_quad->primary_surface_id.frame_sink_id()) {
+          continue;
+        }
+
         // Skip the quad if the transform is not invertible (i.e. it will not
         // be able to receive events).
         gfx::Transform target_to_quad_transform;
@@ -41,12 +53,9 @@
           continue;
         }
 
-        const SurfaceDrawQuad* surface_quad =
-            SurfaceDrawQuad::MaterialCast(quad);
         auto hit_test_region = mojom::HitTestRegion::New();
-        const SurfaceId& surface_id = surface_quad->primary_surface_id;
-        hit_test_region->frame_sink_id = surface_id.frame_sink_id();
-        hit_test_region->local_surface_id = surface_id.local_surface_id();
+        hit_test_region->frame_sink_id =
+            surface_quad->primary_surface_id.frame_sink_id();
         hit_test_region->flags = mojom::kHitTestMouse | mojom::kHitTestTouch |
                                  mojom::kHitTestChildSurface;
         if (should_ask_for_child_region_)
diff --git a/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc b/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
index dc0d0d6..c1f040e8 100644
--- a/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
+++ b/components/viz/client/hit_test_data_provider_draw_quad_unittest.cc
@@ -37,7 +37,9 @@
     const gfx::Rect& rect,
     const gfx::Rect& child_rect,
     const gfx::Transform& render_pass_transform,
-    const gfx::Transform& shared_state_transform) {
+    const gfx::Transform& shared_state_transform,
+    const base::Optional<SurfaceId>& fallback_child_surface_id =
+        base::nullopt) {
   auto pass = RenderPass::Create();
   pass->SetNew(1, rect, rect, render_pass_transform);
 
@@ -47,7 +49,7 @@
 
   auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
   surface_quad->SetNew(pass->shared_quad_state_list.back(), child_rect,
-                       child_rect, child_surface_id, base::nullopt,
+                       child_rect, child_surface_id, fallback_child_surface_id,
                        SK_ColorWHITE, false);
 
   return pass;
@@ -98,8 +100,6 @@
   EXPECT_EQ(1u, hit_test_region_list->regions.size());
   EXPECT_EQ(child_surface_id.frame_sink_id(),
             hit_test_region_list->regions[0]->frame_sink_id);
-  EXPECT_EQ(child_surface_id.local_surface_id(),
-            hit_test_region_list->regions[0]->local_surface_id);
   EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch |
                 mojom::kHitTestChildSurface | mojom::kHitTestAsk,
             hit_test_region_list->regions[0]->flags);
@@ -113,9 +113,10 @@
             hit_test_region_list->regions[0]->transform);
 }
 
-// Test to ensure that we skip regions with a non-invertible transform when
-// preparing hit-test data.
-TEST(HitTestDataProviderDrawQuad, HitTestDataInvertibleTransform) {
+// Test to ensure that we skip regions with non-invertible transforms and with
+// updated FrameSinkId between fallback and primary when preparing for hit-test
+// data.
+TEST(HitTestDataProviderDrawQuad, HitTestDataSkipQuads) {
   std::unique_ptr<HitTestDataProvider> hit_test_data_provider =
       std::make_unique<HitTestDataProviderDrawQuad>(
           true /* should_ask_for_child_region */);
@@ -149,13 +150,21 @@
       not_invertible_transform);
   pass_list.push_back(std::move(pass2));
 
-  // A render pass and its draw quad both have invertible transforms
+  // A render pass and its draw quad both have invertible transforms.
   SurfaceId child_surface_id3 = CreateChildSurfaceId(4);
   auto pass3 = CreateRenderPassWithChildSurface(
       child_surface_id3, kFrameRect, child_rect, invertible_transform,
       invertible_transform);
   pass_list.push_back(std::move(pass3));
 
+  // The draw quad's FrameSinkId changed between fallback and primary.
+  SurfaceId child_surface_id4 = CreateChildSurfaceId(5);
+  SurfaceId fallback_child_surface_id4 = CreateChildSurfaceId(6);
+  auto pass4 = CreateRenderPassWithChildSurface(
+      child_surface_id4, kFrameRect, child_rect, invertible_transform,
+      invertible_transform, fallback_child_surface_id4);
+  pass_list.push_back(std::move(pass4));
+
   auto compositor_frame =
       CompositorFrameBuilder().SetRenderPassList(std::move(pass_list)).Build();
   mojom::HitTestRegionListPtr hit_test_region_list =
@@ -166,8 +175,6 @@
   EXPECT_EQ(1u, hit_test_region_list->regions.size());
   EXPECT_EQ(child_surface_id3.frame_sink_id(),
             hit_test_region_list->regions[0]->frame_sink_id);
-  EXPECT_EQ(child_surface_id3.local_surface_id(),
-            hit_test_region_list->regions[0]->local_surface_id);
 }
 
 }  // namespace viz
diff --git a/components/viz/host/host_frame_sink_manager_unittest.cc b/components/viz/host/host_frame_sink_manager_unittest.cc
index aa09b06..1d57c56c 100644
--- a/components/viz/host/host_frame_sink_manager_unittest.cc
+++ b/components/viz/host/host_frame_sink_manager_unittest.cc
@@ -532,7 +532,7 @@
   EXPECT_FALSE(DisplayHitTestQueryExists(kFrameSinkChild1));
   auto support =
       CreateCompositorFrameSinkSupport(kFrameSinkChild1, true /* is_root */);
-  support->SetUpHitTest();
+  support->SetUpHitTest(nullptr /* local_surface_id_lookup_delegate */);
   EXPECT_TRUE(DisplayHitTestQueryExists(kFrameSinkChild1));
   EXPECT_TRUE(support->GetHitTestAggregator());
 
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index f241c5e1..52759f2 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -139,6 +139,7 @@
     "hit_test/hit_test_aggregator_delegate.h",
     "hit_test/hit_test_manager.cc",
     "hit_test/hit_test_manager.h",
+    "surfaces/latest_local_surface_id_lookup_delegate.h",
     "surfaces/surface.cc",
     "surfaces/surface.h",
     "surfaces/surface_client.h",
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index 5ee1877d..356b576 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -547,6 +547,16 @@
   return current_surface_id_;
 }
 
+LocalSurfaceId Display::GetSurfaceAtAggregation(
+    const FrameSinkId& frame_sink_id) const {
+  if (!aggregator_)
+    return LocalSurfaceId();
+  auto it = aggregator_->previous_contained_frame_sinks().find(frame_sink_id);
+  if (it == aggregator_->previous_contained_frame_sinks().end())
+    return LocalSurfaceId();
+  return it->second;
+}
+
 void Display::ForceImmediateDrawAndSwapIfPossible() {
   if (scheduler_)
     scheduler_->ForceImmediateSwapIfPossible();
diff --git a/components/viz/service/display/display.h b/components/viz/service/display/display.h
index a948579b..7759c67a 100644
--- a/components/viz/service/display/display.h
+++ b/components/viz/service/display/display.h
@@ -19,6 +19,7 @@
 #include "components/viz/service/display/display_scheduler.h"
 #include "components/viz/service/display/output_surface_client.h"
 #include "components/viz/service/display/surface_aggregator.h"
+#include "components/viz/service/surfaces/latest_local_surface_id_lookup_delegate.h"
 #include "components/viz/service/surfaces/surface_manager.h"
 #include "components/viz/service/viz_service_export.h"
 #include "gpu/command_buffer/common/texture_in_use_response.h"
@@ -53,7 +54,8 @@
 // surface IDs used to draw into the display and deciding when to draw.
 class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
                                    public OutputSurfaceClient,
-                                   public ContextLostObserver {
+                                   public ContextLostObserver,
+                                   public LatestLocalSurfaceIdLookupDelegate {
  public:
   // The |begin_frame_source| and |scheduler| may be null (together). In that
   // case, DrawAndSwap must be called externally when needed.
@@ -108,6 +110,10 @@
       uint64_t swap_id,
       const gfx::PresentationFeedback& feedback) override;
 
+  // LatestLocalSurfaceIdLookupDelegate implementation.
+  LocalSurfaceId GetSurfaceAtAggregation(
+      const FrameSinkId& frame_sink_id) const override;
+
   bool has_scheduler() const { return !!scheduler_; }
   DirectRenderer* renderer_for_testing() const { return renderer_.get(); }
 
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index 094cd40..4a2f224 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -91,6 +91,7 @@
 SurfaceAggregator::~SurfaceAggregator() {
   // Notify client of all surfaces being removed.
   contained_surfaces_.clear();
+  contained_frame_sinks_.clear();
   ProcessAddedAndRemovedSurfaces();
 }
 
@@ -843,6 +844,9 @@
     return gfx::Rect();
 
   contained_surfaces_[surface->surface_id()] = surface->GetActiveFrameIndex();
+  contained_frame_sinks_[surface->surface_id().frame_sink_id()] =
+      std::max(surface->surface_id().local_surface_id(),
+               contained_frame_sinks_[surface->surface_id().frame_sink_id()]);
   if (!surface->HasActiveFrame())
     return gfx::Rect();
 
@@ -1148,6 +1152,9 @@
   Surface* surface = manager_->GetSurfaceForId(surface_id);
   DCHECK(surface);
   contained_surfaces_[surface_id] = surface->GetActiveFrameIndex();
+  contained_frame_sinks_[surface_id.frame_sink_id()] =
+      std::max(surface_id.local_surface_id(),
+               contained_frame_sinks_[surface_id.frame_sink_id()]);
 
   if (!surface->HasActiveFrame())
     return {};
@@ -1200,6 +1207,8 @@
   ProcessAddedAndRemovedSurfaces();
   contained_surfaces_.swap(previous_contained_surfaces_);
   contained_surfaces_.clear();
+  contained_frame_sinks_.swap(previous_contained_frame_sinks_);
+  contained_frame_sinks_.clear();
 
   for (auto it : previous_contained_surfaces_) {
     Surface* surface = manager_->GetSurfaceForId(it.first);
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h
index 9a60b49..17beb2c 100644
--- a/components/viz/service/display/surface_aggregator.h
+++ b/components/viz/service/display/surface_aggregator.h
@@ -33,6 +33,7 @@
 class VIZ_SERVICE_EXPORT SurfaceAggregator {
  public:
   using SurfaceIndexMap = base::flat_map<SurfaceId, uint64_t>;
+  using FrameSinkIdMap = base::flat_map<FrameSinkId, LocalSurfaceId>;
 
   SurfaceAggregator(SurfaceManager* manager,
                     cc::DisplayResourceProvider* provider,
@@ -41,9 +42,12 @@
 
   CompositorFrame Aggregate(const SurfaceId& surface_id);
   void ReleaseResources(const SurfaceId& surface_id);
-  SurfaceIndexMap& previous_contained_surfaces() {
+  const SurfaceIndexMap& previous_contained_surfaces() const {
     return previous_contained_surfaces_;
   }
+  const FrameSinkIdMap& previous_contained_frame_sinks() const {
+    return previous_contained_frame_sinks_;
+  }
   void SetFullDamageForSurface(const SurfaceId& surface_id);
   void set_output_is_secure(bool secure) { output_is_secure_ = secure; }
 
@@ -231,6 +235,8 @@
   // that time.
   SurfaceIndexMap previous_contained_surfaces_;
   SurfaceIndexMap contained_surfaces_;
+  FrameSinkIdMap previous_contained_frame_sinks_;
+  FrameSinkIdMap contained_frame_sinks_;
 
   // After surface validation, every Surface in this set is valid.
   base::flat_set<SurfaceId> valid_surfaces_;
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc
index 74b1ef807..0ad33ed 100644
--- a/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -389,6 +389,10 @@
       EXPECT_TRUE(
           aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
           aggregator_.previous_contained_surfaces().end());
+      auto it = aggregator_.previous_contained_frame_sinks().find(
+          surface_ids[i].frame_sink_id());
+      EXPECT_TRUE(it != aggregator_.previous_contained_frame_sinks().end());
+      EXPECT_EQ(it->second, surface_ids[i].local_surface_id());
     }
   }
 
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index 9d14d106e..d96429b6 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -70,11 +70,12 @@
   DCHECK(capture_clients_.empty());
 }
 
-void CompositorFrameSinkSupport::SetUpHitTest() {
+void CompositorFrameSinkSupport::SetUpHitTest(
+    LatestLocalSurfaceIdLookupDelegate* local_surface_id_lookup_delegate) {
   DCHECK(is_root_);
   hit_test_aggregator_ = std::make_unique<HitTestAggregator>(
       frame_sink_manager_->hit_test_manager(), frame_sink_manager_,
-      frame_sink_id_);
+      local_surface_id_lookup_delegate, frame_sink_id_);
 }
 
 void CompositorFrameSinkSupport::SetAggregatedDamageCallbackForTesting(
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index d2ba916..6e179c3 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -27,6 +27,7 @@
 namespace viz {
 
 class FrameSinkManagerImpl;
+class LatestLocalSurfaceIdLookupDelegate;
 class Surface;
 class SurfaceManager;
 
@@ -70,7 +71,8 @@
 
   // Viz hit-test setup is only called when |is_root_| is true (except on
   // android webview).
-  void SetUpHitTest();
+  void SetUpHitTest(
+      LatestLocalSurfaceIdLookupDelegate* local_surface_id_lookup_delegate);
 
   // The provided callback will be run every time a surface owned by this object
   // or one of its descendents is determined to be damaged at aggregation time.
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
index 1749f07c..f139347 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -65,14 +65,16 @@
   support_ = support_manager_->CreateCompositorFrameSinkSupport(
       this, frame_sink_id_, is_root,
       capabilities_.delegated_sync_points_required);
-  if (use_viz_hit_test_)
-    support_->SetUpHitTest();
   begin_frame_source_ = std::make_unique<ExternalBeginFrameSource>(this);
   client_->SetBeginFrameSource(begin_frame_source_.get());
 
   // Avoid initializing GL context here, as this should be sharing the
   // Display's context.
   display_->Initialize(this, frame_sink_manager_->surface_manager());
+
+  if (use_viz_hit_test_)
+    support_->SetUpHitTest(display_);
+
   return true;
 }
 
@@ -208,6 +210,18 @@
 
     for (const DrawQuad* quad : render_pass->quad_list) {
       if (quad->material == DrawQuad::SURFACE_CONTENT) {
+        const SurfaceDrawQuad* surface_quad =
+            SurfaceDrawQuad::MaterialCast(quad);
+
+        // Skip the quad if the FrameSinkId between fallback and primary is not
+        // the same, because we don't know which FrameSinkId would be used to
+        // draw this quad.
+        if (surface_quad->fallback_surface_id.has_value() &&
+            surface_quad->fallback_surface_id->frame_sink_id() !=
+                surface_quad->primary_surface_id.frame_sink_id()) {
+          continue;
+        }
+
         // Skip the quad if the transform is not invertible (i.e. it will not
         // be able to receive events).
         gfx::Transform target_to_quad_transform;
@@ -216,12 +230,9 @@
           continue;
         }
 
-        const SurfaceDrawQuad* surface_quad =
-            SurfaceDrawQuad::MaterialCast(quad);
         auto hit_test_region = mojom::HitTestRegion::New();
-        const SurfaceId& surface_id = surface_quad->primary_surface_id;
-        hit_test_region->frame_sink_id = surface_id.frame_sink_id();
-        hit_test_region->local_surface_id = surface_id.local_surface_id();
+        hit_test_region->frame_sink_id =
+            surface_quad->primary_surface_id.frame_sink_id();
         hit_test_region->flags = mojom::kHitTestMouse | mojom::kHitTestTouch |
                                  mojom::kHitTestChildSurface;
         hit_test_region->rect = surface_quad->rect;
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
index 55ed2397..abdf1f9 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
@@ -196,7 +196,7 @@
 
   const auto* hit_test_region_list =
       frame_sink_manager_.hit_test_manager()->GetActiveHitTestRegionList(
-          display_->CurrentSurfaceId());
+          display_.get(), display_->CurrentSurfaceId().frame_sink_id());
   EXPECT_TRUE(hit_test_region_list);
   EXPECT_EQ(display_rect_, hit_test_region_list->bounds);
   EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine,
@@ -272,7 +272,7 @@
 
   const auto* hit_test_region_list1 =
       frame_sink_manager_.hit_test_manager()->GetActiveHitTestRegionList(
-          display_->CurrentSurfaceId());
+          display_.get(), display_->CurrentSurfaceId().frame_sink_id());
   EXPECT_TRUE(hit_test_region_list1);
   EXPECT_EQ(display_rect_, hit_test_region_list1->bounds);
   EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine,
@@ -280,8 +280,6 @@
   EXPECT_EQ(1u, hit_test_region_list1->regions.size());
   EXPECT_EQ(child_surface_id.frame_sink_id(),
             hit_test_region_list1->regions[0]->frame_sink_id);
-  EXPECT_EQ(child_surface_id.local_surface_id(),
-            hit_test_region_list1->regions[0]->local_surface_id);
   EXPECT_EQ(
       mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestChildSurface,
       hit_test_region_list1->regions[0]->flags);
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
index 293d6f02..6f42f4d 100644
--- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
+++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -50,7 +50,7 @@
   frame_sink_manager->RegisterBeginFrameSource(begin_frame_source(),
                                                frame_sink_id);
   display_->Initialize(this, frame_sink_manager->surface_manager());
-  support_->SetUpHitTest();
+  support_->SetUpHitTest(display_.get());
 }
 
 RootCompositorFrameSinkImpl::~RootCompositorFrameSinkImpl() {
diff --git a/components/viz/service/hit_test/hit_test_aggregator.cc b/components/viz/service/hit_test/hit_test_aggregator.cc
index 544b4a9..c0a0fa36 100644
--- a/components/viz/service/hit_test/hit_test_aggregator.cc
+++ b/components/viz/service/hit_test/hit_test_aggregator.cc
@@ -20,11 +20,14 @@
 
 }  // namespace
 
-HitTestAggregator::HitTestAggregator(const HitTestManager* hit_test_manager,
-                                     HitTestAggregatorDelegate* delegate,
-                                     const FrameSinkId& frame_sink_id)
+HitTestAggregator::HitTestAggregator(
+    const HitTestManager* hit_test_manager,
+    HitTestAggregatorDelegate* delegate,
+    LatestLocalSurfaceIdLookupDelegate* local_surface_id_lookup_delegate,
+    const FrameSinkId& frame_sink_id)
     : hit_test_manager_(hit_test_manager),
       delegate_(delegate),
+      local_surface_id_lookup_delegate_(local_surface_id_lookup_delegate),
       root_frame_sink_id_(frame_sink_id),
       weak_ptr_factory_(this) {
   AllocateHitTestRegionArray();
@@ -33,7 +36,9 @@
 HitTestAggregator::~HitTestAggregator() = default;
 
 void HitTestAggregator::Aggregate(const SurfaceId& display_surface_id) {
+  DCHECK(referenced_child_regions_.empty());
   AppendRoot(display_surface_id);
+  referenced_child_regions_.clear();
   Swap();
 }
 
@@ -96,10 +101,13 @@
   SCOPED_UMA_HISTOGRAM_TIMER("Event.VizHitTest.AggregateTime");
 
   const mojom::HitTestRegionList* hit_test_region_list =
-      hit_test_manager_->GetActiveHitTestRegionList(surface_id);
+      hit_test_manager_->GetActiveHitTestRegionList(
+          local_surface_id_lookup_delegate_, surface_id.frame_sink_id());
   if (!hit_test_region_list)
     return;
 
+  referenced_child_regions_.insert(surface_id.frame_sink_id());
+
   size_t region_index = 1;
   for (const auto& region : hit_test_region_list->regions) {
     if (region_index >= write_size_ - 1)
@@ -132,31 +140,33 @@
   gfx::Transform transform = region->transform;
 
   if (region->flags & mojom::kHitTestChildSurface) {
-    auto surface_id =
-        SurfaceId(region->frame_sink_id, region->local_surface_id.value());
+    if (referenced_child_regions_.count(region->frame_sink_id))
+      return parent_index;
+
     const mojom::HitTestRegionList* hit_test_region_list =
-        hit_test_manager_->GetActiveHitTestRegionList(surface_id);
+        hit_test_manager_->GetActiveHitTestRegionList(
+            local_surface_id_lookup_delegate_, region->frame_sink_id);
     if (!hit_test_region_list) {
-      // Surface HitTestRegionList not found - it may be late.
-      // In this case, this child surface doesn't have any children regions,
-      // so it should accept events itself. E.g. when renderer doesn't submit
-      // any hit-test data for its children, itself should still be able to
-      // get events.
-      flags |= mojom::kHitTestMine;
-    } else {
-      // Rather than add a node in the tree for this hit_test_region_list
-      // element we can simplify the tree by merging the flags and transform
-      // into the kHitTestChildSurface element.
-      if (!hit_test_region_list->transform.IsIdentity())
-        transform.PreconcatTransform(hit_test_region_list->transform);
+      // Hit-test data not found with this FrameSinkId. This means that it
+      // failed to find a surface corresponding to this FrameSinkId at surface
+      // aggregation time.
+      return parent_index;
+    }
 
-      flags |= hit_test_region_list->flags;
+    referenced_child_regions_.insert(region->frame_sink_id);
 
-      for (const auto& child_region : hit_test_region_list->regions) {
-        region_index = AppendRegion(region_index, child_region);
-        if (region_index >= write_size_ - 1)
-          break;
-      }
+    // Rather than add a node in the tree for this hit_test_region_list
+    // element we can simplify the tree by merging the flags and transform
+    // into the kHitTestChildSurface element.
+    if (!hit_test_region_list->transform.IsIdentity())
+      transform.PreconcatTransform(hit_test_region_list->transform);
+
+    flags |= hit_test_region_list->flags;
+
+    for (const auto& child_region : hit_test_region_list->regions) {
+      region_index = AppendRegion(region_index, child_region);
+      if (region_index >= write_size_ - 1)
+        break;
     }
   }
   DCHECK_GE(region_index - parent_index - 1, 0u);
diff --git a/components/viz/service/hit_test/hit_test_aggregator.h b/components/viz/service/hit_test/hit_test_aggregator.h
index 3119691a..3554897 100644
--- a/components/viz/service/hit_test/hit_test_aggregator.h
+++ b/components/viz/service/hit_test/hit_test_aggregator.h
@@ -26,9 +26,11 @@
 class VIZ_SERVICE_EXPORT HitTestAggregator {
  public:
   // |delegate| owns and outlives HitTestAggregator.
-  HitTestAggregator(const HitTestManager* hit_test_manager,
-                    HitTestAggregatorDelegate* delegate,
-                    const FrameSinkId& frame_sink_id);
+  HitTestAggregator(
+      const HitTestManager* hit_test_manager,
+      HitTestAggregatorDelegate* delegate,
+      LatestLocalSurfaceIdLookupDelegate* local_surface_id_lookup_delegate,
+      const FrameSinkId& frame_sink_id);
   ~HitTestAggregator();
 
   // Called after surfaces have been aggregated into the DisplayFrame.
@@ -94,9 +96,15 @@
 
   HitTestAggregatorDelegate* const delegate_;
 
+  LatestLocalSurfaceIdLookupDelegate* const local_surface_id_lookup_delegate_;
+
   // This is the FrameSinkId for the corresponding root CompositorFrameSink.
   const FrameSinkId root_frame_sink_id_;
 
+  // This is the set of FrameSinkIds referenced in the aggregation so far, used
+  // to detect cycles.
+  base::flat_set<FrameSinkId> referenced_child_regions_;
+
   // Handles the case when this object is deleted after
   // the PostTaskAggregation call is scheduled but before invocation.
   base::WeakPtrFactory<HitTestAggregator> weak_ptr_factory_;
diff --git a/components/viz/service/hit_test/hit_test_aggregator_unittest.cc b/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
index cdb74501..08135e6 100644
--- a/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
+++ b/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "components/viz/common/surfaces/frame_sink_id.h"
-#include "components/viz/common/surfaces/local_surface_id.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
@@ -16,6 +15,7 @@
 #include "components/viz/service/hit_test/hit_test_aggregator_delegate.h"
 #include "components/viz/service/surfaces/surface_manager.h"
 #include "components/viz/test/compositor_frame_helpers.h"
+#include "components/viz/test/test_latest_local_surface_id_lookup_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace viz {
@@ -115,10 +115,15 @@
 
 class TestHitTestAggregator final : public HitTestAggregator {
  public:
-  TestHitTestAggregator(const HitTestManager* manager,
-                        HitTestAggregatorDelegate* delegate,
-                        const FrameSinkId& frame_sink_id)
-      : HitTestAggregator(manager, delegate, frame_sink_id),
+  TestHitTestAggregator(
+      const HitTestManager* manager,
+      HitTestAggregatorDelegate* delegate,
+      LatestLocalSurfaceIdLookupDelegate* local_surface_id_lookup_delegate,
+      const FrameSinkId& frame_sink_id)
+      : HitTestAggregator(manager,
+                          delegate,
+                          local_surface_id_lookup_delegate,
+                          frame_sink_id),
         frame_sink_id_(frame_sink_id) {}
   ~TestHitTestAggregator() = default;
 
@@ -158,12 +163,15 @@
   void SetUp() override {
     frame_sink_manager_ = std::make_unique<TestFrameSinkManagerImpl>();
     host_frame_sink_manager_ = std::make_unique<TestHostFrameSinkManager>();
+    local_surface_id_lookup_delegate_ =
+        std::make_unique<TestLatestLocalSurfaceIdLookupDelegate>();
     frame_sink_manager_->SetLocalClient(host_frame_sink_manager_.get());
     support_ = std::make_unique<CompositorFrameSinkSupport>(
         nullptr /* client */, frame_sink_manager_.get(), kDisplayFrameSink,
         true /* is_root */, false /* needs_sync_points */);
     hit_test_aggregator_ = std::make_unique<TestHitTestAggregator>(
-        hit_test_manager(), frame_sink_manager(), kDisplayFrameSink);
+        hit_test_manager(), frame_sink_manager(),
+        local_surface_id_lookup_delegate(), kDisplayFrameSink);
   }
   void TearDown() override {
     support_.reset();
@@ -188,7 +196,6 @@
       hit_test_region->rect.SetRect(100, 100, 100, 100);
       SurfaceId child_surface_id = MakeSurfaceId(client_id);
       hit_test_region->frame_sink_id = child_surface_id.frame_sink_id();
-      hit_test_region->local_surface_id = child_surface_id.local_surface_id();
 
       if (depth > 0) {
         hit_test_region->flags = mojom::kHitTestChildSurface;
@@ -204,6 +211,7 @@
       support()->SubmitCompositorFrame(surface_id.local_surface_id(),
                                        MakeDefaultCompositorFrame(),
                                        std::move(hit_test_region_list));
+      local_surface_id_lookup_delegate()->SetSurfaceIdMap(surface_id);
     } else {
       auto support = std::make_unique<CompositorFrameSinkSupport>(
           nullptr, frame_sink_manager(), surface_id.frame_sink_id(),
@@ -211,6 +219,7 @@
       support->SubmitCompositorFrame(surface_id.local_surface_id(),
                                      MakeDefaultCompositorFrame(),
                                      std::move(hit_test_region_list));
+      local_surface_id_lookup_delegate()->SetSurfaceIdMap(surface_id);
     }
     return client_id;
   }
@@ -242,10 +251,17 @@
     return frame_sink_manager_->surface_manager();
   }
 
+  TestLatestLocalSurfaceIdLookupDelegate* local_surface_id_lookup_delegate()
+      const {
+    return local_surface_id_lookup_delegate_.get();
+  }
+
  private:
   std::unique_ptr<TestHitTestAggregator> hit_test_aggregator_;
   std::unique_ptr<TestFrameSinkManagerImpl> frame_sink_manager_;
   std::unique_ptr<TestHostFrameSinkManager> host_frame_sink_manager_;
+  std::unique_ptr<TestLatestLocalSurfaceIdLookupDelegate>
+      local_surface_id_lookup_delegate_;
   std::unique_ptr<CompositorFrameSinkSupport> support_;
 
   DISALLOW_COPY_AND_ASSIGN(HitTestAggregatorTest);
@@ -275,6 +291,7 @@
   support()->SubmitCompositorFrame(display_surface_id.local_surface_id(),
                                    MakeDefaultCompositorFrame(),
                                    std::move(hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(display_surface_id);
   aggregator->Aggregate(display_surface_id);
   aggregator->SwapHandles();
 
@@ -314,13 +331,11 @@
 
   auto e_hit_test_region_r1 = mojom::HitTestRegion::New();
   e_hit_test_region_r1->frame_sink_id = e_surface_id.frame_sink_id();
-  e_hit_test_region_r1->local_surface_id = e_surface_id.local_surface_id();
   e_hit_test_region_r1->flags = mojom::kHitTestMine;
   e_hit_test_region_r1->rect.SetRect(100, 100, 200, 400);
 
   auto e_hit_test_region_r2 = mojom::HitTestRegion::New();
   e_hit_test_region_r2->frame_sink_id = e_surface_id.frame_sink_id();
-  e_hit_test_region_r2->local_surface_id = e_surface_id.local_surface_id();
   e_hit_test_region_r2->flags = mojom::kHitTestMine;
   e_hit_test_region_r2->rect.SetRect(400, 100, 300, 400);
 
@@ -330,6 +345,7 @@
   support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
                                    MakeDefaultCompositorFrame(),
                                    std::move(e_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
 
   aggregator->Aggregate(e_surface_id);
   aggregator->SwapHandles();
@@ -383,13 +399,11 @@
   auto e_hit_test_region_c1 = mojom::HitTestRegion::New();
   e_hit_test_region_c1->flags = mojom::kHitTestChildSurface;
   e_hit_test_region_c1->frame_sink_id = c1_surface_id.frame_sink_id();
-  e_hit_test_region_c1->local_surface_id = c1_surface_id.local_surface_id();
   e_hit_test_region_c1->rect.SetRect(100, 100, 200, 300);
 
   auto e_hit_test_region_c2 = mojom::HitTestRegion::New();
   e_hit_test_region_c2->flags = mojom::kHitTestChildSurface;
   e_hit_test_region_c2->frame_sink_id = c2_surface_id.frame_sink_id();
-  e_hit_test_region_c2->local_surface_id = c2_surface_id.local_surface_id();
   e_hit_test_region_c2->rect.SetRect(400, 100, 400, 300);
 
   e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c1));
@@ -407,15 +421,18 @@
   support2->SubmitCompositorFrame(c1_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(c1_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(c1_surface_id);
   support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
                                    MakeDefaultCompositorFrame(),
                                    std::move(e_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
   auto support3 = std::make_unique<CompositorFrameSinkSupport>(
       nullptr, frame_sink_manager(), c2_surface_id.frame_sink_id(),
       false /* is_root */, false /* needs_sync_points */);
   support3->SubmitCompositorFrame(c2_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(c2_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(c2_surface_id);
 
   aggregator->Aggregate(e_surface_id);
   aggregator->SwapHandles();
@@ -471,13 +488,11 @@
   auto e_hit_test_region_div = mojom::HitTestRegion::New();
   e_hit_test_region_div->flags = mojom::kHitTestMine;
   e_hit_test_region_div->frame_sink_id = e_surface_id.frame_sink_id();
-  e_hit_test_region_div->local_surface_id = e_surface_id.local_surface_id();
   e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
 
   auto e_hit_test_region_c = mojom::HitTestRegion::New();
   e_hit_test_region_c->flags = mojom::kHitTestChildSurface;
   e_hit_test_region_c->frame_sink_id = c_surface_id.frame_sink_id();
-  e_hit_test_region_c->local_surface_id = c_surface_id.local_surface_id();
   e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
 
   e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_div));
@@ -494,9 +509,11 @@
   support2->SubmitCompositorFrame(c_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(c_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(c_surface_id);
   support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
                                    MakeDefaultCompositorFrame(),
                                    std::move(e_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
 
   aggregator->Aggregate(e_surface_id);
   aggregator->SwapHandles();
@@ -553,13 +570,11 @@
   auto e_hit_test_region_div = mojom::HitTestRegion::New();
   e_hit_test_region_div->flags = mojom::kHitTestMine;
   e_hit_test_region_div->frame_sink_id = e_surface_id.frame_sink_id();
-  e_hit_test_region_div->local_surface_id = e_surface_id.local_surface_id();
   e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
 
   auto e_hit_test_region_c = mojom::HitTestRegion::New();
   e_hit_test_region_c->flags = mojom::kHitTestChildSurface;
   e_hit_test_region_c->frame_sink_id = c_surface_id.frame_sink_id();
-  e_hit_test_region_c->local_surface_id = c_surface_id.local_surface_id();
   e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
 
   e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c));
@@ -577,9 +592,11 @@
   support2->SubmitCompositorFrame(c_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(c_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(c_surface_id);
   support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
                                    MakeDefaultCompositorFrame(),
                                    std::move(e_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
 
   aggregator->Aggregate(e_surface_id);
   aggregator->SwapHandles();
@@ -638,7 +655,6 @@
   auto e_hit_test_region_c = mojom::HitTestRegion::New();
   e_hit_test_region_c->flags = mojom::kHitTestChildSurface;
   e_hit_test_region_c->frame_sink_id = c_surface_id.frame_sink_id();
-  e_hit_test_region_c->local_surface_id = c_surface_id.local_surface_id();
   e_hit_test_region_c->rect.SetRect(300, 100, 1600, 800);
   e_hit_test_region_c->transform.Translate(200, 100);
 
@@ -651,13 +667,11 @@
   auto c_hit_test_region_a = mojom::HitTestRegion::New();
   c_hit_test_region_a->flags = mojom::kHitTestChildSurface;
   c_hit_test_region_a->frame_sink_id = a_surface_id.frame_sink_id();
-  c_hit_test_region_a->local_surface_id = a_surface_id.local_surface_id();
   c_hit_test_region_a->rect.SetRect(0, 0, 200, 100);
 
   auto c_hit_test_region_b = mojom::HitTestRegion::New();
   c_hit_test_region_b->flags = mojom::kHitTestChildSurface;
   c_hit_test_region_b->frame_sink_id = b_surface_id.frame_sink_id();
-  c_hit_test_region_b->local_surface_id = b_surface_id.local_surface_id();
   c_hit_test_region_b->rect.SetRect(0, 100, 800, 600);
 
   c_hit_test_region_list->regions.push_back(std::move(c_hit_test_region_a));
@@ -679,21 +693,25 @@
   support2->SubmitCompositorFrame(c_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(c_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(c_surface_id);
   auto support3 = std::make_unique<CompositorFrameSinkSupport>(
       nullptr, frame_sink_manager(), a_surface_id.frame_sink_id(),
       false /* is_root */, false /* needs_sync_points */);
   support3->SubmitCompositorFrame(a_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(a_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(a_surface_id);
   auto support4 = std::make_unique<CompositorFrameSinkSupport>(
       nullptr, frame_sink_manager(), b_surface_id.frame_sink_id(),
       false /* is_root */, false /* needs_sync_points */);
   support4->SubmitCompositorFrame(b_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(b_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(b_surface_id);
   support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
                                    MakeDefaultCompositorFrame(),
                                    std::move(e_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
 
   aggregator->Aggregate(e_surface_id);
   aggregator->SwapHandles();
@@ -764,7 +782,6 @@
   auto e_hit_test_region_c1 = mojom::HitTestRegion::New();
   e_hit_test_region_c1->flags = mojom::kHitTestChildSurface;
   e_hit_test_region_c1->frame_sink_id = c1_surface_id.frame_sink_id();
-  e_hit_test_region_c1->local_surface_id = c1_surface_id.local_surface_id();
   e_hit_test_region_c1->rect.SetRect(100, 100, 700, 700);
 
   e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c1));
@@ -776,7 +793,6 @@
   auto c1_hit_test_region_c2 = mojom::HitTestRegion::New();
   c1_hit_test_region_c2->flags = mojom::kHitTestChildSurface;
   c1_hit_test_region_c2->frame_sink_id = c2_surface_id.frame_sink_id();
-  c1_hit_test_region_c2->local_surface_id = c2_surface_id.local_surface_id();
   c1_hit_test_region_c2->rect.SetRect(100, 100, 500, 500);
 
   c1_hit_test_region_list->regions.push_back(std::move(c1_hit_test_region_c2));
@@ -788,7 +804,6 @@
   auto c2_hit_test_region_c3 = mojom::HitTestRegion::New();
   c2_hit_test_region_c3->flags = mojom::kHitTestChildSurface;
   c2_hit_test_region_c3->frame_sink_id = c3_surface_id.frame_sink_id();
-  c2_hit_test_region_c3->local_surface_id = c3_surface_id.local_surface_id();
   c2_hit_test_region_c3->rect.SetRect(100, 100, 300, 300);
 
   c2_hit_test_region_list->regions.push_back(std::move(c2_hit_test_region_c3));
@@ -805,21 +820,25 @@
   support2->SubmitCompositorFrame(c1_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(c1_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(c1_surface_id);
   auto support3 = std::make_unique<CompositorFrameSinkSupport>(
       nullptr, frame_sink_manager(), c3_surface_id.frame_sink_id(),
       false /* is_root */, false /* needs_sync_points */);
   support3->SubmitCompositorFrame(c3_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(c3_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(c3_surface_id);
   support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
                                    MakeDefaultCompositorFrame(),
                                    std::move(e_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
   auto support4 = std::make_unique<CompositorFrameSinkSupport>(
       nullptr, frame_sink_manager(), c2_surface_id.frame_sink_id(),
       false /* is_root */, false /* needs_sync_points */);
   support4->SubmitCompositorFrame(c2_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(c2_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(c2_surface_id);
 
   aggregator->Aggregate(e_surface_id);
   aggregator->SwapHandles();
@@ -881,13 +900,11 @@
   auto e_hit_test_region_div = mojom::HitTestRegion::New();
   e_hit_test_region_div->flags = mojom::kHitTestMine;
   e_hit_test_region_div->frame_sink_id = e_surface_id.frame_sink_id();
-  e_hit_test_region_div->local_surface_id = e_surface_id.local_surface_id();
   e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
 
   auto e_hit_test_region_c = mojom::HitTestRegion::New();
   e_hit_test_region_c->flags = mojom::kHitTestChildSurface;
   e_hit_test_region_c->frame_sink_id = c_surface_id.frame_sink_id();
-  e_hit_test_region_c->local_surface_id = c_surface_id.local_surface_id();
   e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
 
   e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c));
@@ -902,11 +919,13 @@
   support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
                                    MakeDefaultCompositorFrame(),
                                    std::move(e_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
 
   aggregator->Aggregate(e_surface_id);
   aggregator->SwapHandles();
 
-  EXPECT_EQ(aggregator->GetRegionCount(), 3);
+  // Child c didn't submit any CompositorFrame. Events should go to parent.
+  EXPECT_EQ(aggregator->GetRegionCount(), 2);
 
   EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
   AggregatedHitTestRegion* regions = host_regions();
@@ -917,17 +936,9 @@
   EXPECT_EQ(region->flags, mojom::kHitTestMine);
   EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
   EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
-  EXPECT_EQ(region->child_count, 2);
+  EXPECT_EQ(region->child_count, 1);
 
-  // |c_hit_test_region_list| was not submitted on time, but
-  // |e_hit_test_region_c| itself should still be present and can get events.
   region = &regions[1];
-  EXPECT_EQ(region->flags, mojom::kHitTestChildSurface | mojom::kHitTestMine);
-  EXPECT_EQ(region->frame_sink_id, c_surface_id.frame_sink_id());
-  EXPECT_EQ(region->rect, gfx::Rect(100, 100, 200, 500));
-  EXPECT_EQ(region->child_count, 0);
-
-  region = &regions[2];
   EXPECT_EQ(region->flags, mojom::kHitTestMine);
   EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
   EXPECT_EQ(region->rect, gfx::Rect(200, 200, 300, 200));
@@ -1000,13 +1011,11 @@
   auto e_hit_test_region_div = mojom::HitTestRegion::New();
   e_hit_test_region_div->flags = mojom::kHitTestMine;
   e_hit_test_region_div->frame_sink_id = e_surface_id.frame_sink_id();
-  e_hit_test_region_div->local_surface_id = e_surface_id.local_surface_id();
   e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
 
   auto e_hit_test_region_c = mojom::HitTestRegion::New();
   e_hit_test_region_c->flags = mojom::kHitTestChildSurface;
   e_hit_test_region_c->frame_sink_id = c_surface_id.frame_sink_id();
-  e_hit_test_region_c->local_surface_id = c_surface_id.local_surface_id();
   e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
 
   e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c));
@@ -1016,8 +1025,10 @@
   c_hit_test_region_list->flags = mojom::kHitTestMine;
   c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500);
 
-  EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(e_surface_id));
-  EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(c_surface_id));
+  EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(
+      local_surface_id_lookup_delegate(), e_surface_id.frame_sink_id()));
+  EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(
+      local_surface_id_lookup_delegate(), c_surface_id.frame_sink_id()));
 
   // Submit in unexpected order.
 
@@ -1027,26 +1038,34 @@
   support2->SubmitCompositorFrame(c_surface_id.local_surface_id(),
                                   MakeDefaultCompositorFrame(),
                                   std::move(c_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(c_surface_id);
   support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
                                    MakeDefaultCompositorFrame(),
                                    std::move(e_hit_test_region_list));
+  local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
 
   aggregator->Aggregate(e_surface_id);
   aggregator->SwapHandles();
 
-  EXPECT_TRUE(hit_test_manager()->GetActiveHitTestRegionList(e_surface_id));
-  EXPECT_TRUE(hit_test_manager()->GetActiveHitTestRegionList(c_surface_id));
+  EXPECT_TRUE(hit_test_manager()->GetActiveHitTestRegionList(
+      local_surface_id_lookup_delegate(), e_surface_id.frame_sink_id()));
+  EXPECT_TRUE(hit_test_manager()->GetActiveHitTestRegionList(
+      local_surface_id_lookup_delegate(), c_surface_id.frame_sink_id()));
 
   // Discard Surface and ensure active count goes down.
   support2->EvictLastActivatedSurface();
   surface_manager()->GarbageCollectSurfaces();
-  EXPECT_TRUE(hit_test_manager()->GetActiveHitTestRegionList(e_surface_id));
-  EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(c_surface_id));
+  EXPECT_TRUE(hit_test_manager()->GetActiveHitTestRegionList(
+      local_surface_id_lookup_delegate(), e_surface_id.frame_sink_id()));
+  EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(
+      local_surface_id_lookup_delegate(), c_surface_id.frame_sink_id()));
 
   support()->EvictLastActivatedSurface();
   surface_manager()->GarbageCollectSurfaces();
-  EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(e_surface_id));
-  EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(c_surface_id));
+  EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(
+      local_surface_id_lookup_delegate(), e_surface_id.frame_sink_id()));
+  EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(
+      local_surface_id_lookup_delegate(), c_surface_id.frame_sink_id()));
 }
 
 }  // namespace viz
diff --git a/components/viz/service/hit_test/hit_test_manager.cc b/components/viz/service/hit_test/hit_test_manager.cc
index 86f562b..886ac9f 100644
--- a/components/viz/service/hit_test/hit_test_manager.cc
+++ b/components/viz/service/hit_test/hit_test_manager.cc
@@ -5,7 +5,7 @@
 #include "components/viz/service/hit_test/hit_test_aggregator.h"
 
 #include "components/viz/common/hit_test/aggregated_hit_test_region.h"
-#include "components/viz/service/hit_test/hit_test_aggregator_delegate.h"
+#include "components/viz/service/surfaces/latest_local_surface_id_lookup_delegate.h"
 
 namespace viz {
 
@@ -20,56 +20,6 @@
 
 HitTestManager::~HitTestManager() = default;
 
-void HitTestManager::SubmitHitTestRegionList(
-    const SurfaceId& surface_id,
-    const uint64_t frame_index,
-    mojom::HitTestRegionListPtr hit_test_region_list) {
-  if (!ValidateHitTestRegionList(surface_id, hit_test_region_list))
-    return;
-  // TODO(gklassen): Runtime validation that hit_test_region_list is valid.
-  // TODO(gklassen): Inform FrameSink that the hit_test_region_list is invalid.
-  // TODO(gklassen): FrameSink needs to inform the host of a difficult renderer.
-  hit_test_region_lists_[surface_id][frame_index] =
-      std::move(hit_test_region_list);
-}
-
-bool HitTestManager::ValidateHitTestRegionList(
-    const SurfaceId& surface_id,
-    const mojom::HitTestRegionListPtr& hit_test_region_list) {
-  if (!hit_test_region_list)
-    return false;
-  if (hit_test_region_list->regions.size() > kMaxRegionsPerSurface)
-    return false;
-  for (auto& region : hit_test_region_list->regions) {
-    if (!ValidateHitTestRegion(surface_id, region))
-      return false;
-  }
-  return true;
-}
-
-bool HitTestManager::ValidateHitTestRegion(
-    const SurfaceId& surface_id,
-    const mojom::HitTestRegionPtr& hit_test_region) {
-  // If client_id is 0 then use the client_id that
-  // matches the compositor frame.
-  if (hit_test_region->frame_sink_id.client_id() == 0) {
-    hit_test_region->frame_sink_id =
-        FrameSinkId(surface_id.frame_sink_id().client_id(),
-                    hit_test_region->frame_sink_id.sink_id());
-  }
-  // TODO(gklassen): Verify that this client is allowed to submit hit test
-  // data for the region associated with this |frame_sink_id|.
-  // TODO(gklassen): Ensure that |region->frame_sink_id| is a child of
-  // |frame_sink_id|.
-  if (hit_test_region->flags & mojom::kHitTestChildSurface) {
-    if (!hit_test_region->local_surface_id.has_value() ||
-        !hit_test_region->local_surface_id->is_valid()) {
-      return false;
-    }
-  }
-  return true;
-}
-
 bool HitTestManager::OnSurfaceDamaged(const SurfaceId& surface_id,
                                       const BeginFrameAck& ack) {
   return false;
@@ -101,8 +51,31 @@
   }
 }
 
+void HitTestManager::SubmitHitTestRegionList(
+    const SurfaceId& surface_id,
+    const uint64_t frame_index,
+    mojom::HitTestRegionListPtr hit_test_region_list) {
+  if (!ValidateHitTestRegionList(surface_id, hit_test_region_list))
+    return;
+  // TODO(gklassen): Runtime validation that hit_test_region_list is valid.
+  // TODO(gklassen): Inform FrameSink that the hit_test_region_list is invalid.
+  // TODO(gklassen): FrameSink needs to inform the host of a difficult renderer.
+  hit_test_region_lists_[surface_id][frame_index] =
+      std::move(hit_test_region_list);
+}
+
 const mojom::HitTestRegionList* HitTestManager::GetActiveHitTestRegionList(
-    const SurfaceId& surface_id) const {
+    LatestLocalSurfaceIdLookupDelegate* delegate,
+    const FrameSinkId& frame_sink_id) const {
+  if (!delegate)
+    return nullptr;
+
+  LocalSurfaceId local_surface_id =
+      delegate->GetSurfaceAtAggregation(frame_sink_id);
+  if (!local_surface_id.is_valid())
+    return nullptr;
+
+  SurfaceId surface_id(frame_sink_id, local_surface_id);
   auto search = hit_test_region_lists_.find(surface_id);
   if (search == hit_test_region_lists_.end())
     return nullptr;
@@ -119,4 +92,23 @@
   return search2->second.get();
 }
 
+bool HitTestManager::ValidateHitTestRegionList(
+    const SurfaceId& surface_id,
+    const mojom::HitTestRegionListPtr& hit_test_region_list) {
+  if (!hit_test_region_list)
+    return false;
+  if (hit_test_region_list->regions.size() > kMaxRegionsPerSurface)
+    return false;
+  for (auto& region : hit_test_region_list->regions) {
+    // TODO(gklassen): Ensure that |region->frame_sink_id| is a child of
+    // |frame_sink_id|.
+    if (region->frame_sink_id.client_id() == 0) {
+      region->frame_sink_id =
+          FrameSinkId(surface_id.frame_sink_id().client_id(),
+                      region->frame_sink_id.sink_id());
+    }
+  }
+  return true;
+}
+
 }  // namespace viz
diff --git a/components/viz/service/hit_test/hit_test_manager.h b/components/viz/service/hit_test/hit_test_manager.h
index dc5ba7f..457f846 100644
--- a/components/viz/service/hit_test/hit_test_manager.h
+++ b/components/viz/service/hit_test/hit_test_manager.h
@@ -13,6 +13,7 @@
 #include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
 
 namespace viz {
+class LatestLocalSurfaceIdLookupDelegate;
 
 // HitTestManager manages the collection of HitTestRegionList objects
 // submitted in calls to SubmitCompositorFrame.  This collection is
@@ -22,18 +23,6 @@
   explicit HitTestManager(SurfaceManager* surface_manager);
   virtual ~HitTestManager();
 
-  // Called when HitTestRegionList is submitted along with every call
-  // to SubmitCompositorFrame.
-  void SubmitHitTestRegionList(
-      const SurfaceId& surface_id,
-      const uint64_t frame_index,
-      mojom::HitTestRegionListPtr hit_test_region_list);
-
-  // Returns the HitTestRegionList corresponding to the given
-  // surface_id and the active CompositorFrame matched by frame_index.
-  const mojom::HitTestRegionList* GetActiveHitTestRegionList(
-      const SurfaceId& surface_id) const;
-
   // SurfaceObserver:
   void OnSurfaceCreated(const SurfaceId& surface_id) override {}
   void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override {}
@@ -46,12 +35,23 @@
   void OnSurfaceDamageExpected(const SurfaceId& surface_id,
                                const BeginFrameArgs& args) override {}
 
+  // Called when HitTestRegionList is submitted along with every call
+  // to SubmitCompositorFrame.
+  void SubmitHitTestRegionList(
+      const SurfaceId& surface_id,
+      const uint64_t frame_index,
+      mojom::HitTestRegionListPtr hit_test_region_list);
+
+  // Returns the HitTestRegionList corresponding to the given
+  // |frame_sink_id| and the active CompositorFrame matched by frame_index.
+  const mojom::HitTestRegionList* GetActiveHitTestRegionList(
+      LatestLocalSurfaceIdLookupDelegate* delegate,
+      const FrameSinkId& frame_sink_id) const;
+
  private:
   bool ValidateHitTestRegionList(
       const SurfaceId& surface_id,
       const mojom::HitTestRegionListPtr& hit_test_region_list);
-  bool ValidateHitTestRegion(const SurfaceId& surface_id,
-                             const mojom::HitTestRegionPtr& hit_test_region);
 
   SurfaceManager* const surface_manager_;
 
diff --git a/components/viz/service/surfaces/latest_local_surface_id_lookup_delegate.h b/components/viz/service/surfaces/latest_local_surface_id_lookup_delegate.h
new file mode 100644
index 0000000..e37359b87
--- /dev/null
+++ b/components/viz/service/surfaces/latest_local_surface_id_lookup_delegate.h
@@ -0,0 +1,23 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_SERVICE_SURFACES_LATEST_LOCAL_SURFACE_ID_LOOKUP_DELEGATE_H_
+#define COMPONENTS_VIZ_SERVICE_SURFACES_LATEST_LOCAL_SURFACE_ID_LOOKUP_DELEGATE_H_
+
+namespace viz {
+// Used by HitTestManager to talk to Display.
+class LatestLocalSurfaceIdLookupDelegate {
+ public:
+  // Called to get the surface with |frame_sink_id| that is used at surface
+  // aggregation time.
+  virtual LocalSurfaceId GetSurfaceAtAggregation(
+      const FrameSinkId& frame_sink_id) const = 0;
+
+ protected:
+  virtual ~LatestLocalSurfaceIdLookupDelegate() {}
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_SERVICE_SURFACES_LATEST_LOCAL_SURFACE_ID_LOOKUP_DELEGATE_H_
diff --git a/components/viz/test/BUILD.gn b/components/viz/test/BUILD.gn
index 6dbd5ca..95f78b14 100644
--- a/components/viz/test/BUILD.gn
+++ b/components/viz/test/BUILD.gn
@@ -52,6 +52,8 @@
     "test_gles2_interface.h",
     "test_gpu_memory_buffer_manager.cc",
     "test_gpu_memory_buffer_manager.h",
+    "test_latest_local_surface_id_lookup_delegate.cc",
+    "test_latest_local_surface_id_lookup_delegate.h",
     "test_layer_tree_frame_sink.cc",
     "test_layer_tree_frame_sink.h",
     "test_shared_bitmap_manager.cc",
diff --git a/components/viz/test/test_latest_local_surface_id_lookup_delegate.cc b/components/viz/test/test_latest_local_surface_id_lookup_delegate.cc
new file mode 100644
index 0000000..aa539a2
--- /dev/null
+++ b/components/viz/test/test_latest_local_surface_id_lookup_delegate.cc
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/test/test_latest_local_surface_id_lookup_delegate.h"
+
+namespace viz {
+
+TestLatestLocalSurfaceIdLookupDelegate::
+    TestLatestLocalSurfaceIdLookupDelegate() = default;
+TestLatestLocalSurfaceIdLookupDelegate::
+    ~TestLatestLocalSurfaceIdLookupDelegate() = default;
+
+LocalSurfaceId TestLatestLocalSurfaceIdLookupDelegate::GetSurfaceAtAggregation(
+    const FrameSinkId& frame_sink_id) const {
+  auto it = surface_id_map_.find(frame_sink_id);
+  if (it == surface_id_map_.end())
+    return LocalSurfaceId();
+  return it->second;
+}
+
+void TestLatestLocalSurfaceIdLookupDelegate::SetSurfaceIdMap(
+    const SurfaceId& surface_id) {
+  surface_id_map_[surface_id.frame_sink_id()] = surface_id.local_surface_id();
+}
+
+}  // namespace viz
diff --git a/components/viz/test/test_latest_local_surface_id_lookup_delegate.h b/components/viz/test/test_latest_local_surface_id_lookup_delegate.h
new file mode 100644
index 0000000..5c20295
--- /dev/null
+++ b/components/viz/test/test_latest_local_surface_id_lookup_delegate.h
@@ -0,0 +1,35 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_TEST_TEST_LATEST_LOCAL_SURFACE_ID_LOOKUP_DELEGATE_H_
+#define COMPONENTS_VIZ_TEST_TEST_LATEST_LOCAL_SURFACE_ID_LOOKUP_DELEGATE_H_
+
+#include "base/containers/flat_map.h"
+#include "base/macros.h"
+#include "components/viz/common/surfaces/surface_id.h"
+#include "components/viz/service/surfaces/latest_local_surface_id_lookup_delegate.h"
+
+namespace viz {
+
+class TestLatestLocalSurfaceIdLookupDelegate
+    : public LatestLocalSurfaceIdLookupDelegate {
+ public:
+  TestLatestLocalSurfaceIdLookupDelegate();
+  ~TestLatestLocalSurfaceIdLookupDelegate() override;
+
+  // LatestLocalSurfaceIdLookupDelegate:
+  LocalSurfaceId GetSurfaceAtAggregation(
+      const FrameSinkId& frame_sink_id) const override;
+
+  void SetSurfaceIdMap(const SurfaceId& surface_id);
+
+ private:
+  base::flat_map<FrameSinkId, LocalSurfaceId> surface_id_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestLatestLocalSurfaceIdLookupDelegate);
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_TEST_TEST_LATEST_LOCAL_SURFACE_ID_LOOKUP_DELEGATE_H_
diff --git a/components/zucchini/zucchini_tools.cc b/components/zucchini/zucchini_tools.cc
index 16eff2da..57ff0b2c 100644
--- a/components/zucchini/zucchini_tools.cc
+++ b/components/zucchini/zucchini_tools.cc
@@ -56,7 +56,7 @@
     out << std::endl;
 
     if (do_dump) {
-      auto refs = group.GetReader(disasm.get());
+      refs = group.GetReader(disasm.get());
 
       for (auto ref = refs->GetNext(); ref; ref = refs->GetNext()) {
         out << "  " << AsHex<8>(ref->location);
diff --git a/content/browser/accessibility/snapshot_ax_tree_browsertest.cc b/content/browser/accessibility/snapshot_ax_tree_browsertest.cc
index 7a5a487..2d43f8b 100644
--- a/content/browser/accessibility/snapshot_ax_tree_browsertest.cc
+++ b/content/browser/accessibility/snapshot_ax_tree_browsertest.cc
@@ -68,14 +68,16 @@
 IN_PROC_BROWSER_TEST_F(SnapshotAXTreeBrowserTest,
                        SnapshotAccessibilityTreeFromWebContents) {
   GURL url("data:text/html,<button>Click</button>");
-  NavigateToURL(shell(), url);
+  EXPECT_TRUE(NavigateToURL(shell(), url));
 
   WebContentsImpl* web_contents =
       static_cast<WebContentsImpl*>(shell()->web_contents());
 
   AXTreeSnapshotWaiter waiter;
-  web_contents->RequestAXTreeSnapshot(base::BindOnce(
-      &AXTreeSnapshotWaiter::ReceiveSnapshot, base::Unretained(&waiter)));
+  web_contents->RequestAXTreeSnapshot(
+      base::BindOnce(&AXTreeSnapshotWaiter::ReceiveSnapshot,
+                     base::Unretained(&waiter)),
+      ui::kAXModeComplete);
   waiter.Wait();
 
   // Dump the whole tree if one of the assertions below fails
@@ -96,8 +98,9 @@
                        SnapshotAccessibilityTreeFromMultipleFrames) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
-  NavigateToURL(shell(), embedded_test_server()->GetURL(
-      "/accessibility/snapshot/outer.html"));
+  EXPECT_TRUE(NavigateToURL(
+      shell(),
+      embedded_test_server()->GetURL("/accessibility/snapshot/outer.html")));
 
   WebContentsImpl* web_contents =
       static_cast<WebContentsImpl*>(shell()->web_contents());
@@ -108,8 +111,10 @@
       "/accessibility/snapshot/inner.html"));
 
   AXTreeSnapshotWaiter waiter;
-  web_contents->RequestAXTreeSnapshot(base::BindOnce(
-      &AXTreeSnapshotWaiter::ReceiveSnapshot, base::Unretained(&waiter)));
+  web_contents->RequestAXTreeSnapshot(
+      base::BindOnce(&AXTreeSnapshotWaiter::ReceiveSnapshot,
+                     base::Unretained(&waiter)),
+      ui::kAXModeComplete);
   waiter.Wait();
 
   // Dump the whole tree if one of the assertions below fails
@@ -140,4 +145,118 @@
       dump);
 }
 
+// This tests to make sure that RequestAXTreeSnapshot() correctly traverses
+// inner contents, as used in features like <webview>.
+IN_PROC_BROWSER_TEST_F(SnapshotAXTreeBrowserTest,
+                       SnapshotAccessibilityTreeWithInnerContents) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  EXPECT_TRUE(NavigateToURL(
+      shell(),
+      embedded_test_server()->GetURL("/accessibility/snapshot/outer.html")));
+
+  WebContentsImpl* web_contents =
+      static_cast<WebContentsImpl*>(shell()->web_contents());
+  FrameTreeNode* root_frame = web_contents->GetFrameTree()->root();
+
+  NavigateFrameToURL(root_frame->child_at(0), GURL("data:text/plain,Alpha"));
+
+  WebContentsImpl* inner_contents =
+      static_cast<WebContentsImpl*>(CreateAndAttachInnerContents(
+          root_frame->child_at(1)->current_frame_host()));
+  NavigateFrameToURL(
+      inner_contents->GetFrameTree()->root(),
+      embedded_test_server()->GetURL("/accessibility/snapshot/inner.html"));
+
+  AXTreeSnapshotWaiter waiter;
+  web_contents->RequestAXTreeSnapshot(
+      base::BindOnce(&AXTreeSnapshotWaiter::ReceiveSnapshot,
+                     base::Unretained(&waiter)),
+      ui::kAXModeComplete);
+  waiter.Wait();
+
+  // Dump the whole tree if one of the assertions below fails
+  // to aid in debugging why it failed.
+  SCOPED_TRACE(waiter.snapshot().ToString());
+
+  ui::AXTree tree(waiter.snapshot());
+  ui::AXNode* root = tree.root();
+  std::string dump;
+  DumpRolesAndNamesAsText(root, 0, &dump);
+  EXPECT_EQ(
+      "rootWebArea\n"
+      "  genericContainer\n"
+      "    button 'Before'\n"
+      "    iframe\n"
+      "      rootWebArea\n"
+      "        pre\n"
+      "          staticText 'Alpha'\n"
+      "    button 'Middle'\n"
+      "    iframe\n"
+      "      rootWebArea\n"
+      "        genericContainer\n"
+      "          button 'Inside Before'\n"
+      "          iframe\n"
+      "            rootWebArea\n"
+      "          button 'Inside After'\n"
+      "    button 'After'\n",
+      dump);
+}
+
+// This tests to make sure that snapshotting with different modes gives
+// different results. This is not intended to ensure that specific modes give
+// specific attributes, but merely to ensure that the mode parameter makes a
+// difference.
+IN_PROC_BROWSER_TEST_F(SnapshotAXTreeBrowserTest,
+                       SnapshotAccessibilityTreeModes) {
+  GURL url("data:text/html,<button>Click</button>");
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+
+  WebContentsImpl* web_contents =
+      static_cast<WebContentsImpl*>(shell()->web_contents());
+
+  AXTreeSnapshotWaiter waiter_complete;
+  web_contents->RequestAXTreeSnapshot(
+      base::BindOnce(&AXTreeSnapshotWaiter::ReceiveSnapshot,
+                     base::Unretained(&waiter_complete)),
+      ui::kAXModeComplete);
+  waiter_complete.Wait();
+  const std::vector<ui::AXNodeData>& complete_nodes =
+      waiter_complete.snapshot().nodes;
+
+  // Dump the whole tree if one of the assertions below fails
+  // to aid in debugging why it failed.
+  SCOPED_TRACE(waiter_complete.snapshot().ToString());
+
+  AXTreeSnapshotWaiter waiter_contents;
+  web_contents->RequestAXTreeSnapshot(
+      base::BindOnce(&AXTreeSnapshotWaiter::ReceiveSnapshot,
+                     base::Unretained(&waiter_contents)),
+      ui::AXMode::kWebContents);
+  waiter_contents.Wait();
+  const std::vector<ui::AXNodeData>& contents_nodes =
+      waiter_contents.snapshot().nodes;
+
+  // Dump the whole tree if one of the assertions below fails
+  // to aid in debugging why it failed.
+  SCOPED_TRACE(waiter_contents.snapshot().ToString());
+
+  // The two snapshot passes walked the tree in the same order, so comparing
+  // element to element is possible by walking the snapshots in parallel.
+
+  auto total_attribute_count = [](const ui::AXNodeData& node_data) {
+    return node_data.string_attributes.size() +
+           node_data.int_attributes.size() + node_data.float_attributes.size() +
+           node_data.bool_attributes.size() +
+           node_data.intlist_attributes.size() +
+           node_data.stringlist_attributes.size() +
+           node_data.html_attributes.size();
+  };
+
+  ASSERT_EQ(complete_nodes.size(), contents_nodes.size());
+  for (size_t i = 0; i < complete_nodes.size(); ++i)
+    EXPECT_LT(total_attribute_count(contents_nodes[i]),
+              total_attribute_count(complete_nodes[i]));
+}
+
 }  // namespace content
diff --git a/content/browser/android/synchronous_compositor_host.cc b/content/browser/android/synchronous_compositor_host.cc
index 79bb68b3..46209b4 100644
--- a/content/browser/android/synchronous_compositor_host.cc
+++ b/content/browser/android/synchronous_compositor_host.cc
@@ -259,11 +259,9 @@
   mojom::SynchronousCompositorAssociatedRequest compositor_request =
       mojo::MakeRequest(&sync_compositor_);
 
-  rwhva_->GetRenderWidgetHostImpl()
-      ->GetWidgetInputHandler()
-      ->AttachSynchronousCompositor(std::move(host_control),
-                                    host.PassInterface(),
-                                    std::move(compositor_request));
+  rwhva_->host()->GetWidgetInputHandler()->AttachSynchronousCompositor(
+      std::move(host_control), host.PassInterface(),
+      std::move(compositor_request));
 }
 
 bool SynchronousCompositorHost::IsReadyForSynchronousCall() {
@@ -595,7 +593,7 @@
 }
 
 void SynchronousCompositorHost::SetNeedsBeginFrames(bool needs_begin_frames) {
-  rwhva_->GetRenderWidgetHostImpl()->SetNeedsBeginFrame(needs_begin_frames);
+  rwhva_->host()->SetNeedsBeginFrame(needs_begin_frames);
 }
 
 void SynchronousCompositorHost::LayerTreeFrameSinkCreated() {
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc
index e5c7291d..6e72086 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -178,8 +178,8 @@
 }
 
 void WebBluetoothServiceImpl::SetClientConnectionErrorHandler(
-    base::Closure closure) {
-  binding_.set_connection_error_handler(closure);
+    base::OnceClosure closure) {
+  binding_.set_connection_error_handler(std::move(closure));
 }
 
 bool WebBluetoothServiceImpl::IsDevicePaired(
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.h b/content/browser/bluetooth/web_bluetooth_service_impl.h
index 5ecd3e0..b60e604 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.h
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -60,7 +60,7 @@
   void CrashRendererAndClosePipe(bad_message::BadMessageReason reason);
 
   // Sets the connection error handler for WebBluetoothServiceImpl's Binding.
-  void SetClientConnectionErrorHandler(base::Closure closure);
+  void SetClientConnectionErrorHandler(base::OnceClosure closure);
 
   // Returns whether the device is paired with the |render_frame_host_|'s
   // GetLastCommittedOrigin().
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 7739a9f..9c9d300 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -638,7 +638,7 @@
 
   if (last_text_input_state_.get()) {
     guest_rwhv->TextInputStateChanged(*last_text_input_state_);
-    if (auto* rwh = guest_rwhv->GetRenderWidgetHostImpl()) {
+    if (auto* rwh = guest_rwhv->host()) {
       // We need composition range information for some IMEs. To get the
       // updates, we need to explicitly ask the renderer to monitor and send the
       // composition information changes. RenderWidgetHostView of the page will
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.cc b/content/browser/devtools/devtools_url_loader_interceptor.cc
index 985ca00..7a4d36c 100644
--- a/content/browser/devtools/devtools_url_loader_interceptor.cc
+++ b/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -320,7 +320,7 @@
   }
 
  private:
-  friend class InterceptionJob;
+  friend class content::InterceptionJob;
 
   template <typename Callback>
   InterceptionJob* FindJob(const std::string& id,
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper.cc b/content/browser/dom_storage/dom_storage_context_wrapper.cc
index f96c74f3..247cb690 100644
--- a/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -396,6 +396,7 @@
 scoped_refptr<SessionStorageNamespaceImpl>
 DOMStorageContextWrapper::MaybeGetExistingNamespace(
     const std::string& namespace_id) const {
+  base::AutoLock lock(alive_namespaces_lock_);
   auto it = alive_namespaces_.find(namespace_id);
   return (it != alive_namespaces_.end()) ? it->second : nullptr;
 }
@@ -403,12 +404,14 @@
 void DOMStorageContextWrapper::AddNamespace(
     const std::string& namespace_id,
     SessionStorageNamespaceImpl* session_namespace) {
+  base::AutoLock lock(alive_namespaces_lock_);
   DCHECK(alive_namespaces_.find(namespace_id) == alive_namespaces_.end());
   alive_namespaces_[namespace_id] = session_namespace;
 }
 
 void DOMStorageContextWrapper::RemoveNamespace(
     const std::string& namespace_id) {
+  base::AutoLock lock(alive_namespaces_lock_);
   DCHECK(alive_namespaces_.find(namespace_id) != alive_namespaces_.end());
   alive_namespaces_.erase(namespace_id);
 }
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper.h b/content/browser/dom_storage/dom_storage_context_wrapper.h
index 87f603ee..5188c48 100644
--- a/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -13,6 +13,7 @@
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
 #include "content/browser/dom_storage/dom_storage_context_impl.h"
 #include "content/common/content_export.h"
 #include "content/common/storage_partition_service.mojom.h"
@@ -105,9 +106,11 @@
   scoped_refptr<SessionStorageNamespaceImpl> MaybeGetExistingNamespace(
       const std::string& namespace_id) const;
 
+  // Note: can be called on multiple threads, protected by a mutex.
   void AddNamespace(const std::string& namespace_id,
                     SessionStorageNamespaceImpl* session_namespace);
 
+  // Note: can be called on multiple threads, protected by a mutex.
   void RemoveNamespace(const std::string& namespace_id);
 
   // Called on UI thread when the system is under memory pressure.
@@ -137,6 +140,7 @@
   // the SessionStorageNamespaceImpl objects that are still alive thanks to the
   // sessions component.
   std::map<std::string, SessionStorageNamespaceImpl*> alive_namespaces_;
+  mutable base::Lock alive_namespaces_lock_;
 
   base::FilePath legacy_localstorage_path_;
 
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index 23111338..d8cf6937 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -3155,7 +3155,14 @@
 
 // Verifies that if the last slice is finished, parallel download resumption
 // can complete.
-IN_PROC_BROWSER_TEST_F(ParallelDownloadTest, ResumptionLastSliceFinished) {
+#if defined(OS_CHROMEOS)
+// Failing on ChromeOS: https://crbug.com/822450
+#define MAYBE_ResumptionLastSliceFinished DISABLED_ResumptionLastSliceFinished
+#else
+#define MAYBE_ResumptionLastSliceFinished ResumptionLastSliceFinished
+#endif
+IN_PROC_BROWSER_TEST_F(ParallelDownloadTest,
+                       MAYBE_ResumptionLastSliceFinished) {
   // Create the received slices data, last slice is actually finished.
   std::vector<download::DownloadItem::ReceivedSlice> received_slices = {
       download::DownloadItem::ReceivedSlice(0, 1000),
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc
index ef1ab7c..feb0b8bd 100644
--- a/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -76,11 +76,9 @@
     // be called during nested WebContents destruction. See
     // https://crbug.com/644306.
     if (is_scroll_bubbling_ && GetParentRenderWidgetHostView() &&
-        GetParentRenderWidgetHostView()
-            ->GetRenderWidgetHostImpl()
-            ->delegate()) {
+        GetParentRenderWidgetHostView()->host()->delegate()) {
       GetParentRenderWidgetHostView()
-          ->GetRenderWidgetHostImpl()
+          ->host()
           ->delegate()
           ->GetInputEventRouter()
           ->CancelScrollBubbling(view_);
@@ -211,8 +209,7 @@
   if (!parent_view)
     return;
 
-  auto* event_router =
-      parent_view->GetRenderWidgetHostImpl()->delegate()->GetInputEventRouter();
+  auto* event_router = parent_view->host()->delegate()->GetInputEventRouter();
 
   gfx::Vector2d offset_from_parent =
       screen_space_rect_in_dip_.OffsetFromOrigin();
@@ -316,13 +313,11 @@
   if (frame_proxy_in_parent_renderer_->frame_tree_node()
           ->render_manager()
           ->ForInnerDelegate()) {
-    view_->GetRenderWidgetHostImpl()
-        ->delegate()
-        ->OnRenderFrameProxyVisibilityChanged(visible);
+    view_->host()->delegate()->OnRenderFrameProxyVisibilityChanged(visible);
     return;
   }
 
-  if (visible && !view_->GetRenderWidgetHostImpl()->delegate()->IsHidden()) {
+  if (visible && !view_->host()->delegate()->IsHidden()) {
     view_->Show();
   } else if (!visible) {
     view_->Hide();
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 8698b7d..f0324d6a 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -3891,15 +3891,16 @@
 }
 
 void RenderFrameHostImpl::UpdateAccessibilityMode() {
-  int accessibility_mode_raw = delegate_->GetAccessibilityMode().mode();
-  Send(new FrameMsg_SetAccessibilityMode(routing_id_, accessibility_mode_raw));
+  Send(new FrameMsg_SetAccessibilityMode(routing_id_,
+                                         delegate_->GetAccessibilityMode()));
 }
 
-void RenderFrameHostImpl::RequestAXTreeSnapshot(
-    AXTreeSnapshotCallback callback) {
+void RenderFrameHostImpl::RequestAXTreeSnapshot(AXTreeSnapshotCallback callback,
+                                                ui::AXMode ax_mode) {
   static int next_id = 1;
   int callback_id = next_id++;
-  Send(new AccessibilityMsg_SnapshotTree(routing_id_, callback_id));
+  Send(new AccessibilityMsg_SnapshotTree(routing_id_, callback_id,
+                                         ax_mode.mode()));
   ax_tree_snapshot_callbacks_.insert(
       std::make_pair(callback_id, std::move(callback)));
 }
@@ -4284,8 +4285,8 @@
   auto web_bluetooth_service =
       std::make_unique<WebBluetoothServiceImpl>(this, std::move(request));
   web_bluetooth_service->SetClientConnectionErrorHandler(
-      base::Bind(&RenderFrameHostImpl::DeleteWebBluetoothService,
-                 base::Unretained(this), web_bluetooth_service.get()));
+      base::BindOnce(&RenderFrameHostImpl::DeleteWebBluetoothService,
+                     base::Unretained(this), web_bluetooth_service.get()));
   web_bluetooth_services_.push_back(std::move(web_bluetooth_service));
   return web_bluetooth_services_.back().get();
 }
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 85c38ec..46e4270 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -494,7 +494,8 @@
 
   // Request a one-time snapshot of the accessibility tree without changing
   // the accessibility mode.
-  void RequestAXTreeSnapshot(AXTreeSnapshotCallback callback);
+  void RequestAXTreeSnapshot(AXTreeSnapshotCallback callback,
+                             ui::AXMode ax_mode);
 
   // Resets the accessibility serializer in the renderer.
   void AccessibilityReset();
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc
index 18f88ef..c0d75f3 100644
--- a/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -143,7 +143,7 @@
   // first place: http://crbug.com/273089.
   //
   // |guest_| is NULL during test.
-  if ((guest_ && guest_->is_in_destruction()) || !host_->is_hidden())
+  if ((guest_ && guest_->is_in_destruction()) || !host()->is_hidden())
     return;
   // Make sure the size of this view matches the size of the WebContentsView.
   // The two sizes may fall out of sync if we switch RenderWidgetHostViews,
@@ -157,14 +157,14 @@
     if (last_received_local_surface_id_.is_valid())
       SendSurfaceInfoToEmbedder();
   }
-  host_->WasShown(ui::LatencyInfo());
+  host()->WasShown(ui::LatencyInfo());
 }
 
 void RenderWidgetHostViewGuest::Hide() {
   // |guest_| is NULL during test.
-  if ((guest_ && guest_->is_in_destruction()) || host_->is_hidden())
+  if ((guest_ && guest_->is_in_destruction()) || host()->is_hidden())
     return;
-  host_->WasHidden();
+  host()->WasHidden();
 }
 
 void RenderWidgetHostViewGuest::SetSize(const gfx::Size& size) {
@@ -178,7 +178,7 @@
   // InterstitialPages are not WebContents, and so BrowserPluginGuest does not
   // have direct access to the interstitial page's RenderWidgetHost.
   if (guest_)
-    guest_->SetFocus(host_, true, blink::kWebFocusTypeNone);
+    guest_->SetFocus(host(), true, blink::kWebFocusTypeNone);
 }
 
 bool RenderWidgetHostViewGuest::HasFocus() const {
@@ -732,19 +732,19 @@
     rescaled_event.wheel_ticks_x /= current_device_scale_factor();
     rescaled_event.wheel_ticks_y /= current_device_scale_factor();
     ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
-    host_->ForwardWheelEventWithLatencyInfo(rescaled_event, latency_info);
+    host()->ForwardWheelEventWithLatencyInfo(rescaled_event, latency_info);
     return;
   }
 
-  ScopedInputScaleDisabler disable(host_, current_device_scale_factor());
+  ScopedInputScaleDisabler disable(host(), current_device_scale_factor());
   if (blink::WebInputEvent::IsMouseEventType(event->GetType())) {
-    host_->ForwardMouseEvent(*static_cast<const blink::WebMouseEvent*>(event));
+    host()->ForwardMouseEvent(*static_cast<const blink::WebMouseEvent*>(event));
     return;
   }
 
   if (event->GetType() == blink::WebInputEvent::kMouseWheel) {
     ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
-    host_->ForwardWheelEventWithLatencyInfo(
+    host()->ForwardWheelEventWithLatencyInfo(
         *static_cast<const blink::WebMouseWheelEvent*>(event), latency_info);
     return;
   }
@@ -752,7 +752,7 @@
   if (blink::WebInputEvent::IsKeyboardEventType(event->GetType())) {
     NativeWebKeyboardEvent keyboard_event(
         *static_cast<const blink::WebKeyboardEvent*>(event), GetNativeView());
-    host_->ForwardKeyboardEvent(keyboard_event);
+    host()->ForwardKeyboardEvent(keyboard_event);
     return;
   }
 
@@ -762,7 +762,7 @@
       embedder->GetView()->Focus();
     }
     ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
-    host_->ForwardTouchEventWithLatencyInfo(
+    host()->ForwardTouchEventWithLatencyInfo(
         *static_cast<const blink::WebTouchEvent*>(event), latency_info);
     return;
   }
@@ -784,7 +784,7 @@
             blink::WebGestureEvent::kMomentumPhase) {
       return;
     }
-    host_->ForwardGestureEvent(gesture_event);
+    host()->ForwardGestureEvent(gesture_event);
     return;
   }
 }
diff --git a/content/browser/network_service_restart_browsertest.cc b/content/browser/network_service_restart_browsertest.cc
index b7dcfb30..55841f1 100644
--- a/content/browser/network_service_restart_browsertest.cc
+++ b/content/browser/network_service_restart_browsertest.cc
@@ -397,8 +397,11 @@
 // Make sure the factory returned from
 // |URLLoaderFactoryGetter::GetNetworkFactory()| doesn't crash if
 // it's called after the StoragePartition is deleted.
-IN_PROC_BROWSER_TEST_F(NetworkServiceRestartBrowserTest,
-                       BrowserIOSharedFactoryAfterStoragePartitionGone) {
+// TODO(crbug.com/822585): Disabled since flaky on at least Linux ASAN and
+// Android.
+IN_PROC_BROWSER_TEST_F(
+    NetworkServiceRestartBrowserTest,
+    DISABLED_BrowserIOSharedFactoryAfterStoragePartitionGone) {
   base::ScopedAllowBlockingForTesting allow_blocking;
   std::unique_ptr<ShellBrowserContext> browser_context =
       std::make_unique<ShellBrowserContext>(true, nullptr);
diff --git a/content/browser/renderer_host/frame_connector_delegate.cc b/content/browser/renderer_host/frame_connector_delegate.cc
index a03a404..aca73b8 100644
--- a/content/browser/renderer_host/frame_connector_delegate.cc
+++ b/content/browser/renderer_host/frame_connector_delegate.cc
@@ -42,7 +42,7 @@
   view_->SetFrameSinkId(surface_id.frame_sink_id());
 #endif  // defined(USE_AURA)
 
-  RenderWidgetHostImpl* render_widget_host = view_->GetRenderWidgetHostImpl();
+  RenderWidgetHostImpl* render_widget_host = view_->host();
   DCHECK(render_widget_host);
 
   if (render_widget_host->auto_resize_enabled()) {
diff --git a/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc b/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
index 8937614..b954ab32 100644
--- a/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
+++ b/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc
@@ -103,14 +103,14 @@
 
 void MouseWheelPhaseHandler::SendWheelEndIfNeeded() {
   if (scroll_phase_state_ == SCROLL_IN_PROGRESS) {
-    RenderWidgetHostImpl* host = host_view_->GetRenderWidgetHostImpl();
-    if (!host) {
+    RenderWidgetHostImpl* widget_host = host_view_->host();
+    if (!widget_host) {
       ResetScrollSequence();
       return;
     }
 
-    bool should_route_event =
-        host->delegate() && host->delegate()->GetInputEventRouter();
+    bool should_route_event = widget_host->delegate() &&
+                              widget_host->delegate()->GetInputEventRouter();
     SendSyntheticWheelEventWithPhaseEnded(should_route_event);
   }
 
@@ -135,11 +135,12 @@
       blink::WebInputEvent::DispatchType::kEventNonBlocking;
 
   if (should_route_event) {
-    RenderWidgetHostImpl* host = host_view_->GetRenderWidgetHostImpl();
-    if (!host)
+    RenderWidgetHostImpl* widget_host = host_view_->host();
+    if (!widget_host || !widget_host->delegate() ||
+        !widget_host->delegate()->GetInputEventRouter())
       return;
 
-    host->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
+    widget_host->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
         host_view_, &last_mouse_wheel_event_,
         ui::LatencyInfo(ui::SourceEventType::WHEEL));
   } else {
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
index 31fc684..8b890578 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
@@ -339,8 +339,7 @@
 
 void TouchSelectionControllerClientAura::InternalClient::MoveCaret(
     const gfx::PointF& position) {
-  RenderWidgetHostDelegate* host_delegate =
-      rwhva_->GetRenderWidgetHostImpl()->delegate();
+  RenderWidgetHostDelegate* host_delegate = rwhva_->host()->delegate();
   if (host_delegate)
     host_delegate->MoveCaret(gfx::ToRoundedPoint(position));
 }
@@ -352,8 +351,7 @@
 
 void TouchSelectionControllerClientAura::InternalClient::
     MoveRangeSelectionExtent(const gfx::PointF& extent) {
-  RenderWidgetHostDelegate* host_delegate =
-      rwhva_->GetRenderWidgetHostImpl()->delegate();
+  RenderWidgetHostDelegate* host_delegate = rwhva_->host()->delegate();
   if (host_delegate)
     host_delegate->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
 }
@@ -367,8 +365,7 @@
 void TouchSelectionControllerClientAura::InternalClient::
     SelectBetweenCoordinates(const gfx::PointF& base,
                              const gfx::PointF& extent) {
-  RenderWidgetHostDelegate* host_delegate =
-      rwhva_->GetRenderWidgetHostImpl()->delegate();
+  RenderWidgetHostDelegate* host_delegate = rwhva_->host()->delegate();
   if (host_delegate) {
     host_delegate->SelectRange(gfx::ToRoundedPoint(base),
                                gfx::ToRoundedPoint(extent));
@@ -477,8 +474,7 @@
 void TouchSelectionControllerClientAura::ExecuteCommand(int command_id,
                                                         int event_flags) {
   rwhva_->selection_controller()->HideAndDisallowShowingAutomatically();
-  RenderWidgetHostDelegate* host_delegate =
-      rwhva_->GetRenderWidgetHostImpl()->delegate();
+  RenderWidgetHostDelegate* host_delegate = rwhva_->host()->delegate();
   if (!host_delegate)
     return;
 
@@ -503,7 +499,7 @@
       rwhva_->selection_controller()->GetRectBetweenBounds();
   gfx::PointF anchor_point =
       gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y());
-  RenderWidgetHostImpl* host = rwhva_->GetRenderWidgetHostImpl();
+  RenderWidgetHostImpl* host = rwhva_->host();
   host->ShowContextMenuAtPoint(gfx::ToRoundedPoint(anchor_point),
                                ui::MENU_SOURCE_TOUCH_EDIT_MENU);
 
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
index 75bbdf3..e419b3fb 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
@@ -113,16 +113,14 @@
 
 void TouchSelectionControllerClientChildFrame::MoveCaret(
     const gfx::PointF& position) {
-  RenderWidgetHostDelegate* host_delegate =
-      rwhv_->GetRenderWidgetHostImpl()->delegate();
+  RenderWidgetHostDelegate* host_delegate = rwhv_->host()->delegate();
   if (host_delegate)
     host_delegate->MoveCaret(ConvertFromRoot(position));
 }
 
 void TouchSelectionControllerClientChildFrame::MoveRangeSelectionExtent(
     const gfx::PointF& extent) {
-  RenderWidgetHostDelegate* host_delegate =
-      rwhv_->GetRenderWidgetHostImpl()->delegate();
+  RenderWidgetHostDelegate* host_delegate = rwhv_->host()->delegate();
   if (host_delegate)
     host_delegate->MoveRangeSelectionExtent(ConvertFromRoot(extent));
 }
@@ -130,8 +128,7 @@
 void TouchSelectionControllerClientChildFrame::SelectBetweenCoordinates(
     const gfx::PointF& base,
     const gfx::PointF& extent) {
-  RenderWidgetHostDelegate* host_delegate =
-      rwhv_->GetRenderWidgetHostImpl()->delegate();
+  RenderWidgetHostDelegate* host_delegate = rwhv_->host()->delegate();
   if (host_delegate) {
     host_delegate->SelectRange(ConvertFromRoot(base), ConvertFromRoot(extent));
   }
@@ -181,8 +178,7 @@
                                                               int event_flags) {
   manager_->GetTouchSelectionController()
       ->HideAndDisallowShowingAutomatically();
-  RenderWidgetHostDelegate* host_delegate =
-      rwhv_->GetRenderWidgetHostImpl()->delegate();
+  RenderWidgetHostDelegate* host_delegate = rwhv_->host()->delegate();
   if (!host_delegate)
     return;
 
@@ -209,7 +205,7 @@
       gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y());
   gfx::PointF origin = rwhv_->TransformPointToRootCoordSpaceF(gfx::PointF());
   anchor_point.Offset(-origin.x(), -origin.y());
-  RenderWidgetHostImpl* host = rwhv_->GetRenderWidgetHostImpl();
+  RenderWidgetHostImpl* host = rwhv_->host();
   host->Send(new ViewMsg_ShowContextMenu(host->GetRoutingID(),
                                          ui::MENU_SOURCE_TOUCH_EDIT_MENU,
                                          gfx::ToRoundedPoint(anchor_point)));
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.cc b/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.cc
index 3c48234..fc96874 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_manager_android.cc
@@ -71,8 +71,10 @@
   // Notify TouchSelectionController if anything should change here. Only
   // update if the client is different and not making a change to empty, or
   // is the same client.
-  GetTouchSelectionController()->OnSelectionBoundsChanged(
-      manager_selection_start_, manager_selection_end_);
+  if (GetTouchSelectionController()) {
+    GetTouchSelectionController()->OnSelectionBoundsChanged(
+        manager_selection_start_, manager_selection_end_);
+  }
 }
 
 void TouchSelectionControllerClientManagerAndroid::InvalidateClient(
diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index 8e90556..d1b38684 100644
--- a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -384,10 +384,9 @@
   // Creation and connection of a UDP socket might be janky.
   DCHECK(network_list_task_runner_->RunsTasksInCurrentSequence());
 
-  std::unique_ptr<net::DatagramClientSocket> socket(
+  auto socket =
       net::ClientSocketFactory::GetDefaultFactory()->CreateDatagramClientSocket(
-          net::DatagramSocket::DEFAULT_BIND, net::RandIntCallback(), nullptr,
-          net::NetLogSource()));
+          net::DatagramSocket::DEFAULT_BIND, nullptr, net::NetLogSource());
 
   net::IPAddress ip_address;
   if (family == AF_INET) {
diff --git a/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
index ed3a9dae..141d0b84 100644
--- a/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
@@ -20,7 +20,6 @@
 #include "ipc/ipc_message_macros.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
 #include "net/log/net_log_source.h"
 #include "net/socket/udp_socket.h"
 #include "ppapi/c/pp_errors.h"
@@ -399,9 +398,8 @@
     return;
   }
 
-  std::unique_ptr<net::UDPSocket> socket(
-      new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND,
-                         net::RandIntCallback(), nullptr, net::NetLogSource()));
+  auto socket = std::make_unique<net::UDPSocket>(
+      net::DatagramSocket::DEFAULT_BIND, nullptr, net::NetLogSource());
 
   net::IPAddressBytes address;
   uint16_t port;
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index ef20041..811ccf95 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -481,10 +481,8 @@
   if (view) {
     view_ = view->GetWeakPtr();
     if (enable_viz_) {
-      if (!create_frame_sink_callback_.is_null()) {
-        view_->CreateCompositorFrameSink(
-            std::move(create_frame_sink_callback_));
-      }
+      if (!create_frame_sink_callback_.is_null())
+        std::move(create_frame_sink_callback_).Run(view_->GetFrameSinkId());
     } else {
       if (renderer_compositor_frame_sink_.is_bound()) {
         view->DidCreateNewRendererCompositorFrameSink(
@@ -2701,7 +2699,7 @@
           std::move(compositor_frame_sink_client));
 
       if (view_)
-        view_->CreateCompositorFrameSink(std::move(callback));
+        std::move(callback).Run(view_->GetFrameSinkId());
       else
         create_frame_sink_callback_ = std::move(callback);
 
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index 634f6ad..d48cf29b 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -198,10 +198,7 @@
   RenderWidgetHostViewBase* target = nullptr;
   bool needs_transform_point = true;
   if (root_view->IsMouseLocked()) {
-    target = root_view->GetRenderWidgetHostImpl()
-                 ->delegate()
-                 ->GetMouseLockWidget()
-                 ->GetView();
+    target = root_view->host()->delegate()->GetMouseLockWidget()->GetView();
   }
 
   constexpr int mouse_button_modifiers =
@@ -247,10 +244,7 @@
   RenderWidgetHostViewBase* target = nullptr;
   gfx::PointF transformed_point;
   if (root_view->IsMouseLocked()) {
-    target = root_view->GetRenderWidgetHostImpl()
-                 ->delegate()
-                 ->GetMouseLockWidget()
-                 ->GetView();
+    target = root_view->host()->delegate()->GetMouseLockWidget()->GetView();
     if (!TransformPointToTargetCoordSpace(
             root_view, target, event.PositionInWidget(), &transformed_point,
             viz::EventSource::MOUSE)) {
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index ede17e8..71e54a4 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -165,7 +165,7 @@
 RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
     RenderWidgetHostImpl* widget_host,
     gfx::NativeView parent_native_view)
-    : host_(widget_host),
+    : RenderWidgetHostViewBase(widget_host),
       begin_frame_source_(nullptr),
       outstanding_begin_frame_requests_(0),
       is_showing_(!widget_host->is_hidden()),
@@ -202,17 +202,17 @@
   if (using_browser_compositor_) {
     delegated_frame_host_ = std::make_unique<ui::DelegatedFrameHostAndroid>(
         &view_, CompositorImpl::GetHostFrameSinkManager(), this,
-        host_->GetFrameSinkId());
+        host()->GetFrameSinkId());
 
     // Let the page-level input event router know about our frame sink ID
     // for surface-based hit testing.
-    if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
-      host_->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(
+    if (host()->delegate() && host()->delegate()->GetInputEventRouter()) {
+      host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(
           GetFrameSinkId(), this);
     }
   }
 
-  host_->SetView(this);
+  host()->SetView(this);
   touch_selection_controller_client_manager_ =
       std::make_unique<TouchSelectionControllerClientManagerAndroid>(this);
   UpdateNativeViewTree(parent_native_view);
@@ -277,7 +277,7 @@
 void RenderWidgetHostViewAndroid::WasResized() {
   if (delegated_frame_host_)
     delegated_frame_host_->WasResized();
-  host_->WasResized();
+  host()->WasResized();
 }
 
 void RenderWidgetHostViewAndroid::SetSize(const gfx::Size& size) {
@@ -320,12 +320,12 @@
 }
 
 void RenderWidgetHostViewAndroid::GotFocus() {
-  host_->GotFocus();
+  host()->GotFocus();
   OnFocusInternal();
 }
 
 void RenderWidgetHostViewAndroid::LostFocus() {
-  host_->LostFocus();
+  host()->LostFocus();
   LostFocusInternal();
 }
 
@@ -644,7 +644,7 @@
   if (event.for_touch_handle())
     return OnTouchHandleEvent(event);
 
-  if (!host_ || !host_->delegate())
+  if (!host() || !host()->delegate())
     return false;
 
   ComputeEventLatencyOSTouchHistograms(event);
@@ -680,11 +680,11 @@
 
   ui::LatencyInfo latency_info(ui::SourceEventType::TOUCH);
   latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
-  if (host_->delegate()->GetInputEventRouter()) {
-    host_->delegate()->GetInputEventRouter()->RouteTouchEvent(this, &web_event,
-                                                              latency_info);
+  if (host()->delegate()->GetInputEventRouter()) {
+    host()->delegate()->GetInputEventRouter()->RouteTouchEvent(this, &web_event,
+                                                               latency_info);
   } else {
-    host_->ForwardTouchEventWithLatencyInfo(web_event, latency_info);
+    host()->ForwardTouchEventWithLatencyInfo(web_event, latency_info);
   }
 
   // Send a proactive BeginFrame for this vsync to reduce scroll latency for
@@ -728,11 +728,11 @@
     blink::WebTouchEvent web_event = ui::CreateWebTouchEventFromMotionEvent(
         *cancel_event, causes_scrolling /* may_cause_scrolling */,
         false /* hovering */);
-    if (host_->delegate()->GetInputEventRouter()) {
-      host_->delegate()->GetInputEventRouter()->RouteTouchEvent(
+    if (host()->delegate()->GetInputEventRouter()) {
+      host()->delegate()->GetInputEventRouter()->RouteTouchEvent(
           this, &web_event, latency_info);
     } else {
-      host_->ForwardTouchEventWithLatencyInfo(web_event, latency_info);
+      host()->ForwardTouchEventWithLatencyInfo(web_event, latency_info);
     }
   }
 }
@@ -763,20 +763,17 @@
 }
 
 void RenderWidgetHostViewAndroid::Destroy() {
-  host_->ViewDestroyed();
+  host()->ViewDestroyed();
   UpdateNativeViewTree(nullptr);
   delegated_frame_host_.reset();
 
-  // The RenderWidgetHost's destruction led here, so don't call it.
-  host_ = NULL;
-
   if (GetTextInputManager() && GetTextInputManager()->HasObserver(this))
     GetTextInputManager()->RemoveObserver(this);
 
   for (auto& observer : destruction_observers_)
     observer.RenderWidgetHostViewDestroyed(this);
   destruction_observers_.Clear();
-
+  RenderWidgetHostViewBase::Destroy();
   delete this;
 }
 
@@ -790,7 +787,7 @@
 
   DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
          SkColorGetA(color) == SK_AlphaTRANSPARENT);
-  host_->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE);
+  host()->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE);
   UpdateBackgroundColor(color);
 }
 
@@ -843,12 +840,12 @@
 std::unique_ptr<SyntheticGestureTarget>
 RenderWidgetHostViewAndroid::CreateSyntheticGestureTarget() {
   return std::unique_ptr<SyntheticGestureTarget>(
-      new SyntheticGestureTargetAndroid(host_, &view_));
+      new SyntheticGestureTargetAndroid(host(), &view_));
 }
 
 void RenderWidgetHostViewAndroid::SendReclaimCompositorResources(
     bool is_swap_ack) {
-  DCHECK(host_);
+  DCHECK(host());
   if (is_swap_ack) {
     renderer_compositor_frame_sink_->DidReceiveCompositorFrameAck(
         surface_returned_resources_);
@@ -900,7 +897,7 @@
     DCHECK(!using_browser_compositor_);
     // We don't expect RendererCompositorFrameSink on Android WebView.
     // (crbug.com/721102)
-    bad_message::ReceivedBadMessage(host_->GetProcess(),
+    bad_message::ReceivedBadMessage(host()->GetProcess(),
                                     bad_message::RWH_BAD_FRAME_SINK_REQUEST);
     return;
   }
@@ -916,7 +913,7 @@
           features::kHideIncorrectlySizedFullscreenFrames)) {
     return;
   }
-  if (host_->delegate()->IsFullscreenForCurrentTab() &&
+  if (host()->delegate()->IsFullscreenForCurrentTab() &&
       current_surface_size_ != view_.GetPhysicalBackingSize()) {
     // When we're in a fullscreen and the frame size doesn't match the view
     // size (e.g. during a fullscreen rotation), we show black instead of the
@@ -961,11 +958,11 @@
   } else {
     delegated_frame_host_->SubmitCompositorFrame(
         local_surface_id, std::move(frame), std::move(hit_test_region_list));
-    frame_evictor_->SwappedFrame(!host_->is_hidden());
+    frame_evictor_->SwappedFrame(!host()->is_hidden());
     AcknowledgeBeginFrame(ack);
   }
 
-  if (host_->is_hidden())
+  if (host()->is_hidden())
     RunAckCallbacks();
 
   // As the metadata update may trigger view invalidation, always call it after
@@ -1020,20 +1017,19 @@
 
   bool is_mobile_optimized = IsMobileOptimizedFrame(frame_metadata);
 
-  if (host_ && host_->input_router()) {
-    host_->input_router()->NotifySiteIsMobileOptimized(
-        is_mobile_optimized);
+  if (host() && host()->input_router()) {
+    host()->input_router()->NotifySiteIsMobileOptimized(is_mobile_optimized);
   }
 
-  if (host_ && frame_metadata.frame_token)
-    host_->DidProcessFrame(frame_metadata.frame_token);
+  if (host() && frame_metadata.frame_token)
+    host()->DidProcessFrame(frame_metadata.frame_token);
 
   // This is a subset of OnSwapCompositorFrame() used in the synchronous
   // compositor flow.
   OnFrameMetadataUpdated(frame_metadata.Clone(), false);
 
   // DevTools ScreenCast support for Android WebView.
-  RenderFrameHost* frame_host = RenderViewHost::From(host_)->GetMainFrame();
+  RenderFrameHost* frame_host = RenderViewHost::From(host())->GetMainFrame();
   if (frame_host) {
     RenderFrameDevToolsAgentHost::SignalSynchronousSwapCompositorFrame(
         frame_host,
@@ -1283,7 +1279,7 @@
   if (!show)
     return;
 
-  if (!host_ || !host_->is_hidden())
+  if (!host() || !host()->is_hidden())
     return;
 
   view_.GetLayer()->SetHideLayerAndSubtree(false);
@@ -1293,7 +1289,7 @@
   if (overscroll_controller_)
     overscroll_controller_->Enable();
 
-  host_->WasShown(ui::LatencyInfo());
+  host()->WasShown(ui::LatencyInfo());
 
   if (view_.parent() && view_.GetWindowAndroid()) {
     StartObservingRootWindow();
@@ -1325,7 +1321,7 @@
     StopObservingRootWindow();
   }
 
-  if (!host_ || host_->is_hidden())
+  if (!host() || host()->is_hidden())
     return;
 
   if (overscroll_controller_)
@@ -1335,7 +1331,7 @@
 
   // Inform the renderer that we are being hidden so it can reduce its resource
   // utilization.
-  host_->WasHidden();
+  host()->WasHidden();
 }
 
 void RenderWidgetHostViewAndroid::SetBeginFrameSource(
@@ -1475,8 +1471,9 @@
       touch.event.unique_touch_event_id, event_consumed,
       InputEventAckStateIsSetNonBlocking(ack_result));
   if (touch.event.touch_start_or_first_touch_move && event_consumed &&
-      host_->delegate() && host_->delegate()->GetInputEventRouter()) {
-    host_->delegate()
+      host()->delegate() && host()->delegate()->GetInputEventRouter()) {
+    host()
+        ->delegate()
         ->GetInputEventRouter()
         ->OnHandledTouchStartOrFirstTouchMove(
             touch.event.unique_touch_event_id);
@@ -1496,7 +1493,7 @@
 
 RenderViewHostDelegateView*
 RenderWidgetHostViewAndroid::GetRenderViewHostDelegateView() const {
-  RenderWidgetHostDelegate* delegate = host_->delegate();
+  RenderWidgetHostDelegate* delegate = host()->delegate();
   return delegate ? delegate->GetDelegateView() : nullptr;
 }
 
@@ -1514,7 +1511,7 @@
     return INPUT_EVENT_ACK_STATE_CONSUMED;
   }
 
-  if (!host_)
+  if (!host())
     return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
 
   if (input_event.GetType() == blink::WebInputEvent::kGestureTapDown ||
@@ -1539,7 +1536,7 @@
         BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
   return new BrowserAccessibilityManagerAndroid(
       BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
-      for_root_frame && host_ ? GetWebContentsAccessibilityAndroid() : nullptr,
+      for_root_frame && host() ? GetWebContentsAccessibilityAndroid() : nullptr,
       delegate);
 }
 
@@ -1556,15 +1553,15 @@
 
 void RenderWidgetHostViewAndroid::SendKeyEvent(
     const NativeWebKeyboardEvent& event) {
-  if (!host_)
+  if (!host())
     return;
 
-  RenderWidgetHostImpl* target_host = host_;
+  RenderWidgetHostImpl* target_host = host();
 
   // If there are multiple widgets on the page (such as when there are
   // out-of-process iframes), pick the one that should process this event.
-  if (host_->delegate())
-    target_host = host_->delegate()->GetFocusedRenderWidgetHost(host_);
+  if (host()->delegate())
+    target_host = host()->delegate()->GetFocusedRenderWidgetHost(host());
   if (!target_host)
     return;
 
@@ -1605,14 +1602,14 @@
   blink::WebMouseEvent mouse_event = WebMouseEventBuilder::Build(
       motion_event, webMouseEventType, click_count, action_button);
 
-  if (!host_ || !host_->delegate())
+  if (!host() || !host()->delegate())
     return;
 
-  if (host_->delegate()->GetInputEventRouter()) {
-    host_->delegate()->GetInputEventRouter()->RouteMouseEvent(
+  if (host()->delegate()->GetInputEventRouter()) {
+    host()->delegate()->GetInputEventRouter()->RouteMouseEvent(
         this, &mouse_event, ui::LatencyInfo());
   } else {
-    host_->ForwardMouseEvent(mouse_event);
+    host()->ForwardMouseEvent(mouse_event);
   }
 }
 
@@ -1642,22 +1639,22 @@
 
 void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
     const blink::WebMouseWheelEvent& event) {
-  if (!host_ || !host_->delegate())
+  if (!host() || !host()->delegate())
     return;
 
   ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
   latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
   blink::WebMouseWheelEvent wheel_event(event);
-  bool should_route_event = !!host_->delegate()->GetInputEventRouter();
+  bool should_route_event = !!host()->delegate()->GetInputEventRouter();
   if (wheel_scroll_latching_enabled()) {
     mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
         wheel_event, should_route_event);
   }
   if (should_route_event) {
-    host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
+    host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
         this, &wheel_event, latency_info);
   } else {
-    host_->ForwardWheelEventWithLatencyInfo(wheel_event, latency_info);
+    host()->ForwardWheelEventWithLatencyInfo(wheel_event, latency_info);
   }
 }
 
@@ -1667,7 +1664,7 @@
   if (overscroll_controller_)
     overscroll_controller_->Enable();
 
-  if (!host_ || !host_->delegate() ||
+  if (!host() || !host()->delegate() ||
       event.GetType() == blink::WebInputEvent::kUndefined) {
     return;
   }
@@ -1724,13 +1721,13 @@
       mouse_wheel_phase_handler_.IgnorePendingWheelEndEvent();
     }
   }
-  bool should_route_event = !!host_->delegate()->GetInputEventRouter();
+  bool should_route_event = !!host()->delegate()->GetInputEventRouter();
   if (should_route_event) {
     blink::WebGestureEvent gesture_event(event);
-    host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
+    host()->delegate()->GetInputEventRouter()->RouteGestureEvent(
         this, &gesture_event, latency_info);
   } else {
-    host_->ForwardGestureEventWithLatencyInfo(event, latency_info);
+    host()->ForwardGestureEventWithLatencyInfo(event, latency_info);
   }
 }
 
@@ -1747,22 +1744,22 @@
     double timestamp_seconds,
     gfx::Point tap_viewport_offset,
     bool is_long_press) {
-  DCHECK(host_);
-  host_->Send(new ViewMsg_ResolveTapDisambiguation(
-      host_->GetRoutingID(), timestamp_seconds, tap_viewport_offset,
+  DCHECK(host());
+  host()->Send(new ViewMsg_ResolveTapDisambiguation(
+      host()->GetRoutingID(), timestamp_seconds, tap_viewport_offset,
       is_long_press));
 }
 
 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
-  if (host_ && host_->delegate())
-    host_->delegate()->MoveCaret(point);
+  if (host() && host()->delegate())
+    host()->delegate()->MoveCaret(point);
 }
 
 void RenderWidgetHostViewAndroid::ShowContextMenuAtPoint(
     const gfx::Point& point,
     ui::MenuSourceType source_type) {
-  if (host_)
-    host_->ShowContextMenuAtPoint(point, source_type);
+  if (host())
+    host()->ShowContextMenuAtPoint(point, source_type);
 }
 
 void RenderWidgetHostViewAndroid::DismissTextHandles() {
@@ -1812,11 +1809,6 @@
   gesture_listener_manager_->DidStopFlinging();
 }
 
-RenderWidgetHostImpl* RenderWidgetHostViewAndroid::GetRenderWidgetHostImpl()
-    const {
-  return host_;
-}
-
 viz::FrameSinkId RenderWidgetHostViewAndroid::GetFrameSinkId() {
   if (!delegated_frame_host_)
     return viz::FrameSinkId();
@@ -2004,7 +1996,7 @@
 void RenderWidgetHostViewAndroid::OnBeginFrame(
     const viz::BeginFrameArgs& args) {
   TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnBeginFrame");
-  if (!host_) {
+  if (!host()) {
     OnDidNotProduceFrame(
         viz::BeginFrameAck(args.source_id, args.sequence_number, false));
     return;
@@ -2032,7 +2024,7 @@
     OnDidNotProduceFrame(
         viz::BeginFrameAck(args.source_id, args.sequence_number, false));
   }
-  host_->ProgressFling(args.frame_time);
+  host()->ProgressFling(args.frame_time);
 }
 
 const viz::BeginFrameArgs& RenderWidgetHostViewAndroid::LastUsedBeginFrameArgs()
@@ -2141,7 +2133,7 @@
   if (overscroll_controller_)
     return;
 
-  RenderWidgetHostDelegate* delegate = host_->delegate();
+  RenderWidgetHostDelegate* delegate = host()->delegate();
   if (!delegate)
     return;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 5ce1f3c..782db81 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -50,7 +50,6 @@
 class GestureListenerManager;
 class ImeAdapterAndroid;
 class OverscrollControllerAndroid;
-class RenderWidgetHostImpl;
 class SelectionPopupController;
 class SynchronousCompositorHost;
 class SynchronousCompositorClient;
@@ -170,7 +169,6 @@
   void OnDidNavigateMainFrameToNewPage() override;
   void SetNeedsBeginFrames(bool needs_begin_frames) override;
   void SetWantsAnimateOnlyBeginFrames() override;
-  RenderWidgetHostImpl* GetRenderWidgetHostImpl() const override;
   viz::FrameSinkId GetFrameSinkId() override;
   bool TransformPointToLocalCoordSpace(const gfx::PointF& point,
                                        const viz::SurfaceId& original_surface,
@@ -392,9 +390,6 @@
   void OnFocusInternal();
   void LostFocusInternal();
 
-  // The model object.
-  RenderWidgetHostImpl* host_;
-
   // The begin frame source being observed.  Null if none.
   viz::BeginFrameSource* begin_frame_source_;
   viz::BeginFrameArgs last_begin_frame_args_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 2573d92..a62fdee 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -233,10 +233,10 @@
     // of the fact that focus was lost for the host window by sending a Blur
     // notification. We also set a flag in the view indicating that we need
     // to force a Focus notification on the next mouse down.
-    if (popup_parent_host_view_ && popup_parent_host_view_->host_) {
+    if (popup_parent_host_view_ && popup_parent_host_view_->host()) {
       popup_parent_host_view_->event_handler()
           ->set_focus_on_mouse_down_or_key_event(true);
-      popup_parent_host_view_->host_->Blur();
+      popup_parent_host_view_->host()->Blur();
     }
     // Note: popup_parent_host_view_ may be NULL when there are multiple
     // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
@@ -333,10 +333,10 @@
 // RenderWidgetHostViewAura, public:
 
 RenderWidgetHostViewAura::RenderWidgetHostViewAura(
-    RenderWidgetHost* host,
+    RenderWidgetHost* widget_host,
     bool is_guest_view_hack,
     bool is_mus_browser_plugin_guest)
-    : host_(RenderWidgetHostImpl::From(host)),
+    : RenderWidgetHostViewBase(widget_host),
       is_mus_browser_plugin_guest_(is_mus_browser_plugin_guest),
       window_(nullptr),
       in_shutdown_(false),
@@ -357,15 +357,18 @@
       has_snapped_to_boundary_(false),
       is_guest_view_hack_(is_guest_view_hack),
       device_scale_factor_(0.0f),
-      event_handler_(new RenderWidgetHostViewEventHandler(host_, this, this)),
+      event_handler_(new RenderWidgetHostViewEventHandler(host(), this, this)),
       frame_sink_id_(base::FeatureList::IsEnabled(features::kMash)
                          ? viz::FrameSinkId()
                          : is_guest_view_hack_
                                ? AllocateFrameSinkIdForGuestViewHack()
-                               : host_->GetFrameSinkId()),
+                               : host()->GetFrameSinkId()),
       weak_ptr_factory_(this) {
+  if (!is_mus_browser_plugin_guest_)
+    CreateDelegatedFrameHostClient();
+
   if (!is_guest_view_hack_)
-    host_->SetView(this);
+    host()->SetView(this);
 
   // We should start observing the TextInputManager for IME-related events as
   // well as monitoring its lifetime.
@@ -381,7 +384,7 @@
       new TouchSelectionControllerClientAura(this));
   CreateSelectionController();
 
-  RenderViewHost* rvh = RenderViewHost::From(host_);
+  RenderViewHost* rvh = RenderViewHost::From(host());
   if (rvh) {
     // TODO(mostynb): actually use prefs.  Landing this as a separate CL
     // first to rebaseline some unreliable layout tests.
@@ -395,9 +398,6 @@
 void RenderWidgetHostViewAura::InitAsChild(gfx::NativeView parent_view) {
   if (is_mus_browser_plugin_guest_)
     return;
-
-  CreateDelegatedFrameHostClient();
-
   CreateAuraWindow(aura::client::WINDOW_TYPE_CONTROL);
 
   if (parent_view)
@@ -411,7 +411,6 @@
     const gfx::Rect& bounds_in_screen) {
   // Popups never have |is_mus_browser_plugin_guest_| set to true.
   DCHECK(!is_mus_browser_plugin_guest_);
-  CreateDelegatedFrameHostClient();
 
   popup_parent_host_view_ =
       static_cast<RenderWidgetHostViewAura*>(parent_host_view);
@@ -463,7 +462,6 @@
   // |is_mus_browser_plugin_guest_| is always false.
   DCHECK(!is_mus_browser_plugin_guest_);
   is_fullscreen_ = true;
-  CreateDelegatedFrameHostClient();
   CreateAuraWindow(aura::client::WINDOW_TYPE_NORMAL);
   window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
 
@@ -546,16 +544,16 @@
 
 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
 #if defined(OS_WIN)
-  aura::WindowTreeHost* host = window_->GetHost();
-  if (!host)
+  aura::WindowTreeHost* window_host = window_->GetHost();
+  if (!window_host)
     return static_cast<gfx::NativeViewAccessible>(NULL);
   BrowserAccessibilityManager* manager =
-      host_->GetOrCreateRootBrowserAccessibilityManager();
+      host()->GetOrCreateRootBrowserAccessibilityManager();
   if (manager)
     return ToBrowserAccessibilityWin(manager->GetRoot())->GetCOM();
 #elif defined(USE_X11)
   BrowserAccessibilityManager* manager =
-      host_->GetOrCreateRootBrowserAccessibilityManager();
+      host()->GetOrCreateRootBrowserAccessibilityManager();
   if (manager && manager->GetRoot())
     return manager->GetRoot()->GetNativeViewAccessible();
 #endif
@@ -579,12 +577,12 @@
 }
 
 void RenderWidgetHostViewAura::OnBeginFrame(base::TimeTicks frame_time) {
-  host_->ProgressFling(frame_time);
+  host()->ProgressFling(frame_time);
   UpdateNeedsBeginFramesInternal();
 }
 
 RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() const {
-  RenderViewHost* rvh = RenderViewHost::From(host_);
+  RenderViewHost* rvh = RenderViewHost::From(host());
   if (!rvh)
     return nullptr;
   FrameTreeNode* focused_frame =
@@ -651,11 +649,11 @@
   ui::LatencyInfo renderer_latency_info, browser_latency_info;
   if (has_saved_frame) {
     browser_latency_info.AddLatencyNumber(ui::TAB_SHOW_COMPONENT,
-                                          host_->GetLatencyComponentId(), 0);
+                                          host()->GetLatencyComponentId(), 0);
     browser_latency_info.set_trace_id(++tab_show_sequence_);
   } else {
     renderer_latency_info.AddLatencyNumber(ui::TAB_SHOW_COMPONENT,
-                                           host_->GetLatencyComponentId(), 0);
+                                           host()->GetLatencyComponentId(), 0);
     renderer_latency_info.set_trace_id(++tab_show_sequence_);
   }
 
@@ -667,7 +665,7 @@
 
   TRACE_EVENT_ASYNC_BEGIN0("latency", "TabSwitching::Latency",
                            tab_show_sequence_);
-  host_->WasShown(renderer_latency_info);
+  host()->WasShown(renderer_latency_info);
 
   aura::Window* root = window_->GetRootWindow();
   if (root) {
@@ -689,8 +687,8 @@
 }
 
 void RenderWidgetHostViewAura::WasOccluded() {
-  if (!host_->is_hidden()) {
-    host_->WasHidden();
+  if (!host()->is_hidden()) {
+    host()->WasHidden();
     if (delegated_frame_host_)
       delegated_frame_host_->WasHidden();
 
@@ -722,7 +720,7 @@
 
   DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
          SkColorGetA(color) == SK_AlphaTRANSPARENT);
-  host_->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE);
+  host()->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE);
 }
 
 SkColor RenderWidgetHostViewAura::background_color() const {
@@ -753,7 +751,7 @@
 void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
   if (insets != insets_) {
     insets_ = insets;
-    host_->WasResized(!insets_.IsEmpty());
+    host()->WasResized(!insets_.IsEmpty());
   }
 }
 
@@ -763,7 +761,7 @@
   ui::OnScreenKeyboardDisplayManager* osk_display_manager =
       ui::OnScreenKeyboardDisplayManager::GetInstance();
   DCHECK(osk_display_manager);
-  if (editable && host_->GetView() && host_->delegate()) {
+  if (editable && host()->GetView() && host()->delegate()) {
     keyboard_observer_.reset(new WinScreenKeyboardObserver(this));
     if (!osk_display_manager->DisplayVirtualKeyboard(keyboard_observer_.get()))
       keyboard_observer_.reset(nullptr);
@@ -864,16 +862,6 @@
 }
 #endif
 
-void RenderWidgetHostViewAura::CreateCompositorFrameSink(
-    CreateCompositorFrameSinkCallback callback) {
-  // DelegatedFrameHost registers the FrameSinkId, so we need to wait
-  // for that to be created before creating a CompositorFrameSink.
-  if (delegated_frame_host_)
-    std::move(callback).Run(frame_sink_id_);
-  else
-    create_frame_sink_callback_ = std::move(callback);
-}
-
 void RenderWidgetHostViewAura::DidCreateNewRendererCompositorFrameSink(
     viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
   renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
@@ -1006,7 +994,7 @@
         event.data.scroll_update.inertial_phase ==
             blink::WebGestureEvent::kMomentumPhase &&
         overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE) {
-      host_->StopFling();
+      host()->StopFling();
     }
   }
 }
@@ -1014,9 +1002,9 @@
 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
     const TouchEventWithLatencyInfo& touch,
     InputEventAckState ack_result) {
-  aura::WindowTreeHost* host = window_->GetHost();
+  aura::WindowTreeHost* window_host = window_->GetHost();
   // |host| is NULL during tests.
-  if (!host)
+  if (!window_host)
     return;
 
   // The TouchScrollStarted event is generated & consumed downstream from the
@@ -1052,13 +1040,14 @@
   for (size_t i = 0; i < touch.event.touches_length; ++i) {
     if (touch.event.touches[i].state == required_state) {
       DCHECK(!sent_ack);
-      host->dispatcher()->ProcessedTouchEvent(
+      window_host->dispatcher()->ProcessedTouchEvent(
           touch.event.unique_touch_event_id, window_, result,
           InputEventAckStateIsSetNonBlocking(ack_result));
       if (touch.event.touch_start_or_first_touch_move &&
-          result == ui::ER_HANDLED && host_->delegate() &&
-          host_->delegate()->GetInputEventRouter()) {
-        host_->delegate()
+          result == ui::ER_HANDLED && host()->delegate() &&
+          host()->delegate()->GetInputEventRouter()) {
+        host()
+            ->delegate()
             ->GetInputEventRouter()
             ->OnHandledTouchStartOrFirstTouchMove(
                 touch.event.unique_touch_event_id);
@@ -1071,7 +1060,7 @@
 std::unique_ptr<SyntheticGestureTarget>
 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
   return std::unique_ptr<SyntheticGestureTarget>(
-      new SyntheticGestureTargetAura(host_));
+      new SyntheticGestureTargetAura(host()));
 }
 
 InputEventAckState RenderWidgetHostViewAura::FilterInputEvent(
@@ -1514,7 +1503,7 @@
 }
 
 void RenderWidgetHostViewAura::OnCaptureLost() {
-  host_->LostCapture();
+  host()->LostCapture();
 }
 
 void RenderWidgetHostViewAura::OnPaint(const ui::PaintContext& context) {
@@ -1712,11 +1701,11 @@
     // We need to honor input bypass if the associated tab is does not want
     // input. This gives the current focused window a chance to be the text
     // input client and handle events.
-    if (host_->ignore_input_events())
+    if (host()->ignore_input_events())
       return;
 
-    host_->GotFocus();
-    host_->SetActive(true);
+    host()->GotFocus();
+    host()->SetActive(true);
 
     ui::InputMethod* input_method = GetInputMethod();
     if (input_method) {
@@ -1726,12 +1715,12 @@
     }
 
     BrowserAccessibilityManager* manager =
-        host_->GetRootBrowserAccessibilityManager();
+        host()->GetRootBrowserAccessibilityManager();
     if (manager)
       manager->OnWindowFocused();
   } else if (window_ == lost_focus) {
-    host_->SetActive(false);
-    host_->LostFocus();
+    host()->SetActive(false);
+    host()->LostFocus();
 
     DetachFromInputMethod();
 
@@ -1745,7 +1734,7 @@
       overscroll_controller_->Cancel();
 
     BrowserAccessibilityManager* manager =
-        host_->GetRootBrowserAccessibilityManager();
+        host()->GetRootBrowserAccessibilityManager();
     if (manager)
       manager->OnWindowBlurred();
 
@@ -1799,7 +1788,7 @@
 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
   // Ask the RWH to drop reference to us.
   if (!is_guest_view_hack_)
-    host_->ViewDestroyed();
+    host()->ViewDestroyed();
 
   selection_controller_.reset();
   selection_controller_client_.reset();
@@ -1883,31 +1872,19 @@
   if (!frame_sink_id_.is_valid())
     return;
 
-  // Tests may set |delegated_frame_host_client_|.
-  if (!delegated_frame_host_client_) {
-    delegated_frame_host_client_ =
-        std::make_unique<DelegatedFrameHostClientAura>(this);
-  }
-
+  delegated_frame_host_client_ =
+      std::make_unique<DelegatedFrameHostClientAura>(this);
   const bool enable_viz =
       base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
   delegated_frame_host_ = std::make_unique<DelegatedFrameHost>(
       frame_sink_id_, delegated_frame_host_client_.get(),
       features::IsSurfaceSynchronizationEnabled(), enable_viz,
       false /* should_register_frame_sink_id */);
-  if (!create_frame_sink_callback_.is_null())
-    std::move(create_frame_sink_callback_).Run(frame_sink_id_);
-
-  if (renderer_compositor_frame_sink_) {
-    delegated_frame_host_->DidCreateNewRendererCompositorFrameSink(
-        renderer_compositor_frame_sink_);
-  }
-  UpdateNeedsBeginFramesInternal();
 
   // Let the page-level input event router know about our surface ID
   // namespace for surface-based hit testing.
-  if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
-    host_->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(
+  if (host()->delegate() && host()->delegate()->GetInputEventRouter()) {
+    host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(
         GetFrameSinkId(), this);
   }
 }
@@ -1916,7 +1893,7 @@
   if (is_mus_browser_plugin_guest_)
     return;
 
-  if (host_->GetProcess()->FastShutdownStarted())
+  if (host()->GetProcess()->FastShutdownStarted())
     return;
 
   aura::Window* root_window = window_->GetRootWindow();
@@ -2008,7 +1985,7 @@
 void RenderWidgetHostViewAura::Shutdown() {
   if (!in_shutdown_) {
     in_shutdown_ = true;
-    host_->ShutdownAndDestroyWidget(true);
+    host()->ShutdownAndDestroyWidget(true);
   }
 }
 
@@ -2041,7 +2018,7 @@
     const ContextMenuParams& params) {
   // Use RenderViewHostDelegate to get to the WebContentsViewAura, which will
   // actually show the disambiguation popup.
-  RenderViewHost* rvh = RenderViewHost::From(host_);
+  RenderViewHost* rvh = RenderViewHost::From(host());
   if (!rvh)
     return;
 
@@ -2057,13 +2034,13 @@
 
 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
     bool is_visible) {
-  if (host_->is_hidden() ||
+  if (host()->is_hidden() ||
       (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
       (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
     return;
 
   cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
-  host_->SendCursorVisibilityState(is_visible);
+  host()->SendCursorVisibilityState(is_visible);
 }
 
 void RenderWidgetHostViewAura::SetOverscrollControllerEnabled(bool enabled) {
@@ -2141,10 +2118,10 @@
   }
   // Note that |host_| will retrieve resize parameters from
   // |delegated_frame_host_|, so it must have WasResized called after.
-  host_->WasResized();
-  if (host_->auto_resize_enabled()) {
-    host_->DidAllocateLocalSurfaceIdForAutoResize(
-        host_->last_auto_resize_request_number());
+  host()->WasResized();
+  if (host()->auto_resize_enabled()) {
+    host()->DidAllocateLocalSurfaceIdForAutoResize(
+        host()->last_auto_resize_request_number());
   }
 }
 
@@ -2167,7 +2144,7 @@
     // the associated RenderWidget is also visible before the
     // LegacyRenderWidgetHostHWND instace is created. Ensure that it is shown
     // here.
-    if (!host_->is_hidden())
+    if (!host()->is_hidden())
       legacy_render_widget_host_HWND_->Show();
   }
 }
@@ -2243,12 +2220,12 @@
     const NativeWebKeyboardEvent& event,
     const ui::LatencyInfo& latency,
     bool* update_event) {
-  RenderWidgetHostImpl* target_host = host_;
+  RenderWidgetHostImpl* target_host = host();
 
   // If there are multiple widgets on the page (such as when there are
   // out-of-process iframes), pick the one that should process this event.
-  if (host_->delegate())
-    target_host = host_->delegate()->GetFocusedRenderWidgetHost(host_);
+  if (host()->delegate())
+    target_host = host()->delegate()->GetFocusedRenderWidgetHost(host());
   if (!target_host)
     return;
 
@@ -2293,11 +2270,6 @@
   ui::GestureRecognizer::Get()->CancelActiveTouches(window_);
 }
 
-RenderWidgetHostImpl* RenderWidgetHostViewAura::GetRenderWidgetHostImpl()
-    const {
-  return host_;
-}
-
 viz::FrameSinkId RenderWidgetHostViewAura::GetFrameSinkId() {
   return frame_sink_id_;
 }
@@ -2326,7 +2298,7 @@
     GetInputMethod()->ShowImeIfNeeded();
   }
 
-  if (auto* render_widget_host = updated_view->GetRenderWidgetHostImpl()) {
+  if (auto* render_widget_host = updated_view->host()) {
     // Monitor the composition information if there is a focused editable node.
     render_widget_host->RequestCompositionUpdates(
         false /* immediate_request */,
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index de586d9..73598e9 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -74,7 +74,6 @@
 class DelegatedFrameHost;
 class DelegatedFrameHostClient;
 class RenderFrameHostImpl;
-class RenderWidgetHostImpl;
 class RenderWidgetHostView;
 class TouchSelectionControllerClientAura;
 
@@ -168,8 +167,6 @@
   void SetMainFrameAXTreeID(ui::AXTreeIDRegistry::AXTreeID id) override;
   bool LockMouse() override;
   void UnlockMouse() override;
-  void CreateCompositorFrameSink(
-      CreateCompositorFrameSinkCallback callback) override;
   void DidCreateNewRendererCompositorFrameSink(
       viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink)
       override;
@@ -181,7 +178,6 @@
   void ClearCompositorFrame() override;
   void DidStopFlinging() override;
   void OnDidNavigateMainFrameToNewPage() override;
-  RenderWidgetHostImpl* GetRenderWidgetHostImpl() const override;
   viz::FrameSinkId GetFrameSinkId() override;
   viz::LocalSurfaceId GetLocalSurfaceId() const override;
   bool TransformPointToLocalCoordSpace(const gfx::PointF& point,
@@ -525,9 +521,6 @@
   // opaqueness changes.
   void UpdateBackgroundColorFromRenderer(SkColor color);
 
-  // The model object.
-  RenderWidgetHostImpl* const host_;
-
   const bool is_mus_browser_plugin_guest_;
 
   // NOTE: this is null if |is_mus_browser_plugin_guest_| is true.
@@ -654,11 +647,6 @@
   std::unique_ptr<CursorManager> cursor_manager_;
   int tab_show_sequence_ = 0;
 
-  // Stashes a request to create a CompositorFrameSink if it arrives before
-  // DelegatedFrameHost is created. This is only used with VizDisplayCompositor
-  // feature.
-  CreateCompositorFrameSinkCallback create_frame_sink_callback_;
-
   base::WeakPtrFactory<RenderWidgetHostViewAura> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index c966e46..3b9ba35a 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -39,6 +39,7 @@
 #include "components/viz/test/compositor_frame_helpers.h"
 #include "components/viz/test/fake_external_begin_frame_source.h"
 #include "components/viz/test/fake_surface_observer.h"
+#include "components/viz/test/test_latest_local_surface_id_lookup_delegate.h"
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/browser_thread_impl.h"
 #include "content/browser/compositor/test/test_image_transport_factory.h"
@@ -490,10 +491,16 @@
         is_guest_view_hack_(false) {}
 
   static void InstallDelegatedFrameHostClient(
-      RenderWidgetHostViewAura* render_widget_host_view,
+      RenderWidgetHostViewAura* view,
       std::unique_ptr<DelegatedFrameHostClient> delegated_frame_host_client) {
-    render_widget_host_view->delegated_frame_host_client_ =
-        std::move(delegated_frame_host_client);
+    view->delegated_frame_host_client_ = std::move(delegated_frame_host_client);
+    const bool enable_viz =
+        base::FeatureList::IsEnabled(features::kVizDisplayCompositor);
+    view->delegated_frame_host_ = nullptr;
+    view->delegated_frame_host_ = std::make_unique<DelegatedFrameHost>(
+        view->frame_sink_id_, view->delegated_frame_host_client_.get(),
+        features::IsSurfaceSynchronizationEnabled(), enable_viz,
+        false /* should_register_frame_sink_id */);
   }
 
   void SetUpEnvironment() {
@@ -640,8 +647,7 @@
     // First mock-focus the widget if not already.
     if (render_widget_host_delegate()->GetFocusedRenderWidgetHost(
             widget_host_) != view->GetRenderWidgetHost()) {
-      render_widget_host_delegate()->set_focused_widget(
-          view->GetRenderWidgetHostImpl());
+      render_widget_host_delegate()->set_focused_widget(view->host());
     }
 
     TextInputManager* manager =
@@ -5903,12 +5909,16 @@
                                MakeDelegatedFrame(1.f, frame_size, view_rect),
                                std::move(hit_test_region_list));
 
-  const viz::mojom::HitTestRegionList* active_hit_test_region_list =
+  viz::TestLatestLocalSurfaceIdLookupDelegate delegate;
+  delegate.SetSurfaceIdMap(
+      viz::SurfaceId(view_->GetFrameSinkId(), kArbitraryLocalSurfaceId));
+  viz::FrameSinkManagerImpl* frame_sink_manager =
       view_->GetDelegatedFrameHost()
           ->GetCompositorFrameSinkSupportForTesting()
-          ->frame_sink_manager()
-          ->hit_test_manager()
-          ->GetActiveHitTestRegionList(surface_id);
+          ->frame_sink_manager();
+  const viz::mojom::HitTestRegionList* active_hit_test_region_list =
+      frame_sink_manager->hit_test_manager()->GetActiveHitTestRegionList(
+          &delegate, surface_id.frame_sink_id());
   EXPECT_EQ(active_hit_test_region_list->flags, viz::mojom::kHitTestMine);
   EXPECT_EQ(active_hit_test_region_list->bounds, view_rect);
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 2e9574b..37da659 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -39,8 +39,9 @@
 
 namespace content {
 
-RenderWidgetHostViewBase::RenderWidgetHostViewBase()
-    : is_fullscreen_(false),
+RenderWidgetHostViewBase::RenderWidgetHostViewBase(RenderWidgetHost* host)
+    : host_(RenderWidgetHostImpl::From(host)),
+      is_fullscreen_(false),
       popup_type_(blink::kWebPopupTypeNone),
       mouse_locked_(false),
       current_device_scale_factor_(0),
@@ -69,14 +70,13 @@
 }
 
 RenderWidgetHostImpl* RenderWidgetHostViewBase::GetFocusedWidget() const {
-  RenderWidgetHostImpl* host = GetRenderWidgetHostImpl();
-  return host && host->delegate()
-             ? host->delegate()->GetFocusedRenderWidgetHost(host)
+  return host() && host()->delegate()
+             ? host()->delegate()->GetFocusedRenderWidgetHost(host())
              : nullptr;
 }
 
 RenderWidgetHost* RenderWidgetHostViewBase::GetRenderWidgetHost() const {
-  return GetRenderWidgetHostImpl();
+  return host();
 }
 
 void RenderWidgetHostViewBase::NotifyObserversAboutShutdown() {
@@ -227,9 +227,8 @@
 }
 
 void RenderWidgetHostViewBase::AccessibilityShowMenu(const gfx::Point& point) {
-  RenderWidgetHostImpl* impl = GetRenderWidgetHostImpl();
-  if (impl)
-    impl->ShowContextMenuAtPoint(point, ui::MENU_SOURCE_NONE);
+  if (host())
+    host()->ShowContextMenuAtPoint(point, ui::MENU_SOURCE_NONE);
 }
 
 gfx::Point RenderWidgetHostViewBase::AccessibilityOriginInScreen(
@@ -247,21 +246,13 @@
   return nullptr;
 }
 
-void RenderWidgetHostViewBase::CreateCompositorFrameSink(
-    CreateCompositorFrameSinkCallback callback) {
-  DCHECK(GetFrameSinkId().is_valid());
-  std::move(callback).Run(GetFrameSinkId());
-}
-
 void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) {
-  RenderWidgetHostImpl* impl = GetRenderWidgetHostImpl();
+  if (host() && host()->delegate())
+    host()->delegate()->SendScreenRects();
 
-  if (impl && impl->delegate())
-    impl->delegate()->SendScreenRects();
-
-  if (HasDisplayPropertyChanged(view) && impl) {
+  if (HasDisplayPropertyChanged(view) && host()) {
     OnSynchronizedDisplayPropertiesChanged();
-    impl->NotifyScreenInfoChanged();
+    host()->NotifyScreenInfoChanged();
   }
 }
 
@@ -312,9 +303,8 @@
 
 std::unique_ptr<SyntheticGestureTarget>
 RenderWidgetHostViewBase::CreateSyntheticGestureTarget() {
-  RenderWidgetHostImpl* host = GetRenderWidgetHostImpl();
   return std::unique_ptr<SyntheticGestureTarget>(
-      new SyntheticGestureTargetBase(host));
+      new SyntheticGestureTargetBase(host()));
 }
 
 void RenderWidgetHostViewBase::FocusedNodeTouched(
@@ -365,16 +355,10 @@
 void RenderWidgetHostViewBase::OnDidNavigateMainFrameToNewPage() {
 }
 
-RenderWidgetHostImpl* RenderWidgetHostViewBase::GetRenderWidgetHostImpl()
-    const {
-  return nullptr;
-}
-
 void RenderWidgetHostViewBase::OnFrameTokenChangedForView(
     uint32_t frame_token) {
-  RenderWidgetHostImpl* host = GetRenderWidgetHostImpl();
-  if (host)
-    host->DidProcessFrame(frame_token);
+  if (host())
+    host()->DidProcessFrame(frame_token);
 }
 
 viz::FrameSinkId RenderWidgetHostViewBase::GetFrameSinkId() {
@@ -423,30 +407,26 @@
     const blink::WebMouseEvent& event,
     const ui::LatencyInfo& latency) {
   PreProcessMouseEvent(event);
-  auto* host = GetRenderWidgetHostImpl();
-  host->ForwardMouseEventWithLatencyInfo(event, latency);
+  host()->ForwardMouseEventWithLatencyInfo(event, latency);
 }
 
 void RenderWidgetHostViewBase::ProcessMouseWheelEvent(
     const blink::WebMouseWheelEvent& event,
     const ui::LatencyInfo& latency) {
-  auto* host = GetRenderWidgetHostImpl();
-  host->ForwardWheelEventWithLatencyInfo(event, latency);
+  host()->ForwardWheelEventWithLatencyInfo(event, latency);
 }
 
 void RenderWidgetHostViewBase::ProcessTouchEvent(
     const blink::WebTouchEvent& event,
     const ui::LatencyInfo& latency) {
   PreProcessTouchEvent(event);
-  auto* host = GetRenderWidgetHostImpl();
-  host->ForwardTouchEventWithLatencyInfo(event, latency);
+  host()->ForwardTouchEventWithLatencyInfo(event, latency);
 }
 
 void RenderWidgetHostViewBase::ProcessGestureEvent(
     const blink::WebGestureEvent& event,
     const ui::LatencyInfo& latency) {
-  auto* host = GetRenderWidgetHostImpl();
-  host->ForwardGestureEventWithLatencyInfo(event, latency);
+  host()->ForwardGestureEventWithLatencyInfo(event, latency);
 }
 
 gfx::PointF RenderWidgetHostViewBase::TransformPointToRootCoordSpaceF(
@@ -487,6 +467,10 @@
   return true;
 }
 
+void RenderWidgetHostViewBase::Destroy() {
+  host_ = nullptr;
+}
+
 void RenderWidgetHostViewBase::TextInputStateChanged(
     const TextInputState& text_input_state) {
   if (GetTextInputManager())
@@ -511,13 +495,12 @@
   if (text_input_manager_)
     return text_input_manager_;
 
-  RenderWidgetHostImpl* host = GetRenderWidgetHostImpl();
-  if (!host || !host->delegate())
+  if (!host() || !host()->delegate())
     return nullptr;
 
   // This RWHV needs to be registered with the TextInputManager so that the
   // TextInputManager starts tracking its state, and observing its lifetime.
-  text_input_manager_ = host->delegate()->GetTextInputManager();
+  text_input_manager_ = host()->delegate()->GetTextInputManager();
   if (text_input_manager_)
     text_input_manager_->Register(this);
 
@@ -604,9 +587,8 @@
 
 void RenderWidgetHostViewBase::OnResizeDueToAutoResizeComplete(
     uint64_t sequence_number) {
-  RenderWidgetHostImpl* host = GetRenderWidgetHostImpl();
-  if (host)
-    host->DidAllocateLocalSurfaceIdForAutoResize(sequence_number);
+  if (host())
+    host()->DidAllocateLocalSurfaceIdForAutoResize(sequence_number);
 }
 
 #if defined(OS_MACOSX)
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h
index 543ce74f..e44d950 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -242,13 +242,6 @@
   virtual void FocusedNodeChanged(bool is_editable_node,
                                   const gfx::Rect& node_bounds_in_screen) {}
 
-  // This method is called by RenderWidgetHostImpl when the renderer has
-  // requested a CompositorFrameSink. The callback takes a FrameSinkId and
-  // fullfills the request. The default implementation will immediately run the
-  // callback with GetFrameSinkId().
-  virtual void CreateCompositorFrameSink(
-      CreateCompositorFrameSinkCallback callback);
-
   // This method is called by RenderWidgetHostImpl when a new
   // RendererCompositorFrameSink is created in the renderer. The view is
   // expected not to return resources belonging to the old
@@ -436,7 +429,7 @@
                                  int error_code) = 0;
 
   // Tells the View to destroy itself.
-  virtual void Destroy() = 0;
+  virtual void Destroy();
 
   // Tells the View that the tooltip text for the current mouse position over
   // the page has changed.
@@ -464,7 +457,7 @@
   virtual void SetShowingContextMenu(bool showing) {}
 
   // Returns the associated RenderWidgetHostImpl.
-  virtual RenderWidgetHostImpl* GetRenderWidgetHostImpl() const;
+  RenderWidgetHostImpl* host() const { return host_; }
 
   // Process swap messages sent before |frame_token| in RenderWidgetHostImpl.
   void OnFrameTokenChangedForView(uint32_t frame_token);
@@ -517,8 +510,7 @@
   virtual void OnRenderWidgetInit() {}
 
  protected:
-  // Interface class only, do not construct.
-  RenderWidgetHostViewBase();
+  explicit RenderWidgetHostViewBase(RenderWidgetHost* host);
 
   void NotifyObserversAboutShutdown();
 
@@ -530,6 +522,10 @@
   ui::mojom::WindowTreeClientPtr GetWindowTreeClientFromRenderer();
 #endif
 
+  // The model object. Members will become private when
+  // RenderWidgetHostViewGuest is removed.
+  RenderWidgetHostImpl* host_;
+
   // Is this a fullscreen view?
   bool is_fullscreen_;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
index 3944c22..6f871af2 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -65,7 +65,7 @@
 
 RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame(
     RenderWidgetHost* widget_host)
-    : host_(RenderWidgetHostImpl::From(widget_host)),
+    : RenderWidgetHostViewBase(widget_host),
       frame_sink_id_(
           base::checked_cast<uint32_t>(widget_host->GetProcess()->GetID()),
           base::checked_cast<uint32_t>(widget_host->GetRoutingID())),
@@ -104,7 +104,7 @@
 
 void RenderWidgetHostViewChildFrame::Init() {
   RegisterFrameSinkId();
-  host_->SetView(this);
+  host()->SetView(this);
   GetTextInputManager();
 }
 
@@ -225,7 +225,7 @@
   // Resizing happens in CrossProcessFrameConnector for child frames.
   if (rect != last_screen_rect_) {
     last_screen_rect_ = rect;
-    host_->SendScreenRects();
+    host()->SendScreenRects();
   }
 }
 
@@ -242,29 +242,29 @@
 }
 
 void RenderWidgetHostViewChildFrame::Show() {
-  if (!host_->is_hidden())
+  if (!host()->is_hidden())
     return;
 
   if (!CanBecomeVisible())
     return;
 
-  host_->WasShown(ui::LatencyInfo());
+  host()->WasShown(ui::LatencyInfo());
 
   if (frame_connector_)
     frame_connector_->SetVisibilityForChildViews(true);
 }
 
 void RenderWidgetHostViewChildFrame::Hide() {
-  if (host_->is_hidden())
+  if (host()->is_hidden())
     return;
-  host_->WasHidden();
+  host()->WasHidden();
 
   if (frame_connector_)
     frame_connector_->SetVisibilityForChildViews(false);
 }
 
 bool RenderWidgetHostViewChildFrame::IsShowing() {
-  return !host_->is_hidden();
+  return !host()->is_hidden();
 }
 
 gfx::Rect RenderWidgetHostViewChildFrame::GetViewBounds() const {
@@ -301,12 +301,13 @@
   // is that Blink ends up using the visual viewport to calculate things like
   // window.innerWidth/innerHeight for main frames, and a guest is considered
   // to be a main frame.  This should be cleaned up eventually.
-  bool is_guest = BrowserPluginGuest::IsGuest(RenderViewHostImpl::From(host_));
+  bool is_guest = BrowserPluginGuest::IsGuest(RenderViewHostImpl::From(host()));
   if (frame_connector_ && !is_guest) {
     // An auto-resize set by the top-level frame overrides what would be
     // reported by embedding RenderWidgetHostViews.
-    if (host_->delegate() && !host_->delegate()->GetAutoResizeSize().IsEmpty())
-      return host_->delegate()->GetAutoResizeSize();
+    if (host()->delegate() &&
+        !host()->delegate()->GetAutoResizeSize().IsEmpty())
+      return host()->delegate()->GetAutoResizeSize();
 
     RenderWidgetHostView* parent_view =
         frame_connector_->GetParentRenderWidgetHostView();
@@ -342,7 +343,7 @@
 
   DCHECK(SkColorGetA(color) == SK_AlphaOPAQUE ||
          SkColorGetA(color) == SK_AlphaTRANSPARENT);
-  host_->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE);
+  host()->SetBackgroundOpaque(SkColorGetA(color) == SK_AlphaOPAQUE);
 }
 
 SkColor RenderWidgetHostViewChildFrame::background_color() const {
@@ -379,7 +380,7 @@
   // inner/outer WebContents, only subframe's RenderWidgetHostView can be a
   // RenderWidgetHostViewChildFrame which do not get a SetIsLoading() call.
   if (GuestMode::IsCrossProcessFrameGuest(
-          WebContents::FromRenderViewHost(RenderViewHost::From(host_))))
+          WebContents::FromRenderViewHost(RenderViewHost::From(host()))))
     return;
 
   NOTREACHED();
@@ -407,8 +408,8 @@
   // RenderWidgetHostInputEventRouter afterwards.
   NotifyObserversAboutShutdown();
 
-  host_->SetView(nullptr);
-  host_ = nullptr;
+  host()->SetView(nullptr);
+  RenderWidgetHostViewBase::Destroy();
 
   delete this;
 }
@@ -426,18 +427,19 @@
 
 void RenderWidgetHostViewChildFrame::RegisterFrameSinkId() {
   // If Destroy() has been called before we get here, host_ may be null.
-  if (host_ && host_->delegate() && host_->delegate()->GetInputEventRouter()) {
+  if (host() && host()->delegate() &&
+      host()->delegate()->GetInputEventRouter()) {
     RenderWidgetHostInputEventRouter* router =
-        host_->delegate()->GetInputEventRouter();
+        host()->delegate()->GetInputEventRouter();
     if (!router->is_registered(frame_sink_id_))
       router->AddFrameSinkIdOwner(frame_sink_id_, this);
   }
 }
 
 void RenderWidgetHostViewChildFrame::UnregisterFrameSinkId() {
-  DCHECK(host_);
-  if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
-    host_->delegate()->GetInputEventRouter()->RemoveFrameSinkIdOwner(
+  DCHECK(host());
+  if (host()->delegate() && host()->delegate()->GetInputEventRouter()) {
+    host()->delegate()->GetInputEventRouter()->RemoveFrameSinkIdOwner(
         frame_sink_id_);
     DetachFromTouchSelectionClientManagerIfNecessary();
   }
@@ -446,23 +448,24 @@
 void RenderWidgetHostViewChildFrame::UpdateViewportIntersection(
     const gfx::Rect& viewport_intersection,
     const gfx::Rect& compositor_visible_rect) {
-  if (host_) {
-    host_->Send(new ViewMsg_SetViewportIntersection(
-        host_->GetRoutingID(), viewport_intersection, compositor_visible_rect));
+  if (host()) {
+    host()->Send(new ViewMsg_SetViewportIntersection(host()->GetRoutingID(),
+                                                     viewport_intersection,
+                                                     compositor_visible_rect));
   }
 }
 
 void RenderWidgetHostViewChildFrame::SetIsInert() {
-  if (host_ && frame_connector_) {
-    host_->Send(new ViewMsg_SetIsInert(host_->GetRoutingID(),
-                                       frame_connector_->IsInert()));
+  if (host() && frame_connector_) {
+    host()->Send(new ViewMsg_SetIsInert(host()->GetRoutingID(),
+                                        frame_connector_->IsInert()));
   }
 }
 
 void RenderWidgetHostViewChildFrame::UpdateRenderThrottlingStatus() {
-  if (host_ && frame_connector_) {
-    host_->Send(new ViewMsg_UpdateRenderThrottlingStatus(
-        host_->GetRoutingID(), frame_connector_->IsThrottled(),
+  if (host() && frame_connector_) {
+    host()->Send(new ViewMsg_UpdateRenderThrottlingStatus(
+        host()->GetRoutingID(), frame_connector_->IsThrottled(),
         frame_connector_->IsSubtreeThrottled()));
   }
 }
@@ -681,21 +684,16 @@
 }
 
 void RenderWidgetHostViewChildFrame::UnlockMouse() {
-  if (host_->delegate() && host_->delegate()->HasMouseLock(host_) &&
+  if (host()->delegate() && host()->delegate()->HasMouseLock(host()) &&
       frame_connector_)
     frame_connector_->UnlockMouse();
 }
 
 bool RenderWidgetHostViewChildFrame::IsMouseLocked() {
-  if (!host_->delegate())
+  if (!host()->delegate())
     return false;
 
-  return host_->delegate()->HasMouseLock(host_);
-}
-
-RenderWidgetHostImpl* RenderWidgetHostViewChildFrame::GetRenderWidgetHostImpl()
-    const {
-  return host_;
+  return host()->delegate()->HasMouseLock(host());
 }
 
 viz::FrameSinkId RenderWidgetHostViewChildFrame::GetFrameSinkId() {
@@ -1025,7 +1023,7 @@
     GetHostFrameSinkManager()->RegisterFrameSinkHierarchy(parent_frame_sink_id_,
                                                           frame_sink_id_);
   }
-  if (host_->needs_begin_frames())
+  if (host()->needs_begin_frames())
     support_->SetNeedsBeginFrame(true);
 }
 
@@ -1099,9 +1097,9 @@
 }
 
 void RenderWidgetHostViewChildFrame::DidNavigate() {
-  if (host_->auto_resize_enabled()) {
-    host_->DidAllocateLocalSurfaceIdForAutoResize(
-        host_->last_auto_resize_request_number());
+  if (host()->auto_resize_enabled()) {
+    host()->DidAllocateLocalSurfaceIdForAutoResize(
+        host()->last_auto_resize_request_number());
   }
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h
index 794ed5dd..7778bca 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.h
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -37,7 +37,6 @@
 namespace content {
 class FrameConnectorDelegate;
 class RenderWidgetHost;
-class RenderWidgetHostImpl;
 class RenderWidgetHostViewChildFrameTest;
 class RenderWidgetHostViewGuestSurfaceTest;
 class TouchSelectionControllerClientChildFrame;
@@ -142,7 +141,6 @@
   void DidStopFlinging() override;
   bool LockMouse() override;
   void UnlockMouse() override;
-  RenderWidgetHostImpl* GetRenderWidgetHostImpl() const override;
   viz::FrameSinkId GetFrameSinkId() override;
   viz::LocalSurfaceId GetLocalSurfaceId() const override;
   void PreProcessTouchEvent(const blink::WebTouchEvent& event) override;
@@ -256,9 +254,6 @@
   // The last scroll offset of the view.
   gfx::Vector2dF last_scroll_offset_;
 
-  // Members will become private when RenderWidgetHostViewGuest is removed.
-  // The model object.
-  RenderWidgetHostImpl* host_;
 
   // The ID for FrameSink associated with this view.
   viz::FrameSinkId frame_sink_id_;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index 90ccb0f..3630935e 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -36,7 +36,6 @@
 namespace content {
 class CursorManager;
 class RenderWidgetHost;
-class RenderWidgetHostImpl;
 class RenderWidgetHostViewMac;
 class RenderWidgetHostViewMacEditCommandHelper;
 class WebContents;
@@ -345,7 +344,6 @@
   std::unique_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
       override;
 
-  RenderWidgetHostImpl* GetRenderWidgetHostImpl() const override;
   viz::FrameSinkId GetFrameSinkId() override;
   viz::LocalSurfaceId GetLocalSurfaceId() const override;
   // Returns true when we can do SurfaceHitTesting for the event type.
@@ -435,10 +433,6 @@
   // These member variables should be private, but the associated ObjC class
   // needs access to them and can't be made a friend.
 
-  // The associated Model.  Can be NULL if Destroy() is called when
-  // someone (other than superview) has retained |cocoa_view_|.
-  RenderWidgetHostImpl* render_widget_host_;
-
   // The background CoreAnimation layer which is hosted by |cocoa_view_|.
   base::scoped_nsobject<CALayer> background_layer_;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 2e85512..8dfd38e 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -334,8 +334,7 @@
   // When making an element on the page fullscreen the element's background
   // may not match the page's, so use black as the gutter color to avoid
   // flashes of brighter colors during the transition.
-  if (render_widget_host_->delegate() &&
-      render_widget_host_->delegate()->IsFullscreenForCurrentTab()) {
+  if (host()->delegate() && host()->delegate()->IsFullscreenForCurrentTab()) {
     return SK_ColorBLACK;
   }
   return last_frame_root_background_color_;
@@ -350,7 +349,7 @@
 }
 
 void RenderWidgetHostViewMac::DidReceiveFirstFrameAfterNavigation() {
-  render_widget_host_->DidReceiveFirstFrameAfterNavigation();
+  host()->DidReceiveFirstFrameAfterNavigation();
 }
 
 void RenderWidgetHostViewMac::DestroyCompositorForShutdown() {
@@ -389,7 +388,7 @@
 
 RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
                                                  bool is_guest_view_hack)
-    : render_widget_host_(RenderWidgetHostImpl::From(widget)),
+    : RenderWidgetHostViewBase(widget),
       page_at_minimum_scale_(true),
       mouse_wheel_phase_handler_(this),
       is_loading_(false),
@@ -409,26 +408,24 @@
 
   viz::FrameSinkId frame_sink_id = is_guest_view_hack_
                                        ? AllocateFrameSinkIdForGuestViewHack()
-                                       : render_widget_host_->GetFrameSinkId();
+                                       : host()->GetFrameSinkId();
 
-  browser_compositor_.reset(
-      new BrowserCompositorMac(this, this, render_widget_host_->is_hidden(),
-                               [cocoa_view_ window], frame_sink_id));
+  browser_compositor_.reset(new BrowserCompositorMac(
+      this, this, host()->is_hidden(), [cocoa_view_ window], frame_sink_id));
 
   display::Screen::GetScreen()->AddObserver(this);
 
   if (!is_guest_view_hack_)
-    render_widget_host_->SetView(this);
+    host()->SetView(this);
 
   // Let the page-level input event router know about our surface ID
   // namespace for surface-based hit testing.
-  if (render_widget_host_->delegate() &&
-      render_widget_host_->delegate()->GetInputEventRouter()) {
-    render_widget_host_->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(
+  if (host()->delegate() && host()->delegate()->GetInputEventRouter()) {
+    host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(
         GetFrameSinkId(), this);
   }
 
-  RenderViewHost* rvh = RenderViewHost::From(render_widget_host_);
+  RenderViewHost* rvh = RenderViewHost::From(host());
   bool needs_begin_frames = true;
 
   if (rvh) {
@@ -470,12 +467,12 @@
   // We are owned by RenderWidgetHostViewCocoa, so if we go away before the
   // RenderWidgetHost does we need to tell it not to hold a stale pointer to
   // us.
-  if (render_widget_host_) {
+  if (host()) {
     // If this is a RenderWidgetHostViewGuest's platform_view_, we're not the
     // RWH's view, the RenderWidgetHostViewGuest is. So don't reset the RWH's
     // view, the RenderWidgetHostViewGuest will do it.
     if (!is_guest_view_hack_)
-      render_widget_host_->SetView(NULL);
+      host()->SetView(NULL);
   }
 
   // In case the view is deleted (by cocoa view) before calling destroy, we need
@@ -597,7 +594,7 @@
   // the rwhvmac: The PepperFlashFullscreenWindow retains cocoa_view_,
   // but cocoa_view_ keeps pepper_fullscreen_window_ in an instance variable.
   // This cycle is normally broken when -keyEvent: receives an <esc> key, which
-  // explicitly calls Shutdown on the render_widget_host_, which calls
+  // explicitly calls Shutdown on the host(), which calls
   // Destroy() on RWHVMac, which drops the reference to
   // pepper_fullscreen_window_.
   [[pepper_fullscreen_window_ contentView] addSubview:cocoa_view_];
@@ -649,7 +646,7 @@
 }
 
 void RenderWidgetHostViewMac::UpdateDisplayVSyncParameters() {
-  if (!render_widget_host_ || !display_link_.get())
+  if (!host() || !display_link_.get())
     return;
 
   if (!display_link_->GetVSyncParameters(&vsync_timebase_, &vsync_interval_)) {
@@ -677,7 +674,7 @@
 RenderWidgetHostViewMac::GetFocusedRenderWidgetHostDelegate() {
   if (auto* focused_widget = GetFocusedWidget())
     return focused_widget->delegate();
-  return render_widget_host_->delegate();
+  return host()->delegate();
 }
 
 void RenderWidgetHostViewMac::UpdateNSViewAndDisplayProperties() {
@@ -686,20 +683,20 @@
 
   // During auto-resize it is the responsibility of the caller to ensure that
   // the NSView and RenderWidgetHostImpl are kept in sync.
-  if (render_widget_host_->auto_resize_enabled())
+  if (host()->auto_resize_enabled())
     return;
 
-  if (render_widget_host_->delegate())
-    render_widget_host_->delegate()->SendScreenRects();
+  if (host()->delegate())
+    host()->delegate()->SendScreenRects();
   else
-    render_widget_host_->SendScreenRects();
+    host()->SendScreenRects();
 
   // RenderWidgetHostImpl will query BrowserCompositorMac for the dimensions
   // to send to the renderer, so it is required that BrowserCompositorMac be
   // updated first. Only notify RenderWidgetHostImpl of the update if any
   // properties it will query have changed.
   if (browser_compositor_->UpdateNSViewAndDisplay())
-    render_widget_host_->NotifyScreenInfoChanged();
+    host()->NotifyScreenInfoChanged();
 }
 
 void RenderWidgetHostViewMac::GetScreenInfo(ScreenInfo* screen_info) const {
@@ -713,16 +710,16 @@
   browser_compositor_->SetRenderWidgetHostIsHidden(false);
 
   ui::LatencyInfo renderer_latency_info;
-  renderer_latency_info.AddLatencyNumber(
-      ui::TAB_SHOW_COMPONENT, render_widget_host_->GetLatencyComponentId(), 0);
+  renderer_latency_info.AddLatencyNumber(ui::TAB_SHOW_COMPONENT,
+                                         host()->GetLatencyComponentId(), 0);
   renderer_latency_info.set_trace_id(++tab_show_sequence_);
-  render_widget_host_->WasShown(renderer_latency_info);
+  host()->WasShown(renderer_latency_info);
   TRACE_EVENT_ASYNC_BEGIN0("latency", "TabSwitching::Latency",
                            tab_show_sequence_);
 
   // If there is not a frame being currently drawn, kick one, so that the below
   // pause will have a frame to wait on.
-  render_widget_host_->ScheduleComposite();
+  host()->ScheduleComposite();
   PauseForPendingResizeOrRepaintsAndDraw();
 }
 
@@ -733,7 +730,7 @@
   ScopedCAActionDisabler disabler;
   [cocoa_view_ setHidden:YES];
 
-  render_widget_host_->WasHidden();
+  host()->WasHidden();
   browser_compositor_->SetRenderWidgetHostIsHidden(true);
 }
 
@@ -742,14 +739,14 @@
     return;
 
   browser_compositor_->SetRenderWidgetHostIsHidden(false);
-  render_widget_host_->WasShown(ui::LatencyInfo());
+  host()->WasShown(ui::LatencyInfo());
 }
 
 void RenderWidgetHostViewMac::WasOccluded() {
   if (!browser_compositor_)
     return;
 
-  render_widget_host_->WasHidden();
+  host()->WasHidden();
   browser_compositor_->SetRenderWidgetHostIsHidden(true);
 }
 
@@ -1026,11 +1023,11 @@
   pepper_fullscreen_window_.autorelease();
 
   // Delete the delegated frame state, which will reach back into
-  // render_widget_host_.
+  // host().
   browser_compositor_.reset();
 
   // Make sure none of our observers send events for us to process after
-  // we release render_widget_host_.
+  // we release host().
   NotifyObserversAboutShutdown();
 
   if (text_input_manager_)
@@ -1038,12 +1035,12 @@
 
   mouse_wheel_phase_handler_.IgnorePendingWheelEndEvent();
 
-  // We get this call just before |render_widget_host_| deletes
+  // We get this call just before host() deletes
   // itself.  But we are owned by |cocoa_view_|, which may be retained
   // by some other code.  Examples are WebContentsViewMac's
   // |latent_focus_view_| and TabWindowController's
   // |cachedContentView_|.
-  render_widget_host_ = NULL;
+  RenderWidgetHostViewBase::Destroy();
 }
 
 // Called from the renderer to tell us what the tooltip text should be. It
@@ -1096,13 +1093,12 @@
   if (!selection)
     return;
 
-  if (selection->selected_text().empty() && render_widget_host_) {
+  if (selection->selected_text().empty() && host()) {
     // TODO: This will not work with OOPIFs (https://crbug.com/659753).
     // If there's no selection, speak all text. Send an asynchronous IPC
     // request for fetching all the text for a webcontent.
     // ViewMsg_GetRenderedTextCompleted is sent back to IPC Message receiver.
-    render_widget_host_->Send(
-        new ViewMsg_GetRenderedText(render_widget_host_->GetRoutingID()));
+    host()->Send(new ViewMsg_GetRenderedText(host()->GetRoutingID()));
     return;
   }
 
@@ -1153,8 +1149,8 @@
 }
 
 void RenderWidgetHostViewMac::ForwardMouseEvent(const WebMouseEvent& event) {
-  if (render_widget_host_)
-    render_widget_host_->ForwardMouseEvent(event);
+  if (host())
+    host()->ForwardMouseEvent(event);
 
   if (event.GetType() == WebInputEvent::kMouseLeave) {
     [cocoa_view_ setToolTipAtMousePoint:nil];
@@ -1175,7 +1171,7 @@
     const gfx::Size& new_size,
     uint64_t sequence_number) {
   browser_compositor_->UpdateForAutoResize(new_size);
-  render_widget_host_->DidAllocateLocalSurfaceIdForAutoResize(sequence_number);
+  host()->DidAllocateLocalSurfaceIdForAutoResize(sequence_number);
 }
 
 void RenderWidgetHostViewMac::SetWantsAnimateOnlyBeginFrames() {
@@ -1287,8 +1283,7 @@
 }
 
 WebContents* RenderWidgetHostViewMac::GetWebContents() {
-  return WebContents::FromRenderViewHost(
-      RenderViewHost::From(render_widget_host_));
+  return WebContents::FromRenderViewHost(RenderViewHost::From(host()));
 }
 
 bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
@@ -1453,8 +1448,8 @@
   CGAssociateMouseAndMouseCursorPosition(YES);
   [NSCursor unhide];
 
-  if (render_widget_host_)
-    render_widget_host_->LostMouseLock();
+  if (host())
+    host()->LostMouseLock();
 }
 
 void RenderWidgetHostViewMac::GestureEventAck(
@@ -1485,10 +1480,6 @@
       new SyntheticGestureTargetMac(host, cocoa_view_));
 }
 
-RenderWidgetHostImpl* RenderWidgetHostViewMac::GetRenderWidgetHostImpl() const {
-  return render_widget_host_;
-}
-
 viz::LocalSurfaceId RenderWidgetHostViewMac::GetLocalSurfaceId() const {
   return browser_compositor_->GetRendererLocalSurfaceId();
 }
@@ -1505,8 +1496,7 @@
   DCHECK(WebInputEvent::IsMouseEventType(event.GetType()) ||
          event.GetType() == WebInputEvent::kMouseWheel ||
          WebInputEvent::IsPinchGestureEventType(event.GetType()));
-  return render_widget_host_->delegate() &&
-         render_widget_host_->delegate()->GetInputEventRouter();
+  return host()->delegate() && host()->delegate()->GetInputEventRouter();
 }
 
 void RenderWidgetHostViewMac::SendGesturePinchEvent(WebGestureEvent* event) {
@@ -1514,11 +1504,11 @@
   if (ShouldRouteEvent(*event)) {
     DCHECK(event->source_device ==
            blink::WebGestureDevice::kWebGestureDeviceTouchpad);
-    render_widget_host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
+    host()->delegate()->GetInputEventRouter()->RouteGestureEvent(
         this, event, ui::LatencyInfo(ui::SourceEventType::WHEEL));
     return;
   }
-  render_widget_host_->ForwardGestureEvent(*event);
+  host()->ForwardGestureEvent(*event);
 }
 
 bool RenderWidgetHostViewMac::TransformPointToLocalCoordSpace(
@@ -1560,26 +1550,26 @@
 }
 
 bool RenderWidgetHostViewMac::Send(IPC::Message* message) {
-  if (render_widget_host_)
-    return render_widget_host_->Send(message);
+  if (host())
+    return host()->Send(message);
   delete message;
   return false;
 }
 
 void RenderWidgetHostViewMac::ShutdownHost() {
   weak_factory_.InvalidateWeakPtrs();
-  render_widget_host_->ShutdownAndDestroyWidget(true);
+  host()->ShutdownAndDestroyWidget(true);
   // Do not touch any members at this point, |this| has been deleted.
 }
 
 void RenderWidgetHostViewMac::SetActive(bool active) {
-  if (render_widget_host_) {
-    render_widget_host_->SetActive(active);
+  if (host()) {
+    host()->SetActive(active);
     if (active) {
       if (HasFocus())
-        render_widget_host_->Focus();
+        host()->Focus();
     } else {
-      render_widget_host_->Blur();
+      host()->Blur();
     }
   }
   if (HasFocus())
@@ -1605,8 +1595,8 @@
   bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE;
   if (background_is_opaque_ != opaque) {
     background_is_opaque_ = opaque;
-    if (render_widget_host_)
-      render_widget_host_->SetBackgroundOpaque(opaque);
+    if (host())
+      host()->SetBackgroundOpaque(opaque);
   }
 }
 
@@ -1673,8 +1663,7 @@
 }
 
 void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() {
-  if (!render_widget_host_ || !browser_compositor_ ||
-      render_widget_host_->is_hidden()) {
+  if (!host() || !browser_compositor_ || host()->is_hidden()) {
     return;
   }
 
@@ -1684,9 +1673,8 @@
     return;
 
   // Wait for a frame of the right size to come in.
-  browser_compositor_->BeginPauseForFrame(
-      render_widget_host_->auto_resize_enabled());
-  render_widget_host_->PauseForPendingResizeOrRepaints();
+  browser_compositor_->BeginPauseForFrame(host()->auto_resize_enabled());
+  host()->PauseForPendingResizeOrRepaints();
   browser_compositor_->EndPauseForFrame();
 }
 
@@ -1908,7 +1896,7 @@
 
   if ([self shouldIgnoreMouseEvent:theEvent]) {
     // If this is the first such event, send a mouse exit to the host view.
-    if (!mouseEventWasIgnored_ && renderWidgetHostView_->render_widget_host_) {
+    if (!mouseEventWasIgnored_ && renderWidgetHostView_->host()) {
       WebMouseEvent exitEvent =
           WebMouseEventBuilder::Build(theEvent, self, pointerType_);
       exitEvent.SetType(WebInputEvent::kMouseLeave);
@@ -1922,7 +1910,7 @@
   if (mouseEventWasIgnored_) {
     // If this is the first mouse event after a previous event that was ignored
     // due to the hitTest, send a mouse enter event to the host view.
-    if (renderWidgetHostView_->render_widget_host_) {
+    if (renderWidgetHostView_->host()) {
       WebMouseEvent enterEvent =
           WebMouseEventBuilder::Build(theEvent, self, pointerType_);
       enterEvent.SetType(WebInputEvent::kMouseMove);
@@ -1930,7 +1918,8 @@
       ui::LatencyInfo latency_info(ui::SourceEventType::OTHER);
       latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
       if (renderWidgetHostView_->ShouldRouteEvent(enterEvent)) {
-        renderWidgetHostView_->render_widget_host_->delegate()
+        renderWidgetHostView_->host()
+            ->delegate()
             ->GetInputEventRouter()
             ->RouteMouseEvent(renderWidgetHostView_.get(), &enterEvent,
                               latency_info);
@@ -1970,7 +1959,8 @@
   ui::LatencyInfo latency_info(ui::SourceEventType::OTHER);
   latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
   if (renderWidgetHostView_->ShouldRouteEvent(event)) {
-    renderWidgetHostView_->render_widget_host_->delegate()
+    renderWidgetHostView_->host()
+        ->delegate()
         ->GetInputEventRouter()
         ->RouteMouseEvent(renderWidgetHostView_.get(), &event, latency_info);
   } else {
@@ -2079,7 +2069,7 @@
   // Don't cancel child popups; the key events are probably what's triggering
   // the popup in the first place.
 
-  RenderWidgetHostImpl* widgetHost = renderWidgetHostView_->render_widget_host_;
+  RenderWidgetHostImpl* widgetHost = renderWidgetHostView_->host();
   DCHECK(widgetHost);
 
   NativeWebKeyboardEvent event(theEvent);
@@ -2203,9 +2193,9 @@
 
   // Calling ForwardKeyboardEventWithCommands() could have destroyed the
   // widget. When the widget was destroyed,
-  // |renderWidgetHostView_->render_widget_host_| will be set to NULL. So we
+  // |renderWidgetHostView_->host()| will be set to NULL. So we
   // check it here and return immediately if it's NULL.
-  if (!renderWidgetHostView_->render_widget_host_)
+  if (!renderWidgetHostView_->host())
     return;
 
   // Then send keypress and/or composition related events.
@@ -2266,7 +2256,7 @@
     fake_event_latency_info.set_source_event_type(ui::SourceEventType::OTHER);
     widgetHost->ForwardKeyboardEventWithLatencyInfo(fakeEvent,
                                                     fake_event_latency_info);
-    // Not checking |renderWidgetHostView_->render_widget_host_| here because
+    // Not checking |renderWidgetHostView_->host()| here because
     // a key event with |skip_in_browser| == true won't be handled by browser,
     // thus it won't destroy the widget.
 
@@ -2275,9 +2265,9 @@
 
     // Calling ForwardKeyboardEventWithCommands() could have destroyed the
     // widget. When the widget was destroyed,
-    // |renderWidgetHostView_->render_widget_host_| will be set to NULL. So we
+    // |renderWidgetHostView_->host()| will be set to NULL. So we
     // check it here and return immediately if it's NULL.
-    if (!renderWidgetHostView_->render_widget_host_)
+    if (!renderWidgetHostView_->host())
       return;
   }
 
@@ -2323,7 +2313,7 @@
     return;
   }
 
-  if (renderWidgetHostView_->render_widget_host_) {
+  if (renderWidgetHostView_->host()) {
     // History-swiping is not possible if the logic reaches this point.
     WebMouseWheelEvent webEvent = WebMouseWheelEventBuilder::Build(
         event, self);
@@ -2334,8 +2324,8 @@
     } else {
       ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
       latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
-      renderWidgetHostView_->render_widget_host_
-          ->ForwardWheelEventWithLatencyInfo(webEvent, latency_info);
+      renderWidgetHostView_->host()->ForwardWheelEventWithLatencyInfo(
+          webEvent, latency_info);
     }
   }
 
@@ -2368,7 +2358,7 @@
       [event type] == NSEventTypeEndGesture) {
     gestureBeginEvent_.reset();
 
-    if (!renderWidgetHostView_->render_widget_host_)
+    if (!renderWidgetHostView_->host())
       return;
 
     if (gestureBeginPinchSent_) {
@@ -2433,9 +2423,8 @@
 - (void)smartMagnifyWithEvent:(NSEvent*)event {
   const WebGestureEvent& smartMagnifyEvent =
       WebGestureEventBuilder::Build(event, self);
-  if (renderWidgetHostView_ && renderWidgetHostView_->render_widget_host_) {
-    renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(
-        smartMagnifyEvent);
+  if (renderWidgetHostView_ && renderWidgetHostView_->host()) {
+    renderWidgetHostView_->host()->ForwardGestureEvent(smartMagnifyEvent);
   }
 }
 
@@ -2504,14 +2493,14 @@
 - (void)showLookUpDictionaryOverlayAtPoint:(NSPoint)point {
   gfx::PointF rootPoint(point.x, NSHeight([self frame]) - point.y);
   gfx::PointF transformedPoint;
-  if (!renderWidgetHostView_->render_widget_host_ ||
-      !renderWidgetHostView_->render_widget_host_->delegate() ||
-      !renderWidgetHostView_->render_widget_host_->delegate()
-           ->GetInputEventRouter())
+  if (!renderWidgetHostView_->host() ||
+      !renderWidgetHostView_->host()->delegate() ||
+      !renderWidgetHostView_->host()->delegate()->GetInputEventRouter())
     return;
 
   RenderWidgetHostImpl* widgetHost =
-      renderWidgetHostView_->render_widget_host_->delegate()
+      renderWidgetHostView_->host()
+          ->delegate()
           ->GetInputEventRouter()
           ->GetRenderWidgetHostAtPoint(renderWidgetHostView_.get(), rootPoint,
                                        &transformedPoint);
@@ -2613,7 +2602,7 @@
   }
 
   // This is responsible for content scrolling!
-  if (renderWidgetHostView_->render_widget_host_) {
+  if (renderWidgetHostView_->host()) {
     WebMouseWheelEvent webEvent = WebMouseWheelEventBuilder::Build(event, self);
     webEvent.rails_mode = mouseWheelFilter_.UpdateRailsMode(webEvent);
     ui::LatencyInfo latency_info(ui::SourceEventType::WHEEL);
@@ -2631,7 +2620,8 @@
     }
 
     if (renderWidgetHostView_->ShouldRouteEvent(webEvent)) {
-      renderWidgetHostView_->render_widget_host_->delegate()
+      renderWidgetHostView_->host()
+          ->delegate()
           ->GetInputEventRouter()
           ->RouteMouseWheelEvent(renderWidgetHostView_.get(), &webEvent,
                                  latency_info);
@@ -2643,7 +2633,7 @@
 
 // Called repeatedly during a pinch gesture, with incremental change values.
 - (void)magnifyWithEvent:(NSEvent*)event {
-  if (!renderWidgetHostView_->render_widget_host_)
+  if (!renderWidgetHostView_->host())
     return;
 
 #if defined(MAC_OS_X_VERSION_10_11) && \
@@ -2802,14 +2792,14 @@
 }
 
 - (BOOL)canBecomeKeyView {
-  if (!renderWidgetHostView_->render_widget_host_)
+  if (!renderWidgetHostView_->host())
     return NO;
 
   return canBeKeyView_;
 }
 
 - (BOOL)acceptsFirstResponder {
-  if (!renderWidgetHostView_->render_widget_host_)
+  if (!renderWidgetHostView_->host())
     return NO;
 
   return canBeKeyView_;
@@ -2840,12 +2830,12 @@
 }
 
 - (BOOL)becomeFirstResponder {
-  if (!renderWidgetHostView_->render_widget_host_)
+  if (!renderWidgetHostView_->host())
     return NO;
   if ([responderDelegate_ respondsToSelector:@selector(becomeFirstResponder)])
     [responderDelegate_ becomeFirstResponder];
 
-  renderWidgetHostView_->render_widget_host_->GotFocus();
+  renderWidgetHostView_->host()->GotFocus();
   renderWidgetHostView_->SetTextInputActive(true);
 
   // Cancel any onging composition text which was left before we lost focus.
@@ -2871,13 +2861,13 @@
   if ([responderDelegate_ respondsToSelector:@selector(resignFirstResponder)])
     [responderDelegate_ resignFirstResponder];
   renderWidgetHostView_->SetTextInputActive(false);
-  if (!renderWidgetHostView_->render_widget_host_)
+  if (!renderWidgetHostView_->host())
     return YES;
 
   if (closeOnDeactivate_)
     renderWidgetHostView_->KillSelf();
 
-  renderWidgetHostView_->render_widget_host_->LostFocus();
+  renderWidgetHostView_->host()->LostFocus();
 
   // We should cancel any onging composition whenever RWH's Blur() method gets
   // called, because in this case, webkit will confirm the ongoing composition
@@ -2901,8 +2891,7 @@
 
   SEL action = [item action];
   BOOL is_render_view =
-      RenderViewHost::From(renderWidgetHostView_->render_widget_host_) !=
-      nullptr;
+      RenderViewHost::From(renderWidgetHostView_->host()) != nullptr;
 
   if (action == @selector(stopSpeaking:))
     return is_render_view && ui::TextServicesContextMenu::IsSpeaking();
@@ -2960,8 +2949,7 @@
 
 - (id)accessibilityAttributeValue:(NSString *)attribute {
   BrowserAccessibilityManager* manager =
-      renderWidgetHostView_->render_widget_host_
-          ->GetRootBrowserAccessibilityManager();
+      renderWidgetHostView_->host()->GetRootBrowserAccessibilityManager();
 
   // Contents specifies document view of RenderWidgetHostViewCocoa provided by
   // BrowserAccessibilityManager. Children includes all subviews in addition to
@@ -2987,8 +2975,7 @@
 
 - (id)accessibilityHitTest:(NSPoint)point {
   BrowserAccessibilityManager* manager =
-      renderWidgetHostView_->render_widget_host_
-          ->GetRootBrowserAccessibilityManager();
+      renderWidgetHostView_->host()->GetRootBrowserAccessibilityManager();
   if (!manager)
     return self;
   NSPoint pointInWindow =
@@ -3003,15 +2990,13 @@
 
 - (BOOL)accessibilityIsIgnored {
   BrowserAccessibilityManager* manager =
-      renderWidgetHostView_->render_widget_host_
-          ->GetRootBrowserAccessibilityManager();
+      renderWidgetHostView_->host()->GetRootBrowserAccessibilityManager();
   return !manager;
 }
 
 - (NSUInteger)accessibilityGetIndexOf:(id)child {
   BrowserAccessibilityManager* manager =
-      renderWidgetHostView_->render_widget_host_
-          ->GetRootBrowserAccessibilityManager();
+      renderWidgetHostView_->host()->GetRootBrowserAccessibilityManager();
   // Only child is root.
   if (manager &&
       ToBrowserAccessibilityCocoa(manager->GetRoot()) == child) {
@@ -3023,8 +3008,7 @@
 
 - (id)accessibilityFocusedUIElement {
   BrowserAccessibilityManager* manager =
-      renderWidgetHostView_->render_widget_host_
-          ->GetRootBrowserAccessibilityManager();
+      renderWidgetHostView_->host()->GetRootBrowserAccessibilityManager();
   if (manager) {
     BrowserAccessibility* focused_item = manager->GetFocus();
     DCHECK(focused_item);
@@ -3120,16 +3104,16 @@
   thePoint = [self convertPoint:thePoint fromView:nil];
   thePoint.y = NSHeight([self frame]) - thePoint.y;
 
-  if (!renderWidgetHostView_->render_widget_host_ ||
-      !renderWidgetHostView_->render_widget_host_->delegate() ||
-      !renderWidgetHostView_->render_widget_host_->delegate()
-           ->GetInputEventRouter())
+  if (!renderWidgetHostView_->host() ||
+      !renderWidgetHostView_->host()->delegate() ||
+      !renderWidgetHostView_->host()->delegate()->GetInputEventRouter())
     return NSNotFound;
 
   gfx::PointF rootPoint(thePoint.x, thePoint.y);
   gfx::PointF transformedPoint;
   RenderWidgetHostImpl* widgetHost =
-      renderWidgetHostView_->render_widget_host_->delegate()
+      renderWidgetHostView_->host()
+          ->delegate()
           ->GetInputEventRouter()
           ->GetRenderWidgetHostAtPoint(renderWidgetHostView_.get(), rootPoint,
                                        &transformedPoint);
@@ -3167,7 +3151,7 @@
 - (NSRect)firstRectForCharacterRange:(NSRange)theRange
                          actualRange:(NSRangePointer)actualRange {
   // During tab closure, events can arrive after RenderWidgetHostViewMac::
-  // Destroy() is called, which will have set |render_widget_host_| to null.
+  // Destroy() is called, which will have set |host()| to null.
   if (!renderWidgetHostView_->GetFocusedWidget()) {
     [self cancelComposition];
     return NSZeroRect;
@@ -3375,9 +3359,9 @@
                           base::CompareCase::INSENSITIVE_ASCII))
       editCommands_.push_back(EditCommand(command, ""));
   } else {
-    if (renderWidgetHostView_->render_widget_host_->delegate()) {
-      renderWidgetHostView_->render_widget_host_->delegate()
-          ->ExecuteEditCommand(command, base::nullopt);
+    if (renderWidgetHostView_->host()->delegate()) {
+      renderWidgetHostView_->host()->delegate()->ExecuteEditCommand(
+          command, base::nullopt);
     }
   }
 }
diff --git a/content/browser/renderer_host/render_widget_targeter.cc b/content/browser/renderer_host/render_widget_targeter.cc
index 2282465f..59724f3c 100644
--- a/content/browser/renderer_host/render_widget_targeter.cc
+++ b/content/browser/renderer_host/render_widget_targeter.cc
@@ -178,8 +178,7 @@
   DCHECK(!request_in_flight_);
 
   request_in_flight_ = true;
-  auto* target_client =
-      target->GetRenderWidgetHostImpl()->input_target_client();
+  auto* target_client = target->host()->input_target_client();
   TracingUmaTracker tracker("Event.AsyncTargeting.ResponseTime",
                             "input,latency");
     async_hit_test_timeout_.reset(new OneShotTimeoutMonitor(
diff --git a/content/browser/renderer_interface_binders.cc b/content/browser/renderer_interface_binders.cc
index f5297f5..9b1c71bd 100644
--- a/content/browser/renderer_interface_binders.cc
+++ b/content/browser/renderer_interface_binders.cc
@@ -125,9 +125,9 @@
   parameterized_binder_registry_.AddInterface(
       base::Bind(&ForwardServiceRequest<device::mojom::VibrationManager>,
                  device::mojom::kServiceName));
-  parameterized_binder_registry_.AddInterface(base::BindRepeating(
-      [](network::mojom::WebSocketRequest request, RenderProcessHost* host,
-         const url::Origin& origin) {
+  parameterized_binder_registry_.AddInterface(
+      base::Bind([](blink::mojom::WebSocketRequest request,
+                    RenderProcessHost* host, const url::Origin& origin) {
         WebSocketManager::CreateWebSocketWithOrigin(
             host->GetID(), origin, std::move(request), MSG_ROUTING_NONE);
       }));
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index 8da1bff..b13d0816 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -10,7 +10,6 @@
 #include "base/feature_list.h"
 #include "base/json/json_reader.h"
 #include "base/test/bind_test_util.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/test_timeouts.h"
 #include "build/build_config.h"
 #include "components/viz/common/features.h"
@@ -1878,17 +1877,12 @@
     EXPECT_EQ("\"scroll: 3\"", reply);
   }
 
- protected:
-  base::test::ScopedFeatureList feature_list_;
-
  private:
   RenderWidgetHostViewAura* rwhv_root_;
 };
 
 IN_PROC_BROWSER_TEST_P(SitePerProcessMouseWheelHitTestBrowserTest,
                        SubframeWheelEventsOnMainThread) {
-  feature_list_.InitWithFeatures({}, {features::kTouchpadAndWheelScrollLatching,
-                                      features::kAsyncWheelEvents});
   GURL main_url(embedded_test_server()->GetURL(
       "/frame_tree/page_with_positioned_nested_frames.html"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1904,8 +1898,6 @@
   // surface information required for event hit testing is ready.
   RenderWidgetHostViewBase* child_rwhv = static_cast<RenderWidgetHostViewBase*>(
       root->child_at(0)->current_frame_host()->GetView());
-
-  EXPECT_FALSE(child_rwhv->wheel_scroll_latching_enabled());
   WaitForChildFrameSurfaceReady(root->child_at(0)->current_frame_host());
 
   content::RenderFrameHostImpl* child = root->child_at(0)->current_frame_host();
@@ -1921,8 +1913,6 @@
 // the same page loaded in the mainframe.
 IN_PROC_BROWSER_TEST_P(SitePerProcessMouseWheelHitTestBrowserTest,
                        MainframeWheelEventsOnMainThread) {
-  feature_list_.InitWithFeatures({}, {features::kTouchpadAndWheelScrollLatching,
-                                      features::kAsyncWheelEvents});
   GURL main_url(
       embedded_test_server()->GetURL("/page_with_scrollable_div.html"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -1931,9 +1921,6 @@
   content::RenderFrameHostImpl* rfhi = root->current_frame_host();
   SetupWheelAndScrollHandlers(rfhi);
 
-  EXPECT_FALSE(
-      rfhi->GetRenderWidgetHost()->GetView()->wheel_scroll_latching_enabled());
-
   gfx::Point pos(10, 10);
 
   RunTest(pos, rfhi->GetRenderWidgetHost()->GetView());
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
index dba83c73..9ffb3e4 100644
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -563,7 +563,8 @@
 
   static_cast<WebContentsImpl*>(web_contents_)
       ->RequestAXTreeSnapshot(
-          base::BindOnce(&AXTreeSnapshotCallback, j_callback));
+          base::BindOnce(&AXTreeSnapshotCallback, j_callback),
+          ui::kAXModeComplete);
 }
 
 ScopedJavaLocalRef<jstring> WebContentsAndroid::GetEncoding(
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 6841945..827b7699 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -219,41 +219,6 @@
   static_cast<RenderFrameHostImpl*>(rfh)->AccessibilityReset();
 }
 
-using AXTreeSnapshotCallback = WebContents::AXTreeSnapshotCallback;
-
-// Helper class used by WebContentsImpl::RequestAXTreeSnapshot.
-// Handles the callbacks from parallel snapshot requests to each frame,
-// and feeds the results to an AXTreeCombiner, which converts them into a
-// single combined accessibility tree.
-class AXTreeSnapshotCombiner : public base::RefCounted<AXTreeSnapshotCombiner> {
- public:
-  explicit AXTreeSnapshotCombiner(AXTreeSnapshotCallback callback)
-      : callback_(std::move(callback)) {}
-
-  AXTreeSnapshotCallback AddFrame(bool is_root) {
-    // Adds a reference to |this|.
-    return base::BindOnce(&AXTreeSnapshotCombiner::ReceiveSnapshot, this,
-                          is_root);
-  }
-
-  void ReceiveSnapshot(bool is_root, const ui::AXTreeUpdate& snapshot) {
-    combiner_.AddTree(snapshot, is_root);
-  }
-
- private:
-  friend class base::RefCounted<AXTreeSnapshotCombiner>;
-
-  // This is called automatically after the last call to ReceiveSnapshot
-  // when there are no more references to this object.
-  ~AXTreeSnapshotCombiner() {
-    combiner_.Combine();
-    std::move(callback_).Run(combiner_.combined());
-  }
-
-  ui::AXTreeCombiner combiner_;
-  AXTreeSnapshotCallback callback_;
-};
-
 // Helper for GetInnerWebContents().
 bool GetInnerWebContentsHelper(
     std::vector<WebContentsImpl*>* all_guest_contents,
@@ -1072,17 +1037,68 @@
   SetAccessibilityMode(new_mode);
 }
 
-void WebContentsImpl::RequestAXTreeSnapshot(AXTreeSnapshotCallback callback) {
+// Helper class used by WebContentsImpl::RequestAXTreeSnapshot.
+// Handles the callbacks from parallel snapshot requests to each frame,
+// and feeds the results to an AXTreeCombiner, which converts them into a
+// single combined accessibility tree.
+class WebContentsImpl::AXTreeSnapshotCombiner
+    : public base::RefCounted<AXTreeSnapshotCombiner> {
+ public:
+  explicit AXTreeSnapshotCombiner(AXTreeSnapshotCallback callback)
+      : callback_(std::move(callback)) {}
+
+  AXTreeSnapshotCallback AddFrame(bool is_root) {
+    // Adds a reference to |this|.
+    return base::BindOnce(&AXTreeSnapshotCombiner::ReceiveSnapshot, this,
+                          is_root);
+  }
+
+  void ReceiveSnapshot(bool is_root, const ui::AXTreeUpdate& snapshot) {
+    combiner_.AddTree(snapshot, is_root);
+  }
+
+ private:
+  friend class base::RefCounted<AXTreeSnapshotCombiner>;
+
+  // This is called automatically after the last call to ReceiveSnapshot
+  // when there are no more references to this object.
+  ~AXTreeSnapshotCombiner() {
+    combiner_.Combine();
+    std::move(callback_).Run(combiner_.combined());
+  }
+
+  ui::AXTreeCombiner combiner_;
+  AXTreeSnapshotCallback callback_;
+};
+
+void WebContentsImpl::RequestAXTreeSnapshot(AXTreeSnapshotCallback callback,
+                                            ui::AXMode ax_mode) {
   // Send a request to each of the frames in parallel. Each one will return
   // an accessibility tree snapshot, and AXTreeSnapshotCombiner will combine
   // them into a single tree and call |callback| with that result, then
   // delete |combiner|.
+  FrameTreeNode* root_node = frame_tree_.root();
   AXTreeSnapshotCombiner* combiner =
       new AXTreeSnapshotCombiner(std::move(callback));
+
+  RecursiveRequestAXTreeSnapshotOnFrame(root_node, combiner, ax_mode);
+}
+
+void WebContentsImpl::RecursiveRequestAXTreeSnapshotOnFrame(
+    FrameTreeNode* root_node,
+    AXTreeSnapshotCombiner* combiner,
+    ui::AXMode ax_mode) {
   for (FrameTreeNode* frame_tree_node : frame_tree_.Nodes()) {
-    bool is_root = frame_tree_node->parent() == nullptr;
-    frame_tree_node->current_frame_host()->RequestAXTreeSnapshot(
-        combiner->AddFrame(is_root));
+    WebContentsImpl* inner_contents =
+        node_.GetInnerWebContentsInFrame(frame_tree_node);
+    if (inner_contents) {
+      inner_contents->RecursiveRequestAXTreeSnapshotOnFrame(root_node, combiner,
+                                                            ax_mode);
+    } else {
+      bool is_root = frame_tree_node == root_node;
+      frame_tree_node->current_frame_host()->RequestAXTreeSnapshot(
+          combiner->AddFrame(is_root), ax_mode);
+    }
   }
 }
 
@@ -2562,8 +2578,7 @@
     widget_host_view->InitAsPopup(view, initial_rect);
   }
 
-  RenderWidgetHostImpl* render_widget_host_impl =
-      widget_host_view->GetRenderWidgetHostImpl();
+  RenderWidgetHostImpl* render_widget_host_impl = widget_host_view->host();
   render_widget_host_impl->Init();
   // Only allow privileged mouse lock for fullscreen render widget, which is
   // used to implement Pepper Flash fullscreen.
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 4ef121b..6d682fb4 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -341,7 +341,8 @@
   bool IsWaitingForResponse() const override;
   const net::LoadStateWithParam& GetLoadState() const override;
   const base::string16& GetLoadStateHost() const override;
-  void RequestAXTreeSnapshot(AXTreeSnapshotCallback callback) override;
+  void RequestAXTreeSnapshot(AXTreeSnapshotCallback callback,
+                             ui::AXMode ax_mode) override;
   uint64_t GetUploadSize() const override;
   uint64_t GetUploadPosition() const override;
   const std::string& GetEncoding() const override;
@@ -1348,6 +1349,11 @@
   // See also UpdateTargetURL.
   void ClearTargetURL();
 
+  class AXTreeSnapshotCombiner;
+  void RecursiveRequestAXTreeSnapshotOnFrame(FrameTreeNode* root_node,
+                                             AXTreeSnapshotCombiner* combiner,
+                                             ui::AXMode ax_mode);
+
   // Data for core operation ---------------------------------------------------
 
   // Delegate for notifying our owner about stuff. Not owned by us.
diff --git a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
index 3f07d2a..254ff38 100644
--- a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
+++ b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -259,16 +259,9 @@
   ExecuteJavascriptAndWaitForOk("getUserMediaAndClone();");
 }
 
-// http://crbug.com/803516 : Flaky on Linux debug
-#if defined(OS_LINUX) && !defined(NDEBUG)
-#define MAYBE_RenderVideoTrackInMultipleTagsAndPause \
-  DISABLED_RenderVideoTrackInMultipleTagsAndPause
-#else
-#define MAYBE_RenderVideoTrackInMultipleTagsAndPause \
-  RenderVideoTrackInMultipleTagsAndPause
-#endif
+// TODO(crbug.com/803516) : Flaky on all platforms.
 IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
-                       MAYBE_RenderVideoTrackInMultipleTagsAndPause) {
+                       DISABLED_RenderVideoTrackInMultipleTagsAndPause) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
diff --git a/content/browser/websockets/README.md b/content/browser/websockets/README.md
index 80f5e442..6f77941 100644
--- a/content/browser/websockets/README.md
+++ b/content/browser/websockets/README.md
@@ -1,5 +1,5 @@
 # WebSocket service
 
-This directory contains the network::mojom::WebSocket implementation. It hosts
+This directory contains the blink::mojom::WebSocket implementation. It hosts
 the WebSocket API implementations in Blink over Mojo, and exports the WebSocket
 protocol implementation in net/websockets/ as a service.
diff --git a/content/browser/websockets/websocket_impl.cc b/content/browser/websockets/websocket_impl.cc
index 533fc04..7fe3088 100644
--- a/content/browser/websockets/websocket_impl.cc
+++ b/content/browser/websockets/websocket_impl.cc
@@ -44,38 +44,38 @@
 
 typedef net::WebSocketEventInterface::ChannelState ChannelState;
 
-// Convert a network::mojom::WebSocketMessageType to a
+// Convert a blink::mojom::WebSocketMessageType to a
 // net::WebSocketFrameHeader::OpCode
 net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
-    network::mojom::WebSocketMessageType type) {
-  DCHECK(type == network::mojom::WebSocketMessageType::CONTINUATION ||
-         type == network::mojom::WebSocketMessageType::TEXT ||
-         type == network::mojom::WebSocketMessageType::BINARY);
+    blink::mojom::WebSocketMessageType type) {
+  DCHECK(type == blink::mojom::WebSocketMessageType::CONTINUATION ||
+         type == blink::mojom::WebSocketMessageType::TEXT ||
+         type == blink::mojom::WebSocketMessageType::BINARY);
   typedef net::WebSocketFrameHeader::OpCode OpCode;
   // These compile asserts verify that the same underlying values are used for
   // both types, so we can simply cast between them.
   static_assert(
-      static_cast<OpCode>(network::mojom::WebSocketMessageType::CONTINUATION) ==
+      static_cast<OpCode>(blink::mojom::WebSocketMessageType::CONTINUATION) ==
           net::WebSocketFrameHeader::kOpCodeContinuation,
       "enum values must match for opcode continuation");
   static_assert(
-      static_cast<OpCode>(network::mojom::WebSocketMessageType::TEXT) ==
+      static_cast<OpCode>(blink::mojom::WebSocketMessageType::TEXT) ==
           net::WebSocketFrameHeader::kOpCodeText,
       "enum values must match for opcode text");
   static_assert(
-      static_cast<OpCode>(network::mojom::WebSocketMessageType::BINARY) ==
+      static_cast<OpCode>(blink::mojom::WebSocketMessageType::BINARY) ==
           net::WebSocketFrameHeader::kOpCodeBinary,
       "enum values must match for opcode binary");
   return static_cast<OpCode>(type);
 }
 
-network::mojom::WebSocketMessageType OpCodeToMessageType(
+blink::mojom::WebSocketMessageType OpCodeToMessageType(
     net::WebSocketFrameHeader::OpCode opCode) {
   DCHECK(opCode == net::WebSocketFrameHeader::kOpCodeContinuation ||
          opCode == net::WebSocketFrameHeader::kOpCodeText ||
          opCode == net::WebSocketFrameHeader::kOpCodeBinary);
   // This cast is guaranteed valid by the static_assert() statements above.
-  return static_cast<network::mojom::WebSocketMessageType>(opCode);
+  return static_cast<blink::mojom::WebSocketMessageType>(opCode);
 }
 
 }  // namespace
@@ -257,12 +257,12 @@
   if (!should_send)
     return WebSocketEventInterface::CHANNEL_ALIVE;
 
-  network::mojom::WebSocketHandshakeRequestPtr request_to_pass(
-      network::mojom::WebSocketHandshakeRequest::New());
+  blink::mojom::WebSocketHandshakeRequestPtr request_to_pass(
+      blink::mojom::WebSocketHandshakeRequest::New());
   request_to_pass->url.Swap(&request->url);
   net::HttpRequestHeaders::Iterator it(request->headers);
   while (it.GetNext()) {
-    network::mojom::HttpHeaderPtr header(network::mojom::HttpHeader::New());
+    blink::mojom::HttpHeaderPtr header(blink::mojom::HttpHeader::New());
     header->name = it.name();
     header->value = it.value();
     request_to_pass->headers.push_back(std::move(header));
@@ -289,15 +289,15 @@
   if (!should_send)
     return WebSocketEventInterface::CHANNEL_ALIVE;
 
-  network::mojom::WebSocketHandshakeResponsePtr response_to_pass(
-      network::mojom::WebSocketHandshakeResponse::New());
+  blink::mojom::WebSocketHandshakeResponsePtr response_to_pass(
+      blink::mojom::WebSocketHandshakeResponse::New());
   response_to_pass->url.Swap(&response->url);
   response_to_pass->status_code = response->status_code;
   response_to_pass->status_text = response->status_text;
   size_t iter = 0;
   std::string name, value;
   while (response->headers->EnumerateHeaderLines(&iter, &name, &value)) {
-    network::mojom::HttpHeaderPtr header(network::mojom::HttpHeader::New());
+    blink::mojom::HttpHeaderPtr header(blink::mojom::HttpHeader::New());
     header->name = name;
     header->value = value;
     response_to_pass->headers.push_back(std::move(header));
@@ -362,7 +362,7 @@
 }
 
 WebSocketImpl::WebSocketImpl(Delegate* delegate,
-                             network::mojom::WebSocketRequest request,
+                             blink::mojom::WebSocketRequest request,
                              int child_id,
                              int frame_id,
                              url::Origin origin,
@@ -392,7 +392,7 @@
     const std::vector<std::string>& requested_protocols,
     const GURL& site_for_cookies,
     const std::string& user_agent_override,
-    network::mojom::WebSocketClientPtr client) {
+    blink::mojom::WebSocketClientPtr client) {
   DVLOG(3) << "WebSocketImpl::AddChannelRequest @"
            << reinterpret_cast<void*>(this) << " socket_url=\"" << socket_url
            << "\" requested_protocols=\""
@@ -425,7 +425,7 @@
 }
 
 void WebSocketImpl::SendFrame(bool fin,
-                              network::mojom::WebSocketMessageType type,
+                              blink::mojom::WebSocketMessageType type,
                               const std::vector<uint8_t>& data) {
   DVLOG(3) << "WebSocketImpl::SendFrame @"
            << reinterpret_cast<void*>(this) << " fin=" << fin
diff --git a/content/browser/websockets/websocket_impl.h b/content/browser/websockets/websocket_impl.h
index c5136fad..996a443c 100644
--- a/content/browser/websockets/websocket_impl.h
+++ b/content/browser/websockets/websocket_impl.h
@@ -16,7 +16,7 @@
 #include "base/time/time.h"
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "services/network/public/mojom/websocket.mojom.h"
+#include "third_party/WebKit/public/platform/modules/websockets/websocket.mojom.h"
 #include "url/origin.h"
 
 class GURL;
@@ -29,7 +29,7 @@
 namespace content {
 
 // Host of net::WebSocketChannel.
-class CONTENT_EXPORT WebSocketImpl : public network::mojom::WebSocket {
+class CONTENT_EXPORT WebSocketImpl : public blink::mojom::WebSocket {
  public:
   class Delegate {
    public:
@@ -41,7 +41,7 @@
   };
 
   WebSocketImpl(Delegate* delegate,
-                network::mojom::WebSocketRequest request,
+                blink::mojom::WebSocketRequest request,
                 int child_id,
                 int frame_id,
                 url::Origin origin,
@@ -52,14 +52,14 @@
   // This function is virtual for testing.
   virtual void GoAway();
 
-  // network::mojom::WebSocket methods:
+  // blink::mojom::WebSocket methods:
   void AddChannelRequest(const GURL& url,
                          const std::vector<std::string>& requested_protocols,
                          const GURL& site_for_cookies,
                          const std::string& user_agent_override,
-                         network::mojom::WebSocketClientPtr client) override;
+                         blink::mojom::WebSocketClientPtr client) override;
   void SendFrame(bool fin,
-                 network::mojom::WebSocketMessageType type,
+                 blink::mojom::WebSocketMessageType type,
                  const std::vector<uint8_t>& data) override;
   void SendFlowControl(int64_t quota) override;
   void StartClosingHandshake(uint16_t code, const std::string& reason) override;
@@ -77,9 +77,9 @@
                   const std::string& user_agent_override);
 
   Delegate* delegate_;
-  mojo::Binding<network::mojom::WebSocket> binding_;
+  mojo::Binding<blink::mojom::WebSocket> binding_;
 
-  network::mojom::WebSocketClientPtr client_;
+  blink::mojom::WebSocketClientPtr client_;
 
   // The channel we use to send events to the network.
   std::unique_ptr<net::WebSocketChannel> channel_;
diff --git a/content/browser/websockets/websocket_manager.cc b/content/browser/websockets/websocket_manager.cc
index 8bfd0bbe..ce41b4a 100644
--- a/content/browser/websockets/websocket_manager.cc
+++ b/content/browser/websockets/websocket_manager.cc
@@ -58,7 +58,7 @@
 void WebSocketManager::CreateWebSocketForFrame(
     int process_id,
     int frame_id,
-    network::mojom::WebSocketRequest request) {
+    blink::mojom::WebSocketRequest request) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // ForFrame() implies a frame: DCHECK this pre-condition.
@@ -73,7 +73,7 @@
 void WebSocketManager::CreateWebSocketWithOrigin(
     int process_id,
     url::Origin origin,
-    network::mojom::WebSocketRequest request,
+    blink::mojom::WebSocketRequest request,
     int frame_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
@@ -138,20 +138,20 @@
 void WebSocketManager::DoCreateWebSocket(
     int frame_id,
     url::Origin origin,
-    network::mojom::WebSocketRequest request) {
+    blink::mojom::WebSocketRequest request) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
   if (num_pending_connections_ >= kMaxPendingWebSocketConnections) {
     // Too many websockets!
     request.ResetWithReason(
-        network::mojom::WebSocket::kInsufficientResources,
+        blink::mojom::WebSocket::kInsufficientResources,
         "Error in connection establishment: net::ERR_INSUFFICIENT_RESOURCES");
     return;
   }
 
   if (context_destroyed_) {
     request.ResetWithReason(
-        network::mojom::WebSocket::kInsufficientResources,
+        blink::mojom::WebSocket::kInsufficientResources,
         "Error in connection establishment: net::ERR_UNEXPECTED");
     return;
   }
@@ -202,7 +202,7 @@
 
 WebSocketImpl* WebSocketManager::CreateWebSocketImpl(
     WebSocketImpl::Delegate* delegate,
-    network::mojom::WebSocketRequest request,
+    blink::mojom::WebSocketRequest request,
     int child_id,
     int frame_id,
     url::Origin origin,
diff --git a/content/browser/websockets/websocket_manager.h b/content/browser/websockets/websocket_manager.h
index 4f635f8f..db02e6c 100644
--- a/content/browser/websockets/websocket_manager.h
+++ b/content/browser/websockets/websocket_manager.h
@@ -30,15 +30,14 @@
   // Called on the UI thread: create a websocket for a frame.
   static void CreateWebSocketForFrame(int process_id,
                                       int frame_id,
-                                      network::mojom::WebSocketRequest request);
+                                      blink::mojom::WebSocketRequest request);
 
   // Called on the UI thread: create a websocket for a worker. Web workers of
   // any type (dedicated, shared, service worker) do not have a frame.
-  static void CreateWebSocketWithOrigin(
-      int process_id,
-      url::Origin origin,
-      network::mojom::WebSocketRequest request,
-      int frame_id = MSG_ROUTING_NONE);
+  static void CreateWebSocketWithOrigin(int process_id,
+                                        url::Origin origin,
+                                        blink::mojom::WebSocketRequest request,
+                                        int frame_id = MSG_ROUTING_NONE);
 
   // net::URLRequestContextGetterObserver implementation.
   void OnContextShuttingDown() override;
@@ -55,14 +54,14 @@
   ~WebSocketManager() override;
   void DoCreateWebSocket(int frame_id,
                          url::Origin origin,
-                         network::mojom::WebSocketRequest request);
+                         blink::mojom::WebSocketRequest request);
   base::TimeDelta CalculateDelay() const;
   void ThrottlingPeriodTimerCallback();
 
   // This is virtual to support testing.
   virtual WebSocketImpl* CreateWebSocketImpl(
       WebSocketImpl::Delegate* delegate,
-      network::mojom::WebSocketRequest request,
+      blink::mojom::WebSocketRequest request,
       int child_id,
       int frame_id,
       url::Origin origin,
diff --git a/content/browser/websockets/websocket_manager_unittest.cc b/content/browser/websockets/websocket_manager_unittest.cc
index 8603b10..d461496 100644
--- a/content/browser/websockets/websocket_manager_unittest.cc
+++ b/content/browser/websockets/websocket_manager_unittest.cc
@@ -22,7 +22,7 @@
 class TestWebSocketImpl : public WebSocketImpl {
  public:
   TestWebSocketImpl(Delegate* delegate,
-                    network::mojom::WebSocketRequest request,
+                    blink::mojom::WebSocketRequest request,
                     int process_id,
                     int frame_id,
                     url::Origin origin,
@@ -61,14 +61,14 @@
            num_previous_succeeded_connections_;
   }
 
-  void DoCreateWebSocket(network::mojom::WebSocketRequest request) {
+  void DoCreateWebSocket(blink::mojom::WebSocketRequest request) {
     WebSocketManager::DoCreateWebSocket(MSG_ROUTING_NONE, url::Origin(),
                                         std::move(request));
   }
 
  private:
   WebSocketImpl* CreateWebSocketImpl(WebSocketImpl::Delegate* delegate,
-                                     network::mojom::WebSocketRequest request,
+                                     blink::mojom::WebSocketRequest request,
                                      int process_id,
                                      int frame_id,
                                      url::Origin origin,
@@ -102,14 +102,14 @@
 
   void AddMultipleChannels(int number_of_channels) {
     for (int i = 0; i < number_of_channels; ++i) {
-      network::mojom::WebSocketPtr websocket;
+      blink::mojom::WebSocketPtr websocket;
       websocket_manager_->DoCreateWebSocket(mojo::MakeRequest(&websocket));
     }
   }
 
   void AddAndCancelMultipleChannels(int number_of_channels) {
     for (int i = 0; i < number_of_channels; ++i) {
-      network::mojom::WebSocketPtr websocket;
+      blink::mojom::WebSocketPtr websocket;
       websocket_manager_->DoCreateWebSocket(mojo::MakeRequest(&websocket));
       websocket_manager_->sockets().back()->SimulateConnectionError();
     }
@@ -127,7 +127,7 @@
 }
 
 TEST_F(WebSocketManagerTest, CreateWebSocket) {
-  network::mojom::WebSocketPtr websocket;
+  blink::mojom::WebSocketPtr websocket;
 
   websocket_manager()->DoCreateWebSocket(mojo::MakeRequest(&websocket));
 
@@ -135,13 +135,13 @@
 }
 
 TEST_F(WebSocketManagerTest, SendFrameButNotConnectedYet) {
-  network::mojom::WebSocketPtr websocket;
+  blink::mojom::WebSocketPtr websocket;
 
   websocket_manager()->DoCreateWebSocket(mojo::MakeRequest(&websocket));
 
   // This should not crash.
   std::vector<uint8_t> data;
-  websocket->SendFrame(true, network::mojom::WebSocketMessageType::TEXT, data);
+  websocket->SendFrame(true, blink::mojom::WebSocketMessageType::TEXT, data);
 }
 
 TEST_F(WebSocketManagerTest, DelayFor4thPendingConnectionIsZero) {
diff --git a/content/common/accessibility_messages.h b/content/common/accessibility_messages.h
index 2fa64a2..c6709bd 100644
--- a/content/common/accessibility_messages.h
+++ b/content/common/accessibility_messages.h
@@ -9,6 +9,7 @@
 
 #include "content/common/ax_content_node_data.h"
 #include "content/common/content_export.h"
+#include "content/common/content_param_traits.h"
 #include "content/common/view_message_enums.h"
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_message_utils.h"
@@ -182,8 +183,9 @@
 // Request a one-time snapshot of the accessibility tree without
 // enabling accessibility if it wasn't already enabled. The passed id
 // will be returned in the AccessibilityHostMsg_SnapshotResponse message.
-IPC_MESSAGE_ROUTED1(AccessibilityMsg_SnapshotTree,
-                    int /* callback id */)
+IPC_MESSAGE_ROUTED2(AccessibilityMsg_SnapshotTree,
+                    int /* callback id */,
+                    ui::AXMode /* ax_mode */)
 
 // Messages sent from the renderer to the browser.
 
diff --git a/content/common/manifest_share_target_util_unittest.cc b/content/common/manifest_share_target_util_unittest.cc
index ff256e1b..edfc676 100644
--- a/content/common/manifest_share_target_util_unittest.cc
+++ b/content/common/manifest_share_target_util_unittest.cc
@@ -18,48 +18,70 @@
 
 }  // namespace
 
-TEST(ManifestShareTargetUtilTest,
-     ReplaceWebShareUrlPlaceholdersInvalidTemplate) {
-  const GURL kUrl(kUrlSpec);
-  GURL url_template_filled;
-
+TEST(ManifestShareTargetUtilTest, ReplaceUrlPlaceholdersInvalidTemplate) {
   // Badly nested placeholders.
   GURL url_template = GURL("http://example.com/?q={");
-  bool succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText,
-                                                  kUrl, &url_template_filled);
-  EXPECT_FALSE(succeeded);
+  EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
+  EXPECT_FALSE(
+      ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
 
   url_template = GURL("http://example.com/?q={title");
-  succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
-                                             &url_template_filled);
-  EXPECT_FALSE(succeeded);
+  EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
+  EXPECT_FALSE(
+      ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
 
   url_template = GURL("http://example.com/?q={title{text}}");
-  succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
-                                             &url_template_filled);
-  EXPECT_FALSE(succeeded);
+  EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
+  EXPECT_FALSE(
+      ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
 
   url_template = GURL("http://example.com/?q={title{}");
-  succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
-                                             &url_template_filled);
-  EXPECT_FALSE(succeeded);
+  EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
+  EXPECT_FALSE(
+      ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
 
   url_template = GURL("http://example.com/?q={{title}}");
-  succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
-                                             &url_template_filled);
-  EXPECT_FALSE(succeeded);
+  EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
+  EXPECT_FALSE(
+      ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
 
   // Placeholder with non-identifier character.
   url_template = GURL("http://example.com/?q={title?}");
-  succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
-                                             &url_template_filled);
-  EXPECT_FALSE(succeeded);
+  EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
+  EXPECT_FALSE(
+      ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
+
+  // Placeholder with digit character.
+  url_template = GURL("http://example.com/?q={title1}");
+  EXPECT_TRUE(ValidateWebShareUrlTemplate(url_template));
+  EXPECT_TRUE(
+      ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
+
+  // Empty placeholder.
+  url_template = GURL("http://example.com/?q={}");
+  EXPECT_TRUE(ValidateWebShareUrlTemplate(url_template));
+  EXPECT_TRUE(
+      ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
 
   // Invalid placeholder in URL fragment.
   url_template = GURL("http://example.com/#{title?}");
-  succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
-                                             &url_template_filled);
-  EXPECT_FALSE(succeeded);
+  EXPECT_FALSE(ValidateWebShareUrlTemplate(url_template));
+  EXPECT_FALSE(
+      ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
+
+  // { in path.
+  url_template = GURL("http://example.com/subpath{/");
+  EXPECT_TRUE(ValidateWebShareUrlTemplate(url_template));
+  EXPECT_TRUE(
+      ReplaceWebShareUrlPlaceholders(url_template, "", "", GURL(), nullptr));
+
+  // Invalid placeholder. Non-empty title, text, share URL and non-empty output
+  // parameter.
+  GURL url_template_filled;
+  url_template = GURL("http://example.com/?q={");
+  EXPECT_FALSE(ReplaceWebShareUrlPlaceholders(url_template, "text", "title",
+                                              GURL("http://www.google.com"),
+                                              &url_template_filled));
 }
 
 TEST(ManifestShareTargetUtilTest, ReplaceWebShareUrlPlaceholders) {
@@ -73,13 +95,6 @@
   EXPECT_TRUE(succeeded);
   EXPECT_EQ(url_template, url_template_filled);
 
-  // Empty |url_template|
-  url_template = GURL();
-  succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
-                                             &url_template_filled);
-  EXPECT_TRUE(succeeded);
-  EXPECT_EQ(GURL(), url_template_filled);
-
   // One title placeholder.
   url_template = GURL("http://example.com/#{title}");
   succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
@@ -147,13 +162,6 @@
       "text=My%20text&title=My%20title&url=https%3A%2F%2Fwww.google.com%2F",
       url_template_filled.spec());
 
-  // Placeholder with digit character.
-  url_template = GURL("http://example.com/#{title1}");
-  succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
-                                             &url_template_filled);
-  EXPECT_TRUE(succeeded);
-  EXPECT_EQ("http://example.com/#", url_template_filled.spec());
-
   // Empty placeholder.
   url_template = GURL("http://example.com/#{}");
   succeeded = ReplaceWebShareUrlPlaceholders(url_template, kTitle, kText, kUrl,
diff --git a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java
index 2b7d8255..7574c04 100644
--- a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java
@@ -66,6 +66,7 @@
         // Limit the number of concurrent surfaces.
         if (mNumOverlays >= MAX_OVERLAYS) {
             client.onDestroyed();
+            client.close();
             return;
         }
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java
index 0b6711c..c019cf6 100644
--- a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java
@@ -309,6 +309,8 @@
         mDialogCore = null;
 
         // If we wanted to send any message to |mClient|, we should have done so already.
+        // We close |mClient| first to prevent leaking the mojo router object.
+        if (mClient != null) mClient.close();
         mClient = null;
     }
 
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 1296ebb2..6d944ed1 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -153,6 +153,7 @@
           "blink::mojom::TextSuggestionHost",
           "blink::mojom::UnhandledTapNotifier",
           "blink::mojom::WebBluetoothService",
+          "blink::mojom::WebSocket",
 
           // TODO(beng): figure out how to overlay test interfaces like this.
           "content::mojom::BrowserTarget",
@@ -181,7 +182,6 @@
           "media::mojom::RemoterFactory",
           "media::mojom::Renderer",
           "network::mojom::RestrictedCookieManager",
-          "network::mojom::WebSocket",
           "password_manager::mojom::CredentialManager",
           "payments::mojom::PaymentManager",
           "payments::mojom::PaymentRequest",
@@ -221,8 +221,8 @@
           "blink::mojom::NotificationService",
           "blink::mojom::PermissionService",
           "blink::mojom::QuotaDispatcherHost",
+          "blink::mojom::WebSocket",
           "network::mojom::RestrictedCookieManager",
-          "network::mojom::WebSocket",
           "payments::mojom::PaymentManager",
           "shape_detection::mojom::BarcodeDetection",
           "shape_detection::mojom::FaceDetectionProvider",
@@ -238,7 +238,7 @@
           "blink::mojom::NotificationService",
           "blink::mojom::PermissionService",
           "blink::mojom::QuotaDispatcherHost",
-          "network::mojom::WebSocket",
+          "blink::mojom::WebSocket",
           "payments::mojom::PaymentManager",
           "shape_detection::mojom::BarcodeDetection",
           "shape_detection::mojom::FaceDetectionProvider",
diff --git a/content/public/browser/touch_selection_controller_client_manager.h b/content/public/browser/touch_selection_controller_client_manager.h
index 01460afe..8d037d95 100644
--- a/content/public/browser/touch_selection_controller_client_manager.h
+++ b/content/public/browser/touch_selection_controller_client_manager.h
@@ -55,7 +55,7 @@
   virtual void InvalidateClient(ui::TouchSelectionControllerClient* client) = 0;
 
   // Provides direct access to the TouchSelectionController that will be used
-  // with all clients accessing this manager. Always returns non-null value.
+  // with all clients accessing this manager. May return null values on Android.
   virtual ui::TouchSelectionController* GetTouchSelectionController() = 0;
 
   // The following two functions allow clients (or their owners, etc.) to
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index b74438d7..42e684b 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -31,6 +31,7 @@
 #include "content/public/common/stop_find_action.h"
 #include "third_party/WebKit/public/common/frame/sandbox_flags.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/accessibility/ax_modes.h"
 #include "ui/accessibility/ax_tree_update.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/gfx/geometry/rect.h"
@@ -299,10 +300,11 @@
   virtual RenderWidgetHostView* GetTopLevelRenderWidgetHostView() = 0;
 
   // Request a one-time snapshot of the accessibility tree without changing
-  // the accessibility mode.
+  // the accessibility mode. |ax_mode| is the accessibility mode to use.
   using AXTreeSnapshotCallback =
       base::OnceCallback<void(const ui::AXTreeUpdate&)>;
-  virtual void RequestAXTreeSnapshot(AXTreeSnapshotCallback callback) = 0;
+  virtual void RequestAXTreeSnapshot(AXTreeSnapshotCallback callback,
+                                     ui::AXMode ax_mode) = 0;
 
   // Causes the current page to be closed, including running its onunload event
   // handler.
diff --git a/content/public/common/manifest_share_target_util.cc b/content/public/common/manifest_share_target_util.cc
index 5be23648..ada0a39 100644
--- a/content/public/common/manifest_share_target_util.cc
+++ b/content/public/common/manifest_share_target_util.cc
@@ -19,27 +19,16 @@
   return base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) || c == '-' || c == '_';
 }
 
-// Returns to |out| the result of running the "replace placeholders" algorithm
-// on |template_string|. The algorithm is specified at
+// Returns to |out| the result of running the "replace placeholders"
+// algorithm on |url_template|. The algorithm is specified at
 // https://wicg.github.io/web-share-target/#dfn-replace-placeholders
+// Does not copy any string data. The resulting vector can be concatenated
+// together with base::StrCat to produce the final string.
 bool ReplacePlaceholders(base::StringPiece template_string,
-                         base::StringPiece title,
-                         base::StringPiece text,
-                         const GURL& share_url,
-                         std::string* out) {
-  constexpr char kTitlePlaceholder[] = "title";
-  constexpr char kTextPlaceholder[] = "text";
-  constexpr char kUrlPlaceholder[] = "url";
+                         const std::map<base::StringPiece, std::string>& data,
+                         std::vector<base::StringPiece>* out) {
+  DCHECK(out);
 
-  std::map<base::StringPiece, std::string> placeholder_to_data;
-  placeholder_to_data[kTitlePlaceholder] =
-      net::EscapeQueryParamValue(title, false);
-  placeholder_to_data[kTextPlaceholder] =
-      net::EscapeQueryParamValue(text, false);
-  placeholder_to_data[kUrlPlaceholder] =
-      net::EscapeQueryParamValue(share_url.spec(), false);
-
-  std::vector<base::StringPiece> split_template;
   bool last_saw_open = false;
   size_t start_index_to_copy = 0;
   for (size_t i = 0; i < template_string.size(); ++i) {
@@ -47,10 +36,10 @@
       if (template_string[i] == '}') {
         base::StringPiece placeholder = template_string.substr(
             start_index_to_copy + 1, i - 1 - start_index_to_copy);
-        auto it = placeholder_to_data.find(placeholder);
-        if (it != placeholder_to_data.end()) {
+        auto it = data.find(placeholder);
+        if (it != data.end()) {
           // Replace the placeholder text with the parameter value.
-          split_template.push_back(it->second);
+          out->push_back(it->second);
         }
 
         last_saw_open = false;
@@ -64,8 +53,8 @@
         // Error: Saw close, with no corresponding open.
         return false;
       } else if (template_string[i] == '{') {
-        split_template.push_back(template_string.substr(
-            start_index_to_copy, i - start_index_to_copy));
+        out->push_back(template_string.substr(start_index_to_copy,
+                                              i - start_index_to_copy));
 
         last_saw_open = true;
         start_index_to_copy = i;
@@ -76,31 +65,56 @@
     // Error: Saw open that was never closed.
     return false;
   }
-  split_template.push_back(template_string.substr(
+  out->push_back(template_string.substr(
       start_index_to_copy, template_string.size() - start_index_to_copy));
-
-  *out = base::StrCat(split_template);
   return true;
 }
 
 }  // namespace
 
+bool ValidateWebShareUrlTemplate(const GURL& url_template) {
+  return ReplaceWebShareUrlPlaceholders(url_template, /*title=*/"", /*text=*/"",
+                                        /*share_url=*/GURL(),
+                                        /*url_template_filled=*/nullptr);
+}
+
 bool ReplaceWebShareUrlPlaceholders(const GURL& url_template,
                                     base::StringPiece title,
                                     base::StringPiece text,
                                     const GURL& share_url,
                                     GURL* url_template_filled) {
-  std::string new_query;
-  std::string new_ref;
-  if (!ReplacePlaceholders(url_template.query_piece(), title, text, share_url,
-                           &new_query) ||
-      !ReplacePlaceholders(url_template.ref_piece(), title, text, share_url,
-                           &new_ref)) {
+  constexpr char kTitlePlaceholder[] = "title";
+  constexpr char kTextPlaceholder[] = "text";
+  constexpr char kUrlPlaceholder[] = "url";
+  std::map<base::StringPiece, std::string> replacements;
+  replacements[kTitlePlaceholder] = net::EscapeQueryParamValue(title, false);
+  replacements[kTextPlaceholder] = net::EscapeQueryParamValue(text, false);
+  replacements[kUrlPlaceholder] =
+      net::EscapeQueryParamValue(share_url.spec(), false);
+
+  std::vector<base::StringPiece> new_query_split;
+  std::vector<base::StringPiece> new_ref_split;
+  if (!ReplacePlaceholders(url_template.query_piece(), replacements,
+                           &new_query_split) ||
+      !ReplacePlaceholders(url_template.ref_piece(), replacements,
+                           &new_ref_split)) {
     return false;
   }
 
-  // Check whether |url_template| has a query in order to preserve the '?' in a
-  // URL with an empty query. e.g. http://www.google.com/?
+  // Early-return optimization, since ReplaceWebShareUrlPlaceholders() is called
+  // at manifest parse time just to get the success boolean, ignoring the
+  // result.
+  if (!url_template_filled)
+    return true;
+
+  // Ensure that the replacements are not deleted prior to
+  // GURL::ReplaceComponents() being called. GURL::Replacements::SetQueryStr()
+  // does not make a copy.
+  std::string new_query = base::StrCat(new_query_split);
+  std::string new_ref = base::StrCat(new_ref_split);
+
+  // Check whether |url_template| has a query in order to preserve the '?' in
+  // a URL with an empty query. e.g. http://www.google.com/?
   GURL::Replacements url_replacements;
   if (url_template.has_query())
     url_replacements.SetQueryStr(new_query);
diff --git a/content/public/common/manifest_share_target_util.h b/content/public/common/manifest_share_target_util.h
index dd7f441c..ee46b28 100644
--- a/content/public/common/manifest_share_target_util.h
+++ b/content/public/common/manifest_share_target_util.h
@@ -14,6 +14,10 @@
 
 namespace content {
 
+// Determines whether |url_template| is valid; that is, whether
+// ReplaceWebShareUrlPlaceholders() would succeed for the given template.
+CONTENT_EXPORT bool ValidateWebShareUrlTemplate(const GURL& url_template);
+
 // Writes to |url_template_filled|, a copy of |url_template| with all
 // instances of "{title}", "{text}", and "{url}" in the query and fragment
 // parts of the URL replaced with |title|, |text|, and |url| respectively.
diff --git a/content/public/test/test_browser_thread_bundle.h b/content/public/test/test_browser_thread_bundle.h
index afc45cb..cd838ad 100644
--- a/content/public/test/test_browser_thread_bundle.h
+++ b/content/public/test/test_browser_thread_bundle.h
@@ -130,7 +130,6 @@
 
   std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
   std::unique_ptr<TestBrowserThread> ui_thread_;
-  std::unique_ptr<TestBrowserThread> process_launcher_thread_;
   std::unique_ptr<TestBrowserThread> io_thread_;
 
   int options_;
diff --git a/content/renderer/accessibility/aom_content_ax_tree.cc b/content/renderer/accessibility/aom_content_ax_tree.cc
index 668df0f..208e2a3 100644
--- a/content/renderer/accessibility/aom_content_ax_tree.cc
+++ b/content/renderer/accessibility/aom_content_ax_tree.cc
@@ -127,8 +127,8 @@
 
 bool AomContentAxTree::ComputeAccessibilityTree() {
   AXContentTreeUpdate content_tree_update;
-  RenderAccessibilityImpl::SnapshotAccessibilityTree(render_frame_,
-                                                     &content_tree_update);
+  RenderAccessibilityImpl::SnapshotAccessibilityTree(
+      render_frame_, &content_tree_update, ui::kAXModeComplete);
 
   // Hack to convert between AXContentNodeData and AXContentTreeData to just
   // AXNodeData and AXTreeData to preserve content specific attributes while
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc
index 6e5c47a..1af2bb0 100644
--- a/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -59,7 +59,8 @@
 // static
 void RenderAccessibilityImpl::SnapshotAccessibilityTree(
     RenderFrameImpl* render_frame,
-    AXContentTreeUpdate* response) {
+    AXContentTreeUpdate* response,
+    ui::AXMode ax_mode) {
   TRACE_EVENT0("accessibility",
                "RenderAccessibilityImpl::SnapshotAccessibilityTree");
 
@@ -73,10 +74,7 @@
   WebAXObject root = context.Root();
   if (!root.UpdateLayoutAndCheckValidity())
     return;
-  BlinkAXTreeSource tree_source(
-      render_frame, ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents |
-                        ui::AXMode::kInlineTextBoxes |
-                        ui::AXMode::kScreenReader | ui::AXMode::kHTML);
+  BlinkAXTreeSource tree_source(render_frame, ax_mode);
   tree_source.SetRoot(root);
   ScopedFreezeBlinkAXTreeSource freeze(&tree_source);
   BlinkAXTreeSerializer serializer(&tree_source);
diff --git a/content/renderer/accessibility/render_accessibility_impl.h b/content/renderer/accessibility/render_accessibility_impl.h
index 47f569d..1352917 100644
--- a/content/renderer/accessibility/render_accessibility_impl.h
+++ b/content/renderer/accessibility/render_accessibility_impl.h
@@ -61,9 +61,9 @@
  public:
   // Request a one-time snapshot of the accessibility tree without
   // enabling accessibility if it wasn't already enabled.
-  static void SnapshotAccessibilityTree(
-      RenderFrameImpl* render_frame,
-      AXContentTreeUpdate* response);
+  static void SnapshotAccessibilityTree(RenderFrameImpl* render_frame,
+                                        AXContentTreeUpdate* response,
+                                        ui::AXMode ax_mode);
 
   RenderAccessibilityImpl(RenderFrameImpl* render_frame, ui::AXMode mode);
   ~RenderAccessibilityImpl() override;
diff --git a/content/renderer/loader/web_url_request_util.cc b/content/renderer/loader/web_url_request_util.cc
index 35a2e40b..9f269d7 100644
--- a/content/renderer/loader/web_url_request_util.cc
+++ b/content/renderer/loader/web_url_request_util.cc
@@ -25,7 +25,6 @@
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/WebKit/public/mojom/blob/blob.mojom.h"
-#include "third_party/WebKit/public/mojom/blob/blob_registry.mojom.h"
 #include "third_party/WebKit/public/platform/FilePathConversion.h"
 #include "third_party/WebKit/public/platform/Platform.h"
 #include "third_party/WebKit/public/platform/WebData.h"
@@ -106,94 +105,6 @@
   std::string buffer_;
 };
 
-// Vends data pipes to read a Blob. It stays alive until all Mojo connections
-// close.
-class DataPipeGetter : public network::mojom::DataPipeGetter {
- public:
-  DataPipeGetter(blink::mojom::BlobPtr blob,
-                 network::mojom::DataPipeGetterRequest request) {
-    // If a sync XHR is doing the upload, then the main thread will be blocked.
-    // So we must bind on a background thread, otherwise the methods below will
-    // never be called and the process will hang.
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner =
-        base::CreateSingleThreadTaskRunnerWithTraits(
-            {base::TaskPriority::USER_VISIBLE,
-             base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
-    task_runner->PostTask(
-        FROM_HERE,
-        base::BindOnce(&DataPipeGetter::BindInternal, base::Unretained(this),
-                       blob.PassInterface(), std::move(request)));
-  }
-  ~DataPipeGetter() override = default;
-
- private:
-  class BlobReaderClient : public blink::mojom::BlobReaderClient {
-   public:
-    explicit BlobReaderClient(ReadCallback callback)
-        : callback_(std::move(callback)) {
-      DCHECK(!callback_.is_null());
-    }
-    ~BlobReaderClient() override = default;
-
-    // blink::mojom::BlobReaderClient implementation:
-    void OnCalculatedSize(uint64_t total_size,
-                          uint64_t expected_content_size) override {
-      // Check if null since it's conceivable OnComplete() was already called
-      // with error.
-      if (!callback_.is_null())
-        std::move(callback_).Run(net::OK, total_size);
-    }
-    void OnComplete(int32_t status, uint64_t data_length) override {
-      // Check if null since OnCalculatedSize() may have already been called
-      // and an error occurred later.
-      if (!callback_.is_null() && status != net::OK) {
-        // On error, signal failure immediately. On success, OnCalculatedSize()
-        // is guaranteed to be called, and the result will be signaled from
-        // there.
-        std::move(callback_).Run(status, 0);
-      }
-    }
-
-   private:
-    ReadCallback callback_;
-
-    DISALLOW_COPY_AND_ASSIGN(BlobReaderClient);
-  };
-
-  void BindInternal(blink::mojom::BlobPtrInfo blob,
-                    network::mojom::DataPipeGetterRequest request) {
-    bindings_.set_connection_error_handler(base::BindRepeating(
-        &DataPipeGetter::OnConnectionError, base::Unretained(this)));
-    bindings_.AddBinding(this, std::move(request));
-    blob_.Bind(std::move(blob));
-  }
-
-  void OnConnectionError() {
-    if (bindings_.empty())
-      delete this;
-  }
-
-  // network::mojom::DataPipeGetter implementation:
-  void Read(mojo::ScopedDataPipeProducerHandle handle,
-            ReadCallback callback) override {
-    blink::mojom::BlobReaderClientPtr blob_reader_client_ptr;
-    mojo::MakeStrongBinding(
-        std::make_unique<BlobReaderClient>(std::move(callback)),
-        mojo::MakeRequest(&blob_reader_client_ptr));
-    blob_->ReadAll(std::move(handle), std::move(blob_reader_client_ptr));
-  }
-
-  void Clone(network::mojom::DataPipeGetterRequest request) override {
-    bindings_.AddBinding(this, std::move(request));
-  }
-
- private:
-  blink::mojom::BlobPtr blob_;
-  mojo::BindingSet<network::mojom::DataPipeGetter> bindings_;
-
-  DISALLOW_COPY_AND_ASSIGN(DataPipeGetter);
-};
-
 }  // namespace
 
 ResourceType WebURLRequestContextToResourceType(
@@ -444,19 +355,12 @@
   return GetRequestBodyForWebHTTPBody(request.HttpBody());
 }
 
-void GetBlobRegistry(blink::mojom::BlobRegistryRequest request) {
-  ChildThreadImpl::current()->GetConnector()->BindInterface(
-      mojom::kBrowserServiceName, std::move(request));
-}
-
 scoped_refptr<network::ResourceRequestBody> GetRequestBodyForWebHTTPBody(
     const blink::WebHTTPBody& httpBody) {
   scoped_refptr<network::ResourceRequestBody> request_body =
       new network::ResourceRequestBody();
   size_t i = 0;
   WebHTTPBody::Element element;
-  // TODO(jam): cache this somewhere so we don't request it each time?
-  blink::mojom::BlobRegistryPtr blob_registry;
   while (httpBody.ElementAt(i++, element)) {
     switch (element.type) {
       case WebHTTPBody::Element::kTypeData:
@@ -482,29 +386,13 @@
         break;
       case WebHTTPBody::Element::kTypeBlob: {
         if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-          if (!blob_registry.is_bound()) {
-            if (ChildThreadImpl::current()) {
-              ChildThreadImpl::current()->GetConnector()->BindInterface(
-                  mojom::kBrowserServiceName, MakeRequest(&blob_registry));
-            } else {
-              // TODO(sammc): We should use per-frame / per-worker
-              // InterfaceProvider instead (crbug.com/734210).
-              blink::Platform::Current()
-                  ->MainThread()
-                  ->GetTaskRunner()
-                  ->PostTask(FROM_HERE,
-                             base::BindOnce(&GetBlobRegistry,
-                                            MakeRequest(&blob_registry)));
-            }
-          }
-          blink::mojom::BlobPtr blob_ptr;
-          blob_registry->GetBlobFromUUID(MakeRequest(&blob_ptr),
-                                         element.blob_uuid.Utf8());
+          DCHECK(element.optional_blob_handle.is_valid());
+          blink::mojom::BlobPtr blob_ptr(
+              blink::mojom::BlobPtrInfo(std::move(element.optional_blob_handle),
+                                        blink::mojom::Blob::Version_));
 
           network::mojom::DataPipeGetterPtr data_pipe_getter_ptr;
-          // Object deletes itself.
-          new DataPipeGetter(std::move(blob_ptr),
-                             MakeRequest(&data_pipe_getter_ptr));
+          blob_ptr->AsDataPipeGetter(MakeRequest(&data_pipe_getter_ptr));
 
           request_body->AppendDataPipe(std::move(data_pipe_getter_ptr));
         } else {
diff --git a/content/renderer/manifest/manifest_parser.cc b/content/renderer/manifest/manifest_parser.cc
index bc4583e..4e829bf7 100644
--- a/content/renderer/manifest/manifest_parser.cc
+++ b/content/renderer/manifest/manifest_parser.cc
@@ -15,6 +15,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "content/public/common/manifest.h"
+#include "content/public/common/manifest_share_target_util.h"
 #include "content/public/common/manifest_util.h"
 #include "content/renderer/manifest/manifest_uma_util.h"
 #include "third_party/WebKit/public/platform/WebColor.h"
@@ -349,8 +350,16 @@
 
 GURL ManifestParser::ParseShareTargetURLTemplate(
     const base::DictionaryValue& share_target) {
-  return ParseURL(share_target, "url_template", manifest_url_,
-                  ParseURLOriginRestrictions::kSameOriginOnly);
+  GURL url_template = ParseURL(share_target, "url_template", manifest_url_,
+                               ParseURLOriginRestrictions::kSameOriginOnly);
+  if (!ValidateWebShareUrlTemplate(url_template)) {
+    AddErrorInfo(
+        "property 'url_template' ignored. Placeholders have incorrect "
+        "syntax.");
+    return GURL();
+  }
+
+  return url_template;
 }
 
 base::Optional<Manifest::ShareTarget> ManifestParser::ParseShareTarget(
diff --git a/content/renderer/manifest/manifest_parser_unittest.cc b/content/renderer/manifest/manifest_parser_unittest.cc
index be5a78a..db1768db 100644
--- a/content/renderer/manifest/manifest_parser_unittest.cc
+++ b/content/renderer/manifest/manifest_parser_unittest.cc
@@ -1089,9 +1089,24 @@
     Manifest manifest = ParseManifestWithURLs(
         "{ \"share_target\": {\"url_template\": \"share/?title={title\" } }",
         manifest_url, document_url);
+    ASSERT_FALSE(manifest.share_target.has_value());
+    EXPECT_TRUE(manifest.IsEmpty());
+    EXPECT_EQ(1u, GetErrorCount());
+    EXPECT_EQ(
+        "property 'url_template' ignored. Placeholders have incorrect "
+        "syntax.",
+        errors()[0]);
+  }
+
+  // Smoke test: Contains share_target and url_template, and url_template
+  // contains unknown placeholder.
+  {
+    Manifest manifest = ParseManifestWithURLs(
+        "{ \"share_target\": {\"url_template\": \"share/?title={abcxyz}\" } }",
+        manifest_url, document_url);
     ASSERT_TRUE(manifest.share_target.has_value());
     EXPECT_EQ(manifest.share_target.value().url_template.spec(),
-              "https://foo.com/share/?title={title");
+              "https://foo.com/share/?title={abcxyz}");
     EXPECT_FALSE(manifest.IsEmpty());
     EXPECT_EQ(0u, GetErrorCount());
   }
diff --git a/content/renderer/media/stream/user_media_client_impl.cc b/content/renderer/media/stream/user_media_client_impl.cc
index 7efc556..a99f6f2 100644
--- a/content/renderer/media/stream/user_media_client_impl.cc
+++ b/content/renderer/media/stream/user_media_client_impl.cc
@@ -125,7 +125,7 @@
   // Save histogram data so we can see how much GetUserMedia is used.
   // The histogram counts the number of calls to the JS API
   // webGetUserMedia.
-  UpdateWebRTCMethodCount(WEBKIT_GET_USER_MEDIA);
+  UpdateWebRTCMethodCount(blink::WebRTCAPIName::kGetUserMedia);
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!web_request.IsNull());
   DCHECK(web_request.Audio() || web_request.Video());
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 97d30e5..51679b7 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -129,7 +129,7 @@
   // Save histogram data so we can see how much PeerConnetion is used.
   // The histogram counts the number of calls to the JS API
   // webKitRTCPeerConnection.
-  UpdateWebRTCMethodCount(WEBKIT_RTC_PEER_CONNECTION);
+  UpdateWebRTCMethodCount(blink::WebRTCAPIName::kRTCPeerConnection);
 
   return std::make_unique<RTCPeerConnectionHandler>(client, this, task_runner);
 }
diff --git a/content/renderer/media/webrtc/webrtc_uma_histograms.cc b/content/renderer/media/webrtc/webrtc_uma_histograms.cc
index cb76b39c..2d4063d 100644
--- a/content/renderer/media/webrtc/webrtc_uma_histograms.cc
+++ b/content/renderer/media/webrtc/webrtc_uma_histograms.cc
@@ -19,9 +19,11 @@
                             NUM_MEDIA_REQUEST_RESULTS);
 }
 
-void UpdateWebRTCMethodCount(JavaScriptAPIName api_name) {
-  DVLOG(3) << "Incrementing WebRTC.webkitApiCount for " << api_name;
-  UMA_HISTOGRAM_ENUMERATION("WebRTC.webkitApiCount", api_name, INVALID_NAME);
+void UpdateWebRTCMethodCount(blink::WebRTCAPIName api_name) {
+  DVLOG(3) << "Incrementing WebRTC.webkitApiCount for "
+           << static_cast<int>(api_name);
+  UMA_HISTOGRAM_ENUMERATION("WebRTC.webkitApiCount", api_name,
+                            blink::WebRTCAPIName::kInvalidName);
   PerSessionWebRTCAPIMetrics::GetInstance()->LogUsageOnlyOnce(api_name);
 }
 
@@ -50,16 +52,18 @@
   ResetUsage();
 }
 
-void PerSessionWebRTCAPIMetrics::LogUsage(JavaScriptAPIName api_name) {
-  DVLOG(3) << "Incrementing WebRTC.webkitApiCountPerSession for " << api_name;
-  UMA_HISTOGRAM_ENUMERATION("WebRTC.webkitApiCountPerSession",
-                            api_name, INVALID_NAME);
+void PerSessionWebRTCAPIMetrics::LogUsage(blink::WebRTCAPIName api_name) {
+  DVLOG(3) << "Incrementing WebRTC.webkitApiCountPerSession for "
+           << static_cast<int>(api_name);
+  UMA_HISTOGRAM_ENUMERATION("WebRTC.webkitApiCountPerSession", api_name,
+                            blink::WebRTCAPIName::kInvalidName);
 }
 
-void PerSessionWebRTCAPIMetrics::LogUsageOnlyOnce(JavaScriptAPIName api_name) {
+void PerSessionWebRTCAPIMetrics::LogUsageOnlyOnce(
+    blink::WebRTCAPIName api_name) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!has_used_api_[api_name]) {
-    has_used_api_[api_name] = true;
+  if (!has_used_api_[static_cast<int>(api_name)]) {
+    has_used_api_[static_cast<int>(api_name)] = true;
     LogUsage(api_name);
   }
 }
diff --git a/content/renderer/media/webrtc/webrtc_uma_histograms.h b/content/renderer/media/webrtc/webrtc_uma_histograms.h
index 65da3d6..3f29fd32 100644
--- a/content/renderer/media/webrtc/webrtc_uma_histograms.h
+++ b/content/renderer/media/webrtc/webrtc_uma_histograms.h
@@ -10,6 +10,7 @@
 #include "base/sequence_checker.h"
 #include "content/common/content_export.h"
 #include "content/public/common/media_stream_request.h"
+#include "third_party/WebKit/public/platform/WebRTCAPIName.h"
 
 namespace content {
 
@@ -30,20 +31,6 @@
 void LogUserMediaRequestWithNoResult(MediaStreamRequestState state);
 void LogUserMediaRequestResult(MediaStreamRequestResult result);
 
-// Helper enum used for histogramming calls to WebRTC APIs from JavaScript.
-// The entries are linked to UMA values and cannot be changed.
-enum JavaScriptAPIName {
-  WEBKIT_GET_USER_MEDIA,
-  WEBKIT_PEER_CONNECTION,
-  WEBKIT_DEPRECATED_PEER_CONNECTION,
-  WEBKIT_RTC_PEER_CONNECTION,
-  WEBKIT_GET_MEDIA_DEVICES,
-  WEBKIT_MEDIA_STREAM_RECORDER,
-  WEBKIT_CANVAS_CAPTURE_STREAM,
-  WEBKIT_VIDEO_CAPTURE_STREAM,
-  INVALID_NAME
-};
-
 // Helper method used to collect information about the number of times
 // different WebRTC APIs are called from JavaScript.
 //
@@ -55,7 +42,7 @@
 // that gets incremented only once per "session" as established by the
 // PerSessionWebRTCAPIMetrics singleton below. It can be viewed at
 // chrome://histograms/WebRTC.webkitApiCountPerSession.
-void UpdateWebRTCMethodCount(JavaScriptAPIName api_name);
+void UpdateWebRTCMethodCount(blink::WebRTCAPIName api_name);
 
 // A singleton that keeps track of the number of MediaStreams being
 // sent over PeerConnections. It uses the transition to zero such
@@ -79,24 +66,24 @@
 
  protected:
   friend struct base::DefaultSingletonTraits<PerSessionWebRTCAPIMetrics>;
-  friend void UpdateWebRTCMethodCount(JavaScriptAPIName);
+  friend void UpdateWebRTCMethodCount(blink::WebRTCAPIName);
 
   // Protected so that unit tests can test without this being a
   // singleton.
   PerSessionWebRTCAPIMetrics();
 
   // Overridable by unit tests.
-  virtual void LogUsage(JavaScriptAPIName api_name);
+  virtual void LogUsage(blink::WebRTCAPIName api_name);
 
   // Called by UpdateWebRTCMethodCount above. Protected rather than
   // private so that unit tests can call it.
-  void LogUsageOnlyOnce(JavaScriptAPIName api_name);
+  void LogUsageOnlyOnce(blink::WebRTCAPIName api_name);
 
  private:
   void ResetUsage();
 
   int num_streams_;
-  bool has_used_api_[INVALID_NAME];
+  bool has_used_api_[static_cast<int>(blink::WebRTCAPIName::kInvalidName)];
 
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/content/renderer/media/webrtc/webrtc_uma_histograms_unittest.cc b/content/renderer/media/webrtc/webrtc_uma_histograms_unittest.cc
index bcb5b10d..3f7a4fa4 100644
--- a/content/renderer/media/webrtc/webrtc_uma_histograms_unittest.cc
+++ b/content/renderer/media/webrtc/webrtc_uma_histograms_unittest.cc
@@ -17,63 +17,67 @@
 
   using PerSessionWebRTCAPIMetrics::LogUsageOnlyOnce;
 
-  MOCK_METHOD1(LogUsage, void(JavaScriptAPIName));
+  MOCK_METHOD1(LogUsage, void(blink::WebRTCAPIName));
 };
 
 TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingGetUserMedia) {
   MockPerSessionWebRTCAPIMetrics metrics;
   EXPECT_CALL(metrics, LogUsage(_)).Times(1);
-  metrics.LogUsageOnlyOnce(WEBKIT_GET_USER_MEDIA);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kGetUserMedia);
 }
 
 TEST(PerSessionWebRTCAPIMetrics, CallOngoingGetUserMedia) {
   MockPerSessionWebRTCAPIMetrics metrics;
   metrics.IncrementStreamCounter();
-  EXPECT_CALL(metrics, LogUsage(WEBKIT_GET_USER_MEDIA)).Times(1);
-  metrics.LogUsageOnlyOnce(WEBKIT_GET_USER_MEDIA);
+  EXPECT_CALL(metrics, LogUsage(blink::WebRTCAPIName::kGetUserMedia)).Times(1);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kGetUserMedia);
 }
 
 TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingGetMediaDevices) {
   MockPerSessionWebRTCAPIMetrics metrics;
   EXPECT_CALL(metrics, LogUsage(_)).Times(1);
-  metrics.LogUsageOnlyOnce(WEBKIT_GET_MEDIA_DEVICES);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kEnumerateDevices);
 }
 
 TEST(PerSessionWebRTCAPIMetrics, CallOngoingGetMediaDevices) {
   MockPerSessionWebRTCAPIMetrics metrics;
   metrics.IncrementStreamCounter();
-  EXPECT_CALL(metrics, LogUsage(WEBKIT_GET_MEDIA_DEVICES)).Times(1);
-  metrics.LogUsageOnlyOnce(WEBKIT_GET_MEDIA_DEVICES);
+  EXPECT_CALL(metrics, LogUsage(blink::WebRTCAPIName::kEnumerateDevices))
+      .Times(1);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kEnumerateDevices);
 }
 
 TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingRTCPeerConnection) {
   MockPerSessionWebRTCAPIMetrics metrics;
-  EXPECT_CALL(metrics, LogUsage(WEBKIT_RTC_PEER_CONNECTION));
-  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  EXPECT_CALL(metrics, LogUsage(blink::WebRTCAPIName::kRTCPeerConnection));
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
 }
 
 TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingMultiplePC) {
   MockPerSessionWebRTCAPIMetrics metrics;
-  EXPECT_CALL(metrics, LogUsage(WEBKIT_RTC_PEER_CONNECTION)).Times(1);
-  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
-  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
-  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  EXPECT_CALL(metrics, LogUsage(blink::WebRTCAPIName::kRTCPeerConnection))
+      .Times(1);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
 }
 
 TEST(PerSessionWebRTCAPIMetrics, BeforeAfterCallMultiplePC) {
   MockPerSessionWebRTCAPIMetrics metrics;
-  EXPECT_CALL(metrics, LogUsage(WEBKIT_RTC_PEER_CONNECTION)).Times(1);
-  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
-  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  EXPECT_CALL(metrics, LogUsage(blink::WebRTCAPIName::kRTCPeerConnection))
+      .Times(1);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
   metrics.IncrementStreamCounter();
   metrics.IncrementStreamCounter();
-  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
   metrics.DecrementStreamCounter();
-  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
   metrics.DecrementStreamCounter();
-  EXPECT_CALL(metrics, LogUsage(WEBKIT_RTC_PEER_CONNECTION)).Times(1);
-  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
-  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  EXPECT_CALL(metrics, LogUsage(blink::WebRTCAPIName::kRTCPeerConnection))
+      .Times(1);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
+  metrics.LogUsageOnlyOnce(blink::WebRTCAPIName::kRTCPeerConnection);
 }
 
 }  // namespace content
diff --git a/content/renderer/media_capture_from_element/canvas_capture_handler.cc b/content/renderer/media_capture_from_element/canvas_capture_handler.cc
index 9190dd7..19dadd25 100644
--- a/content/renderer/media_capture_from_element/canvas_capture_handler.cc
+++ b/content/renderer/media_capture_from_element/canvas_capture_handler.cc
@@ -145,7 +145,7 @@
     blink::WebMediaStreamTrack* track) {
   // Save histogram data so we can see how much CanvasCapture is used.
   // The histogram counts the number of calls to the JS API.
-  UpdateWebRTCMethodCount(WEBKIT_CANVAS_CAPTURE_STREAM);
+  UpdateWebRTCMethodCount(blink::WebRTCAPIName::kCanvasCaptureStream);
 
   return std::unique_ptr<CanvasCaptureHandler>(new CanvasCaptureHandler(
       size, frame_rate, std::move(io_task_runner), track));
diff --git a/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
index 1da1f23..a6b6b20 100644
--- a/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc
@@ -35,7 +35,7 @@
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
   // Save histogram data so we can see how much HTML Video capture is used.
   // The histogram counts the number of calls to the JS API.
-  UpdateWebRTCMethodCount(WEBKIT_VIDEO_CAPTURE_STREAM);
+  UpdateWebRTCMethodCount(blink::WebRTCAPIName::kVideoCaptureStream);
 
   return base::WrapUnique(new HtmlVideoElementCapturerSource(
       static_cast<media::WebMediaPlayerImpl*>(player)->AsWeakPtr(),
diff --git a/content/renderer/media_recorder/media_recorder_handler.cc b/content/renderer/media_recorder/media_recorder_handler.cc
index 047c1da..115523c 100644
--- a/content/renderer/media_recorder/media_recorder_handler.cc
+++ b/content/renderer/media_recorder/media_recorder_handler.cc
@@ -190,7 +190,7 @@
   DCHECK(main_render_thread_checker_.CalledOnValidThread());
   // Save histogram data so we can see how much MediaStream Recorder is used.
   // The histogram counts the number of calls to the JS API.
-  UpdateWebRTCMethodCount(WEBKIT_MEDIA_STREAM_RECORDER);
+  UpdateWebRTCMethodCount(blink::WebRTCAPIName::kMediaStreamRecorder);
 
   if (!CanSupportMimeType(type, codecs)) {
     DLOG(ERROR) << "Unsupported " << type.Utf8() << ";codecs=" << codecs.Utf8();
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index e526cdb..00f0670 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -2405,9 +2405,10 @@
     observer.AccessibilityModeChanged();
 }
 
-void RenderFrameImpl::OnSnapshotAccessibilityTree(int callback_id) {
+void RenderFrameImpl::OnSnapshotAccessibilityTree(int callback_id,
+                                                  ui::AXMode ax_mode) {
   AXContentTreeUpdate response;
-  RenderAccessibilityImpl::SnapshotAccessibilityTree(this, &response);
+  RenderAccessibilityImpl::SnapshotAccessibilityTree(this, &response, ax_mode);
   Send(new AccessibilityHostMsg_SnapshotResponse(
       routing_id_, callback_id, response));
 }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 417b520..611a112 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -1042,7 +1042,7 @@
   void OnReloadLoFiImages();
   void OnTextSurroundingSelectionRequest(uint32_t max_length);
   void OnSetAccessibilityMode(ui::AXMode new_mode);
-  void OnSnapshotAccessibilityTree(int callback_id);
+  void OnSnapshotAccessibilityTree(int callback_id, ui::AXMode ax_mode);
   void OnUpdateOpener(int opener_routing_id);
   void OnDidUpdateFramePolicy(const blink::FramePolicy& frame_policy);
   void OnSetFrameOwnerProperties(
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 8211d37df..4ca3668 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -157,6 +157,7 @@
 #if BUILDFLAG(ENABLE_WEBRTC)
 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
 #include "content/renderer/media/webrtc/rtc_certificate_generator.h"
+#include "content/renderer/media/webrtc/webrtc_uma_histograms.h"
 #endif
 
 using blink::Platform;
@@ -1021,6 +1022,13 @@
 #endif  // BUILDFLAG(ENABLE_WEBRTC)
 }
 
+void RendererBlinkPlatformImpl::UpdateWebRTCAPICount(
+    blink::WebRTCAPIName api_name) {
+#if BUILDFLAG(ENABLE_WEBRTC)
+  UpdateWebRTCMethodCount(api_name);
+#endif
+}
+
 //------------------------------------------------------------------------------
 
 std::unique_ptr<blink::WebSocketHandshakeThrottle>
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index 9a91a0c7..10f0f9d 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -187,6 +187,7 @@
       blink::WebMediaPlayer* web_media_player) override;
   std::unique_ptr<blink::WebImageCaptureFrameGrabber>
   CreateImageCaptureFrameGrabber() override;
+  void UpdateWebRTCAPICount(blink::WebRTCAPIName api_name) override;
   std::unique_ptr<blink::WebSocketHandshakeThrottle>
   CreateWebSocketHandshakeThrottle() override;
   std::unique_ptr<blink::WebGraphicsContext3DProvider>
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 3db0800..4cb499b8a 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -226,6 +226,16 @@
         'blitframebuffer-srgb-and-linear-drawbuffers.html',
         ['win', 'nvidia', 'opengl'], bug=2355) # ANGLE bug ID
 
+    self.Flaky('deqp/functional/gles3/transformfeedback/' +
+        'basic_types_interleaved_points.html',
+        ['win', ('nvidia', 0x1cb3), 'opengl'], bug=822733)
+    self.Flaky('deqp/functional/gles3/transformfeedback/' +
+        'basic_types_interleaved_lines.html',
+        ['win', ('nvidia', 0x1cb3), 'opengl'], bug=822733)
+    self.Flaky('deqp/functional/gles3/transformfeedback/' +
+        'basic_types_interleaved_triangles.html',
+        ['win', ('nvidia', 0x1cb3), 'opengl'], bug=822733)
+
     # Win / AMD
     self.Fail('conformance2/rendering/blitframebuffer-stencil-only.html',
         ['win', 'amd', 'd3d11'], bug=483282) # owner:jmadill
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc
index fee3816d..1a234c45 100644
--- a/content/test/test_render_view_host.cc
+++ b/content/test/test_render_view_host.cc
@@ -60,7 +60,7 @@
 }
 
 TestRenderWidgetHostView::TestRenderWidgetHostView(RenderWidgetHost* rwh)
-    : rwh_(RenderWidgetHostImpl::From(rwh)),
+    : RenderWidgetHostViewBase(rwh),
       is_showing_(false),
       is_occluded_(false),
       did_swap_compositor_frame_(false),
@@ -80,7 +80,7 @@
   }
 #endif
 
-  rwh_->SetView(this);
+  host()->SetView(this);
 
 #if defined(USE_AURA)
   window_.reset(new aura::Window(
@@ -199,11 +199,6 @@
 void TestRenderWidgetHostView::UnlockMouse() {
 }
 
-RenderWidgetHostImpl* TestRenderWidgetHostView::GetRenderWidgetHostImpl()
-    const {
-  return rwh_;
-}
-
 viz::FrameSinkId TestRenderWidgetHostView::GetFrameSinkId() {
   return frame_sink_id_;
 }
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h
index a14a005..6ae7d716 100644
--- a/content/test/test_render_view_host.h
+++ b/content/test/test_render_view_host.h
@@ -115,7 +115,6 @@
   gfx::Rect GetBoundsInRootWindow() override;
   bool LockMouse() override;
   void UnlockMouse() override;
-  RenderWidgetHostImpl* GetRenderWidgetHostImpl() const override;
   viz::FrameSinkId GetFrameSinkId() override;
   viz::SurfaceId GetCurrentSurfaceId() const override;
 
@@ -139,7 +138,6 @@
   void OnFrameTokenChanged(uint32_t frame_token) override;
 
  protected:
-  RenderWidgetHostImpl* rwh_;
   viz::FrameSinkId frame_sink_id_;
 
  private:
diff --git a/device/BUILD.gn b/device/BUILD.gn
index d021dfa..4a5a7de 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -66,13 +66,13 @@
     "bluetooth/uribeacon/uri_encoder_unittest.cc",
     "fido/ctap_request_unittest.cc",
     "fido/ctap_response_unittest.cc",
-    "fido/fake_u2f_discovery_unittest.cc",
+    "fido/fake_fido_discovery_unittest.cc",
+    "fido/fido_discovery_unittest.cc",
     "fido/fido_hid_message_unittest.cc",
     "fido/test_callback_receiver_unittest.cc",
     "fido/u2f_ble_connection_unittest.cc",
     "fido/u2f_ble_device_unittest.cc",
     "fido/u2f_ble_frames_unittest.cc",
-    "fido/u2f_discovery_unittest.cc",
     "fido/u2f_register_unittest.cc",
     "fido/u2f_request_unittest.cc",
     "fido/u2f_sign_unittest.cc",
@@ -118,8 +118,8 @@
   # Linux, requires udev.
   if (!is_linux_without_udev && !is_android) {
     sources += [
-      "fido/u2f_hid_device_unittest.cc",
-      "fido/u2f_hid_discovery_unittest.cc",
+      "fido/fido_hid_device_unittest.cc",
+      "fido/fido_hid_discovery_unittest.cc",
     ]
     deps += [
       "//device/fido:test_support",
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn
index 41e1741d..80ec1b9c 100644
--- a/device/fido/BUILD.gn
+++ b/device/fido/BUILD.gn
@@ -39,6 +39,10 @@
     "fido_ble_uuids.h",
     "fido_constants.cc",
     "fido_constants.h",
+    "fido_device.cc",
+    "fido_device.h",
+    "fido_discovery.cc",
+    "fido_discovery.h",
     "fido_hid_message.cc",
     "fido_hid_message.h",
     "fido_hid_packet.cc",
@@ -69,10 +73,6 @@
     "u2f_ble_frames.h",
     "u2f_ble_transaction.cc",
     "u2f_ble_transaction.h",
-    "u2f_device.cc",
-    "u2f_device.h",
-    "u2f_discovery.cc",
-    "u2f_discovery.h",
     "u2f_parsing_utils.cc",
     "u2f_parsing_utils.h",
     "u2f_register.cc",
@@ -108,10 +108,10 @@
   # HID is not supported on Android.
   if (!is_android) {
     sources += [
-      "u2f_hid_device.cc",
-      "u2f_hid_device.h",
-      "u2f_hid_discovery.cc",
-      "u2f_hid_discovery.h",
+      "fido_hid_device.cc",
+      "fido_hid_device.h",
+      "fido_hid_discovery.cc",
+      "fido_hid_discovery.h",
     ]
 
     deps += [
@@ -125,12 +125,12 @@
   testonly = true
 
   sources = [
+    "mock_fido_device.cc",
+    "mock_fido_device.h",
+    "mock_fido_discovery_observer.cc",
+    "mock_fido_discovery_observer.h",
     "mock_u2f_ble_connection.cc",
     "mock_u2f_ble_connection.h",
-    "mock_u2f_device.cc",
-    "mock_u2f_device.h",
-    "mock_u2f_discovery_observer.cc",
-    "mock_u2f_discovery_observer.h",
   ]
 
   deps = [
@@ -204,8 +204,8 @@
 source_set("test_support") {
   testonly = true
   sources = [
-    "fake_u2f_discovery.cc",
-    "fake_u2f_discovery.h",
+    "fake_fido_discovery.cc",
+    "fake_fido_discovery.h",
     "test_callback_receiver.h",
   ]
   deps = [
diff --git a/device/fido/fake_fido_discovery.cc b/device/fido/fake_fido_discovery.cc
new file mode 100644
index 0000000..943c5e9
--- /dev/null
+++ b/device/fido/fake_fido_discovery.cc
@@ -0,0 +1,120 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/fido/fake_fido_discovery.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device {
+namespace test {
+
+// FakeFidoDiscovery ----------------------------------------------------------
+
+FakeFidoDiscovery::FakeFidoDiscovery(U2fTransportProtocol transport,
+                                     StartStopMode mode)
+    : transport_(transport),
+      mode_(mode),
+      start_called_callback_(wait_for_start_loop_.QuitClosure()),
+      stop_called_callback_(wait_for_stop_loop_.QuitClosure()) {}
+FakeFidoDiscovery::~FakeFidoDiscovery() = default;
+
+void FakeFidoDiscovery::WaitForCallToStart() {
+  wait_for_start_loop_.Run();
+  ASSERT_FALSE(start_called_callback_);
+}
+
+void FakeFidoDiscovery::WaitForCallToStop() {
+  wait_for_stop_loop_.Run();
+  ASSERT_FALSE(stop_called_callback_);
+}
+
+void FakeFidoDiscovery::SimulateStarted(bool success) {
+  ASSERT_FALSE(is_running_);
+  is_running_ = success;
+  NotifyDiscoveryStarted(success);
+}
+
+void FakeFidoDiscovery::SimulateStopped(bool success) {
+  ASSERT_TRUE(is_running_);
+  is_running_ = !success;
+  NotifyDiscoveryStopped(success);
+}
+
+void FakeFidoDiscovery::WaitForCallToStartAndSimulateSuccess() {
+  WaitForCallToStart();
+  SimulateStarted(true /* success */);
+}
+
+void FakeFidoDiscovery::WaitForCallToStopAndSimulateSuccess() {
+  WaitForCallToStop();
+  SimulateStopped(true /* success */);
+}
+
+U2fTransportProtocol FakeFidoDiscovery::GetTransportProtocol() const {
+  return transport_;
+}
+
+void FakeFidoDiscovery::Start() {
+  if (is_running_)
+    return;
+
+  ASSERT_TRUE(start_called_callback_) << "Start called twice.";
+  std::move(start_called_callback_).Run();
+
+  if (mode_ == StartStopMode::kAutomatic)
+    SimulateStarted(true /* success */);
+}
+
+void FakeFidoDiscovery::Stop() {
+  if (!is_running_)
+    return;
+
+  ASSERT_TRUE(stop_called_callback_) << "Stop called twice.";
+  std::move(stop_called_callback_).Run();
+
+  if (mode_ == StartStopMode::kAutomatic)
+    SimulateStopped(true /* success */);
+}
+
+// ScopedFakeFidoDiscoveryFactory ---------------------------------------------
+
+ScopedFakeFidoDiscoveryFactory::ScopedFakeFidoDiscoveryFactory() = default;
+ScopedFakeFidoDiscoveryFactory::~ScopedFakeFidoDiscoveryFactory() = default;
+
+FakeFidoDiscovery* ScopedFakeFidoDiscoveryFactory::ForgeNextHidDiscovery(
+    FakeFidoDiscovery::StartStopMode mode) {
+  next_hid_discovery_ = std::make_unique<FakeFidoDiscovery>(
+      U2fTransportProtocol::kUsbHumanInterfaceDevice, mode);
+  return next_hid_discovery_.get();
+}
+
+FakeFidoDiscovery* ScopedFakeFidoDiscoveryFactory::ForgeNextBleDiscovery(
+    FakeFidoDiscovery::StartStopMode mode) {
+  next_ble_discovery_ = std::make_unique<FakeFidoDiscovery>(
+      U2fTransportProtocol::kBluetoothLowEnergy, mode);
+  return next_ble_discovery_.get();
+}
+
+std::unique_ptr<FidoDiscovery>
+ScopedFakeFidoDiscoveryFactory::CreateFidoDiscovery(
+    U2fTransportProtocol transport,
+    ::service_manager::Connector* connector) {
+  switch (transport) {
+    case U2fTransportProtocol::kBluetoothLowEnergy:
+      DCHECK(next_ble_discovery_);
+      return std::move(next_ble_discovery_);
+    case U2fTransportProtocol::kUsbHumanInterfaceDevice:
+      DCHECK(next_hid_discovery_);
+      return std::move(next_hid_discovery_);
+  }
+  NOTREACHED();
+  return nullptr;
+}
+
+}  // namespace test
+
+}  // namespace device
diff --git a/device/fido/fake_u2f_discovery.h b/device/fido/fake_fido_discovery.h
similarity index 63%
rename from device/fido/fake_u2f_discovery.h
rename to device/fido/fake_fido_discovery.h
index 94e13fa..2591784 100644
--- a/device/fido/fake_u2f_discovery.h
+++ b/device/fido/fake_fido_discovery.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_FIDO_FAKE_U2F_DISCOVERY_H_
-#define DEVICE_FIDO_FAKE_U2F_DISCOVERY_H_
+#ifndef DEVICE_FIDO_FAKE_FIDO_DISCOVERY_H_
+#define DEVICE_FIDO_FAKE_FIDO_DISCOVERY_H_
 
 #include <memory>
 
@@ -11,7 +11,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
-#include "device/fido/u2f_discovery.h"
+#include "device/fido/fido_discovery.h"
 #include "device/fido/u2f_transport_protocol.h"
 
 namespace service_manager {
@@ -21,19 +21,20 @@
 namespace device {
 namespace test {
 
-// Fake U2F discovery simulating the behavior of the production implementations,
-// and can be used to feed U2fRequests with fake/mock U2F devices.
+// Fake FIDO discovery simulating the behavior of the production
+// implementations, and can be used to feed U2fRequests with fake/mock FIDO
+// devices.
 //
-// Most often this class is used together with ScopedFakeU2fDiscoveryFactory:
+// Most often this class is used together with ScopedFakeFidoDiscoveryFactory:
 //
-//   ScopedFakeU2fDiscoveryFactory factory;
+//   ScopedFakeFidoDiscoveryFactory factory;
 //   auto* fake_hid_discovery = factory.ForgeNextHidDiscovery();
 //   auto* fake_ble_discovery = factory.ForgeNextBleDiscovery();
 //
 //   // Run the production code that will eventually call:
-//   //// U2fDiscovery::Create(U2fTransportProtocol::kUsbHumanInterfaceDevice)
+//   //// FidoDiscovery::Create(U2fTransportProtocol::kUsbHumanInterfaceDevice)
 //   //// hid_instance->Start();
-//   //// U2fDiscovery::Create(U2fTransportProtocol::kBluetoothLowEnergy)
+//   //// FidoDiscovery::Create(U2fTransportProtocol::kBluetoothLowEnergy)
 //   //// ble_instance->Start();
 //
 //   // Wait, i.e. spin the message loop until the fake discoveries are started.
@@ -41,14 +42,14 @@
 //   fake_ble_discovery->WaitForCallToStart();
 //
 //   // Add devices to be discovered immediately.
-//   fake_hid_discovery->AddDevice(std::make_unique<MockU2fDevice>(...));
+//   fake_hid_discovery->AddDevice(std::make_unique<MockFidoDevice>(...));
 //
 //   // Start discoveries (HID succeeds, BLE fails).
 //   fake_hid_discovery->SimulateStart(true /* success */);
 //   fake_ble_discovery->SimulateStart(false /* success */);
 //
 //   // Add devices discovered after doing some heavy lifting.
-//   fake_hid_discovery->AddDevice(std::make_unique<MockU2fDevice>(...));
+//   fake_hid_discovery->AddDevice(std::make_unique<MockFidoDevice>(...));
 //
 //   // Run the production code that will eventually stop the discovery.
 //   //// hid_instance->Stop();
@@ -57,8 +58,8 @@
 //   // the discovery starting successfully.
 //   fake_hid_discovery->WaitForCallToStopAndSimulateSuccess();
 //
-class FakeU2fDiscovery : public U2fDiscovery,
-                         public base::SupportsWeakPtr<FakeU2fDiscovery> {
+class FakeFidoDiscovery : public FidoDiscovery,
+                          public base::SupportsWeakPtr<FakeFidoDiscovery> {
  public:
   enum class StartStopMode {
     // SimulateStarted()/SimualteStopped() needs to be called manually after the
@@ -69,9 +70,9 @@
     kAutomatic
   };
 
-  explicit FakeU2fDiscovery(U2fTransportProtocol transport,
-                            StartStopMode mode = StartStopMode::kManual);
-  ~FakeU2fDiscovery() override;
+  explicit FakeFidoDiscovery(U2fTransportProtocol transport,
+                             StartStopMode mode = StartStopMode::kManual);
+  ~FakeFidoDiscovery() override;
 
   // Blocks until start/stop is requested.
   void WaitForCallToStart();
@@ -91,10 +92,10 @@
 
   // Tests are to directly call Add/RemoveDevice to simulate adding/removing
   // devices. Observers are automatically notified.
-  using U2fDiscovery::AddDevice;
-  using U2fDiscovery::RemoveDevice;
+  using FidoDiscovery::AddDevice;
+  using FidoDiscovery::RemoveDevice;
 
-  // U2fDiscovery:
+  // FidoDiscovery:
   U2fTransportProtocol GetTransportProtocol() const override;
   void Start() override;
   void Stop() override;
@@ -111,43 +112,43 @@
   base::OnceClosure start_called_callback_;
   base::OnceClosure stop_called_callback_;
 
-  DISALLOW_COPY_AND_ASSIGN(FakeU2fDiscovery);
+  DISALLOW_COPY_AND_ASSIGN(FakeFidoDiscovery);
 };
 
-// Overrides U2fDiscovery::Create to construct FakeU2fDiscoveries while this
+// Overrides FidoDiscovery::Create to construct FakeFidoDiscoveries while this
 // instance is in scope.
-class ScopedFakeU2fDiscoveryFactory
-    : public ::device::internal::ScopedU2fDiscoveryFactory {
+class ScopedFakeFidoDiscoveryFactory
+    : public ::device::internal::ScopedFidoDiscoveryFactory {
  public:
-  using StartStopMode = FakeU2fDiscovery::StartStopMode;
+  using StartStopMode = FakeFidoDiscovery::StartStopMode;
 
-  ScopedFakeU2fDiscoveryFactory();
-  ~ScopedFakeU2fDiscoveryFactory();
+  ScopedFakeFidoDiscoveryFactory();
+  ~ScopedFakeFidoDiscoveryFactory();
 
   // Constructs a fake BLE/HID discovery to be returned from the next call to
-  // U2fDiscovery::Create. Returns a raw pointer to the fake so that tests can
+  // FidoDiscovery::Create. Returns a raw pointer to the fake so that tests can
   // set it up according to taste.
   //
   // It is an error not to call the relevant method prior to a call to
-  // U2fDiscovery::Create with the respective transport.
-  FakeU2fDiscovery* ForgeNextHidDiscovery(
+  // FidoDiscovery::Create with the respective transport.
+  FakeFidoDiscovery* ForgeNextHidDiscovery(
       StartStopMode mode = StartStopMode::kManual);
-  FakeU2fDiscovery* ForgeNextBleDiscovery(
+  FakeFidoDiscovery* ForgeNextBleDiscovery(
       StartStopMode mode = StartStopMode::kManual);
 
  protected:
-  std::unique_ptr<U2fDiscovery> CreateU2fDiscovery(
+  std::unique_ptr<FidoDiscovery> CreateFidoDiscovery(
       U2fTransportProtocol transport,
       ::service_manager::Connector* connector) override;
 
  private:
-  std::unique_ptr<FakeU2fDiscovery> next_hid_discovery_;
-  std::unique_ptr<FakeU2fDiscovery> next_ble_discovery_;
+  std::unique_ptr<FakeFidoDiscovery> next_hid_discovery_;
+  std::unique_ptr<FakeFidoDiscovery> next_ble_discovery_;
 
-  DISALLOW_COPY_AND_ASSIGN(ScopedFakeU2fDiscoveryFactory);
+  DISALLOW_COPY_AND_ASSIGN(ScopedFakeFidoDiscoveryFactory);
 };
 
 }  // namespace test
 }  // namespace device
 
-#endif  // DEVICE_FIDO_FAKE_U2F_DISCOVERY_H_
+#endif  // DEVICE_FIDO_FAKE_FIDO_DISCOVERY_H_
diff --git a/device/fido/fake_u2f_discovery_unittest.cc b/device/fido/fake_fido_discovery_unittest.cc
similarity index 76%
rename from device/fido/fake_u2f_discovery_unittest.cc
rename to device/fido/fake_fido_discovery_unittest.cc
index da2629539..ac44eb8 100644
--- a/device/fido/fake_u2f_discovery_unittest.cc
+++ b/device/fido/fake_fido_discovery_unittest.cc
@@ -2,58 +2,58 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "device/fido/fake_u2f_discovery.h"
+#include "device/fido/fake_fido_discovery.h"
 
 #include "base/macros.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
-#include "device/fido/mock_u2f_device.h"
-#include "device/fido/mock_u2f_discovery_observer.h"
+#include "device/fido/mock_fido_device.h"
+#include "device/fido/mock_fido_discovery_observer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace device {
 namespace test {
 
-class FakeU2fDiscoveryTest : public ::testing::Test {
+class FakeFidoDiscoveryTest : public ::testing::Test {
  public:
-  FakeU2fDiscoveryTest() = default;
-  ~FakeU2fDiscoveryTest() override = default;
+  FakeFidoDiscoveryTest() = default;
+  ~FakeFidoDiscoveryTest() override = default;
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(FakeU2fDiscoveryTest);
+  DISALLOW_COPY_AND_ASSIGN(FakeFidoDiscoveryTest);
 };
 
-using ScopedFakeU2fDiscoveryFactoryTest = FakeU2fDiscoveryTest;
+using ScopedFakeFidoDiscoveryFactoryTest = FakeFidoDiscoveryTest;
 
-TEST_F(FakeU2fDiscoveryTest, Transport) {
-  FakeU2fDiscovery discovery_ble(U2fTransportProtocol::kBluetoothLowEnergy);
+TEST_F(FakeFidoDiscoveryTest, Transport) {
+  FakeFidoDiscovery discovery_ble(U2fTransportProtocol::kBluetoothLowEnergy);
   EXPECT_EQ(U2fTransportProtocol::kBluetoothLowEnergy,
             discovery_ble.GetTransportProtocol());
 
-  FakeU2fDiscovery discovery_hid(
+  FakeFidoDiscovery discovery_hid(
       U2fTransportProtocol::kUsbHumanInterfaceDevice);
   EXPECT_EQ(U2fTransportProtocol::kUsbHumanInterfaceDevice,
             discovery_hid.GetTransportProtocol());
 }
 
-TEST_F(FakeU2fDiscoveryTest, InitialState) {
-  FakeU2fDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+TEST_F(FakeFidoDiscoveryTest, InitialState) {
+  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
 
   ASSERT_FALSE(discovery.is_running());
   ASSERT_FALSE(discovery.is_start_requested());
   ASSERT_FALSE(discovery.is_stop_requested());
 }
 
-TEST_F(FakeU2fDiscoveryTest, StartStopDiscovery) {
-  FakeU2fDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+TEST_F(FakeFidoDiscoveryTest, StartStopDiscovery) {
+  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
 
-  MockU2fDiscoveryObserver observer;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
 
   discovery.Start();
@@ -85,10 +85,10 @@
   ASSERT_TRUE(discovery.is_stop_requested());
 }
 
-TEST_F(FakeU2fDiscoveryTest, WaitThenStartStopDiscovery) {
-  FakeU2fDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+TEST_F(FakeFidoDiscoveryTest, WaitThenStartStopDiscovery) {
+  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
 
-  MockU2fDiscoveryObserver observer;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -127,10 +127,10 @@
 }
 
 // Starting discovery and failing: instance stays in "not running" state
-TEST_F(FakeU2fDiscoveryTest, StartFail) {
-  FakeU2fDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+TEST_F(FakeFidoDiscoveryTest, StartFail) {
+  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
 
-  MockU2fDiscoveryObserver observer;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
 
   discovery.Start();
@@ -145,10 +145,10 @@
 }
 
 // Stopping discovery and failing: instance stays in a "running" state.
-TEST_F(FakeU2fDiscoveryTest, StopFail) {
-  FakeU2fDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+TEST_F(FakeFidoDiscoveryTest, StopFail) {
+  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
 
-  MockU2fDiscoveryObserver observer;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
 
   discovery.Start();
@@ -173,15 +173,15 @@
 }
 
 // Adding device is possible both before and after discovery actually starts.
-TEST_F(FakeU2fDiscoveryTest, AddDevice) {
-  FakeU2fDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
+TEST_F(FakeFidoDiscoveryTest, AddDevice) {
+  FakeFidoDiscovery discovery(U2fTransportProtocol::kBluetoothLowEnergy);
 
-  MockU2fDiscoveryObserver observer;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
 
   discovery.Start();
 
-  auto device0 = std::make_unique<MockU2fDevice>();
+  auto device0 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device0, GetId()).WillOnce(::testing::Return("device0"));
   EXPECT_CALL(observer, DeviceAdded(&discovery, ::testing::_));
   discovery.AddDevice(std::move(device0));
@@ -191,7 +191,7 @@
   discovery.SimulateStarted(true);
   ::testing::Mock::VerifyAndClearExpectations(&observer);
 
-  auto device1 = std::make_unique<MockU2fDevice>();
+  auto device1 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device1, GetId()).WillOnce(::testing::Return("device1"));
   EXPECT_CALL(observer, DeviceAdded(&discovery, ::testing::_));
   discovery.AddDevice(std::move(device1));
@@ -199,35 +199,35 @@
 }
 
 #if !defined(OS_ANDROID)
-TEST_F(ScopedFakeU2fDiscoveryFactoryTest,
+TEST_F(ScopedFakeFidoDiscoveryFactoryTest,
        OverridesUsbFactoryFunctionWhileInScope) {
-  ScopedFakeU2fDiscoveryFactory factory;
+  ScopedFakeFidoDiscoveryFactory factory;
   auto* injected_fake_discovery = factory.ForgeNextHidDiscovery();
   ASSERT_EQ(U2fTransportProtocol::kUsbHumanInterfaceDevice,
             injected_fake_discovery->GetTransportProtocol());
-  auto produced_discovery = U2fDiscovery::Create(
+  auto produced_discovery = FidoDiscovery::Create(
       U2fTransportProtocol::kUsbHumanInterfaceDevice, nullptr);
   EXPECT_TRUE(produced_discovery);
   EXPECT_EQ(injected_fake_discovery, produced_discovery.get());
 }
 #endif
 
-TEST_F(ScopedFakeU2fDiscoveryFactoryTest,
+TEST_F(ScopedFakeFidoDiscoveryFactoryTest,
        OverridesBleFactoryFunctionWhileInScope) {
-  ScopedFakeU2fDiscoveryFactory factory;
+  ScopedFakeFidoDiscoveryFactory factory;
 
   auto* injected_fake_discovery_1 = factory.ForgeNextBleDiscovery();
   ASSERT_EQ(U2fTransportProtocol::kBluetoothLowEnergy,
             injected_fake_discovery_1->GetTransportProtocol());
   auto produced_discovery_1 =
-      U2fDiscovery::Create(U2fTransportProtocol::kBluetoothLowEnergy, nullptr);
+      FidoDiscovery::Create(U2fTransportProtocol::kBluetoothLowEnergy, nullptr);
   EXPECT_EQ(injected_fake_discovery_1, produced_discovery_1.get());
 
   auto* injected_fake_discovery_2 = factory.ForgeNextBleDiscovery();
   ASSERT_EQ(U2fTransportProtocol::kBluetoothLowEnergy,
             injected_fake_discovery_2->GetTransportProtocol());
   auto produced_discovery_2 =
-      U2fDiscovery::Create(U2fTransportProtocol::kBluetoothLowEnergy, nullptr);
+      FidoDiscovery::Create(U2fTransportProtocol::kBluetoothLowEnergy, nullptr);
   EXPECT_EQ(injected_fake_discovery_2, produced_discovery_2.get());
 }
 
diff --git a/device/fido/fake_u2f_discovery.cc b/device/fido/fake_u2f_discovery.cc
deleted file mode 100644
index 0bf3432f0..0000000
--- a/device/fido/fake_u2f_discovery.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/fido/fake_u2f_discovery.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace device {
-namespace test {
-
-// FakeU2fDiscovery ----------------------------------------------------------
-
-FakeU2fDiscovery::FakeU2fDiscovery(U2fTransportProtocol transport,
-                                   StartStopMode mode)
-    : transport_(transport),
-      mode_(mode),
-      start_called_callback_(wait_for_start_loop_.QuitClosure()),
-      stop_called_callback_(wait_for_stop_loop_.QuitClosure()) {}
-FakeU2fDiscovery::~FakeU2fDiscovery() = default;
-
-void FakeU2fDiscovery::WaitForCallToStart() {
-  wait_for_start_loop_.Run();
-  ASSERT_FALSE(start_called_callback_);
-}
-
-void FakeU2fDiscovery::WaitForCallToStop() {
-  wait_for_stop_loop_.Run();
-  ASSERT_FALSE(stop_called_callback_);
-}
-
-void FakeU2fDiscovery::SimulateStarted(bool success) {
-  ASSERT_FALSE(is_running_);
-  is_running_ = success;
-  NotifyDiscoveryStarted(success);
-}
-
-void FakeU2fDiscovery::SimulateStopped(bool success) {
-  ASSERT_TRUE(is_running_);
-  is_running_ = !success;
-  NotifyDiscoveryStopped(success);
-}
-
-void FakeU2fDiscovery::WaitForCallToStartAndSimulateSuccess() {
-  WaitForCallToStart();
-  SimulateStarted(true /* success */);
-}
-
-void FakeU2fDiscovery::WaitForCallToStopAndSimulateSuccess() {
-  WaitForCallToStop();
-  SimulateStopped(true /* success */);
-}
-
-U2fTransportProtocol FakeU2fDiscovery::GetTransportProtocol() const {
-  return transport_;
-}
-
-void FakeU2fDiscovery::Start() {
-  if (is_running_)
-    return;
-
-  ASSERT_TRUE(start_called_callback_) << "Start called twice.";
-  std::move(start_called_callback_).Run();
-
-  if (mode_ == StartStopMode::kAutomatic)
-    SimulateStarted(true /* success */);
-}
-
-void FakeU2fDiscovery::Stop() {
-  if (!is_running_)
-    return;
-
-  ASSERT_TRUE(stop_called_callback_) << "Stop called twice.";
-  std::move(stop_called_callback_).Run();
-
-  if (mode_ == StartStopMode::kAutomatic)
-    SimulateStopped(true /* success */);
-}
-
-// ScopedFakeU2fDiscoveryFactory ---------------------------------------------
-
-ScopedFakeU2fDiscoveryFactory::ScopedFakeU2fDiscoveryFactory() = default;
-ScopedFakeU2fDiscoveryFactory::~ScopedFakeU2fDiscoveryFactory() = default;
-
-FakeU2fDiscovery* ScopedFakeU2fDiscoveryFactory::ForgeNextHidDiscovery(
-    FakeU2fDiscovery::StartStopMode mode) {
-  next_hid_discovery_ = std::make_unique<FakeU2fDiscovery>(
-      U2fTransportProtocol::kUsbHumanInterfaceDevice, mode);
-  return next_hid_discovery_.get();
-}
-
-FakeU2fDiscovery* ScopedFakeU2fDiscoveryFactory::ForgeNextBleDiscovery(
-    FakeU2fDiscovery::StartStopMode mode) {
-  next_ble_discovery_ = std::make_unique<FakeU2fDiscovery>(
-      U2fTransportProtocol::kBluetoothLowEnergy, mode);
-  return next_ble_discovery_.get();
-}
-
-std::unique_ptr<U2fDiscovery> ScopedFakeU2fDiscoveryFactory::CreateU2fDiscovery(
-    U2fTransportProtocol transport,
-    ::service_manager::Connector* connector) {
-  switch (transport) {
-    case U2fTransportProtocol::kBluetoothLowEnergy:
-      DCHECK(next_ble_discovery_);
-      return std::move(next_ble_discovery_);
-    case U2fTransportProtocol::kUsbHumanInterfaceDevice:
-      DCHECK(next_hid_discovery_);
-      return std::move(next_hid_discovery_);
-  }
-  NOTREACHED();
-  return nullptr;
-}
-
-}  // namespace test
-}  // namespace device
diff --git a/device/fido/u2f_device.cc b/device/fido/fido_device.cc
similarity index 65%
rename from device/fido/u2f_device.cc
rename to device/fido/fido_device.cc
index eb75a59..98bdbee 100644
--- a/device/fido/u2f_device.cc
+++ b/device/fido/fido_device.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "device/fido/u2f_device.h"
+#include "device/fido/fido_device.h"
 
 namespace device {
 
-U2fDevice::U2fDevice() = default;
-U2fDevice::~U2fDevice() = default;
+FidoDevice::FidoDevice() = default;
+FidoDevice::~FidoDevice() = default;
 
 }  // namespace device
diff --git a/device/fido/u2f_device.h b/device/fido/fido_device.h
similarity index 68%
rename from device/fido/u2f_device.h
rename to device/fido/fido_device.h
index 6065e05..3c98f7ad 100644
--- a/device/fido/u2f_device.h
+++ b/device/fido/fido_device.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_FIDO_U2F_DEVICE_H_
-#define DEVICE_FIDO_U2F_DEVICE_H_
+#ifndef DEVICE_FIDO_FIDO_DEVICE_H_
+#define DEVICE_FIDO_FIDO_DEVICE_H_
 
 #include <stdint.h>
 
@@ -19,9 +19,8 @@
 
 namespace device {
 
-// Device abstraction for an individual U2F device. A U2F device defines the
-// standardized Register, Sign, and GetVersion methods.
-class COMPONENT_EXPORT(DEVICE_FIDO) U2fDevice {
+// Device abstraction for an individual CTAP1.0/CTAP2.0 device.
+class COMPONENT_EXPORT(DEVICE_FIDO) FidoDevice {
  public:
   using WinkCallback = base::OnceClosure;
   using DeviceCallback =
@@ -30,21 +29,22 @@
   // Internal state machine states.
   enum class State { kInit, kConnected, kBusy, kReady, kDeviceError };
 
-  U2fDevice();
-  virtual ~U2fDevice();
+  FidoDevice();
+  virtual ~FidoDevice();
   // Pure virtual function defined by each device type, implementing
-  // the device communication transaction.
+  // the device communication transaction. The function must not immediately
+  // call (i.e. hairpin) |callback|.
   virtual void DeviceTransact(std::vector<uint8_t> command,
                               DeviceCallback callback) = 0;
   virtual void TryWink(WinkCallback callback) = 0;
   virtual std::string GetId() const = 0;
 
  protected:
-  virtual base::WeakPtr<U2fDevice> GetWeakPtr() = 0;
+  virtual base::WeakPtr<FidoDevice> GetWeakPtr() = 0;
 
-  DISALLOW_COPY_AND_ASSIGN(U2fDevice);
+  DISALLOW_COPY_AND_ASSIGN(FidoDevice);
 };
 
 }  // namespace device
 
-#endif  // DEVICE_FIDO_U2F_DEVICE_H_
+#endif  // DEVICE_FIDO_FIDO_DEVICE_H_
diff --git a/device/fido/fido_discovery.cc b/device/fido/fido_discovery.cc
new file mode 100644
index 0000000..0a432100
--- /dev/null
+++ b/device/fido/fido_discovery.cc
@@ -0,0 +1,168 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/fido/fido_discovery.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "device/fido/fido_device.h"
+#include "device/fido/u2f_ble_discovery.h"
+
+// HID is not supported on Android.
+#if !defined(OS_ANDROID)
+#include "device/fido/fido_hid_discovery.h"
+#endif  // !defined(OS_ANDROID)
+
+namespace device {
+
+namespace {
+
+std::unique_ptr<FidoDiscovery> CreateFidoDiscoveryImpl(
+    U2fTransportProtocol transport,
+    service_manager::Connector* connector) {
+  std::unique_ptr<FidoDiscovery> discovery;
+  switch (transport) {
+    case U2fTransportProtocol::kUsbHumanInterfaceDevice:
+#if !defined(OS_ANDROID)
+      DCHECK(connector);
+      discovery = std::make_unique<FidoHidDiscovery>(connector);
+#else
+      NOTREACHED() << "USB HID not supported on Android.";
+#endif  // !defined(OS_ANDROID)
+      break;
+    case U2fTransportProtocol::kBluetoothLowEnergy:
+      discovery = std::make_unique<U2fBleDiscovery>();
+      break;
+  }
+
+  DCHECK(discovery);
+  DCHECK_EQ(discovery->GetTransportProtocol(), transport);
+  return discovery;
+}
+
+}  // namespace
+
+FidoDiscovery::Observer::~Observer() = default;
+
+// static
+FidoDiscovery::FactoryFuncPtr FidoDiscovery::g_factory_func_ =
+    &CreateFidoDiscoveryImpl;
+
+// static
+std::unique_ptr<FidoDiscovery> FidoDiscovery::Create(
+    U2fTransportProtocol transport,
+    service_manager::Connector* connector) {
+  return (*g_factory_func_)(transport, connector);
+}
+
+FidoDiscovery::FidoDiscovery() = default;
+
+FidoDiscovery::~FidoDiscovery() = default;
+
+void FidoDiscovery::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void FidoDiscovery::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void FidoDiscovery::NotifyDiscoveryStarted(bool success) {
+  for (auto& observer : observers_)
+    observer.DiscoveryStarted(this, success);
+}
+
+void FidoDiscovery::NotifyDiscoveryStopped(bool success) {
+  for (auto& observer : observers_)
+    observer.DiscoveryStopped(this, success);
+}
+
+void FidoDiscovery::NotifyDeviceAdded(FidoDevice* device) {
+  for (auto& observer : observers_)
+    observer.DeviceAdded(this, device);
+}
+
+void FidoDiscovery::NotifyDeviceRemoved(FidoDevice* device) {
+  for (auto& observer : observers_)
+    observer.DeviceRemoved(this, device);
+}
+
+std::vector<FidoDevice*> FidoDiscovery::GetDevices() {
+  std::vector<FidoDevice*> devices;
+  devices.reserve(devices_.size());
+  for (const auto& device : devices_)
+    devices.push_back(device.second.get());
+  return devices;
+}
+
+std::vector<const FidoDevice*> FidoDiscovery::GetDevices() const {
+  std::vector<const FidoDevice*> devices;
+  devices.reserve(devices_.size());
+  for (const auto& device : devices_)
+    devices.push_back(device.second.get());
+  return devices;
+}
+
+FidoDevice* FidoDiscovery::GetDevice(base::StringPiece device_id) {
+  return const_cast<FidoDevice*>(
+      static_cast<const FidoDiscovery*>(this)->GetDevice(device_id));
+}
+
+const FidoDevice* FidoDiscovery::GetDevice(base::StringPiece device_id) const {
+  auto found = devices_.find(device_id);
+  return found != devices_.end() ? found->second.get() : nullptr;
+}
+
+bool FidoDiscovery::AddDevice(std::unique_ptr<FidoDevice> device) {
+  std::string device_id = device->GetId();
+  const auto result = devices_.emplace(std::move(device_id), std::move(device));
+  if (result.second)
+    NotifyDeviceAdded(result.first->second.get());
+  return result.second;
+}
+
+bool FidoDiscovery::RemoveDevice(base::StringPiece device_id) {
+  auto found = devices_.find(device_id);
+  if (found == devices_.end())
+    return false;
+
+  auto device = std::move(found->second);
+  devices_.erase(found);
+  NotifyDeviceRemoved(device.get());
+  return true;
+}
+
+// ScopedFidoDiscoveryFactory -------------------------------------------------
+
+namespace internal {
+
+ScopedFidoDiscoveryFactory::ScopedFidoDiscoveryFactory() {
+  original_factory_ = std::exchange(g_current_factory, this);
+  original_factory_func_ =
+      std::exchange(FidoDiscovery::g_factory_func_,
+                    &ForwardCreateFidoDiscoveryToCurrentFactory);
+}
+
+ScopedFidoDiscoveryFactory::~ScopedFidoDiscoveryFactory() {
+  g_current_factory = original_factory_;
+  FidoDiscovery::g_factory_func_ = original_factory_func_;
+}
+
+// static
+std::unique_ptr<FidoDiscovery>
+ScopedFidoDiscoveryFactory::ForwardCreateFidoDiscoveryToCurrentFactory(
+    U2fTransportProtocol transport,
+    ::service_manager::Connector* connector) {
+  DCHECK(g_current_factory);
+  return g_current_factory->CreateFidoDiscovery(transport, connector);
+}
+
+// static
+ScopedFidoDiscoveryFactory* ScopedFidoDiscoveryFactory::g_current_factory =
+    nullptr;
+
+}  // namespace internal
+}  // namespace device
diff --git a/device/fido/fido_discovery.h b/device/fido/fido_discovery.h
new file mode 100644
index 0000000..3c263d7
--- /dev/null
+++ b/device/fido/fido_discovery.h
@@ -0,0 +1,127 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_FIDO_FIDO_DISCOVERY_H_
+#define DEVICE_FIDO_FIDO_DISCOVERY_H_
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/strings/string_piece.h"
+#include "device/fido/u2f_transport_protocol.h"
+
+namespace service_manager {
+class Connector;
+}
+
+namespace device {
+
+class FidoDevice;
+
+namespace internal {
+class ScopedFidoDiscoveryFactory;
+}
+
+class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscovery {
+ public:
+  class COMPONENT_EXPORT(DEVICE_FIDO) Observer {
+   public:
+    virtual ~Observer();
+    virtual void DiscoveryStarted(FidoDiscovery* discovery, bool success) = 0;
+    virtual void DiscoveryStopped(FidoDiscovery* discovery, bool success) = 0;
+    virtual void DeviceAdded(FidoDiscovery* discovery, FidoDevice* device) = 0;
+    virtual void DeviceRemoved(FidoDiscovery* discovery,
+                               FidoDevice* device) = 0;
+  };
+
+  // Factory function to construct an instance that discovers authenticators on
+  // the given |transport| protocol.
+  //
+  // U2fTransportProtocol::kUsbHumanInterfaceDevice requires specifying a valid
+  // |connector| on Desktop, and is not valid on Android.
+  static std::unique_ptr<FidoDiscovery> Create(
+      U2fTransportProtocol transport,
+      ::service_manager::Connector* connector);
+
+  virtual ~FidoDiscovery();
+
+  virtual U2fTransportProtocol GetTransportProtocol() const = 0;
+  virtual void Start() = 0;
+  virtual void Stop() = 0;
+
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+  void NotifyDiscoveryStarted(bool success);
+  void NotifyDiscoveryStopped(bool success);
+  void NotifyDeviceAdded(FidoDevice* device);
+  void NotifyDeviceRemoved(FidoDevice* device);
+
+  std::vector<FidoDevice*> GetDevices();
+  std::vector<const FidoDevice*> GetDevices() const;
+
+  FidoDevice* GetDevice(base::StringPiece device_id);
+  const FidoDevice* GetDevice(base::StringPiece device_id) const;
+
+ protected:
+  FidoDiscovery();
+
+  virtual bool AddDevice(std::unique_ptr<FidoDevice> device);
+  virtual bool RemoveDevice(base::StringPiece device_id);
+
+  std::map<std::string, std::unique_ptr<FidoDevice>, std::less<>> devices_;
+  base::ObserverList<Observer> observers_;
+
+ private:
+  friend class internal::ScopedFidoDiscoveryFactory;
+
+  // Factory function can be overridden by tests to construct fakes.
+  using FactoryFuncPtr = decltype(&Create);
+  static FactoryFuncPtr g_factory_func_;
+
+  DISALLOW_COPY_AND_ASSIGN(FidoDiscovery);
+};
+
+namespace internal {
+
+// Base class for a scoped override of FidoDiscovery::Create, used in unit
+// tests, layout tests, and when running with the Web Authn Testing API enabled.
+//
+// While there is a subclass instance in scope, calls to the factory method will
+// be hijacked such that the derived class's CreateFidoDiscovery method will be
+// invoked instead.
+class COMPONENT_EXPORT(DEVICE_FIDO) ScopedFidoDiscoveryFactory {
+ public:
+  ScopedFidoDiscoveryFactory();
+  ~ScopedFidoDiscoveryFactory();
+
+ protected:
+  virtual std::unique_ptr<FidoDiscovery> CreateFidoDiscovery(
+      U2fTransportProtocol transport,
+      ::service_manager::Connector* connector) = 0;
+
+ private:
+  static std::unique_ptr<FidoDiscovery>
+  ForwardCreateFidoDiscoveryToCurrentFactory(
+      U2fTransportProtocol transport,
+      ::service_manager::Connector* connector);
+
+  static ScopedFidoDiscoveryFactory* g_current_factory;
+  ScopedFidoDiscoveryFactory* original_factory_;
+  FidoDiscovery::FactoryFuncPtr original_factory_func_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedFidoDiscoveryFactory);
+};
+
+}  // namespace internal
+}  // namespace device
+
+#endif  // DEVICE_FIDO_FIDO_DISCOVERY_H_
diff --git a/device/fido/u2f_discovery_unittest.cc b/device/fido/fido_discovery_unittest.cc
similarity index 75%
rename from device/fido/u2f_discovery_unittest.cc
rename to device/fido/fido_discovery_unittest.cc
index be5d820..bd2a160b 100644
--- a/device/fido/u2f_discovery_unittest.cc
+++ b/device/fido/fido_discovery_unittest.cc
@@ -2,13 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "device/fido/u2f_discovery.h"
-
 #include <utility>
 
 #include "base/macros.h"
-#include "device/fido/mock_u2f_device.h"
-#include "device/fido/mock_u2f_discovery_observer.h"
+#include "device/fido/fido_discovery.h"
+#include "device/fido/mock_fido_device.h"
+#include "device/fido/mock_fido_discovery_observer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -20,14 +19,14 @@
 using ::testing::Return;
 using ::testing::UnorderedElementsAre;
 
-// A minimal implementation of U2FDiscovery that is no longer abstract.
-class ConcreteU2fDiscovery : public U2fDiscovery {
+// A minimal implementation of FidoDiscovery that is no longer abstract.
+class ConcreteFidoDiscovery : public FidoDiscovery {
  public:
-  ConcreteU2fDiscovery() = default;
-  ~ConcreteU2fDiscovery() override = default;
+  ConcreteFidoDiscovery() = default;
+  ~ConcreteFidoDiscovery() override = default;
 
-  using U2fDiscovery::AddDevice;
-  using U2fDiscovery::RemoveDevice;
+  using FidoDiscovery::AddDevice;
+  using FidoDiscovery::RemoveDevice;
 
   const base::ObserverList<Observer>& observers() const { return observers_; }
 
@@ -39,26 +38,26 @@
   void Stop() override {}
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(ConcreteU2fDiscovery);
+  DISALLOW_COPY_AND_ASSIGN(ConcreteFidoDiscovery);
 };
 
 }  // namespace
 
-TEST(U2fDiscoveryTest, TestAddAndRemoveObserver) {
-  ConcreteU2fDiscovery discovery;
-  MockU2fDiscoveryObserver observer;
+TEST(FidoDiscoveryTest, TestAddAndRemoveObserver) {
+  ConcreteFidoDiscovery discovery;
+  MockFidoDiscoveryObserver observer;
   EXPECT_FALSE(discovery.observers().HasObserver(&observer));
-
   discovery.AddObserver(&observer);
+
   EXPECT_TRUE(discovery.observers().HasObserver(&observer));
 
   discovery.RemoveObserver(&observer);
   EXPECT_FALSE(discovery.observers().HasObserver(&observer));
 }
 
-TEST(U2fDiscoveryTest, TestNotifications) {
-  ConcreteU2fDiscovery discovery;
-  MockU2fDiscoveryObserver observer;
+TEST(FidoDiscoveryTest, TestNotifications) {
+  ConcreteFidoDiscovery discovery;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
 
   EXPECT_CALL(observer, DiscoveryStarted(&discovery, true));
@@ -73,7 +72,7 @@
   EXPECT_CALL(observer, DiscoveryStopped(&discovery, false));
   discovery.NotifyDiscoveryStopped(false);
 
-  MockU2fDevice device;
+  MockFidoDevice device;
   EXPECT_CALL(observer, DeviceAdded(&discovery, &device));
   discovery.NotifyDeviceAdded(&device);
 
@@ -81,27 +80,27 @@
   discovery.NotifyDeviceRemoved(&device);
 }
 
-TEST(U2fDiscoveryTest, TestAddRemoveDevices) {
-  ConcreteU2fDiscovery discovery;
-  MockU2fDiscoveryObserver observer;
+TEST(FidoDiscoveryTest, TestAddRemoveDevices) {
+  ConcreteFidoDiscovery discovery;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
 
   // Expect successful insertion.
-  auto device0 = std::make_unique<MockU2fDevice>();
+  auto device0 = std::make_unique<MockFidoDevice>();
   auto* device0_raw = device0.get();
   EXPECT_CALL(observer, DeviceAdded(&discovery, device0_raw));
   EXPECT_CALL(*device0, GetId()).WillOnce(Return("device0"));
   EXPECT_TRUE(discovery.AddDevice(std::move(device0)));
 
   // // Expect successful insertion.
-  auto device1 = std::make_unique<MockU2fDevice>();
+  auto device1 = std::make_unique<MockFidoDevice>();
   auto* device1_raw = device1.get();
   EXPECT_CALL(observer, DeviceAdded(&discovery, device1_raw));
   EXPECT_CALL(*device1, GetId()).WillOnce(Return("device1"));
   EXPECT_TRUE(discovery.AddDevice(std::move(device1)));
 
   // Inserting a device with an already present id should be prevented.
-  auto device1_dup = std::make_unique<MockU2fDevice>();
+  auto device1_dup = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(observer, DeviceAdded(_, _)).Times(0);
   EXPECT_CALL(*device1_dup, GetId()).WillOnce(Return("device1"));
   EXPECT_FALSE(discovery.AddDevice(std::move(device1_dup)));
@@ -111,7 +110,7 @@
   EXPECT_THAT(discovery.GetDevices(),
               UnorderedElementsAre(device0_raw, device1_raw));
 
-  const U2fDiscovery& const_discovery = discovery;
+  const FidoDiscovery& const_discovery = discovery;
   EXPECT_EQ(device0_raw, const_discovery.GetDevice("device0"));
   EXPECT_EQ(device1_raw, const_discovery.GetDevice("device1"));
   EXPECT_THAT(const_discovery.GetDevices(),
diff --git a/device/fido/u2f_hid_device.cc b/device/fido/fido_hid_device.cc
similarity index 71%
rename from device/fido/u2f_hid_device.cc
rename to device/fido/fido_hid_device.cc
index 88df56b..4f76c20f 100644
--- a/device/fido/u2f_hid_device.cc
+++ b/device/fido/fido_hid_device.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "device/fido/u2f_hid_device.h"
+#include "device/fido/fido_hid_device.h"
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -23,23 +23,23 @@
 static constexpr uint8_t kReportId = 0x00;
 }  // namespace
 
-U2fHidDevice::U2fHidDevice(device::mojom::HidDeviceInfoPtr device_info,
-                           device::mojom::HidManager* hid_manager)
-    : U2fDevice(),
+FidoHidDevice::FidoHidDevice(device::mojom::HidDeviceInfoPtr device_info,
+                             device::mojom::HidManager* hid_manager)
+    : FidoDevice(),
       state_(State::kInit),
       hid_manager_(hid_manager),
       device_info_(std::move(device_info)),
       weak_factory_(this) {}
 
-U2fHidDevice::~U2fHidDevice() = default;
+FidoHidDevice::~FidoHidDevice() = default;
 
-void U2fHidDevice::DeviceTransact(std::vector<uint8_t> command,
-                                  DeviceCallback callback) {
+void FidoHidDevice::DeviceTransact(std::vector<uint8_t> command,
+                                   DeviceCallback callback) {
   Transition(std::move(command), std::move(callback));
 }
 
-void U2fHidDevice::Transition(std::vector<uint8_t> command,
-                              DeviceCallback callback) {
+void FidoHidDevice::Transition(std::vector<uint8_t> command,
+                               DeviceCallback callback) {
   // This adapter is needed to support the calls to ArmTimeout(). However, it is
   // still guaranteed that |callback| will only be invoked once.
   auto repeating_callback =
@@ -48,7 +48,7 @@
     case State::kInit:
       state_ = State::kBusy;
       ArmTimeout(repeating_callback);
-      Connect(base::BindOnce(&U2fHidDevice::OnConnect,
+      Connect(base::BindOnce(&FidoHidDevice::OnConnect,
                              weak_factory_.GetWeakPtr(), std::move(command),
                              repeating_callback));
       break;
@@ -65,7 +65,7 @@
           FidoHidMessage::Create(channel_id_, FidoHidDeviceCommand::kMsg,
                                  std::move(command)),
           true,
-          base::BindOnce(&U2fHidDevice::MessageReceived,
+          base::BindOnce(&FidoHidDevice::MessageReceived,
                          weak_factory_.GetWeakPtr(), repeating_callback));
       break;
     }
@@ -74,7 +74,7 @@
       break;
     case State::kDeviceError:
     default:
-      base::WeakPtr<U2fHidDevice> self = weak_factory_.GetWeakPtr();
+      base::WeakPtr<FidoHidDevice> self = weak_factory_.GetWeakPtr();
       repeating_callback.Run(base::nullopt);
       // Executing callbacks may free |this|. Check |self| first.
       while (self && !pending_transactions_.empty()) {
@@ -88,14 +88,14 @@
   }
 }
 
-void U2fHidDevice::Connect(ConnectCallback callback) {
+void FidoHidDevice::Connect(ConnectCallback callback) {
   DCHECK(hid_manager_);
   hid_manager_->Connect(device_info_->guid, std::move(callback));
 }
 
-void U2fHidDevice::OnConnect(std::vector<uint8_t> command,
-                             DeviceCallback callback,
-                             device::mojom::HidConnectionPtr connection) {
+void FidoHidDevice::OnConnect(std::vector<uint8_t> command,
+                              DeviceCallback callback,
+                              device::mojom::HidConnectionPtr connection) {
   if (state_ == State::kDeviceError)
     return;
   timeout_callback_.Cancel();
@@ -109,24 +109,24 @@
   Transition(std::move(command), std::move(callback));
 }
 
-void U2fHidDevice::AllocateChannel(std::vector<uint8_t> command,
-                                   DeviceCallback callback) {
+void FidoHidDevice::AllocateChannel(std::vector<uint8_t> command,
+                                    DeviceCallback callback) {
   // Send random nonce to device to verify received message.
   std::vector<uint8_t> nonce(8);
   crypto::RandBytes(nonce.data(), nonce.size());
   WriteMessage(
       FidoHidMessage::Create(channel_id_, FidoHidDeviceCommand::kInit, nonce),
       true,
-      base::BindOnce(&U2fHidDevice::OnAllocateChannel,
+      base::BindOnce(&FidoHidDevice::OnAllocateChannel,
                      weak_factory_.GetWeakPtr(), nonce, std::move(command),
                      std::move(callback)));
 }
 
-void U2fHidDevice::OnAllocateChannel(std::vector<uint8_t> nonce,
-                                     std::vector<uint8_t> command,
-                                     DeviceCallback callback,
-                                     bool success,
-                                     std::unique_ptr<FidoHidMessage> message) {
+void FidoHidDevice::OnAllocateChannel(std::vector<uint8_t> nonce,
+                                      std::vector<uint8_t> command,
+                                      DeviceCallback callback,
+                                      bool success,
+                                      std::unique_ptr<FidoHidMessage> message) {
   if (state_ == State::kDeviceError)
     return;
   timeout_callback_.Cancel();
@@ -159,7 +159,7 @@
     auto repeating_callback =
         base::AdaptCallbackForRepeating(std::move(callback));
     ArmTimeout(repeating_callback);
-    ReadMessage(base::BindOnce(&U2fHidDevice::OnAllocateChannel,
+    ReadMessage(base::BindOnce(&FidoHidDevice::OnAllocateChannel,
                                weak_factory_.GetWeakPtr(), nonce,
                                std::move(command), repeating_callback));
     return;
@@ -175,9 +175,9 @@
   Transition(std::move(command), std::move(callback));
 }
 
-void U2fHidDevice::WriteMessage(std::unique_ptr<FidoHidMessage> message,
-                                bool response_expected,
-                                U2fHidMessageCallback callback) {
+void FidoHidDevice::WriteMessage(std::unique_ptr<FidoHidMessage> message,
+                                 bool response_expected,
+                                 HidMessageCallback callback) {
   if (!connection_ || !message || message->NumPackets() == 0) {
     std::move(callback).Run(false, nullptr);
     return;
@@ -185,14 +185,14 @@
   const auto& packet = message->PopNextPacket();
   connection_->Write(
       kReportId, packet,
-      base::BindOnce(&U2fHidDevice::PacketWritten, weak_factory_.GetWeakPtr(),
+      base::BindOnce(&FidoHidDevice::PacketWritten, weak_factory_.GetWeakPtr(),
                      std::move(message), true, std::move(callback)));
 }
 
-void U2fHidDevice::PacketWritten(std::unique_ptr<FidoHidMessage> message,
-                                 bool response_expected,
-                                 U2fHidMessageCallback callback,
-                                 bool success) {
+void FidoHidDevice::PacketWritten(std::unique_ptr<FidoHidMessage> message,
+                                  bool response_expected,
+                                  HidMessageCallback callback,
+                                  bool success) {
   if (success && message->NumPackets() > 0) {
     WriteMessage(std::move(message), response_expected, std::move(callback));
   } else if (success && response_expected) {
@@ -202,19 +202,19 @@
   }
 }
 
-void U2fHidDevice::ReadMessage(U2fHidMessageCallback callback) {
+void FidoHidDevice::ReadMessage(HidMessageCallback callback) {
   if (!connection_) {
     std::move(callback).Run(false, nullptr);
     return;
   }
   connection_->Read(base::BindOnce(
-      &U2fHidDevice::OnRead, weak_factory_.GetWeakPtr(), std::move(callback)));
+      &FidoHidDevice::OnRead, weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void U2fHidDevice::OnRead(U2fHidMessageCallback callback,
-                          bool success,
-                          uint8_t report_id,
-                          const base::Optional<std::vector<uint8_t>>& buf) {
+void FidoHidDevice::OnRead(HidMessageCallback callback,
+                           bool success,
+                           uint8_t report_id,
+                           const base::Optional<std::vector<uint8_t>>& buf) {
   if (!success) {
     std::move(callback).Run(success, nullptr);
     return;
@@ -229,7 +229,7 @@
 
   // Received a message from a different channel, so try again.
   if (channel_id_ != read_message->channel_id()) {
-    connection_->Read(base::BindOnce(&U2fHidDevice::OnRead,
+    connection_->Read(base::BindOnce(&FidoHidDevice::OnRead,
                                      weak_factory_.GetWeakPtr(),
                                      std::move(callback)));
     return;
@@ -242,13 +242,13 @@
 
   // Continue reading additional packets.
   connection_->Read(base::BindOnce(
-      &U2fHidDevice::OnReadContinuation, weak_factory_.GetWeakPtr(),
+      &FidoHidDevice::OnReadContinuation, weak_factory_.GetWeakPtr(),
       std::move(read_message), std::move(callback)));
 }
 
-void U2fHidDevice::OnReadContinuation(
+void FidoHidDevice::OnReadContinuation(
     std::unique_ptr<FidoHidMessage> message,
-    U2fHidMessageCallback callback,
+    HidMessageCallback callback,
     bool success,
     uint8_t report_id,
     const base::Optional<std::vector<uint8_t>>& buf) {
@@ -263,14 +263,14 @@
     std::move(callback).Run(success, std::move(message));
     return;
   }
-  connection_->Read(base::BindOnce(&U2fHidDevice::OnReadContinuation,
+  connection_->Read(base::BindOnce(&FidoHidDevice::OnReadContinuation,
                                    weak_factory_.GetWeakPtr(),
                                    std::move(message), std::move(callback)));
 }
 
-void U2fHidDevice::MessageReceived(DeviceCallback callback,
-                                   bool success,
-                                   std::unique_ptr<FidoHidMessage> message) {
+void FidoHidDevice::MessageReceived(DeviceCallback callback,
+                                    bool success,
+                                    std::unique_ptr<FidoHidMessage> message) {
   if (state_ == State::kDeviceError)
     return;
   timeout_callback_.Cancel();
@@ -281,7 +281,7 @@
   }
 
   state_ = State::kReady;
-  base::WeakPtr<U2fHidDevice> self = weak_factory_.GetWeakPtr();
+  base::WeakPtr<FidoHidDevice> self = weak_factory_.GetWeakPtr();
   std::move(callback).Run(
       (success && message) ? base::make_optional(message->GetMessagePayload())
                            : base::nullopt);
@@ -296,7 +296,7 @@
   }
 }
 
-void U2fHidDevice::TryWink(WinkCallback callback) {
+void FidoHidDevice::TryWink(WinkCallback callback) {
   // Only try to wink if device claims support.
   if (!(capabilities_ & kWinkCapability) || state_ != State::kReady) {
     std::move(callback).Run();
@@ -306,19 +306,19 @@
   WriteMessage(FidoHidMessage::Create(channel_id_, FidoHidDeviceCommand::kWink,
                                       std::vector<uint8_t>()),
                true,
-               base::BindOnce(&U2fHidDevice::OnWink, weak_factory_.GetWeakPtr(),
-                              std::move(callback)));
+               base::BindOnce(&FidoHidDevice::OnWink,
+                              weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void U2fHidDevice::OnWink(WinkCallback callback,
-                          bool success,
-                          std::unique_ptr<FidoHidMessage> response) {
+void FidoHidDevice::OnWink(WinkCallback callback,
+                           bool success,
+                           std::unique_ptr<FidoHidMessage> response) {
   std::move(callback).Run();
 }
 
-void U2fHidDevice::ArmTimeout(DeviceCallback callback) {
+void FidoHidDevice::ArmTimeout(DeviceCallback callback) {
   DCHECK(timeout_callback_.IsCancelled());
-  timeout_callback_.Reset(base::BindOnce(&U2fHidDevice::OnTimeout,
+  timeout_callback_.Reset(base::BindOnce(&FidoHidDevice::OnTimeout,
                                          weak_factory_.GetWeakPtr(),
                                          std::move(callback)));
   // Setup timeout task for 3 seconds.
@@ -326,28 +326,28 @@
       FROM_HERE, timeout_callback_.callback(), kDeviceTimeout);
 }
 
-void U2fHidDevice::OnTimeout(DeviceCallback callback) {
+void FidoHidDevice::OnTimeout(DeviceCallback callback) {
   state_ = State::kDeviceError;
   Transition(std::vector<uint8_t>(), std::move(callback));
 }
 
-std::string U2fHidDevice::GetId() const {
+std::string FidoHidDevice::GetId() const {
   return GetIdForDevice(*device_info_);
 }
 
 // static
-std::string U2fHidDevice::GetIdForDevice(
+std::string FidoHidDevice::GetIdForDevice(
     const device::mojom::HidDeviceInfo& device_info) {
   return "hid:" + device_info.guid;
 }
 
 // static
-bool U2fHidDevice::IsTestEnabled() {
+bool FidoHidDevice::IsTestEnabled() {
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   return command_line->HasSwitch(switches::kEnableU2fHidTest);
 }
 
-base::WeakPtr<U2fDevice> U2fHidDevice::GetWeakPtr() {
+base::WeakPtr<FidoDevice> FidoHidDevice::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
 
diff --git a/device/fido/u2f_hid_device.h b/device/fido/fido_hid_device.h
similarity index 76%
rename from device/fido/u2f_hid_device.h
rename to device/fido/fido_hid_device.h
index a42e6a6c..2dcfecf 100644
--- a/device/fido/u2f_hid_device.h
+++ b/device/fido/fido_hid_device.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_FIDO_U2F_HID_DEVICE_H_
-#define DEVICE_FIDO_U2F_HID_DEVICE_H_
+#ifndef DEVICE_FIDO_FIDO_HID_DEVICE_H_
+#define DEVICE_FIDO_FIDO_HID_DEVICE_H_
 
 #include <memory>
 #include <queue>
@@ -17,18 +17,18 @@
 #include "base/macros.h"
 #include "components/apdu/apdu_command.h"
 #include "components/apdu/apdu_response.h"
-#include "device/fido/u2f_device.h"
+#include "device/fido/fido_device.h"
 #include "services/device/public/mojom/hid.mojom.h"
 
 namespace device {
 
 class FidoHidMessage;
 
-class COMPONENT_EXPORT(DEVICE_FIDO) U2fHidDevice : public U2fDevice {
+class COMPONENT_EXPORT(DEVICE_FIDO) FidoHidDevice : public FidoDevice {
  public:
-  U2fHidDevice(device::mojom::HidDeviceInfoPtr device_info,
-               device::mojom::HidManager* hid_manager);
-  ~U2fHidDevice() final;
+  FidoHidDevice(device::mojom::HidDeviceInfoPtr device_info,
+                device::mojom::HidManager* hid_manager);
+  ~FidoHidDevice() final;
 
   // Send a command to this device.
   void DeviceTransact(std::vector<uint8_t> command,
@@ -45,15 +45,15 @@
   static bool IsTestEnabled();
 
  private:
-  FRIEND_TEST_ALL_PREFIXES(U2fHidDeviceTest, TestConnectionFailure);
-  FRIEND_TEST_ALL_PREFIXES(U2fHidDeviceTest, TestDeviceError);
-  FRIEND_TEST_ALL_PREFIXES(U2fHidDeviceTest, TestRetryChannelAllocation);
+  FRIEND_TEST_ALL_PREFIXES(FidoHidDeviceTest, TestConnectionFailure);
+  FRIEND_TEST_ALL_PREFIXES(FidoHidDeviceTest, TestDeviceError);
+  FRIEND_TEST_ALL_PREFIXES(FidoHidDeviceTest, TestRetryChannelAllocation);
 
   static constexpr uint8_t kWinkCapability = 0x01;
   static constexpr uint8_t kLockCapability = 0x02;
   static constexpr uint32_t kBroadcastChannel = 0xffffffff;
 
-  using U2fHidMessageCallback =
+  using HidMessageCallback =
       base::OnceCallback<void(bool, std::unique_ptr<FidoHidMessage>)>;
   using ConnectCallback = device::mojom::HidManager::ConnectCallback;
 
@@ -73,22 +73,22 @@
   // Write all message packets to device, and read response if expected.
   void WriteMessage(std::unique_ptr<FidoHidMessage> message,
                     bool response_expected,
-                    U2fHidMessageCallback callback);
+                    HidMessageCallback callback);
   void PacketWritten(std::unique_ptr<FidoHidMessage> message,
                      bool response_expected,
-                     U2fHidMessageCallback callback,
+                     HidMessageCallback callback,
                      bool success);
   // Read all response message packets from device.
-  void ReadMessage(U2fHidMessageCallback callback);
+  void ReadMessage(HidMessageCallback callback);
   void MessageReceived(DeviceCallback callback,
                        bool success,
                        std::unique_ptr<FidoHidMessage> message);
-  void OnRead(U2fHidMessageCallback callback,
+  void OnRead(HidMessageCallback callback,
               bool success,
               uint8_t report_id,
               const base::Optional<std::vector<uint8_t>>& buf);
   void OnReadContinuation(std::unique_ptr<FidoHidMessage> message,
-                          U2fHidMessageCallback callback,
+                          HidMessageCallback callback,
                           bool success,
                           uint8_t report_id,
                           const base::Optional<std::vector<uint8_t>>& buf);
@@ -97,7 +97,7 @@
               std::unique_ptr<FidoHidMessage> response);
   void ArmTimeout(DeviceCallback callback);
   void OnTimeout(DeviceCallback callback);
-  base::WeakPtr<U2fDevice> GetWeakPtr() override;
+  base::WeakPtr<FidoDevice> GetWeakPtr() override;
 
   uint32_t channel_id_ = kBroadcastChannel;
   uint8_t capabilities_ = 0;
@@ -107,17 +107,17 @@
   std::queue<std::pair<std::vector<uint8_t>, DeviceCallback>>
       pending_transactions_;
 
-  // All the U2fHidDevice instances are owned by U2fRequest. So it is safe to
-  // let the U2fHidDevice share the device::mojo::HidManager raw pointer from
+  // All the FidoHidDevice instances are owned by U2fRequest. So it is safe to
+  // let the FidoHidDevice share the device::mojo::HidManager raw pointer from
   // U2fRequest.
   device::mojom::HidManager* hid_manager_;
   device::mojom::HidDeviceInfoPtr device_info_;
   device::mojom::HidConnectionPtr connection_;
-  base::WeakPtrFactory<U2fHidDevice> weak_factory_;
+  base::WeakPtrFactory<FidoHidDevice> weak_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(U2fHidDevice);
+  DISALLOW_COPY_AND_ASSIGN(FidoHidDevice);
 };
 
 }  // namespace device
 
-#endif  // DEVICE_FIDO_U2F_HID_DEVICE_H_
+#endif  // DEVICE_FIDO_FIDO_HID_DEVICE_H_
diff --git a/device/fido/u2f_hid_device_unittest.cc b/device/fido/fido_hid_device_unittest.cc
similarity index 88%
rename from device/fido/u2f_hid_device_unittest.cc
rename to device/fido/fido_hid_device_unittest.cc
index 4e2d5f3..be65157 100644
--- a/device/fido/u2f_hid_device_unittest.cc
+++ b/device/fido/fido_hid_device_unittest.cc
@@ -14,8 +14,8 @@
 #include "components/apdu/apdu_response.h"
 #include "device/fido/fake_hid_impl_for_testing.h"
 #include "device/fido/fido_constants.h"
+#include "device/fido/fido_hid_device.h"
 #include "device/fido/test_callback_receiver.h"
-#include "device/fido/u2f_hid_device.h"
 #include "device/fido/u2f_request.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
@@ -91,23 +91,23 @@
   return hid_device;
 }
 
-class U2fDeviceEnumerateCallbackReceiver
+class FidoDeviceEnumerateCallbackReceiver
     : public test::TestCallbackReceiver<std::vector<mojom::HidDeviceInfoPtr>> {
  public:
-  explicit U2fDeviceEnumerateCallbackReceiver(
+  explicit FidoDeviceEnumerateCallbackReceiver(
       device::mojom::HidManager* hid_manager)
       : hid_manager_(hid_manager) {}
-  ~U2fDeviceEnumerateCallbackReceiver() = default;
+  ~FidoDeviceEnumerateCallbackReceiver() = default;
 
-  std::vector<std::unique_ptr<U2fHidDevice>> TakeReturnedDevicesFiltered() {
-    std::vector<std::unique_ptr<U2fHidDevice>> filtered_results;
+  std::vector<std::unique_ptr<FidoHidDevice>> TakeReturnedDevicesFiltered() {
+    std::vector<std::unique_ptr<FidoHidDevice>> filtered_results;
     std::vector<mojom::HidDeviceInfoPtr> results;
     std::tie(results) = TakeResult();
     for (auto& device_info : results) {
       HidDeviceFilter filter;
       filter.SetUsagePage(0xf1d0);
       if (filter.Matches(*device_info)) {
-        filtered_results.push_back(std::make_unique<U2fHidDevice>(
+        filtered_results.push_back(std::make_unique<FidoHidDevice>(
             std::move(device_info), hid_manager_));
       }
     }
@@ -117,7 +117,7 @@
  private:
   device::mojom::HidManager* hid_manager_;
 
-  DISALLOW_COPY_AND_ASSIGN(U2fDeviceEnumerateCallbackReceiver);
+  DISALLOW_COPY_AND_ASSIGN(FidoDeviceEnumerateCallbackReceiver);
 };
 
 using TestDeviceCallbackReceiver =
@@ -125,9 +125,9 @@
 
 }  // namespace
 
-class U2fHidDeviceTest : public ::testing::Test {
+class FidoHidDeviceTest : public ::testing::Test {
  public:
-  U2fHidDeviceTest()
+  FidoHidDeviceTest()
       : scoped_task_environment_(
             base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
 
@@ -142,21 +142,21 @@
   base::test::ScopedTaskEnvironment scoped_task_environment_;
 };
 
-TEST_F(U2fHidDeviceTest, TestConnectionFailure) {
+TEST_F(FidoHidDeviceTest, TestConnectionFailure) {
   // Setup and enumerate mock device.
-  U2fDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
+  FidoDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
   auto hid_device = TestHidDevice();
   fake_hid_manager_->AddDevice(std::move(hid_device));
   hid_manager_->GetDevices(receiver.callback());
   receiver.WaitForCallback();
 
-  std::vector<std::unique_ptr<U2fHidDevice>> u2f_devices =
+  std::vector<std::unique_ptr<FidoHidDevice>> u2f_devices =
       receiver.TakeReturnedDevicesFiltered();
 
   ASSERT_EQ(static_cast<size_t>(1), u2f_devices.size());
   auto& device = u2f_devices.front();
   // Put device in IDLE state.
-  device->state_ = U2fDevice::State::kReady;
+  device->state_ = FidoDevice::State::kReady;
 
   // Manually delete connection.
   device->connection_ = nullptr;
@@ -172,23 +172,23 @@
   device->DeviceTransact(U2fRequest::GetU2fVersionApduCommand(),
                          receiver_3.callback());
 
-  EXPECT_EQ(U2fDevice::State::kDeviceError, device->state_);
+  EXPECT_EQ(FidoDevice::State::kDeviceError, device->state_);
 
   EXPECT_FALSE(std::get<0>(*receiver_1.result()));
   EXPECT_FALSE(std::get<0>(*receiver_2.result()));
   EXPECT_FALSE(std::get<0>(*receiver_3.result()));
 }
 
-TEST_F(U2fHidDeviceTest, TestDeviceError) {
+TEST_F(FidoHidDeviceTest, TestDeviceError) {
   // Setup and enumerate mock device.
-  U2fDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
+  FidoDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
 
   auto hid_device = TestHidDevice();
   fake_hid_manager_->AddDevice(std::move(hid_device));
   hid_manager_->GetDevices(receiver.callback());
   receiver.WaitForCallback();
 
-  std::vector<std::unique_ptr<U2fHidDevice>> u2f_devices =
+  std::vector<std::unique_ptr<FidoHidDevice>> u2f_devices =
       receiver.TakeReturnedDevicesFiltered();
 
   ASSERT_EQ(static_cast<size_t>(1), u2f_devices.size());
@@ -196,16 +196,15 @@
 
   // Mock connection where writes always fail.
   FakeHidConnection::mock_connection_error_ = true;
-  device->state_ = U2fDevice::State::kReady;
+  device->state_ = FidoDevice::State::kReady;
 
   TestDeviceCallbackReceiver receiver_0;
   device->DeviceTransact(U2fRequest::GetU2fVersionApduCommand(),
                          receiver_0.callback());
   EXPECT_FALSE(std::get<0>(*receiver_0.result()));
-  EXPECT_EQ(U2fDevice::State::kDeviceError, device->state_);
+  EXPECT_EQ(FidoDevice::State::kDeviceError, device->state_);
 
   // Add pending transactions manually and ensure they are processed.
-  // Add pending transactions manually and ensure they are processed.
   TestDeviceCallbackReceiver receiver_1;
   device->pending_transactions_.emplace(U2fRequest::GetU2fVersionApduCommand(),
                                         receiver_1.callback());
@@ -217,13 +216,13 @@
                          receiver_3.callback());
   FakeHidConnection::mock_connection_error_ = false;
 
-  EXPECT_EQ(U2fDevice::State::kDeviceError, device->state_);
+  EXPECT_EQ(FidoDevice::State::kDeviceError, device->state_);
   EXPECT_FALSE(std::get<0>(*receiver_1.result()));
   EXPECT_FALSE(std::get<0>(*receiver_2.result()));
   EXPECT_FALSE(std::get<0>(*receiver_3.result()));
 }
 
-TEST_F(U2fHidDeviceTest, TestRetryChannelAllocation) {
+TEST_F(FidoHidDeviceTest, TestRetryChannelAllocation) {
   const std::vector<uint8_t> kIncorrectNonce = {0x00, 0x00, 0x00, 0x00,
                                                 0x00, 0x00, 0x00, 0x00};
 
@@ -283,13 +282,12 @@
   fake_hid_manager_->AddDeviceAndSetConnection(std::move(hid_device),
                                                std::move(connection_client));
 
-  U2fDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
+  FidoDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
   hid_manager_->GetDevices(receiver.callback());
   receiver.WaitForCallback();
 
-  std::vector<std::unique_ptr<U2fHidDevice>> u2f_devices =
+  std::vector<std::unique_ptr<FidoHidDevice>> u2f_devices =
       receiver.TakeReturnedDevicesFiltered();
-
   ASSERT_EQ(1u, u2f_devices.size());
   auto& device = u2f_devices.front();
 
diff --git a/device/fido/u2f_hid_discovery.cc b/device/fido/fido_hid_discovery.cc
similarity index 62%
rename from device/fido/u2f_hid_discovery.cc
rename to device/fido/fido_hid_discovery.cc
index f91c103..c7bf892 100644
--- a/device/fido/u2f_hid_discovery.cc
+++ b/device/fido/fido_hid_discovery.cc
@@ -2,30 +2,30 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "device/fido/u2f_hid_discovery.h"
+#include "device/fido/fido_hid_discovery.h"
 
 #include <utility>
 
-#include "device/fido/u2f_hid_device.h"
+#include "device/fido/fido_hid_device.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace device {
 
-U2fHidDiscovery::U2fHidDiscovery(::service_manager::Connector* connector)
+FidoHidDiscovery::FidoHidDiscovery(::service_manager::Connector* connector)
     : connector_(connector), binding_(this), weak_factory_(this) {
   // TODO(piperc@): Give this constant a name.
   filter_.SetUsagePage(0xf1d0);
 }
 
-U2fHidDiscovery::~U2fHidDiscovery() = default;
+FidoHidDiscovery::~FidoHidDiscovery() = default;
 
-U2fTransportProtocol U2fHidDiscovery::GetTransportProtocol() const {
+U2fTransportProtocol FidoHidDiscovery::GetTransportProtocol() const {
   return U2fTransportProtocol::kUsbHumanInterfaceDevice;
 }
 
-void U2fHidDiscovery::Start() {
+void FidoHidDiscovery::Start() {
   DCHECK(connector_);
   connector_->BindInterface(device::mojom::kServiceName,
                             mojo::MakeRequest(&hid_manager_));
@@ -33,31 +33,32 @@
   binding_.Bind(mojo::MakeRequest(&client));
 
   hid_manager_->GetDevicesAndSetClient(
-      std::move(client), base::BindOnce(&U2fHidDiscovery::OnGetDevices,
+      std::move(client), base::BindOnce(&FidoHidDiscovery::OnGetDevices,
                                         weak_factory_.GetWeakPtr()));
 }
-void U2fHidDiscovery::Stop() {
+void FidoHidDiscovery::Stop() {
   binding_.Unbind();
   NotifyDiscoveryStopped(true);
 }
 
-void U2fHidDiscovery::DeviceAdded(device::mojom::HidDeviceInfoPtr device_info) {
-  // Ignore non-U2F devices
-  if (filter_.Matches(*device_info)) {
-    AddDevice(std::make_unique<U2fHidDevice>(std::move(device_info),
-                                             hid_manager_.get()));
-  }
-}
-
-void U2fHidDiscovery::DeviceRemoved(
+void FidoHidDiscovery::DeviceAdded(
     device::mojom::HidDeviceInfoPtr device_info) {
-  // Ignore non-U2F devices
+  // Ignore non-U2F devices.
   if (filter_.Matches(*device_info)) {
-    RemoveDevice(U2fHidDevice::GetIdForDevice(*device_info));
+    AddDevice(std::make_unique<FidoHidDevice>(std::move(device_info),
+                                              hid_manager_.get()));
   }
 }
 
-void U2fHidDiscovery::OnGetDevices(
+void FidoHidDiscovery::DeviceRemoved(
+    device::mojom::HidDeviceInfoPtr device_info) {
+  // Ignore non-U2F devices.
+  if (filter_.Matches(*device_info)) {
+    RemoveDevice(FidoHidDevice::GetIdForDevice(*device_info));
+  }
+}
+
+void FidoHidDiscovery::OnGetDevices(
     std::vector<device::mojom::HidDeviceInfoPtr> device_infos) {
   for (auto& device_info : device_infos)
     DeviceAdded(std::move(device_info));
diff --git a/device/fido/u2f_hid_discovery.h b/device/fido/fido_hid_discovery.h
similarity index 75%
rename from device/fido/u2f_hid_discovery.h
rename to device/fido/fido_hid_discovery.h
index 48982eab..fff111e 100644
--- a/device/fido/u2f_hid_discovery.h
+++ b/device/fido/fido_hid_discovery.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_FIDO_U2F_HID_DISCOVERY_H_
-#define DEVICE_FIDO_U2F_HID_DISCOVERY_H_
+#ifndef DEVICE_FIDO_FIDO_HID_DISCOVERY_H_
+#define DEVICE_FIDO_FIDO_HID_DISCOVERY_H_
 
 #include <memory>
 #include <vector>
@@ -11,7 +11,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "device/fido/u2f_discovery.h"
+#include "device/fido/fido_discovery.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "services/device/public/cpp/hid/hid_device_filter.h"
 #include "services/device/public/mojom/hid.mojom.h"
@@ -25,15 +25,14 @@
 // TODO(crbug/769631): Now the U2F is talking to HID via mojo, once the U2F
 // servicification is unblocked, we'll move U2F back to //service/device/.
 // Then it will talk to HID via C++ as part of servicifying U2F.
-
-class COMPONENT_EXPORT(DEVICE_FIDO) U2fHidDiscovery
-    : public U2fDiscovery,
+class COMPONENT_EXPORT(DEVICE_FIDO) FidoHidDiscovery
+    : public FidoDiscovery,
       device::mojom::HidManagerClient {
  public:
-  explicit U2fHidDiscovery(::service_manager::Connector* connector);
-  ~U2fHidDiscovery() override;
+  explicit FidoHidDiscovery(::service_manager::Connector* connector);
+  ~FidoHidDiscovery() override;
 
-  // U2fDiscovery:
+  // FidoDiscovery:
   U2fTransportProtocol GetTransportProtocol() const override;
   void Start() override;
   void Stop() override;
@@ -49,11 +48,11 @@
   device::mojom::HidManagerPtr hid_manager_;
   mojo::AssociatedBinding<device::mojom::HidManagerClient> binding_;
   HidDeviceFilter filter_;
-  base::WeakPtrFactory<U2fHidDiscovery> weak_factory_;
+  base::WeakPtrFactory<FidoHidDiscovery> weak_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(U2fHidDiscovery);
+  DISALLOW_COPY_AND_ASSIGN(FidoHidDiscovery);
 };
 
 }  // namespace device
 
-#endif  // DEVICE_FIDO_U2F_HID_DISCOVERY_H_
+#endif  // DEVICE_FIDO_FIDO_HID_DISCOVERY_H_
diff --git a/device/fido/u2f_hid_discovery_unittest.cc b/device/fido/fido_hid_discovery_unittest.cc
similarity index 87%
rename from device/fido/u2f_hid_discovery_unittest.cc
rename to device/fido/fido_hid_discovery_unittest.cc
index fbe51cb..a0609b8 100644
--- a/device/fido/u2f_hid_discovery_unittest.cc
+++ b/device/fido/fido_hid_discovery_unittest.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "device/fido/u2f_hid_discovery.h"
+#include "device/fido/fido_hid_discovery.h"
 
 #include <string>
 #include <utility>
 
 #include "base/test/scoped_task_environment.h"
 #include "device/fido/fake_hid_impl_for_testing.h"
-#include "device/fido/mock_u2f_discovery_observer.h"
-#include "device/fido/u2f_hid_device.h"
+#include "device/fido/fido_hid_device.h"
+#include "device/fido/mock_fido_discovery_observer.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/hid.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -24,7 +24,7 @@
 
 namespace {
 
-device::mojom::HidDeviceInfoPtr MakeU2fDevice(std::string guid) {
+device::mojom::HidDeviceInfoPtr MakeFidoHidDevice(std::string guid) {
   auto c_info = device::mojom::HidCollectionInfo::New();
   c_info->usage = device::mojom::HidUsageAndPage::New(1, 0xf1d0);
 
@@ -54,7 +54,7 @@
 
 }  // namespace
 
-class U2fHidDiscoveryTest : public ::testing::Test {
+class FidoHidDiscoveryTest : public ::testing::Test {
  public:
   base::test::ScopedTaskEnvironment& scoped_task_environment() {
     return scoped_task_environment_;
@@ -79,11 +79,11 @@
   std::unique_ptr<FakeHidManager> fake_hid_manager_;
 };
 
-TEST_F(U2fHidDiscoveryTest, TestAddRemoveDevice) {
-  U2fHidDiscovery discovery(connector_.get());
-  MockU2fDiscoveryObserver observer;
+TEST_F(FidoHidDiscoveryTest, TestAddRemoveDevice) {
+  FidoHidDiscovery discovery(connector_.get());
+  MockFidoDiscoveryObserver observer;
 
-  fake_hid_manager_->AddDevice(MakeU2fDevice("known"));
+  fake_hid_manager_->AddDevice(MakeFidoHidDevice("known"));
 
   EXPECT_CALL(observer, DiscoveryStarted(&discovery, true));
   discovery.AddObserver(&observer);
@@ -96,7 +96,7 @@
 
   // Devices added during the discovery should be reported as ADDED.
   EXPECT_CALL(observer, DeviceAdded(&discovery, IdMatches("added")));
-  fake_hid_manager_->AddDevice(MakeU2fDevice("added"));
+  fake_hid_manager_->AddDevice(MakeFidoHidDevice("added"));
   scoped_task_environment().RunUntilIdle();
 
   // Added non-U2F devices should not be reported at all.
diff --git a/device/fido/mock_u2f_device.cc b/device/fido/mock_fido_device.cc
similarity index 70%
rename from device/fido/mock_u2f_device.cc
rename to device/fido/mock_fido_device.cc
index 77fac1ce..39a2db0 100644
--- a/device/fido/mock_u2f_device.cc
+++ b/device/fido/mock_fido_device.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "device/fido/mock_u2f_device.h"
+#include "device/fido/mock_fido_device.h"
 
 #include <utility>
 
@@ -12,21 +12,21 @@
 
 namespace device {
 
-MockU2fDevice::MockU2fDevice() : weak_factory_(this) {}
-MockU2fDevice::~MockU2fDevice() = default;
+MockFidoDevice::MockFidoDevice() : weak_factory_(this) {}
+MockFidoDevice::~MockFidoDevice() = default;
 
-void MockU2fDevice::TryWink(WinkCallback cb) {
+void MockFidoDevice::TryWink(WinkCallback cb) {
   TryWinkRef(cb);
 }
 
-void MockU2fDevice::DeviceTransact(std::vector<uint8_t> command,
-                                   DeviceCallback cb) {
+void MockFidoDevice::DeviceTransact(std::vector<uint8_t> command,
+                                    DeviceCallback cb) {
   DeviceTransactPtr(command, cb);
 }
 
 // static
-void MockU2fDevice::NotSatisfied(const std::vector<uint8_t>& command,
-                                 DeviceCallback& cb) {
+void MockFidoDevice::NotSatisfied(const std::vector<uint8_t>& command,
+                                  DeviceCallback& cb) {
   std::move(cb).Run(apdu::ApduResponse(
                         std::vector<uint8_t>(),
                         apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED)
@@ -34,8 +34,8 @@
 }
 
 // static
-void MockU2fDevice::WrongData(const std::vector<uint8_t>& command,
-                              DeviceCallback& cb) {
+void MockFidoDevice::WrongData(const std::vector<uint8_t>& command,
+                               DeviceCallback& cb) {
   std::move(cb).Run(
       apdu::ApduResponse(std::vector<uint8_t>(),
                          apdu::ApduResponse::Status::SW_WRONG_DATA)
@@ -43,8 +43,8 @@
 }
 
 // static
-void MockU2fDevice::NoErrorSign(const std::vector<uint8_t>& command,
-                                DeviceCallback& cb) {
+void MockFidoDevice::NoErrorSign(const std::vector<uint8_t>& command,
+                                 DeviceCallback& cb) {
   std::move(cb).Run(
       apdu::ApduResponse(
           std::vector<uint8_t>(std::begin(test_data::kTestU2fSignResponse),
@@ -54,8 +54,8 @@
 }
 
 // static
-void MockU2fDevice::NoErrorRegister(const std::vector<uint8_t>& command,
-                                    DeviceCallback& cb) {
+void MockFidoDevice::NoErrorRegister(const std::vector<uint8_t>& command,
+                                     DeviceCallback& cb) {
   std::move(cb).Run(
       apdu::ApduResponse(
           std::vector<uint8_t>(std::begin(test_data::kTestU2fRegisterResponse),
@@ -65,8 +65,8 @@
 }
 
 // static
-void MockU2fDevice::NoErrorVersion(const std::vector<uint8_t>& command,
-                                   DeviceCallback& cb) {
+void MockFidoDevice::NoErrorVersion(const std::vector<uint8_t>& command,
+                                    DeviceCallback& cb) {
   std::move(cb).Run(
       apdu::ApduResponse(std::vector<uint8_t>(kU2fVersionResponse.cbegin(),
                                               kU2fVersionResponse.cend()),
@@ -75,7 +75,7 @@
 }
 
 // static
-void MockU2fDevice::SignWithCorruptedResponse(
+void MockFidoDevice::SignWithCorruptedResponse(
     const std::vector<uint8_t>& command,
     DeviceCallback& cb) {
   std::move(cb).Run(
@@ -88,11 +88,11 @@
 }
 
 // static
-void MockU2fDevice::WinkDoNothing(WinkCallback& cb) {
+void MockFidoDevice::WinkDoNothing(WinkCallback& cb) {
   std::move(cb).Run();
 }
 
-base::WeakPtr<U2fDevice> MockU2fDevice::GetWeakPtr() {
+base::WeakPtr<FidoDevice> MockFidoDevice::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
 
diff --git a/device/fido/mock_u2f_device.h b/device/fido/mock_fido_device.h
similarity index 82%
rename from device/fido/mock_u2f_device.h
rename to device/fido/mock_fido_device.h
index 0302b37..fd4f329 100644
--- a/device/fido/mock_u2f_device.h
+++ b/device/fido/mock_fido_device.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_FIDO_MOCK_U2F_DEVICE_H_
-#define DEVICE_FIDO_MOCK_U2F_DEVICE_H_
+#ifndef DEVICE_FIDO_MOCK_FIDO_DEVICE_H_
+#define DEVICE_FIDO_MOCK_FIDO_DEVICE_H_
 
 #include <stdint.h>
 
@@ -12,15 +12,15 @@
 
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "device/fido/u2f_device.h"
+#include "device/fido/fido_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace device {
 
-class MockU2fDevice : public U2fDevice {
+class MockFidoDevice : public FidoDevice {
  public:
-  MockU2fDevice();
-  ~MockU2fDevice() override;
+  MockFidoDevice();
+  ~MockFidoDevice() override;
 
   // GMock cannot mock a method taking a move-only type.
   // TODO(crbug.com/729950): Remove these workarounds once support for move-only
@@ -36,7 +36,7 @@
                void(const std::vector<uint8_t>& command, DeviceCallback& cb));
   void DeviceTransact(std::vector<uint8_t> command, DeviceCallback cb) override;
 
-  base::WeakPtr<U2fDevice> GetWeakPtr() override;
+  base::WeakPtr<FidoDevice> GetWeakPtr() override;
   static void NotSatisfied(const std::vector<uint8_t>& command,
                            DeviceCallback& cb);
   static void WrongData(const std::vector<uint8_t>& command,
@@ -52,11 +52,11 @@
   static void WinkDoNothing(WinkCallback& cb);
 
  private:
-  base::WeakPtrFactory<U2fDevice> weak_factory_;
+  base::WeakPtrFactory<FidoDevice> weak_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(MockU2fDevice);
+  DISALLOW_COPY_AND_ASSIGN(MockFidoDevice);
 };
 
 }  // namespace device
 
-#endif  // DEVICE_FIDO_MOCK_U2F_DEVICE_H_
+#endif  // DEVICE_FIDO_MOCK_FIDO_DEVICE_H_
diff --git a/device/fido/mock_fido_discovery_observer.cc b/device/fido/mock_fido_discovery_observer.cc
new file mode 100644
index 0000000..2ef62ccd44
--- /dev/null
+++ b/device/fido/mock_fido_discovery_observer.cc
@@ -0,0 +1,12 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/fido/mock_fido_discovery_observer.h"
+
+namespace device {
+
+MockFidoDiscoveryObserver::MockFidoDiscoveryObserver() = default;
+MockFidoDiscoveryObserver::~MockFidoDiscoveryObserver() = default;
+
+}  // namespace device
diff --git a/device/fido/mock_fido_discovery_observer.h b/device/fido/mock_fido_discovery_observer.h
new file mode 100644
index 0000000..8d4ecb7c
--- /dev/null
+++ b/device/fido/mock_fido_discovery_observer.h
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_FIDO_MOCK_FIDO_DISCOVERY_OBSERVER_H_
+#define DEVICE_FIDO_MOCK_FIDO_DISCOVERY_OBSERVER_H_
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "device/fido/fido_discovery.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace device {
+
+class FidoDevice;
+
+class MockFidoDiscoveryObserver : public FidoDiscovery::Observer {
+ public:
+  MockFidoDiscoveryObserver();
+  ~MockFidoDiscoveryObserver() override;
+
+  MOCK_METHOD2(DiscoveryStarted, void(FidoDiscovery*, bool));
+  MOCK_METHOD2(DiscoveryStopped, void(FidoDiscovery*, bool));
+  MOCK_METHOD2(DeviceAdded, void(FidoDiscovery*, FidoDevice*));
+  MOCK_METHOD2(DeviceRemoved, void(FidoDiscovery*, FidoDevice*));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockFidoDiscoveryObserver);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_MOCK_FIDO_DISCOVERY_OBSERVER_H_
diff --git a/device/fido/mock_u2f_discovery_observer.cc b/device/fido/mock_u2f_discovery_observer.cc
deleted file mode 100644
index f73f63b..0000000
--- a/device/fido/mock_u2f_discovery_observer.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/fido/mock_u2f_discovery_observer.h"
-
-namespace device {
-
-MockU2fDiscoveryObserver::MockU2fDiscoveryObserver() = default;
-MockU2fDiscoveryObserver::~MockU2fDiscoveryObserver() = default;
-
-}  // namespace device
diff --git a/device/fido/mock_u2f_discovery_observer.h b/device/fido/mock_u2f_discovery_observer.h
deleted file mode 100644
index 5a2e08d..0000000
--- a/device/fido/mock_u2f_discovery_observer.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef DEVICE_FIDO_MOCK_U2F_DISCOVERY_OBSERVER_H_
-#define DEVICE_FIDO_MOCK_U2F_DISCOVERY_OBSERVER_H_
-
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "device/fido/u2f_discovery.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace device {
-
-class U2fDevice;
-
-class MockU2fDiscoveryObserver : public U2fDiscovery::Observer {
- public:
-  MockU2fDiscoveryObserver();
-  ~MockU2fDiscoveryObserver() override;
-
-  MOCK_METHOD2(DiscoveryStarted, void(U2fDiscovery*, bool));
-  MOCK_METHOD2(DiscoveryStopped, void(U2fDiscovery*, bool));
-  MOCK_METHOD2(DeviceAdded, void(U2fDiscovery*, U2fDevice*));
-  MOCK_METHOD2(DeviceRemoved, void(U2fDiscovery*, U2fDevice*));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockU2fDiscoveryObserver);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_FIDO_MOCK_U2F_DISCOVERY_OBSERVER_H_
diff --git a/device/fido/u2f_ble_device.cc b/device/fido/u2f_ble_device.cc
index 0dc9a38..e8bf480 100644
--- a/device/fido/u2f_ble_device.cc
+++ b/device/fido/u2f_ble_device.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/strings/string_piece.h"
 #include "components/apdu/apdu_response.h"
+#include "device/fido/fido_constants.h"
 #include "device/fido/u2f_ble_frames.h"
 #include "device/fido/u2f_ble_transaction.h"
 
@@ -86,7 +87,7 @@
   Transition();
 }
 
-base::WeakPtr<U2fDevice> U2fBleDevice::GetWeakPtr() {
+base::WeakPtr<FidoDevice> U2fBleDevice::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
 
diff --git a/device/fido/u2f_ble_device.h b/device/fido/u2f_ble_device.h
index 06ada63..16ac087 100644
--- a/device/fido/u2f_ble_device.h
+++ b/device/fido/u2f_ble_device.h
@@ -18,15 +18,15 @@
 #include "base/strings/string_piece.h"
 #include "base/timer/timer.h"
 #include "device/fido/fido_constants.h"
+#include "device/fido/fido_device.h"
 #include "device/fido/u2f_ble_connection.h"
 #include "device/fido/u2f_ble_transaction.h"
-#include "device/fido/u2f_device.h"
 
 namespace device {
 
 class U2fBleFrame;
 
-class COMPONENT_EXPORT(DEVICE_FIDO) U2fBleDevice : public U2fDevice {
+class COMPONENT_EXPORT(DEVICE_FIDO) U2fBleDevice : public FidoDevice {
  public:
   using FrameCallback = U2fBleTransaction::FrameCallback;
   explicit U2fBleDevice(std::string address);
@@ -37,7 +37,7 @@
   void SendPing(std::vector<uint8_t> data, DeviceCallback callback);
   static std::string GetId(base::StringPiece address);
 
-  // U2fDevice:
+  // FidoDevice:
   void TryWink(WinkCallback callback) override;
   std::string GetId() const override;
 
@@ -46,10 +46,10 @@
   U2fBleConnection::ReadCallback GetReadCallbackForTesting();
 
  protected:
-  // U2fDevice:
+  // FidoDevice:
   void DeviceTransact(std::vector<uint8_t> command,
                       DeviceCallback callback) override;
-  base::WeakPtr<U2fDevice> GetWeakPtr() override;
+  base::WeakPtr<FidoDevice> GetWeakPtr() override;
 
  private:
   void Transition();
diff --git a/device/fido/u2f_ble_device_unittest.cc b/device/fido/u2f_ble_device_unittest.cc
index f89a7fe..658fa9e 100644
--- a/device/fido/u2f_ble_device_unittest.cc
+++ b/device/fido/u2f_ble_device_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/optional.h"
 #include "base/test/scoped_task_environment.h"
 #include "device/bluetooth/test/bluetooth_test.h"
+#include "device/fido/fido_constants.h"
 #include "device/fido/mock_u2f_ble_connection.h"
 #include "device/fido/test_callback_receiver.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/device/fido/u2f_ble_discovery.h b/device/fido/u2f_ble_discovery.h
index 1aab86f..8ae1004 100644
--- a/device/fido/u2f_ble_discovery.h
+++ b/device/fido/u2f_ble_discovery.h
@@ -12,7 +12,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "device/bluetooth/bluetooth_adapter.h"
-#include "device/fido/u2f_discovery.h"
+#include "device/fido/fido_discovery.h"
 
 namespace device {
 
@@ -21,13 +21,13 @@
 class BluetoothUUID;
 
 class COMPONENT_EXPORT(DEVICE_FIDO) U2fBleDiscovery
-    : public U2fDiscovery,
+    : public FidoDiscovery,
       BluetoothAdapter::Observer {
  public:
   U2fBleDiscovery();
   ~U2fBleDiscovery() override;
 
-  // U2fDiscovery:
+  // FidoDiscovery:
   U2fTransportProtocol GetTransportProtocol() const override;
   void Start() override;
   void Stop() override;
diff --git a/device/fido/u2f_ble_discovery_unittest.cc b/device/fido/u2f_ble_discovery_unittest.cc
index 9566fbb..e88faf8 100644
--- a/device/fido/u2f_ble_discovery_unittest.cc
+++ b/device/fido/u2f_ble_discovery_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/run_loop.h"
 #include "build/build_config.h"
 #include "device/bluetooth/test/bluetooth_test.h"
-#include "device/fido/mock_u2f_discovery_observer.h"
+#include "device/fido/mock_fido_discovery_observer.h"
 #include "device/fido/u2f_ble_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -44,7 +44,7 @@
   U2fBleDiscovery discovery;
 
   // We don't expect any calls to the notification methods.
-  MockU2fDiscoveryObserver observer;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
   EXPECT_CALL(observer, DiscoveryStarted(&discovery, _)).Times(0);
   EXPECT_CALL(observer, DiscoveryStopped(&discovery, _)).Times(0);
@@ -63,7 +63,7 @@
   SimulateLowEnergyDevice(7);
 
   U2fBleDiscovery discovery;
-  MockU2fDiscoveryObserver observer;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
 
   {
@@ -101,7 +101,7 @@
   InitWithFakeAdapter();
 
   U2fBleDiscovery discovery;
-  MockU2fDiscoveryObserver observer;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
 
   {
@@ -155,7 +155,7 @@
   SimulateLowEnergyDevice(3);
 
   U2fBleDiscovery discovery;
-  MockU2fDiscoveryObserver observer;
+  MockFidoDiscoveryObserver observer;
   discovery.AddObserver(&observer);
 
   {
diff --git a/device/fido/u2f_ble_transaction.cc b/device/fido/u2f_ble_transaction.cc
index aa12b94..25b336b0 100644
--- a/device/fido/u2f_ble_transaction.cc
+++ b/device/fido/u2f_ble_transaction.cc
@@ -6,8 +6,8 @@
 
 #include <utility>
 
+#include "device/fido/fido_constants.h"
 #include "device/fido/u2f_ble_connection.h"
-#include "device/fido/u2f_device.h"
 
 namespace device {
 
diff --git a/device/fido/u2f_discovery.cc b/device/fido/u2f_discovery.cc
deleted file mode 100644
index ad7bd4f..0000000
--- a/device/fido/u2f_discovery.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/fido/u2f_discovery.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "device/fido/u2f_ble_discovery.h"
-#include "device/fido/u2f_device.h"
-
-// HID is not supported on Android.
-#if !defined(OS_ANDROID)
-#include "device/fido/u2f_hid_discovery.h"
-#endif  // !defined(OS_ANDROID)
-
-namespace device {
-
-namespace {
-
-std::unique_ptr<U2fDiscovery> CreateU2fDiscoveryImpl(
-    U2fTransportProtocol transport,
-    service_manager::Connector* connector) {
-  std::unique_ptr<U2fDiscovery> discovery;
-  switch (transport) {
-    case U2fTransportProtocol::kUsbHumanInterfaceDevice:
-#if !defined(OS_ANDROID)
-      DCHECK(connector);
-      discovery = std::make_unique<U2fHidDiscovery>(connector);
-#else
-      NOTREACHED() << "USB HID not supported on Android.";
-#endif  // !defined(OS_ANDROID)
-      break;
-    case U2fTransportProtocol::kBluetoothLowEnergy:
-      discovery = std::make_unique<U2fBleDiscovery>();
-      break;
-  }
-
-  DCHECK(discovery);
-  DCHECK_EQ(discovery->GetTransportProtocol(), transport);
-  return discovery;
-}
-
-}  // namespace
-
-U2fDiscovery::Observer::~Observer() = default;
-
-// static
-U2fDiscovery::FactoryFuncPtr U2fDiscovery::g_factory_func_ =
-    &CreateU2fDiscoveryImpl;
-
-// static
-std::unique_ptr<U2fDiscovery> U2fDiscovery::Create(
-    U2fTransportProtocol transport,
-    service_manager::Connector* connector) {
-  return (*g_factory_func_)(transport, connector);
-}
-
-U2fDiscovery::U2fDiscovery() = default;
-U2fDiscovery::~U2fDiscovery() = default;
-
-void U2fDiscovery::AddObserver(Observer* observer) {
-  observers_.AddObserver(observer);
-}
-
-void U2fDiscovery::RemoveObserver(Observer* observer) {
-  observers_.RemoveObserver(observer);
-}
-
-void U2fDiscovery::NotifyDiscoveryStarted(bool success) {
-  for (auto& observer : observers_)
-    observer.DiscoveryStarted(this, success);
-}
-
-void U2fDiscovery::NotifyDiscoveryStopped(bool success) {
-  for (auto& observer : observers_)
-    observer.DiscoveryStopped(this, success);
-}
-
-void U2fDiscovery::NotifyDeviceAdded(U2fDevice* device) {
-  for (auto& observer : observers_)
-    observer.DeviceAdded(this, device);
-}
-
-void U2fDiscovery::NotifyDeviceRemoved(U2fDevice* device) {
-  for (auto& observer : observers_)
-    observer.DeviceRemoved(this, device);
-}
-
-std::vector<U2fDevice*> U2fDiscovery::GetDevices() {
-  std::vector<U2fDevice*> devices;
-  devices.reserve(devices_.size());
-  for (const auto& device : devices_)
-    devices.push_back(device.second.get());
-  return devices;
-}
-
-std::vector<const U2fDevice*> U2fDiscovery::GetDevices() const {
-  std::vector<const U2fDevice*> devices;
-  devices.reserve(devices_.size());
-  for (const auto& device : devices_)
-    devices.push_back(device.second.get());
-  return devices;
-}
-
-U2fDevice* U2fDiscovery::GetDevice(base::StringPiece device_id) {
-  return const_cast<U2fDevice*>(
-      static_cast<const U2fDiscovery*>(this)->GetDevice(device_id));
-}
-
-const U2fDevice* U2fDiscovery::GetDevice(base::StringPiece device_id) const {
-  auto found = devices_.find(device_id);
-  return found != devices_.end() ? found->second.get() : nullptr;
-}
-
-bool U2fDiscovery::AddDevice(std::unique_ptr<U2fDevice> device) {
-  std::string device_id = device->GetId();
-  const auto result = devices_.emplace(std::move(device_id), std::move(device));
-  if (result.second)
-    NotifyDeviceAdded(result.first->second.get());
-  return result.second;
-}
-
-bool U2fDiscovery::RemoveDevice(base::StringPiece device_id) {
-  auto found = devices_.find(device_id);
-  if (found == devices_.end())
-    return false;
-
-  auto device = std::move(found->second);
-  devices_.erase(found);
-  NotifyDeviceRemoved(device.get());
-  return true;
-}
-
-// ScopedU2fDiscoveryFactory -------------------------------------------------
-
-namespace internal {
-
-ScopedU2fDiscoveryFactory::ScopedU2fDiscoveryFactory() {
-  original_factory_ = std::exchange(g_current_factory, this);
-  original_factory_func_ =
-      std::exchange(U2fDiscovery::g_factory_func_,
-                    &ForwardCreateU2fDiscoveryToCurrentFactory);
-}
-
-ScopedU2fDiscoveryFactory::~ScopedU2fDiscoveryFactory() {
-  g_current_factory = original_factory_;
-  U2fDiscovery::g_factory_func_ = original_factory_func_;
-}
-
-// static
-std::unique_ptr<U2fDiscovery>
-ScopedU2fDiscoveryFactory::ForwardCreateU2fDiscoveryToCurrentFactory(
-    U2fTransportProtocol transport,
-    ::service_manager::Connector* connector) {
-  DCHECK(g_current_factory);
-  return g_current_factory->CreateU2fDiscovery(transport, connector);
-}
-
-// static
-ScopedU2fDiscoveryFactory* ScopedU2fDiscoveryFactory::g_current_factory =
-    nullptr;
-
-}  // namespace internal
-}  // namespace device
diff --git a/device/fido/u2f_discovery.h b/device/fido/u2f_discovery.h
deleted file mode 100644
index a30a2b43..0000000
--- a/device/fido/u2f_discovery.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef DEVICE_FIDO_U2F_DISCOVERY_H_
-#define DEVICE_FIDO_U2F_DISCOVERY_H_
-
-#include <functional>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "base/strings/string_piece.h"
-#include "device/fido/u2f_transport_protocol.h"
-
-namespace service_manager {
-class Connector;
-}
-
-namespace device {
-
-class U2fDevice;
-
-namespace internal {
-class ScopedU2fDiscoveryFactory;
-}
-
-class COMPONENT_EXPORT(DEVICE_FIDO) U2fDiscovery {
- public:
-  class COMPONENT_EXPORT(DEVICE_FIDO) Observer {
-   public:
-    virtual ~Observer();
-    virtual void DiscoveryStarted(U2fDiscovery* discovery, bool success) = 0;
-    virtual void DiscoveryStopped(U2fDiscovery* discovery, bool success) = 0;
-    virtual void DeviceAdded(U2fDiscovery* discovery, U2fDevice* device) = 0;
-    virtual void DeviceRemoved(U2fDiscovery* discovery, U2fDevice* device) = 0;
-  };
-
-  // Factory function to construct an instance that discovers authenticators on
-  // the given |transport| protocol.
-  //
-  // U2fTransportProtocol::kUsbHumanInterfaceDevice requires specifying a valid
-  // |connector| on Desktop, and is not valid on Android.
-  static std::unique_ptr<U2fDiscovery> Create(
-      U2fTransportProtocol transport,
-      ::service_manager::Connector* connector);
-
-  virtual ~U2fDiscovery();
-
-  virtual U2fTransportProtocol GetTransportProtocol() const = 0;
-  virtual void Start() = 0;
-  virtual void Stop() = 0;
-
-  void AddObserver(Observer* observer);
-  void RemoveObserver(Observer* observer);
-
-  void NotifyDiscoveryStarted(bool success);
-  void NotifyDiscoveryStopped(bool success);
-  void NotifyDeviceAdded(U2fDevice* device);
-  void NotifyDeviceRemoved(U2fDevice* device);
-
-  std::vector<U2fDevice*> GetDevices();
-  std::vector<const U2fDevice*> GetDevices() const;
-
-  U2fDevice* GetDevice(base::StringPiece device_id);
-  const U2fDevice* GetDevice(base::StringPiece device_id) const;
-
- protected:
-  U2fDiscovery();
-
-  virtual bool AddDevice(std::unique_ptr<U2fDevice> device);
-  virtual bool RemoveDevice(base::StringPiece device_id);
-
-  std::map<std::string, std::unique_ptr<U2fDevice>, std::less<>> devices_;
-  base::ObserverList<Observer> observers_;
-
- private:
-  friend class internal::ScopedU2fDiscoveryFactory;
-
-  // Factory function can be overridden by tests to construct fakes.
-  using FactoryFuncPtr = decltype(&Create);
-  static FactoryFuncPtr g_factory_func_;
-
-  DISALLOW_COPY_AND_ASSIGN(U2fDiscovery);
-};
-
-namespace internal {
-
-// Base class for a scoped override of U2fDiscovery::Create, used in unit tests,
-// layout tests, and when running with the Web Authn Testing API enabled.
-//
-// While there is a subclass instance in scope, calls to the factory method will
-// be hijacked such that the derived class's CreateU2fDiscovery method will be
-// invoked instead.
-class COMPONENT_EXPORT(DEVICE_FIDO) ScopedU2fDiscoveryFactory {
- public:
-  ScopedU2fDiscoveryFactory();
-  ~ScopedU2fDiscoveryFactory();
-
- protected:
-  virtual std::unique_ptr<U2fDiscovery> CreateU2fDiscovery(
-      U2fTransportProtocol transport,
-      ::service_manager::Connector* connector) = 0;
-
- private:
-  static std::unique_ptr<U2fDiscovery>
-  ForwardCreateU2fDiscoveryToCurrentFactory(
-      U2fTransportProtocol transport,
-      ::service_manager::Connector* connector);
-
-  static ScopedU2fDiscoveryFactory* g_current_factory;
-  ScopedU2fDiscoveryFactory* original_factory_;
-  U2fDiscovery::FactoryFuncPtr original_factory_func_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedU2fDiscoveryFactory);
-};
-
-}  // namespace internal
-}  // namespace device
-
-#endif  // DEVICE_FIDO_U2F_DISCOVERY_H_
diff --git a/device/fido/u2f_register_unittest.cc b/device/fido/u2f_register_unittest.cc
index de346f6..63367139 100644
--- a/device/fido/u2f_register_unittest.cc
+++ b/device/fido/u2f_register_unittest.cc
@@ -14,10 +14,10 @@
 #include "device/fido/attested_credential_data.h"
 #include "device/fido/authenticator_data.h"
 #include "device/fido/ec_public_key.h"
-#include "device/fido/fake_u2f_discovery.h"
+#include "device/fido/fake_fido_discovery.h"
 #include "device/fido/fido_attestation_statement.h"
 #include "device/fido/fido_constants.h"
-#include "device/fido/mock_u2f_device.h"
+#include "device/fido/mock_fido_device.h"
 #include "device/fido/register_response_data.h"
 #include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_parsing_utils.h"
@@ -318,7 +318,7 @@
         kNoIndividualAttestation, register_callback_receiver_.callback());
   }
 
-  test::FakeU2fDiscovery* discovery() const { return discovery_; }
+  test::FakeFidoDiscovery* discovery() const { return discovery_; }
   TestRegisterCallback& register_callback_receiver() {
     return register_callback_receiver_;
   }
@@ -331,8 +331,8 @@
                                             std::end(kChallengeDigest)};
   std::vector<std::vector<uint8_t>> key_handles_;
   base::flat_set<U2fTransportProtocol> protocols_;
-  test::ScopedFakeU2fDiscoveryFactory scoped_fake_discovery_factory_;
-  test::FakeU2fDiscovery* discovery_;
+  test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_;
+  test::FakeFidoDiscovery* discovery_;
   TestRegisterCallback register_callback_receiver_;
 };
 
@@ -429,12 +429,12 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<MockU2fDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device"));
   EXPECT_CALL(*device, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorRegister));
+      .WillOnce(testing::Invoke(MockFidoDevice::NoErrorRegister));
   EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
   register_callback_receiver().WaitForCallback();
@@ -465,15 +465,15 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<MockU2fDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device"));
   // Go through the state machine twice before success.
   EXPECT_CALL(*device, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NotSatisfied))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorRegister));
+      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
   EXPECT_CALL(*device, TryWinkRef(_))
       .Times(2)
-      .WillRepeatedly(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillRepeatedly(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
   register_callback_receiver().WaitForCallback();
@@ -487,23 +487,23 @@
   auto request = CreateRegisterRequest();
   request->Start();
 
-  auto device0 = std::make_unique<MockU2fDevice>();
+  auto device0 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
   EXPECT_CALL(*device0, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NotSatisfied));
+      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied));
   // One wink per device.
   EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device0));
 
   // Second device will have a successful touch.
-  auto device1 = std::make_unique<MockU2fDevice>();
+  auto device1 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
   EXPECT_CALL(*device1, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorRegister));
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
   // One wink per device.
   EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device1));
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -525,25 +525,25 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<MockU2fDevice>();
+  auto device = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
   // DeviceTransact() will be called four times including three check
   // only sign-in calls and one registration call. For the first three calls,
-  // device will invoke MockU2fDevice::WrongData as the authenticator did not
+  // device will invoke MockFidoDevice::WrongData as the authenticator did not
   // create the three key handles provided in the exclude list. At the fourth
-  // call, MockU2fDevice::NoErrorRegister will be invoked after registration.
+  // call, MockFidoDevice::NoErrorRegister will be invoked after registration.
   EXPECT_CALL(*device.get(), DeviceTransactPtr(_, _))
       .Times(4)
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorRegister));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
   // TryWink() will be called twice. First during the check only sign-in. After
   // check only sign operation is complete, request state is changed to IDLE,
   // and TryWink() is called again before Register() is called.
   EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
   register_callback_receiver().WaitForCallback();
@@ -563,39 +563,39 @@
        std::vector<uint8_t>(32, 0x0D)});
   request->Start();
 
-  auto device0 = std::make_unique<MockU2fDevice>();
+  auto device0 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
   // DeviceTransact() will be called four times: three times to check for
   // duplicate key handles and once for registration. Since user
   // will register using "device1", the fourth call will invoke
-  // MockU2fDevice::NotSatisfied.
+  // MockFidoDevice::NotSatisfied.
   EXPECT_CALL(*device0, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NotSatisfied));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied));
   // TryWink() will be called twice on both devices -- during check only
   // sign-in operation and during registration attempt.
   EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device0));
 
-  auto device1 = std::make_unique<MockU2fDevice>();
-  EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
+  auto device1 = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device1, GetId()).WillRepeatedly(testing::Return("device1"));
   // We assume that user registers with second device. Therefore, the fourth
-  // DeviceTransact() will invoke MockU2fDevice::NoErrorRegister after
+  // DeviceTransact() will invoke MockFidoDevice::NoErrorRegister after
   // successful registration.
   EXPECT_CALL(*device1, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorRegister));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
   // TryWink() will be called twice on both devices -- during check only
   // sign-in operation and during registration attempt.
   EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device1));
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -619,25 +619,25 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<MockU2fDevice>();
+  auto device = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
   // For four keys in exclude list, the first three keys will invoke
-  // MockU2fDevice::WrongData and the final duplicate key handle will invoke
-  // MockU2fDevice::NoErrorSign. Once duplicate key handle is found, bogus
+  // MockFidoDevice::WrongData and the final duplicate key handle will invoke
+  // MockFidoDevice::NoErrorSign. Once duplicate key handle is found, bogus
   // registration is called to confirm user presence. This invokes
-  // MockU2fDevice::NoErrorRegister.
+  // MockFidoDevice::NoErrorRegister.
   EXPECT_CALL(*device, DeviceTransactPtr(_, _))
       .Times(5)
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorSign))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorRegister));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
   // Since duplicate key handle is found, registration process is terminated
   // before actual Register() is called on the device. Therefore, TryWink() is
   // invoked once.
   EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
   register_callback_receiver().WaitForCallback();
@@ -656,39 +656,39 @@
        std::vector<uint8_t>(32, 0x0D), std::vector<uint8_t>(32, 0x0A)});
   request->Start();
 
-  auto device0 = std::make_unique<MockU2fDevice>();
-  EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
+  auto device0 = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device0, GetId()).WillRepeatedly(testing::Return("device0"));
   // Since the first device did not create any of the key handles provided in
   // exclude list, we expect that check only sign() should be called
   // four times, and all the calls to DeviceTransact() invoke
-  // MockU2fDevice::WrongData.
+  // MockFidoDevice::WrongData.
   EXPECT_CALL(*device0, DeviceTransactPtr(_, _))
       .Times(4)
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
   EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device0));
 
-  auto device1 = std::make_unique<MockU2fDevice>();
+  auto device1 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
   // Since the last key handle in exclude list is a duplicate key, we expect
   // that the first three calls to check only sign() invoke
-  // MockU2fDevice::WrongData and that fourth sign() call invoke
-  // MockU2fDevice::NoErrorSign. After duplicate key is found, process is
+  // MockFidoDevice::WrongData and that fourth sign() call invoke
+  // MockFidoDevice::NoErrorSign. After duplicate key is found, process is
   // terminated after user presence is verified using bogus registration, which
-  // invokes MockU2fDevice::NoErrorRegister.
+  // invokes MockFidoDevice::NoErrorRegister.
   EXPECT_CALL(*device1, DeviceTransactPtr(_, _))
       .Times(5)
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorSign))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorRegister));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
   EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device1));
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -819,14 +819,14 @@
     request->Start();
     discovery()->WaitForCallToStartAndSimulateSuccess();
 
-    auto device = std::make_unique<MockU2fDevice>();
+    auto device = std::make_unique<MockFidoDevice>();
     EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
     EXPECT_CALL(*device,
                 DeviceTransactPtr(
                     IndicatesIndividualAttestation(individual_attestation), _))
-        .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorRegister));
+        .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
     EXPECT_CALL(*device, TryWinkRef(_))
-        .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+        .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
     discovery()->AddDevice(std::move(device));
 
     cb.WaitForCallback();
diff --git a/device/fido/u2f_request.cc b/device/fido/u2f_request.cc
index 817eb8c..a7dc278 100644
--- a/device/fido/u2f_request.cc
+++ b/device/fido/u2f_request.cc
@@ -29,7 +29,7 @@
       registered_keys_(registered_keys),
       weak_factory_(this) {
   for (const auto transport : transports) {
-    auto discovery = U2fDiscovery::Create(transport, connector);
+    auto discovery = FidoDiscovery::Create(transport, connector);
     discovery->AddObserver(this);
     discoveries_.push_back(std::move(discovery));
   }
@@ -139,7 +139,7 @@
 
 void U2fRequest::InitiateDeviceTransaction(
     base::Optional<std::vector<uint8_t>> cmd,
-    U2fDevice::DeviceCallback callback) {
+    FidoDevice::DeviceCallback callback) {
   if (!cmd) {
     std::move(callback).Run(base::nullopt);
     return;
@@ -149,7 +149,7 @@
 
 void U2fRequest::OnDeviceVersionRequest(
     VersionCallback callback,
-    base::WeakPtr<U2fDevice> device,
+    base::WeakPtr<FidoDevice> device,
     bool legacy,
     base::Optional<std::vector<uint8_t>> response) {
   const auto apdu_response =
@@ -172,13 +172,13 @@
   }
 }
 
-void U2fRequest::DiscoveryStarted(U2fDiscovery* discovery, bool success) {
+void U2fRequest::DiscoveryStarted(FidoDiscovery* discovery, bool success) {
   if (success) {
     // The discovery might know about devices that have already been added to
     // the system. Add them to the |devices_| list if we don't already know
     // about them. This case could happen if a DeviceAdded() event is emitted
     // before DiscoveryStarted() is invoked. In that case both the U2fRequest
-    // and the U2fDiscovery already know about the just added device.
+    // and the FidoDiscovery already know about the just added device.
     std::set<std::string> current_device_ids;
     for (const auto* device : attempted_devices_)
       current_device_ids.insert(device->GetId());
@@ -190,7 +190,7 @@
     auto new_devices = discovery->GetDevices();
     std::copy_if(
         new_devices.begin(), new_devices.end(), std::back_inserter(devices_),
-        [&current_device_ids](U2fDevice* device) {
+        [&current_device_ids](FidoDevice* device) {
           return !base::ContainsKey(current_device_ids, device->GetId());
         });
   }
@@ -204,9 +204,9 @@
   }
 }
 
-void U2fRequest::DiscoveryStopped(U2fDiscovery* discovery, bool success) {}
+void U2fRequest::DiscoveryStopped(FidoDiscovery* discovery, bool success) {}
 
-void U2fRequest::DeviceAdded(U2fDiscovery* discovery, U2fDevice* device) {
+void U2fRequest::DeviceAdded(FidoDiscovery* discovery, FidoDevice* device) {
   devices_.push_back(device);
 
   // Start the state machine if this is the only device
@@ -217,9 +217,9 @@
   }
 }
 
-void U2fRequest::DeviceRemoved(U2fDiscovery* discovery, U2fDevice* device) {
+void U2fRequest::DeviceRemoved(FidoDiscovery* discovery, FidoDevice* device) {
   const std::string device_id = device->GetId();
-  auto device_id_eq = [&device_id](const U2fDevice* this_device) {
+  auto device_id_eq = [&device_id](const FidoDevice* this_device) {
     return device_id == this_device->GetId();
   };
 
diff --git a/device/fido/u2f_request.h b/device/fido/u2f_request.h
index 88e4f99..2ee9563 100644
--- a/device/fido/u2f_request.h
+++ b/device/fido/u2f_request.h
@@ -18,8 +18,8 @@
 #include "base/macros.h"
 #include "base/optional.h"
 #include "device/fido/fido_constants.h"
-#include "device/fido/u2f_device.h"
-#include "device/fido/u2f_discovery.h"
+#include "device/fido/fido_device.h"
+#include "device/fido/fido_discovery.h"
 #include "device/fido/u2f_transport_protocol.h"
 
 namespace service_manager {
@@ -28,7 +28,8 @@
 
 namespace device {
 
-class COMPONENT_EXPORT(DEVICE_FIDO) U2fRequest : public U2fDiscovery::Observer {
+class COMPONENT_EXPORT(DEVICE_FIDO) U2fRequest
+    : public FidoDiscovery::Observer {
  public:
   using VersionCallback = base::OnceCallback<void(ProtocolVersion version)>;
 
@@ -75,11 +76,11 @@
   // Starts sign, register, and version request transaction on
   // |current_device_|.
   void InitiateDeviceTransaction(base::Optional<std::vector<uint8_t>> cmd,
-                                 U2fDevice::DeviceCallback callback);
+                                 FidoDevice::DeviceCallback callback);
   // Callback function to U2F version request. If non-legacy version request
   // fails, retry with legacy version request.
   void OnDeviceVersionRequest(VersionCallback callback,
-                              base::WeakPtr<U2fDevice> device,
+                              base::WeakPtr<FidoDevice> device,
                               bool legacy,
                               base::Optional<std::vector<uint8_t>> response);
 
@@ -93,11 +94,11 @@
   // gets popped and becomes the new |current_device_|. Once all |devices_| are
   // exhausted, |attempted_devices_| get moved into |devices_| and
   // |current_device_| is reset.
-  U2fDevice* current_device_ = nullptr;
-  std::list<U2fDevice*> devices_;
-  std::list<U2fDevice*> attempted_devices_;
+  FidoDevice* current_device_ = nullptr;
+  std::list<FidoDevice*> devices_;
+  std::list<FidoDevice*> attempted_devices_;
   State state_;
-  std::vector<std::unique_ptr<U2fDiscovery>> discoveries_;
+  std::vector<std::unique_ptr<FidoDiscovery>> discoveries_;
   std::vector<uint8_t> application_parameter_;
   std::vector<uint8_t> challenge_digest_;
   std::vector<std::vector<uint8_t>> registered_keys_;
@@ -111,11 +112,11 @@
   FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestMultipleDiscoveriesWithFailures);
   FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestLegacyVersionRequest);
 
-  // U2fDiscovery::Observer
-  void DiscoveryStarted(U2fDiscovery* discovery, bool success) override;
-  void DiscoveryStopped(U2fDiscovery* discovery, bool success) override;
-  void DeviceAdded(U2fDiscovery* discovery, U2fDevice* device) override;
-  void DeviceRemoved(U2fDiscovery* discovery, U2fDevice* device) override;
+  // FidoDiscovery::Observer
+  void DiscoveryStarted(FidoDiscovery* discovery, bool success) override;
+  void DiscoveryStopped(FidoDiscovery* discovery, bool success) override;
+  void DeviceAdded(FidoDiscovery* discovery, FidoDevice* device) override;
+  void DeviceRemoved(FidoDiscovery* discovery, FidoDevice* device) override;
 
   void IterateDevice();
   void OnWaitComplete();
diff --git a/device/fido/u2f_request_unittest.cc b/device/fido/u2f_request_unittest.cc
index f57a9c09..457f889 100644
--- a/device/fido/u2f_request_unittest.cc
+++ b/device/fido/u2f_request_unittest.cc
@@ -1,16 +1,17 @@
 // Copyright 2017 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
+#include "device/fido/u2f_request.h"
 
 #include <list>
 #include <string>
 #include <utility>
 
 #include "base/test/scoped_task_environment.h"
-#include "device/fido/fake_u2f_discovery.h"
-#include "device/fido/mock_u2f_device.h"
+#include "device/fido/fake_fido_discovery.h"
+#include "device/fido/mock_fido_device.h"
 #include "device/fido/test_callback_receiver.h"
-#include "device/fido/u2f_request.h"
+#include "device/fido/u2f_transport_protocol.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ::testing::_;
@@ -46,7 +47,7 @@
     return scoped_task_environment_;
   }
 
-  test::ScopedFakeU2fDiscoveryFactory& discovery_factory() {
+  test::ScopedFakeFidoDiscoveryFactory& discovery_factory() {
     return discovery_factory_;
   }
 
@@ -57,8 +58,8 @@
  private:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
       base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
-  test::ScopedFakeU2fDiscoveryFactory discovery_factory_;
   TestVersionCallback version_callback_receiver_;
+  test::ScopedFakeFidoDiscoveryFactory discovery_factory_;
 };
 
 TEST_F(U2fRequestTest, TestIterateDevice) {
@@ -67,8 +68,8 @@
   FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice});
   request.Start();
 
-  auto device0 = std::make_unique<MockU2fDevice>();
-  auto device1 = std::make_unique<MockU2fDevice>();
+  auto device0 = std::make_unique<MockFidoDevice>();
+  auto device1 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
   EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
 
@@ -96,7 +97,7 @@
 
   // Moving attempted devices results in a delayed retry, after which the first
   // device will be tried again. Check for the expected behavior here.
-  auto* mock_device = static_cast<MockU2fDevice*>(request.devices_.front());
+  auto* mock_device = static_cast<MockFidoDevice*>(request.devices_.front());
   EXPECT_CALL(*mock_device, TryWinkRef(_));
   scoped_task_environment().FastForwardUntilNoTasksRemain();
 
@@ -107,17 +108,16 @@
 
 TEST_F(U2fRequestTest, TestBasicMachine) {
   auto* discovery = discovery_factory().ForgeNextHidDiscovery();
-
   FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice});
   request.Start();
 
   ASSERT_NO_FATAL_FAILURE(discovery->WaitForCallToStartAndSimulateSuccess());
 
   // Add one U2F device
-  auto device = std::make_unique<MockU2fDevice>();
+  auto device = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device, GetId());
   EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery->AddDevice(std::move(device));
 
   EXPECT_EQ(U2fRequest::State::BUSY, request.state_);
@@ -129,12 +129,11 @@
   FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice});
   request.Start();
 
-  auto device = std::make_unique<MockU2fDevice>();
+  auto device = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
   discovery->AddDevice(std::move(device));
 
   ASSERT_NO_FATAL_FAILURE(discovery->WaitForCallToStartAndSimulateSuccess());
-
   EXPECT_NE(nullptr, request.current_device_);
 }
 
@@ -152,10 +151,11 @@
   ASSERT_NO_FATAL_FAILURE(discovery_2->WaitForCallToStartAndSimulateSuccess());
 
   // Let each discovery find a device.
-  auto device_1 = std::make_unique<MockU2fDevice>();
-  auto device_2 = std::make_unique<MockU2fDevice>();
+  auto device_1 = std::make_unique<MockFidoDevice>();
+  auto device_2 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device_1, GetId()).WillRepeatedly(::testing::Return("device_1"));
   EXPECT_CALL(*device_2, GetId()).WillRepeatedly(::testing::Return("device_2"));
+
   auto* device_1_ptr = device_1.get();
   auto* device_2_ptr = device_2.get();
   discovery_1->AddDevice(std::move(device_1));
@@ -173,7 +173,7 @@
   EXPECT_EQ(2u, request.devices_.size());
 
   // Add a third device.
-  auto device_3 = std::make_unique<MockU2fDevice>();
+  auto device_3 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device_3, GetId()).WillRepeatedly(::testing::Return("device_3"));
   auto* device_3_ptr = device_3.get();
   discovery_1->AddDevice(std::move(device_3));
@@ -199,8 +199,8 @@
   FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice,
                           U2fTransportProtocol::kBluetoothLowEnergy});
 
-  auto fast_device = std::make_unique<MockU2fDevice>();
-  auto slow_device = std::make_unique<MockU2fDevice>();
+  auto fast_device = std::make_unique<MockFidoDevice>();
+  auto slow_device = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*fast_device, GetId())
       .WillRepeatedly(::testing::Return("fast_device"));
   EXPECT_CALL(*slow_device, GetId())
@@ -210,13 +210,13 @@
   EXPECT_CALL(*fast_device, TryWinkRef(_))
       .WillOnce(
           ::testing::DoAll(::testing::Assign(&fast_winked, true),
-                           ::testing::Invoke(MockU2fDevice::WinkDoNothing)))
-      .WillRepeatedly(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+                           ::testing::Invoke(MockFidoDevice::WinkDoNothing)))
+      .WillRepeatedly(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   bool slow_winked = false;
   EXPECT_CALL(*slow_device, TryWinkRef(_))
-      .WillOnce(
-          ::testing::DoAll(::testing::Assign(&slow_winked, true),
-                           ::testing::Invoke(MockU2fDevice::WinkDoNothing)));
+      .WillOnce(testing::DoAll(testing::Assign(&slow_winked, true),
+                               testing::Invoke(MockFidoDevice::WinkDoNothing)));
+
   auto* fast_device_ptr = fast_device.get();
   auto* slow_device_ptr = slow_device.get();
 
@@ -304,11 +304,11 @@
     ASSERT_NO_FATAL_FAILURE(discovery_2->WaitForCallToStart());
     ASSERT_NO_FATAL_FAILURE(discovery_2->SimulateStarted(true /* success */));
 
-    auto device0 = std::make_unique<MockU2fDevice>();
+    auto device0 = std::make_unique<MockFidoDevice>();
     EXPECT_CALL(*device0, GetId())
         .WillRepeatedly(::testing::Return("device_0"));
     EXPECT_CALL(*device0, TryWinkRef(_))
-        .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+        .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
     discovery_2->AddDevice(std::move(device0));
 
     EXPECT_EQ(U2fRequest::State::BUSY, request.state_);
@@ -319,11 +319,11 @@
     request.state_ = U2fRequest::State::IDLE;
 
     // Adding another device should trigger examination and a busy state.
-    auto device1 = std::make_unique<MockU2fDevice>();
+    auto device1 = std::make_unique<MockFidoDevice>();
     EXPECT_CALL(*device1, GetId())
         .WillRepeatedly(::testing::Return("device_1"));
     EXPECT_CALL(*device1, TryWinkRef(_))
-        .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+        .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
     discovery_2->AddDevice(std::move(device1));
 
     request.Transition();
@@ -353,12 +353,12 @@
   FakeU2fRequest request({U2fTransportProtocol::kUsbHumanInterfaceDevice});
   request.Start();
 
-  auto device0 = std::make_unique<MockU2fDevice>();
+  auto device0 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
   EXPECT_CALL(*device0,
               DeviceTransactPtr(U2fRequest::GetU2fVersionApduCommand(true), _))
       // Success response for legacy version request after retry.
-      .WillOnce(testing::Invoke(MockU2fDevice::NoErrorVersion));
+      .WillOnce(testing::Invoke(MockFidoDevice::NoErrorVersion));
 
   auto* device_ptr = device0.get();
   discovery->AddDevice(std::move(device0));
diff --git a/device/fido/u2f_sign_unittest.cc b/device/fido/u2f_sign_unittest.cc
index 9da509f..ec54a0e 100644
--- a/device/fido/u2f_sign_unittest.cc
+++ b/device/fido/u2f_sign_unittest.cc
@@ -11,8 +11,8 @@
 #include "crypto/ec_private_key.h"
 #include "crypto/sha2.h"
 #include "device/fido/authenticator_data.h"
-#include "device/fido/fake_u2f_discovery.h"
-#include "device/fido/mock_u2f_device.h"
+#include "device/fido/fake_fido_discovery.h"
+#include "device/fido/mock_fido_device.h"
 #include "device/fido/sign_response_data.h"
 #include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_response_test_data.h"
@@ -140,7 +140,7 @@
         sign_callback_receiver_.callback());
   }
 
-  test::FakeU2fDiscovery* discovery() const { return discovery_; }
+  test::FakeFidoDiscovery* discovery() const { return discovery_; }
   TestSignCallback& sign_callback_receiver() { return sign_callback_receiver_; }
 
  protected:
@@ -149,8 +149,8 @@
                                               std::end(kAppId)};
   std::vector<uint8_t> challenge_parameter_{std::begin(kChallengeDigest),
                                             std::end(kChallengeDigest)};
-  test::ScopedFakeU2fDiscoveryFactory scoped_fake_discovery_factory_;
-  test::FakeU2fDiscovery* discovery_;
+  test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_;
+  test::FakeFidoDiscovery* discovery_;
   TestSignCallback sign_callback_receiver_;
   std::vector<std::vector<uint8_t>> key_handles_;
   base::flat_set<U2fTransportProtocol> protocols_;
@@ -225,12 +225,12 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<MockU2fDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device"));
   EXPECT_CALL(*device, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorSign));
+      .WillOnce(testing::Invoke(MockFidoDevice::NoErrorSign));
   EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
@@ -285,14 +285,14 @@
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
   // Go through the state machine twice before success.
-  auto device = std::make_unique<MockU2fDevice>();
+  auto device = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
   EXPECT_CALL(*device, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NotSatisfied))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorSign));
+      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
   EXPECT_CALL(*device, TryWinkRef(_))
       .Times(2)
-      .WillRepeatedly(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillRepeatedly(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
@@ -316,17 +316,17 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<MockU2fDevice>();
+  auto device = std::make_unique<MockFidoDevice>();
   // Wrong key would respond with SW_WRONG_DATA.
   EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
   EXPECT_CALL(*device, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorSign));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
   // Only one wink expected per device.
   EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
@@ -346,24 +346,24 @@
       {correct_key_handle, std::vector<uint8_t>(32, 0x0B)});
   request->Start();
 
-  auto device0 = std::make_unique<MockU2fDevice>();
+  auto device0 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
   EXPECT_CALL(*device0, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NotSatisfied));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied));
   // One wink per device.
   EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device0));
 
   // Second device will have a successful touch.
-  auto device1 = std::make_unique<MockU2fDevice>();
+  auto device1 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
   EXPECT_CALL(*device1, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorSign));
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
   // One wink per device.
   EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device1));
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -384,27 +384,27 @@
       {correct_key_handle, std::vector<uint8_t>(32, 0x0B)});
   request->Start();
 
-  auto device0 = std::make_unique<MockU2fDevice>();
+  auto device0 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
   EXPECT_CALL(*device0, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NotSatisfied));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied));
   // One wink per device.
   EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device0));
 
   // Second device will be have a successful touch.
-  auto device1 = std::make_unique<MockU2fDevice>();
+  auto device1 = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
   // Both keys will be tried, when both fail, register is tried on that device.
   EXPECT_CALL(*device1, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorRegister));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData))
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
   // One wink per device.
   EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device1));
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -483,12 +483,12 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<MockU2fDevice>();
+  auto device = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
   EXPECT_CALL(*device, DeviceTransactPtr(_, _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::SignWithCorruptedResponse));
+      .WillOnce(::testing::Invoke(MockFidoDevice::SignWithCorruptedResponse));
   EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
@@ -527,18 +527,18 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<MockU2fDevice>();
+  auto device = std::make_unique<MockFidoDevice>();
   EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
   // The first request will use the primary app_param, which will be rejected.
   EXPECT_CALL(*device,
               DeviceTransactPtr(WithApplicationParameter(primary_app_param), _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WrongData));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
   // After the rejection, the alternative should be tried.
   EXPECT_CALL(*device,
               DeviceTransactPtr(WithApplicationParameter(alt_app_param), _))
-      .WillOnce(::testing::Invoke(MockU2fDevice::NoErrorSign));
+      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
   EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
+      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
diff --git a/device/fido/virtual_u2f_device.cc b/device/fido/virtual_u2f_device.cc
index 1607914..7384d48 100644
--- a/device/fido/virtual_u2f_device.cc
+++ b/device/fido/virtual_u2f_device.cc
@@ -6,7 +6,10 @@
 
 #include <utility>
 
+#include "base/bind.h"
+#include "base/location.h"
 #include "base/numerics/safe_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "components/apdu/apdu_command.h"
 #include "components/apdu/apdu_response.h"
 #include "crypto/ec_private_key.h"
@@ -81,6 +84,13 @@
   dst->insert(dst->end(), std::begin(src), std::end(src));
 }
 
+// Returns an error response with the given status.
+base::Optional<std::vector<uint8_t>> ErrorStatus(
+    apdu::ApduResponse::Status status) {
+  return apdu::ApduResponse(std::vector<uint8_t>(), status)
+      .GetEncodedResponse();
+}
+
 }  // namespace
 
 VirtualU2fDevice::RegistrationData::RegistrationData() = default;
@@ -125,40 +135,41 @@
                                       DeviceCallback cb) {
   // Note, here we are using the code-under-test in this fake.
   auto parsed_command = apdu::ApduCommand::CreateFromMessage(command);
+
+  base::Optional<std::vector<uint8_t>> response;
+
   switch (parsed_command->ins()) {
     case base::strict_cast<uint8_t>(U2fApduInstruction::kVersion):
       break;
     case base::strict_cast<uint8_t>(U2fApduInstruction::kRegister):
-      DoRegister(parsed_command->ins(), parsed_command->p1(),
-                 parsed_command->p2(), parsed_command->data(), std::move(cb));
+      response = DoRegister(parsed_command->ins(), parsed_command->p1(),
+                            parsed_command->p2(), parsed_command->data());
       break;
     case base::strict_cast<uint8_t>(U2fApduInstruction::kSign):
-      DoSign(parsed_command->ins(), parsed_command->p1(), parsed_command->p2(),
-             parsed_command->data(), std::move(cb));
+      response = DoSign(parsed_command->ins(), parsed_command->p1(),
+                        parsed_command->p2(), parsed_command->data());
       break;
     default:
-      std::move(cb).Run(
-          apdu::ApduResponse(std::vector<uint8_t>(),
-                             apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED)
-              .GetEncodedResponse());
+      response = ErrorStatus(apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED);
   }
+
+  // Call |callback| via the |MessageLoop| because |AuthenticatorImpl| doesn't
+  // support callback hairpinning.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(cb), std::move(response)));
 }
 
-base::WeakPtr<U2fDevice> VirtualU2fDevice::GetWeakPtr() {
+base::WeakPtr<FidoDevice> VirtualU2fDevice::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
 
-void VirtualU2fDevice::DoRegister(uint8_t ins,
-                                  uint8_t p1,
-                                  uint8_t p2,
-                                  base::span<const uint8_t> data,
-                                  DeviceCallback cb) {
+base::Optional<std::vector<uint8_t>> VirtualU2fDevice::DoRegister(
+    uint8_t ins,
+    uint8_t p1,
+    uint8_t p2,
+    base::span<const uint8_t> data) {
   if (data.size() != 64) {
-    std::move(cb).Run(
-        apdu::ApduResponse(std::vector<uint8_t>(),
-                           apdu::ApduResponse::Status::SW_WRONG_LENGTH)
-            .GetEncodedResponse());
-    return;
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
   }
 
   // For now we ignore P1 here. Spec says it should always be 0, and TUP is
@@ -219,24 +230,20 @@
                   std::vector<uint8_t>(app_id_hash.begin(), app_id_hash.end()),
                   1);
 
-  std::move(cb).Run(apdu::ApduResponse(std::move(response),
-                                       apdu::ApduResponse::Status::SW_NO_ERROR)
-                        .GetEncodedResponse());
+  return apdu::ApduResponse(std::move(response),
+                            apdu::ApduResponse::Status::SW_NO_ERROR)
+      .GetEncodedResponse();
 }
 
-void VirtualU2fDevice::DoSign(uint8_t ins,
-                              uint8_t p1,
-                              uint8_t p2,
-                              base::span<const uint8_t> data,
-                              DeviceCallback cb) {
+base::Optional<std::vector<uint8_t>> VirtualU2fDevice::DoSign(
+    uint8_t ins,
+    uint8_t p1,
+    uint8_t p2,
+    base::span<const uint8_t> data) {
   if (!(p1 == kP1CheckOnly || p1 == kP1TupRequiredConsumed ||
         p1 == kP1IndividualAttestation) ||
       p2 != 0) {
-    std::move(cb).Run(
-        apdu::ApduResponse(std::vector<uint8_t>(),
-                           apdu::ApduResponse::Status::SW_WRONG_DATA)
-            .GetEncodedResponse());
-    return;
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
   }
 
   auto challenge_param = data.first(32);
@@ -245,18 +252,10 @@
   if (key_handle_length != 32) {
     // Our own keyhandles are always 32 bytes long, if the request has something
     // else then we already know it is not ours.
-    std::move(cb).Run(
-        apdu::ApduResponse(std::vector<uint8_t>(),
-                           apdu::ApduResponse::Status::SW_WRONG_DATA)
-            .GetEncodedResponse());
-    return;
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
   }
   if (data.size() != 32 + 32 + 1 + key_handle_length) {
-    std::move(cb).Run(
-        apdu::ApduResponse(std::vector<uint8_t>(),
-                           apdu::ApduResponse::Status::SW_WRONG_LENGTH)
-            .GetEncodedResponse());
-    return;
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
   }
   auto key_handle = data.last(key_handle_length);
 
@@ -265,11 +264,7 @@
       std::vector<uint8_t>(key_handle.cbegin(), key_handle.cend()));
 
   if (it == registrations_.end()) {
-    std::move(cb).Run(
-        apdu::ApduResponse(std::vector<uint8_t>(),
-                           apdu::ApduResponse::Status::SW_WRONG_DATA)
-            .GetEncodedResponse());
-    return;
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
   }
 
   base::span<const uint8_t> registered_app_id_hash =
@@ -277,11 +272,7 @@
   if (app_id_hash != registered_app_id_hash) {
     // It's important this error looks identical to the previous one, as
     // tokens should not reveal the existence of keyHandles to unrelated appIds.
-    std::move(cb).Run(
-        apdu::ApduResponse(std::vector<uint8_t>(),
-                           apdu::ApduResponse::Status::SW_WRONG_DATA)
-            .GetEncodedResponse());
-    return;
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
   }
 
   auto& registration = it->second;
@@ -312,9 +303,9 @@
   // Add signature for full response.
   AppendTo(&response, sig);
 
-  std::move(cb).Run(apdu::ApduResponse(std::move(response),
-                                       apdu::ApduResponse::Status::SW_NO_ERROR)
-                        .GetEncodedResponse());
+  return apdu::ApduResponse(std::move(response),
+                            apdu::ApduResponse::Status::SW_NO_ERROR)
+      .GetEncodedResponse();
 }
 
 }  // namespace device
diff --git a/device/fido/virtual_u2f_device.h b/device/fido/virtual_u2f_device.h
index 1f56c1d..6a8e6e34 100644
--- a/device/fido/virtual_u2f_device.h
+++ b/device/fido/virtual_u2f_device.h
@@ -10,12 +10,13 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/component_export.h"
 #include "base/containers/span.h"
 #include "base/macros.h"
-#include "device/fido/u2f_device.h"
+#include "device/fido/fido_device.h"
 
 namespace crypto {
 class ECPrivateKey;
@@ -23,7 +24,7 @@
 
 namespace device {
 
-class COMPONENT_EXPORT(DEVICE_FIDO) VirtualU2fDevice : public U2fDevice {
+class COMPONENT_EXPORT(DEVICE_FIDO) VirtualU2fDevice : public FidoDevice {
  public:
   VirtualU2fDevice();
   ~VirtualU2fDevice() override;
@@ -38,7 +39,7 @@
   void TryWink(WinkCallback cb) override;
   std::string GetId() const override;
   void DeviceTransact(std::vector<uint8_t> command, DeviceCallback cb) override;
-  base::WeakPtr<U2fDevice> GetWeakPtr() override;
+  base::WeakPtr<FidoDevice> GetWeakPtr() override;
 
  private:
   struct RegistrationData {
@@ -58,21 +59,20 @@
     DISALLOW_COPY_AND_ASSIGN(RegistrationData);
   };
 
-  void DoRegister(uint8_t ins,
-                  uint8_t p1,
-                  uint8_t p2,
-                  base::span<const uint8_t> data,
-                  DeviceCallback cb);
+  base::Optional<std::vector<uint8_t>> DoRegister(
+      uint8_t ins,
+      uint8_t p1,
+      uint8_t p2,
+      base::span<const uint8_t> data);
 
-  void DoSign(uint8_t ins,
-              uint8_t p1,
-              uint8_t p2,
-              base::span<const uint8_t> data,
-              DeviceCallback cb);
+  base::Optional<std::vector<uint8_t>> DoSign(uint8_t ins,
+                                              uint8_t p1,
+                                              uint8_t p2,
+                                              base::span<const uint8_t> data);
 
   // Keyed on appId/rpId hash (aka "applicationParam")
   std::map<std::vector<uint8_t>, RegistrationData> registrations_;
-  base::WeakPtrFactory<U2fDevice> weak_factory_;
+  base::WeakPtrFactory<FidoDevice> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(VirtualU2fDevice);
 };
diff --git a/docs/optional.md b/docs/optional.md
index 14b3ed8..fee3a1a4 100644
--- a/docs/optional.md
+++ b/docs/optional.md
@@ -109,7 +109,9 @@
 It is recommended to not use `base::Optional<T>` as a function parameter as it
 will force the callers to use `base::Optional<T>`. Instead, it is recommended to
 keep using `T*` for arguments that can be omitted, with `nullptr` representing
-no value.
+no value. A helper, `base::OptionalOrNullptr`, is available in
+[stl_util.h](https://code.google.com/p/chromium/codesearch#chromium/src/base/stl_util.h)
+and can make it easier to convert `base::Optional<T>` to `T*`.
 
 Furthermore, depending on `T`, MSVC might fail to compile code using
 `base::Optional<T>` as a parameter because of memory alignment issues.
diff --git a/docs/security/sheriff.md b/docs/security/sheriff.md
index ba5a34c..e729fa0 100644
--- a/docs/security/sheriff.md
+++ b/docs/security/sheriff.md
@@ -128,8 +128,8 @@
 
 #### Step 1. Reproduce legitimate-sounding issues.
 
-If you can't reproduce the issue, ask for help on IRC (#chrome-security), or
-find an area owner to help.
+If you can't reproduce the issue, ask for help on IRC (#chrome-security) or the
+Chrome Security chat, or find an area owner to help.
 
 Tips for reproducing bugs:
 
@@ -199,6 +199,13 @@
 SafeBrowsing), make sure the affected team is informed and has access to the
 necessary bugs.
 
+##### Labeling For Chrome On iOS
+
+* Reproduce using iOS device, desktop Safari, or [Browserstack](http://browserstack.com/)
+* Assign severity, impact, milestone, and component labels
+* CC Apple friends (if you don't know who they are, ping awhalley@)
+* Label **ExternalDependency**
+
 ### Find An Owner To Fix The Bug
 
 That owner can be you! Otherwise, this is one of the more grey areas of
diff --git a/extensions/browser/api/alarms/alarm_manager.cc b/extensions/browser/api/alarms/alarm_manager.cc
index 0b05f4a..ba498ff 100644
--- a/extensions/browser/api/alarms/alarm_manager.cc
+++ b/extensions/browser/api/alarms/alarm_manager.cc
@@ -20,6 +20,7 @@
 #include "extensions/browser/api/alarms/alarms_api_constants.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_registry_factory.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/state_store.h"
 #include "extensions/common/api/alarms.h"
@@ -231,6 +232,11 @@
     BrowserContextKeyedAPIFactory<AlarmManager>>::DestructorAtExit g_factory =
     LAZY_INSTANCE_INITIALIZER;
 
+template <>
+void BrowserContextKeyedAPIFactory<AlarmManager>::DeclareFactoryDependencies() {
+  DependsOn(ExtensionRegistryFactory::GetInstance());
+}
+
 // static
 BrowserContextKeyedAPIFactory<AlarmManager>*
 AlarmManager::GetFactoryInstance() {
diff --git a/extensions/browser/api/display_source/display_source_apitestbase.cc b/extensions/browser/api/display_source/display_source_apitestbase.cc
index bc11b30..3c93f308 100644
--- a/extensions/browser/api/display_source/display_source_apitestbase.cc
+++ b/extensions/browser/api/display_source/display_source_apitestbase.cc
@@ -466,8 +466,7 @@
 void MockDisplaySourceConnectionDelegate::BindToUdpSocket() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  socket_.reset(new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND,
-                                   net::RandIntCallback(), nullptr,
+  socket_.reset(new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND, nullptr,
                                    net::NetLogSource()));
 
   net::IPAddress address;
diff --git a/extensions/browser/extensions_test.cc b/extensions/browser/extensions_test.cc
index 4354d9d..c527c15 100644
--- a/extensions/browser/extensions_test.cc
+++ b/extensions/browser/extensions_test.cc
@@ -109,15 +109,15 @@
   // as member variables instead of singletons. The individual services will be
   // cleaned up before the factories are destroyed.
   BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
-      browser_context_.get());
-  BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
       incognito_context_.get());
+  BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
+      browser_context_.get());
 
   extensions_browser_client_.reset();
   ExtensionsBrowserClient::Set(nullptr);
 
-  browser_context_.reset();
   incognito_context_.reset();
+  browser_context_.reset();
   pref_service_.reset();
 }
 
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn
index 88bec59..01f8a88 100644
--- a/extensions/shell/BUILD.gn
+++ b/extensions/shell/BUILD.gn
@@ -41,7 +41,6 @@
     "//base",
     "//components/feedback",
     "//components/guest_view/browser",
-    "//components/guest_view/common",
     "//components/guest_view/renderer",
     "//components/keep_alive_registry",
     "//components/keyed_service/content:content",
@@ -49,13 +48,15 @@
     "//components/network_session_configurator/common",
     "//components/pref_registry",
     "//components/prefs",
+    "//components/storage_monitor",
     "//components/update_client",
     "//components/user_prefs",
-    "//components/web_cache/renderer",
+    "//components/version_info",
     "//content",
     "//content/shell:content_shell_lib",
     "//device/base",
     "//device/bluetooth",
+    "//device/usb",
     "//extensions:extensions_resources",
     "//extensions:shell_and_test_pak",
     "//extensions/browser",
@@ -68,12 +69,10 @@
     "//extensions/shell/common/api",
     "//extensions/shell/common/api:api_registration",
     "//extensions/shell/common/api:extensions_features",
-    "//skia",
+    "//google_apis",
     "//third_party/WebKit/public:blink",
-    "//third_party/cld_3/src/src:cld_3",
     "//ui/base",
     "//ui/base/ime",
-    "//v8",
   ]
 
   # TODO(michaelpg): remove Mac support and always use aura.
@@ -84,7 +83,7 @@
     ]
 
     if (use_x11) {
-      deps += [ "//ui/events" ]
+      deps += [ "//ui/events/devices/x11" ]
     }
   }
 
@@ -201,6 +200,9 @@
       "//ui/wm",
       "//ui/wm/public",
     ]
+    if (is_chromeos) {
+      deps += [ "//ui/ozone" ]
+    }
   }
 
   if (is_desktop_linux) {
@@ -221,7 +223,6 @@
   if (is_chromeos) {
     sources += [
       "browser/api/vpn_provider/vpn_service_factory.cc",
-      "browser/api/vpn_provider/vpn_service_factory.h",
       "browser/shell_screen.cc",
       "browser/shell_screen.h",
     ]
@@ -244,6 +245,7 @@
       "//components/nacl/loader",
       "//components/nacl/renderer",
       "//components/nacl/renderer/plugin:nacl_trusted_plugin",
+      "//ppapi/shared_impl:shared_impl",
     ]
 
     if (is_linux) {
@@ -266,6 +268,7 @@
     deps = [
       ":app_shell_framework_bundle_data",
       "//build/config:exe_and_shlib_deps",
+      "//content/public/app:both",
       "//extensions:shell_and_test_pak",
     ]
     ldflags = [
@@ -286,12 +289,14 @@
       ":app_shell_lib",
       "//build/config:exe_and_shlib_deps",
       "//build/win:default_exe_manifest",
+      "//content/public/app:both",
       "//extensions:shell_and_test_pak",
     ]
 
     if (is_win) {
       configs += [ "//build/config/win:windowed" ]
       configs -= [ "//build/config/win:console" ]
+      deps += [ "//sandbox/win:sandbox" ]
     }
   }
 }
@@ -322,14 +327,21 @@
     "//apps",
     "//base",
     "//base/test:test_support",
+    "//components/crx_file",
     "//components/feedback",
     "//components/keep_alive_registry",
+    "//components/prefs",
+    "//components/user_prefs",
     "//content/test:test_support",
     "//extensions:shell_and_test_pak",
     "//extensions:test_support",
     "//extensions/browser",
     "//extensions/common",
+    "//extensions/common/api",
+    "//extensions/shell/browser/system_logs",
+    "//google_apis",
     "//testing/gtest",
+    "//ui/gl:test_support",
   ]
 
   data_deps = [
@@ -359,7 +371,10 @@
       "browser/shell_audio_controller_chromeos_unittest.cc",
       "browser/shell_screen_unittest.cc",
     ]
-    deps += [ "//chromeos:test_support_without_gmock" ]
+    deps += [
+      "//chromeos",
+      "//chromeos:test_support_without_gmock",
+    ]
   }
 
   if (enable_nacl) {
@@ -417,6 +432,7 @@
     ]
     deps = [
       ":app_shell_framework_resources",
+      "//content/public/app:both",
     ]
     ldflags = [ "-Wl,-install_name,@rpath/Frameworks/App Shell Framework.framework/App Shell Framework" ]
     if (is_component_build) {
@@ -437,6 +453,7 @@
     deps = [
       ":app_shell_framework+link",
       "//build/config:exe_and_shlib_deps",
+      "//content/public/app:both",
     ]
     ldflags = [
       "-rpath",
diff --git a/extensions/shell/app/shell_main_delegate.cc b/extensions/shell/app/shell_main_delegate.cc
index 392d454..af2b737 100644
--- a/extensions/shell/app/shell_main_delegate.cc
+++ b/extensions/shell/app/shell_main_delegate.cc
@@ -32,9 +32,9 @@
 #endif
 
 #if BUILDFLAG(ENABLE_NACL)
-#include "components/nacl/common/nacl_switches.h"
+#include "components/nacl/common/nacl_switches.h"  // nogncheck
 #if defined(OS_LINUX)
-#include "components/nacl/common/nacl_paths.h"
+#include "components/nacl/common/nacl_paths.h"  // nogncheck
 #endif  // OS_LINUX
 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
 #include "components/nacl/zygote/nacl_fork_delegate_linux.h"
@@ -50,8 +50,8 @@
 #endif
 
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-#include "components/crash/content/app/breakpad_linux.h"
-#include "components/crash/content/app/crash_reporter_client.h"
+#include "components/crash/content/app/breakpad_linux.h"         // nogncheck
+#include "components/crash/content/app/crash_reporter_client.h"  // nogncheck
 #include "extensions/shell/app/shell_crash_reporter_client.h"
 #endif
 
diff --git a/extensions/shell/browser/shell_browser_main_parts.cc b/extensions/shell/browser/shell_browser_main_parts.cc
index f40f7f1..80e5a35 100644
--- a/extensions/shell/browser/shell_browser_main_parts.cc
+++ b/extensions/shell/browser/shell_browser_main_parts.cc
@@ -17,6 +17,7 @@
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/context_factory.h"
 #include "content/public/browser/devtools_agent_host.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/result_codes.h"
 #include "content/shell/browser/shell_devtools_manager_delegate.h"
 #include "extensions/browser/browser_context_keyed_service_factories.h"
@@ -75,7 +76,7 @@
 #endif
 
 #if defined(USE_AURA) && defined(USE_X11)
-#include "ui/events/devices/x11/touch_factory_x11.h"
+#include "ui/events/devices/x11/touch_factory_x11.h"  // nogncheck
 #endif
 
 using base::CommandLine;
@@ -87,6 +88,16 @@
 
 namespace extensions {
 
+namespace {
+
+// Intentionally dereferences a null pointer to test the crash reporter.
+void CrashForTest() {
+  int* bad_pointer = nullptr;
+  *bad_pointer = 0;
+}
+
+}  // namespace
+
 ShellBrowserMainParts::ShellBrowserMainParts(
     const content::MainFunctionParams& parameters,
     ShellBrowserMainDelegate* browser_main_delegate)
@@ -232,6 +243,10 @@
 
   content::ShellDevToolsManagerDelegate::StartHttpHandler(
       browser_context_.get());
+
+  if (cmd->HasSwitch(::switches::kBrowserCrashTest))
+    CrashForTest();
+
   if (parameters_.ui_task) {
     // For running browser tests.
     parameters_.ui_task->Run();
diff --git a/extensions/shell/browser/shell_content_browser_client.cc b/extensions/shell/browser/shell_content_browser_client.cc
index 16285974..d1c6b9962 100644
--- a/extensions/shell/browser/shell_content_browser_client.cc
+++ b/extensions/shell/browser/shell_content_browser_client.cc
@@ -49,8 +49,8 @@
 #include "components/nacl/browser/nacl_browser.h"
 #include "components/nacl/browser/nacl_host_message_filter.h"
 #include "components/nacl/browser/nacl_process_host.h"
-#include "components/nacl/common/nacl_process_type.h"
-#include "components/nacl/common/nacl_switches.h"
+#include "components/nacl/common/nacl_process_type.h"  // nogncheck
+#include "components/nacl/common/nacl_switches.h"      // nogncheck
 #include "content/public/browser/browser_child_process_host.h"
 #include "content/public/browser/child_process_data.h"
 #endif
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc
index 934ae5e8..0fc6d92 100644
--- a/extensions/shell/browser/shell_desktop_controller_aura.cc
+++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -41,7 +41,7 @@
 #include "ui/display/types/display_mode.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/display/types/native_display_delegate.h"
-#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/ozone_platform.h"  // nogncheck
 #else
 #include "ui/views/widget/desktop_aura/desktop_screen.h"
 #endif  // defined(OS_CHROMEOS)
diff --git a/extensions/shell/common/shell_content_client.cc b/extensions/shell/common/shell_content_client.cc
index 7934ceb..bfc59e7 100644
--- a/extensions/shell/common/shell_content_client.cc
+++ b/extensions/shell/common/shell_content_client.cc
@@ -17,10 +17,10 @@
 #include "base/base_paths.h"
 #include "base/files/file_path.h"
 #include "base/path_service.h"
-#include "components/nacl/common/nacl_constants.h"
-#include "components/nacl/renderer/plugin/ppapi_entrypoints.h"
-#include "content/public/common/pepper_plugin_info.h"
-#include "ppapi/shared_impl/ppapi_permissions.h"
+#include "components/nacl/common/nacl_constants.h"              // nogncheck
+#include "components/nacl/renderer/plugin/ppapi_entrypoints.h"  // nogncheck
+#include "content/public/common/pepper_plugin_info.h"           // nogncheck
+#include "ppapi/shared_impl/ppapi_permissions.h"                // nogncheck
 #endif
 
 namespace extensions {
diff --git a/gin/converter.h b/gin/converter.h
index c47ec0a..38c1f7f 100644
--- a/gin/converter.h
+++ b/gin/converter.h
@@ -224,36 +224,17 @@
   return Converter<T>::ToV8(isolate, input);
 }
 
-template<typename T, bool = ToV8ReturnsMaybe<T>::value> struct ToV8Traits;
+template <typename T>
+std::enable_if_t<ToV8ReturnsMaybe<T>::value, bool>
+TryConvertToV8(v8::Isolate* isolate, T input, v8::Local<v8::Value>* output) {
+  return ConvertToV8(isolate, input).ToLocal(output);
+}
 
 template <typename T>
-struct ToV8Traits<T, true> {
-  static bool TryConvertToV8(v8::Isolate* isolate,
-                             T input,
-                             v8::Local<v8::Value>* output) {
-    auto maybe = ConvertToV8(isolate->GetCurrentContext(), input);
-    if (maybe.IsEmpty())
-      return false;
-    *output = maybe.ToLocalChecked();
-    return true;
-  }
-};
-
-template <typename T>
-struct ToV8Traits<T, false> {
-  static bool TryConvertToV8(v8::Isolate* isolate,
-                             T input,
-                             v8::Local<v8::Value>* output) {
-    *output = ConvertToV8(isolate, input);
-    return true;
-  }
-};
-
-template <typename T>
-bool TryConvertToV8(v8::Isolate* isolate,
-                    T input,
-                    v8::Local<v8::Value>* output) {
-  return ToV8Traits<T>::TryConvertToV8(isolate, input, output);
+std::enable_if_t<!ToV8ReturnsMaybe<T>::value, bool>
+TryConvertToV8(v8::Isolate* isolate, T input, v8::Local<v8::Value>* output) {
+  *output = ConvertToV8(isolate, input);
+  return true;
 }
 
 // This crashes when input.size() > v8::String::kMaxLength.
diff --git a/gin/converter_unittest.cc b/gin/converter_unittest.cc
index 967ca134..ee48620 100644
--- a/gin/converter_unittest.cc
+++ b/gin/converter_unittest.cc
@@ -167,10 +167,15 @@
   v8::MaybeLocal<v8::Value> maybe = ConvertToV8(isolate, vector);
   v8::Local<v8::Value> array;
   ASSERT_TRUE(maybe.ToLocal(&array));
+  v8::Local<v8::Value> array2;
+  ASSERT_TRUE(TryConvertToV8(isolate, vector, &array2));
 
   std::vector<MyObject*> out_value;
   ASSERT_TRUE(ConvertFromV8(isolate, array, &out_value));
   EXPECT_THAT(out_value, testing::ContainerEq(vector));
+  std::vector<MyObject*> out_value2;
+  ASSERT_TRUE(ConvertFromV8(isolate, array2, &out_value2));
+  EXPECT_THAT(out_value2, testing::ContainerEq(vector));
 }
 
 }  // namespace gin
diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc
index 5a3f935b..e73ded1 100644
--- a/gpu/command_buffer/tests/gl_test_utils.cc
+++ b/gpu/command_buffer/tests/gl_test_utils.cc
@@ -375,6 +375,16 @@
       return false;
     }
 
+    gpu::GPUInfo gpu_info;
+    gpu::CollectContextGraphicsInfo(&gpu_info);
+    // See crbug.com/822716, the ATI proprietary driver has eglGetProcAddress
+    // but eglInitialize crashes with x11.
+    if (gpu_info.driver_vendor.find("ATI Technologies Inc.") !=
+        std::string::npos) {
+      LOG(INFO) << "Skip test, ATI proprietary driver crashes with egl/x11";
+      return false;
+    }
+
     gl_reinitialized_ = true;
     gl::init::ShutdownGL(false /* due_to_fallback */);
     if (!GLTestHelper::InitializeGL(
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
index ebc2f9b..80eb4fc 100644
--- a/gpu/config/gpu_driver_bug_list.json
+++ b/gpu/config/gpu_driver_bug_list.json
@@ -2863,6 +2863,23 @@
       "features": [
         "init_gl_position_in_vertex_shader"
       ]
+    },
+    {
+      "id": 265,
+      "cr_bugs": [811661],
+      "description": "Crash in glQueryCounter() in VMware driver",
+      "os": {
+        "type": "linux"
+      },
+      "vendor_id": "0x15ad",
+      "device_id": ["0x0405"],
+      "features": [
+        "disable_timestamp_queries"
+      ],
+      "disabled_extensions": [
+        "GL_EXT_disjoint_timer_query",
+        "GL_EXT_disjoint_timer_query_webgl2"
+      ]
     }
   ]
 }
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index 5e3ec5a..7c39dc54 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -296,11 +296,21 @@
   }
 }
 
+# GPU bots run very long tests sometimes on a single tester. The regular
+# timeout isn't enough on some testers during the migration when they run both
+# the buildbot and LUCI tests. Double the timeout for them.
+# TODO(cwallez@chromium.org): remove this when the migration is complete
+builder_mixins {
+  name: "gpu-slow-bot"
+  execution_timeout_secs: 21600  # 2 x 3h for a double workload
+}
+
 builder_mixins {
   name: "win-gpu-fyi-ci"
   dimensions: "cpu:x86-64"
   mixins: "win"
   mixins: "gpu-fyi-ci"
+  mixins: "gpu-slow-bot"
 }
 
 builder_mixins {
@@ -313,15 +323,6 @@
   }
 }
 
-# GPU bots run very long tests sometimes on a single tester. The regular
-# timeout isn't enough on some testers during the migration when they run both
-# the buildbot and LUCI tests. Double the timeout for them.
-# TODO(cwallez@chromium.org): remove this when the migration is complete
-builder_mixins {
-  name: "gpu-slow-bot"
-  execution_timeout_secs: 21600  # 2 x 3h for a double workload
-}
-
 buckets {
   name: "luci.chromium.ci"
   acl_sets: "ci"
@@ -721,7 +722,6 @@
     builders {
       name: "Win10 FYI Debug (NVIDIA)"
       mixins: "win-gpu-fyi-ci"
-      mixins: "gpu-slow-bot"
     }
     builders {
       name: "Win10 FYI dEQP Release (NVIDIA)"
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index 615d741..9c4453b47 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -1702,118 +1702,6 @@
     short_name: "bb"
   }
 
-  # GPU FYI Linux bots, prefixed with GPU FYI|Linux
-  builders: {
-    name: "buildbucket/luci.chromium.ci/GPU FYI Linux Builder"
-    category: "GPU FYI|Linux|Builder|Release"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Linux Builder"
-    category: "GPU FYI|Linux|Builder|Release"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/GPU FYI Linux Builder (dbg)"
-    category: "GPU FYI|Linux|Builder|Debug"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Linux Builder (dbg)"
-    category: "GPU FYI|Linux|Builder|Debug"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/GPU FYI Linux Ozone Builder"
-    category: "GPU FYI|Linux|Builder|Ozone"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Linux Ozone Builder"
-    category: "GPU FYI|Linux|Builder|Ozone"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/GPU FYI Linux dEQP Builder"
-    category: "GPU FYI|Linux|Builder|dEQP"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Linux dEQP Builder"
-    category: "GPU FYI|Linux|Builder|dEQP"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Linux FYI Release (Intel HD 630)"
-    category: "GPU FYI|Linux|Intel|Release"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI Release (Intel HD 630)"
-    category: "GPU FYI|Linux|Intel|Release"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Linux FYI Ozone (Intel)"
-    category: "GPU FYI|Linux|Intel|Ozone"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI Ozone (Intel)"
-    category: "GPU FYI|Linux|Intel|Ozone"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Linux FYI Release (AMD R7 240)"
-    category: "GPU FYI|Linux|AMD|Release"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI Release (AMD R7 240)"
-    category: "GPU FYI|Linux|AMD|Release"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Linux FYI Release (NVIDIA)"
-    category: "GPU FYI|Linux|Nvidia|Release"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI Release (NVIDIA)"
-    category: "GPU FYI|Linux|Nvidia|Release"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Linux FYI Debug (NVIDIA)"
-    category: "GPU FYI|Linux|Nvidia|Debug"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI Debug (NVIDIA)"
-    category: "GPU FYI|Linux|Nvidia|Debug"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Linux FYI dEQP Release (NVIDIA)"
-    category: "GPU FYI|Linux|Nvidia|dEQP"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI dEQP Release (NVIDIA)"
-    category: "GPU FYI|Linux|Nvidia|dEQP"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Linux FYI GPU TSAN Release"
-    category: "GPU FYI|Linux|TSAN"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI GPU TSAN Release"
-    category: "GPU FYI|Linux|TSAN"
-    short_name: "🦖"
-  }
-
   # GPU FYI Mac bots, prefixed with GPU FYI|Mac
   builders: {
     name: "buildbucket/luci.chromium.ci/GPU FYI Mac Builder"
@@ -3452,67 +3340,56 @@
     short_name: "asn"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Linux Builder"
     name: "buildbucket/luci.chromium.ci/GPU FYI Linux Builder"
     category: "Linux|Builder"
     short_name: "rel"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Linux Builder (dbg)"
     name: "buildbucket/luci.chromium.ci/GPU FYI Linux Builder (dbg)"
     category: "Linux|Builder"
     short_name: "dbg"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Linux Ozone Builder"
     name: "buildbucket/luci.chromium.ci/GPU FYI Linux Ozone Builder"
     category: "Linux|Builder"
     short_name: "ozn"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Linux dEQP Builder"
     name: "buildbucket/luci.chromium.ci/GPU FYI Linux dEQP Builder"
     category: "Linux|Builder"
     short_name: "dqp"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI Release (Intel HD 630)"
     name: "buildbucket/luci.chromium.ci/Linux FYI Release (Intel HD 630)"
     category: "Linux|Intel"
     short_name: "630"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI Ozone (Intel)"
     name: "buildbucket/luci.chromium.ci/Linux FYI Ozone (Intel)"
     category: "Linux|Intel"
     short_name: "ozn"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI Release (AMD R7 240)"
     name: "buildbucket/luci.chromium.ci/Linux FYI Release (AMD R7 240)"
     category: "Linux"
     short_name: "amd"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI Release (NVIDIA)"
     name: "buildbucket/luci.chromium.ci/Linux FYI Release (NVIDIA)"
     category: "Linux|Nvidia"
     short_name: "rel"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI Debug (NVIDIA)"
     name: "buildbucket/luci.chromium.ci/Linux FYI Debug (NVIDIA)"
     category: "Linux|Nvidia"
     short_name: "dbg"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI dEQP Release (NVIDIA)"
     name: "buildbucket/luci.chromium.ci/Linux FYI dEQP Release (NVIDIA)"
     category: "Linux|Nvidia"
     short_name: "dqp"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Linux FYI GPU TSAN Release"
     name: "buildbucket/luci.chromium.ci/Linux FYI GPU TSAN Release"
     category: "Linux"
     short_name: "tsn"
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 0560ebb..031235a8 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1442,6 +1442,39 @@
       <message name="IDS_IOS_SYNC_UPDATE_CREDENTIALS" desc="Title displayed when the signed in user needs to update its credentials. [Length: 20em] [iOS only]">
         Update
       </message>
+      <message name="IDS_IOS_TAB_GRID_DONE_BUTTON" desc="Title of the Done button in the tab grid UI. [iOS only]">
+        Done
+      </message>
+      <message name="IDS_IOS_TAB_GRID_CLOSE_ALL_BUTTON" desc="Title of the button in the tab grid UI that closes all the tabs in the grid. [iOS only]">
+        Close All
+      </message>
+      <message name="IDS_IOS_TAB_GRID_INCOGNITO_TABS_TITLE" desc="The accessibility label of the Incognito Tabs page in the tab grid UI. [iOS only]">
+        Incognito Tabs
+      </message>
+      <message name="IDS_IOS_TAB_GRID_REGULAR_TABS_TITLE" desc="The accessibility label of the Regular Tabs page (as opposed to the Incognito Tabs page) in the tab grid UI. [iOS only]">
+        Open Tabs
+      </message>
+      <message name="IDS_IOS_TAB_GRID_REMOTE_TABS_TITLE" desc="The accessibility label of the Remote Tabs page in the tab grid UI. [iOS only]">
+        Tabs from other devices
+      </message>
+      <message name="IDS_IOS_TAB_GRID_INCOGNITO_TABS_EMPTY_STATE_TITLE" desc="Title shown in the Incognito Tabs page when the grid is empty. [iOS only]">
+        No Incognito Tabs
+      </message>
+      <message name="IDS_IOS_TAB_GRID_REGULAR_TABS_EMPTY_STATE_TITLE" desc="Title shown in the Regular Tabs page (as opposed to the Incognito Tabs page) when the grid is empty. [iOS only]">
+        No Open Tabs
+      </message>
+      <message name="IDS_IOS_TAB_GRID_INCOGNITO_TABS_EMPTY_STATE_BODY" desc="Text body shown in the Incognito Tabs page when the grid is empty, explaining that the user can open a new tab. [iOS only]">
+        Open a tab to browse the web privately.
+      </message>
+      <message name="IDS_IOS_TAB_GRID_REGULAR_TABS_EMPTY_STATE_BODY" desc="Text body shown in the Regular Tabs page (as opposed to the Incognito Tabs page) when the grid is empty, explaining that the user can open a new tab. [iOS only]">
+        Open a tab to browse the web.
+      </message>
+      <message name="IDS_IOS_TAB_GRID_CREATE_NEW_INCOGNITO_TAB" desc="The accessibility label for the button that creates new incognito tabs. [iOS only]">
+        Create new incognito tab.
+      </message>
+      <message name="IDS_IOS_TAB_GRID_CREATE_NEW_TAB" desc="The accessibility label for the button that creates new regular tabs (as opposed to incognito tabs). [iOS only]">
+        Create new tab.
+      </message>
       <message name="IDS_IOS_TAB_STRIP_ENTER_TAB_SWITCHER" desc="The accessibility label of the tab strip button to enter the tab switcher. The tab switcher is a view showing the opened tabs, and allows users to switch, close, and open new tabs. [iOS only]">
         Enter Tab Switcher
       </message>
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn
index ccd4fc9..2f3e35a 100644
--- a/ios/chrome/browser/BUILD.gn
+++ b/ios/chrome/browser/BUILD.gn
@@ -248,7 +248,6 @@
     "//net",
     "//net:test_support",
     "//testing/gtest",
-    "//third_party/ocmock",
     "//url",
   ]
 }
diff --git a/ios/chrome/browser/download/BUILD.gn b/ios/chrome/browser/download/BUILD.gn
index 4853e17..da58770 100644
--- a/ios/chrome/browser/download/BUILD.gn
+++ b/ios/chrome/browser/download/BUILD.gn
@@ -10,8 +10,6 @@
     "browser_download_service_factory.mm",
     "download_directory_util.cc",
     "download_directory_util.h",
-    "download_manager_metric_names.cc",
-    "download_manager_metric_names.h",
     "download_manager_tab_helper.h",
     "download_manager_tab_helper.mm",
     "download_manager_tab_helper_delegate.h",
diff --git a/ios/chrome/browser/download/download_manager_metric_names.cc b/ios/chrome/browser/download/download_manager_metric_names.cc
deleted file mode 100644
index b8b99203..0000000
--- a/ios/chrome/browser/download/download_manager_metric_names.cc
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ios/chrome/browser/download/download_manager_metric_names.h"
-
-const char kDownloadManagerGoogleDriveInstalled[] =
-    "MobileDownloadFileUIInstallGoogleDrive";
diff --git a/ios/chrome/browser/download/download_manager_metric_names.h b/ios/chrome/browser/download/download_manager_metric_names.h
deleted file mode 100644
index 71686fe9..0000000
--- a/ios/chrome/browser/download/download_manager_metric_names.h
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_METRIC_NAMES_H_
-#define IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_METRIC_NAMES_H_
-
-// MobileDownloadFileUIInstallGoogleDrive UMA action. Logged when Google Drive
-// app is installed after presenting Store Kit dialog from the Download Manager.
-extern const char kDownloadManagerGoogleDriveInstalled[];
-
-#endif  // IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_METRIC_NAMES_H_
diff --git a/ios/chrome/browser/installation_notifier.mm b/ios/chrome/browser/installation_notifier.mm
index 701aa62..d68fc922 100644
--- a/ios/chrome/browser/installation_notifier.mm
+++ b/ios/chrome/browser/installation_notifier.mm
@@ -59,6 +59,9 @@
 @interface InstallationNotifier (Testing)
 // Sets the dispatcher.
 - (void)setDispatcher:(id<DispatcherProtocol>)dispatcher;
+// Sets the UIApplication used to determine if a scheme can be opened by an
+// application.
+- (void)setSharedApplication:(UIApplication*)sharedApplication;
 @end
 
 @implementation InstallationNotifier {
@@ -86,6 +89,7 @@
     _dispatcher = [[DefaultDispatcher alloc] init];
     _installedAppObservers = [[NSMutableDictionary alloc] init];
     _notificationCenter = [NSNotificationCenter defaultCenter];
+    sharedApplication_ = [UIApplication sharedApplication];
     _backoffEntry.reset(new net::BackoffEntry([self backOffPolicy]));
   }
   return self;
@@ -182,7 +186,7 @@
     DCHECK([observers count] > 0);
     NSURL* testSchemeURL =
         [NSURL URLWithString:[NSString stringWithFormat:@"%@:", scheme]];
-    if ([[UIApplication sharedApplication] canOpenURL:testSchemeURL]) {
+    if ([sharedApplication_ canOpenURL:testSchemeURL]) {
       [_notificationCenter postNotificationName:scheme object:self];
       for (id weakReferenceToObserver in observers) {
         id observer = [weakReferenceToObserver nonretainedObjectValue];
@@ -212,8 +216,11 @@
   _dispatcher = dispatcher;
 }
 
-- (void)resetDispatcher {
-  _dispatcher = [[DefaultDispatcher alloc] init];
+- (void)setSharedApplication:(id)sharedApplication {
+  // Verify that the test application object responds to all the selectors that
+  // will be called on it.
+  CHECK([sharedApplication respondsToSelector:@selector(canOpenURL:)]);
+  sharedApplication_ = (UIApplication*)sharedApplication;
 }
 
 @end
diff --git a/ios/chrome/browser/installation_notifier_unittest.mm b/ios/chrome/browser/installation_notifier_unittest.mm
index e330fd2d..226621a8 100644
--- a/ios/chrome/browser/installation_notifier_unittest.mm
+++ b/ios/chrome/browser/installation_notifier_unittest.mm
@@ -13,7 +13,6 @@
 #include "ios/web/public/test/test_web_thread.h"
 #include "net/base/backoff_entry.h"
 #include "testing/platform_test.h"
-#import "third_party/ocmock/OCMock/OCMock.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -79,9 +78,27 @@
 
 @end
 
+@interface MockUIApplication : NSObject
+// Mocks UIApplication's canOpenURL.
+@end
+
+@implementation MockUIApplication {
+  BOOL canOpen_;
+}
+
+- (void)setCanOpenURL:(BOOL)canOpen {
+  canOpen_ = canOpen;
+}
+
+- (BOOL)canOpenURL:(NSURL*)url {
+  return canOpen_;
+}
+
+@end
+
 @interface InstallationNotifier (Testing)
 - (void)setDispatcher:(id<DispatcherProtocol>)dispatcher;
-- (void)resetDispatcher;
+- (void)setSharedApplication:(id)sharedApplication;
 - (void)dispatchInstallationNotifierBlock;
 - (void)registerForInstallationNotifications:(id)observer
                                 withSelector:(SEL)notificationSelector
@@ -103,16 +120,12 @@
     dispatcher_ = dispatcher;
     notificationReceiver1_ = ([[MockNotificationReceiver alloc] init]);
     notificationReceiver2_ = ([[MockNotificationReceiver alloc] init]);
-    application_ = OCMClassMock([UIApplication class]);
-    OCMStub([application_ sharedApplication]).andReturn(application_);
+    sharedApplication_ = [[MockUIApplication alloc] init];
+    [installationNotifier_ setSharedApplication:sharedApplication_];
     [installationNotifier_ setDispatcher:dispatcher_];
     histogramTester_.reset(new base::HistogramTester());
   }
 
-  ~InstallationNotifierTest() override {
-    [installationNotifier_ resetDispatcher];
-  }
-
   void VerifyHistogramValidity(int expectedYes, int expectedNo) {
     histogramTester_->ExpectTotalCount("NativeAppLauncher.InstallationDetected",
                                        expectedYes + expectedNo);
@@ -141,12 +154,12 @@
   __weak FakeDispatcher* dispatcher_;
   MockNotificationReceiver* notificationReceiver1_;
   MockNotificationReceiver* notificationReceiver2_;
-  id application_;
+  MockUIApplication* sharedApplication_;
   std::unique_ptr<base::HistogramTester> histogramTester_;
 };
 
 TEST_F(InstallationNotifierTest, RegisterWithAppAlreadyInstalled) {
-  OCMStub([application_ canOpenURL:[OCMArg any]]).andReturn(YES);
+  [sharedApplication_ setCanOpenURL:YES];
   [installationNotifier_
       registerForInstallationNotifications:notificationReceiver1_
                               withSelector:@selector(receivedNotification)
@@ -161,11 +174,11 @@
 }
 
 TEST_F(InstallationNotifierTest, RegisterWithAppInstalledAfterSomeTime) {
-  [dispatcher_
-      executeAfter:10
-             block:^{
-               OCMStub([application_ canOpenURL:[OCMArg any]]).andReturn(YES);
-             }];
+  [sharedApplication_ setCanOpenURL:NO];
+  [dispatcher_ executeAfter:10
+                      block:^{
+                        [sharedApplication_ setCanOpenURL:YES];
+                      }];
   [installationNotifier_
       registerForInstallationNotifications:notificationReceiver1_
                               withSelector:@selector(receivedNotification)
@@ -175,11 +188,11 @@
 }
 
 TEST_F(InstallationNotifierTest, RegisterForTwoInstallations) {
-  [dispatcher_
-      executeAfter:10
-             block:^{
-               OCMStub([application_ canOpenURL:[OCMArg any]]).andReturn(YES);
-             }];
+  [sharedApplication_ setCanOpenURL:NO];
+  [dispatcher_ executeAfter:10
+                      block:^{
+                        [sharedApplication_ setCanOpenURL:YES];
+                      }];
   [installationNotifier_
       registerForInstallationNotifications:notificationReceiver1_
                               withSelector:@selector(receivedNotification)
@@ -202,7 +215,7 @@
 }
 
 TEST_F(InstallationNotifierTest, RegisterAndThenUnregister) {
-  OCMStub([application_ canOpenURL:[OCMArg any]]).andReturn(NO);
+  [sharedApplication_ setCanOpenURL:NO];
   [dispatcher_ executeAfter:10
                       block:^{
                         [installationNotifier_
@@ -217,7 +230,7 @@
 }
 
 TEST_F(InstallationNotifierTest, TestExponentialBackoff) {
-  OCMStub([application_ canOpenURL:[OCMArg any]]).andReturn(NO);
+  [sharedApplication_ setCanOpenURL:NO];
   // Making sure that delay is multiplied by |multiplyFactor| every time.
   [dispatcher_ executeAfter:0
                       block:^{
diff --git a/ios/chrome/browser/ui/download/BUILD.gn b/ios/chrome/browser/ui/download/BUILD.gn
index 4914a11..c0c8813e 100644
--- a/ios/chrome/browser/ui/download/BUILD.gn
+++ b/ios/chrome/browser/ui/download/BUILD.gn
@@ -79,7 +79,6 @@
     "//ios/chrome/browser/ui:ui_util",
     "//ios/chrome/browser/web:test_support",
     "//ios/chrome/test:test_support",
-    "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/fakes",
     "//ios/testing:ios_test_support",
     "//ios/web/public/test",
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator.mm b/ios/chrome/browser/ui/download/download_manager_coordinator.mm
index e3a0478..3705f5f 100644
--- a/ios/chrome/browser/ui/download/download_manager_coordinator.mm
+++ b/ios/chrome/browser/ui/download/download_manager_coordinator.mm
@@ -7,14 +7,10 @@
 #include <memory>
 
 #import "base/logging.h"
-#include "base/metrics/user_metrics.h"
-#include "base/metrics/user_metrics_action.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/strings/grit/components_strings.h"
-#include "ios/chrome/browser/download/download_manager_metric_names.h"
 #import "ios/chrome/browser/download/download_manager_tab_helper.h"
 #import "ios/chrome/browser/download/google_drive_app_util.h"
-#import "ios/chrome/browser/installation_notifier.h"
 #import "ios/chrome/browser/store_kit/store_kit_coordinator.h"
 #import "ios/chrome/browser/ui/download/download_manager_mediator.h"
 #import "ios/chrome/browser/ui/download/download_manager_view_controller.h"
@@ -49,10 +45,6 @@
 @synthesize animatesPresentation = _animatesPresentation;
 @synthesize downloadTask = _downloadTask;
 
-- (void)dealloc {
-  [[InstallationNotifier sharedInstance] unregisterForNotifications:self];
-}
-
 - (void)start {
   DCHECK(self.presenter);
 
@@ -179,11 +171,6 @@
   }
   [_storeKitCoordinator start];
   [controller setInstallDriveButtonVisible:NO animated:YES];
-
-  [[InstallationNotifier sharedInstance]
-      registerForInstallationNotifications:self
-                              withSelector:@selector(didInstallGoogleDriveApp)
-                                 forScheme:kGoogleDriveAppURLScheme];
 }
 
 - (void)downloadManagerViewControllerDidStartDownload:
@@ -249,10 +236,4 @@
                                       completion:nil];
 }
 
-// Called when Google Drive app is installed after starting StoreKitCoordinator.
-- (void)didInstallGoogleDriveApp {
-  base::RecordAction(
-      base::UserMetricsAction(kDownloadManagerGoogleDriveInstalled));
-}
-
 @end
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm b/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
index 65e496f..7d74fd62 100644
--- a/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
@@ -11,11 +11,8 @@
 #include "base/mac/foundation_util.h"
 #include "base/run_loop.h"
 #include "base/strings/sys_string_conversions.h"
-#include "base/test/user_action_tester.h"
 #include "ios/chrome/browser/download/download_directory_util.h"
-#include "ios/chrome/browser/download/download_manager_metric_names.h"
 #import "ios/chrome/browser/download/download_manager_tab_helper.h"
-#import "ios/chrome/browser/download/google_drive_app_util.h"
 #import "ios/chrome/browser/ui/download/download_manager_view_controller.h"
 #import "ios/chrome/test/fakes/fake_contained_presenter.h"
 #import "ios/chrome/test/fakes/fake_document_interaction_controller.h"
@@ -81,22 +78,15 @@
   }
   ~DownloadManagerCoordinatorTest() override {
     [document_interaction_controller_class_ stopMocking];
-    [application_ stopMocking];
   }
 
-  web::TestWebThreadBundle thread_bundle_;
   FakeContainedPresenter* presenter_;
   UIViewController* base_view_controller_;
   ScopedKeyWindow scoped_key_window_;
   web::TestWebState web_state_;
   id document_interaction_controller_class_;
   StubTabHelper tab_helper_;
-  // Application can be lazily created by tests, but it has to be OCMock.
-  // Destructor will call -stopMocking on this object to make sure that
-  // UIApplication is not mocked after these test finish running.
-  id application_;
   DownloadManagerCoordinator* coordinator_;
-  base::UserActionTester user_action_tester_;
 };
 
 // Tests starting the coordinator. Verifies that view controller is presented
@@ -284,11 +274,8 @@
   DownloadManagerViewController* viewController =
       base_view_controller_.childViewControllers.firstObject;
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
-  @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
-    [viewController.delegate
-        downloadManagerViewControllerDidClose:viewController];
-  }
+  [viewController.delegate
+      downloadManagerViewControllerDidClose:viewController];
 
   // Verify that child view controller is removed, download task is set to null
   // and download task is cancelled.
@@ -318,11 +305,9 @@
   // button changes it's alpha.
   ASSERT_EQ(1.0f, viewController.installDriveButton.superview.alpha);
 
-  @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
-    [viewController.delegate
-        installDriveForDownloadManagerViewController:viewController];
-  }
+  [viewController.delegate
+      installDriveForDownloadManagerViewController:viewController];
+
   // Verify that Store Kit dialog was presented.
   EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, ^{
     return [base_view_controller_.presentedViewController class] ==
@@ -334,27 +319,14 @@
     return viewController.installDriveButton.superview.alpha == 0.0f;
   }));
 
-  // Simulate Google Drive app installation and verify that expected user action
-  // has been recorded.
-  ASSERT_EQ(0, user_action_tester_.GetActionCount(
-                   kDownloadManagerGoogleDriveInstalled));
-  // SKStoreProductViewController uses UIApplication, so it's not possible to
-  // install the mock before the test run.
-  application_ = OCMClassMock([UIApplication class]);
-  OCMStub([application_ sharedApplication]).andReturn(application_);
-  OCMStub([application_ canOpenURL:GetGoogleDriveAppUrl()]).andReturn(YES);
-  EXPECT_TRUE(WaitUntilConditionOrTimeout(testing::kWaitForActionTimeout, ^{
-    base::RunLoop().RunUntilIdle();
-    return user_action_tester_.GetActionCount(
-               kDownloadManagerGoogleDriveInstalled) == 1;
-  }));
-
   // Stop to avoid holding a dangling pointer to destroyed task.
   [coordinator_ stop];
 }
 
 // Tests presenting Open In... menu.
 TEST_F(DownloadManagerCoordinatorTest, OpenIn) {
+  web::TestWebThreadBundle thread_bundle;
+
   web::FakeDownloadTask task(GURL(kTestUrl), kTestMimeType);
   task.SetSuggestedFilename(base::SysNSStringToUTF16(kTestSuggestedFileName));
   coordinator_.downloadTask = &task;
@@ -385,11 +357,8 @@
   UIView* view = [[UIView alloc] init];
   [view addLayoutGuide:guide];
   ASSERT_FALSE(document_interaction_controller.presentedOpenInMenu);
-  @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
-    [viewController.delegate downloadManagerViewController:viewController
-                          presentOpenInMenuWithLayoutGuide:guide];
-  }
+  [viewController.delegate downloadManagerViewController:viewController
+                        presentOpenInMenuWithLayoutGuide:guide];
   ASSERT_TRUE(document_interaction_controller.presentedOpenInMenu);
   ASSERT_TRUE(CGRectEqualToRect(
       CGRectZero, document_interaction_controller.presentedOpenInMenu.rect));
@@ -409,11 +378,9 @@
   DownloadManagerViewController* viewController =
       base_view_controller_.childViewControllers.firstObject;
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
-  @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
-    [viewController.delegate
-        downloadManagerViewControllerDidClose:viewController];
-  }
+  [viewController.delegate
+      downloadManagerViewControllerDidClose:viewController];
+
   // Verify that UIAlert is presented.
   ASSERT_TRUE([base_view_controller_.presentedViewController
       isKindOfClass:[UIAlertController class]]);
@@ -461,6 +428,8 @@
 // Tests starting the download. Verifies that download task is started and its
 // file writer is configured to write into download directory.
 TEST_F(DownloadManagerCoordinatorTest, StartDownload) {
+  web::TestWebThreadBundle thread_bundle;
+
   web::FakeDownloadTask task(GURL(kTestUrl), kTestMimeType);
   task.SetSuggestedFilename(base::SysNSStringToUTF16(kTestSuggestedFileName));
   web::DownloadTask* task_ptr = &task;
@@ -470,11 +439,8 @@
   DownloadManagerViewController* viewController =
       base_view_controller_.childViewControllers.firstObject;
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
-  @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
-    [viewController.delegate
-        downloadManagerViewControllerDidStartDownload:viewController];
-  }
+  [viewController.delegate
+      downloadManagerViewControllerDidStartDownload:viewController];
 
   // Starting download is async for model.
   ASSERT_TRUE(WaitUntilConditionOrTimeout(testing::kWaitForDownloadTimeout, ^{
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm b/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
index 27e6d86a..08332fe5 100644
--- a/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
+++ b/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
@@ -30,33 +30,30 @@
 };
 
 TEST_F(BrowserViewWranglerTest, TestInitNilObserver) {
-  // |thread_bundle_| must outlive all objects created by BVC, because those
-  // objects may rely on threading API in dealloc.
-  @autoreleasepool {
-    BrowserViewWrangler* wrangler = [[BrowserViewWrangler alloc]
-              initWithBrowserState:chrome_browser_state_.get()
+  BrowserViewWrangler* wrangler = [[BrowserViewWrangler alloc]
+            initWithBrowserState:chrome_browser_state_.get()
 
-                  tabModelObserver:nil
-        applicationCommandEndpoint:(id<ApplicationCommands>)nil];
-    // Test that BVC and tab model are created on demand.
-    BrowserViewController* bvc = [wrangler mainBVC];
-    EXPECT_NE(bvc, nil);
+                tabModelObserver:nil
+      applicationCommandEndpoint:(id<ApplicationCommands>)nil];
 
-    TabModel* tabModel = [wrangler mainTabModel];
-    EXPECT_NE(tabModel, nil);
+  // Test that BVC and tab model are created on demand.
+  BrowserViewController* bvc = [wrangler mainBVC];
+  EXPECT_NE(bvc, nil);
 
-    // Test that once created the BVC and tab model aren't re-created.
-    EXPECT_EQ(bvc, [wrangler mainBVC]);
-    EXPECT_EQ(tabModel, [wrangler mainTabModel]);
+  TabModel* tabModel = [wrangler mainTabModel];
+  EXPECT_NE(tabModel, nil);
 
-    // Test that the OTR objects are (a) OTR and (b) not the same as the non-OTR
-    // objects.
-    EXPECT_NE(bvc, [wrangler otrBVC]);
-    EXPECT_NE(tabModel, [wrangler otrTabModel]);
-    EXPECT_TRUE([wrangler otrTabModel].browserState->IsOffTheRecord());
+  // Test that once created the BVC and tab model aren't re-created.
+  EXPECT_EQ(bvc, [wrangler mainBVC]);
+  EXPECT_EQ(tabModel, [wrangler mainTabModel]);
 
-    [wrangler shutdown];
-  }
+  // Test that the OTR objects are (a) OTR and (b) not the same as the non-OTR
+  // objects.
+  EXPECT_NE(bvc, [wrangler otrBVC]);
+  EXPECT_NE(tabModel, [wrangler otrTabModel]);
+  EXPECT_TRUE([wrangler otrTabModel].browserState->IsOffTheRecord());
+
+  [wrangler shutdown];
 }
 
 }  // namespace
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn
index 9c698007..8cba5359 100644
--- a/ios/chrome/browser/ui/tab_grid/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -53,6 +53,8 @@
     "grid_view_controller.mm",
     "tab_grid_bottom_toolbar.h",
     "tab_grid_bottom_toolbar.mm",
+    "tab_grid_constants.h",
+    "tab_grid_constants.mm",
     "tab_grid_page_control.h",
     "tab_grid_page_control.mm",
     "tab_grid_paging.h",
diff --git a/ios/chrome/browser/ui/tab_grid/grid_cell.mm b/ios/chrome/browser/ui/tab_grid/grid_cell.mm
index 1bdd3b5..b7e4cd7 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_cell.mm
+++ b/ios/chrome/browser/ui/tab_grid/grid_cell.mm
@@ -15,15 +15,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-// Height of the top bar containing the icon, title, and close button.
-const CGFloat kTopBarHeight = 28.0f;
-// Width and height of the icon.
-const CGFloat kIconDiameter = 20.0f;
-// Width of selection border.
-const CGFloat kBorderWidth = 6.0f;
-}  // namespace
-
 @interface GridCell ()
 // Visual components of the cell.
 @property(nonatomic, weak) UIView* topBar;
@@ -57,7 +48,7 @@
   if (self) {
     [self setupSelectedBackgroundView];
     UIView* contentView = self.contentView;
-    contentView.layer.cornerRadius = 11.0f;
+    contentView.layer.cornerRadius = kGridCellCornerRadius;
     contentView.layer.masksToBounds = YES;
     UIView* topBar = [self setupTopBar];
     TopAlignedImageView* snapshotView = [[TopAlignedImageView alloc] init];
@@ -71,7 +62,7 @@
       [topBar.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor],
       [topBar.trailingAnchor
           constraintEqualToAnchor:contentView.trailingAnchor],
-      [topBar.heightAnchor constraintEqualToConstant:kTopBarHeight],
+      [topBar.heightAnchor constraintEqualToConstant:kGridCellHeaderHeight],
       [snapshotView.topAnchor constraintEqualToAnchor:topBar.bottomAnchor],
       [snapshotView.leadingAnchor
           constraintEqualToAnchor:contentView.leadingAnchor],
@@ -177,7 +168,7 @@
   UIImageView* iconView = [[UIImageView alloc] init];
   iconView.translatesAutoresizingMaskIntoConstraints = NO;
   iconView.contentMode = UIViewContentModeScaleAspectFill;
-  iconView.layer.cornerRadius = 4.0f;
+  iconView.layer.cornerRadius = kGridCellIconCornerRadius;
   iconView.layer.masksToBounds = YES;
 
   UILabel* titleLabel = [[UILabel alloc] init];
@@ -203,19 +194,22 @@
   _closeButton = closeButton;
 
   NSArray* constraints = @[
-    [iconView.leadingAnchor constraintEqualToAnchor:topBar.leadingAnchor
-                                           constant:4.0f],
+    [iconView.leadingAnchor
+        constraintEqualToAnchor:topBar.leadingAnchor
+                       constant:kGridCellHeaderLeadingInset],
     [iconView.centerYAnchor constraintEqualToAnchor:topBar.centerYAnchor],
-    [iconView.widthAnchor constraintEqualToConstant:kIconDiameter],
-    [iconView.heightAnchor constraintEqualToConstant:kIconDiameter],
-    [titleLabel.leadingAnchor constraintEqualToAnchor:iconView.trailingAnchor
-                                             constant:4.0f],
+    [iconView.widthAnchor constraintEqualToConstant:kGridCellIconDiameter],
+    [iconView.heightAnchor constraintEqualToConstant:kGridCellIconDiameter],
+    [titleLabel.leadingAnchor
+        constraintEqualToAnchor:iconView.trailingAnchor
+                       constant:kGridCellHeaderLeadingInset],
     [titleLabel.centerYAnchor constraintEqualToAnchor:topBar.centerYAnchor],
     [closeButton.leadingAnchor
         constraintEqualToAnchor:titleLabel.trailingAnchor],
     [closeButton.centerYAnchor constraintEqualToAnchor:topBar.centerYAnchor],
-    [closeButton.trailingAnchor constraintEqualToAnchor:topBar.trailingAnchor
-                                               constant:-6.0f],
+    [closeButton.trailingAnchor
+        constraintEqualToAnchor:topBar.trailingAnchor
+                       constant:-kGridCellHeaderTrailingInset],
   ];
   [NSLayoutConstraint activateConstraints:constraints];
   [titleLabel setContentHuggingPriority:UILayoutPriorityDefaultLow
@@ -232,27 +226,34 @@
 // selected.
 - (void)setupSelectedBackgroundView {
   self.selectedBackgroundView = [[UIView alloc] init];
-  self.selectedBackgroundView.backgroundColor = [UIColor blackColor];
+  self.selectedBackgroundView.backgroundColor =
+      UIColorFromRGB(kGridBackgroundColor);
   UIView* border = [[UIView alloc] init];
   border.translatesAutoresizingMaskIntoConstraints = NO;
-  border.backgroundColor = [UIColor blackColor];
-  border.layer.cornerRadius = 17.0f;
-  border.layer.borderWidth = 4.0f;
+  border.backgroundColor = UIColorFromRGB(kGridBackgroundColor);
+  border.layer.cornerRadius = kGridCellCornerRadius +
+                              kGridCellSelectionRingGapWidth +
+                              kGridCellSelectionRingTintWidth;
+  border.layer.borderWidth = kGridCellSelectionRingTintWidth;
   [self.selectedBackgroundView addSubview:border];
   _border = border;
   [NSLayoutConstraint activateConstraints:@[
     [border.topAnchor
         constraintEqualToAnchor:self.selectedBackgroundView.topAnchor
-                       constant:-kBorderWidth],
+                       constant:-kGridCellSelectionRingTintWidth -
+                                kGridCellSelectionRingGapWidth],
     [border.leadingAnchor
         constraintEqualToAnchor:self.selectedBackgroundView.leadingAnchor
-                       constant:-kBorderWidth],
+                       constant:-kGridCellSelectionRingTintWidth -
+                                kGridCellSelectionRingGapWidth],
     [border.trailingAnchor
         constraintEqualToAnchor:self.selectedBackgroundView.trailingAnchor
-                       constant:kBorderWidth],
+                       constant:kGridCellSelectionRingTintWidth +
+                                kGridCellSelectionRingGapWidth],
     [border.bottomAnchor
         constraintEqualToAnchor:self.selectedBackgroundView.bottomAnchor
-                       constant:kBorderWidth]
+                       constant:kGridCellSelectionRingTintWidth +
+                                kGridCellSelectionRingGapWidth]
   ]];
 }
 
diff --git a/ios/chrome/browser/ui/tab_grid/grid_constants.h b/ios/chrome/browser/ui/tab_grid/grid_constants.h
index 049e310..b9442451 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_constants.h
+++ b/ios/chrome/browser/ui/tab_grid/grid_constants.h
@@ -20,19 +20,33 @@
 // converted into UIColors using the UIColorFromRGB() function, from
 // uikit_ui_util.h
 
+// Grid styling.
+extern const int kGridBackgroundColor;
+
 // GridCell styling.
 // Common colors.
-extern const CGFloat kGridCellIconBackgroundColor;
-extern const CGFloat kGridCellSnapshotBackgroundColor;
+extern const int kGridCellIconBackgroundColor;
+extern const int kGridCellSnapshotBackgroundColor;
 // Light theme colors.
-extern const CGFloat kGridLightThemeCellTitleColor;
-extern const CGFloat kGridLightThemeCellHeaderColor;
-extern const CGFloat kGridLightThemeCellSelectionColor;
-extern const CGFloat kGridLightThemeCellCloseButtonTintColor;
+extern const int kGridLightThemeCellTitleColor;
+extern const int kGridLightThemeCellHeaderColor;
+extern const int kGridLightThemeCellSelectionColor;
+extern const int kGridLightThemeCellCloseButtonTintColor;
 // Dark theme colors.
-extern const CGFloat kGridDarkThemeCellTitleColor;
-extern const CGFloat kGridDarkThemeCellHeaderColor;
-extern const CGFloat kGridDarkThemeCellSelectionColor;
-extern const CGFloat kGridDarkThemeCellCloseButtonTintColor;
+extern const int kGridDarkThemeCellTitleColor;
+extern const int kGridDarkThemeCellHeaderColor;
+extern const int kGridDarkThemeCellSelectionColor;
+extern const int kGridDarkThemeCellCloseButtonTintColor;
+
+// GridCell dimensions.
+extern const CGFloat kGridCellCornerRadius;
+extern const CGFloat kGridCellIconCornerRadius;
+// Height of the cell header containing the icon, title, and close button.
+extern const CGFloat kGridCellHeaderHeight;
+extern const CGFloat kGridCellHeaderLeadingInset;
+extern const CGFloat kGridCellHeaderTrailingInset;
+extern const CGFloat kGridCellIconDiameter;
+extern const CGFloat kGridCellSelectionRingGapWidth;
+extern const CGFloat kGridCellSelectionRingTintWidth;
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_constants.mm b/ios/chrome/browser/ui/tab_grid/grid_constants.mm
index c59e74c3..c12868e 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_constants.mm
+++ b/ios/chrome/browser/ui/tab_grid/grid_constants.mm
@@ -15,17 +15,31 @@
 NSString* const kGridCellCloseButtonIdentifier =
     @"GridCellCloseButtonIdentifier";
 
+// Grid styling.
+const int kGridBackgroundColor = 0x222222;
+
 // GridCell styling.
 // Common colors.
-const CGFloat kGridCellIconBackgroundColor = 0xF1F3F4;
-const CGFloat kGridCellSnapshotBackgroundColor = 0xE8EAED;
+const int kGridCellIconBackgroundColor = 0xF1F3F4;
+const int kGridCellSnapshotBackgroundColor = 0xE8EAED;
 // Light theme colors.
-const CGFloat kGridLightThemeCellTitleColor = 0x000000;
-const CGFloat kGridLightThemeCellHeaderColor = 0xF8F9FA;
-const CGFloat kGridLightThemeCellSelectionColor = 0x1A73E8;
-const CGFloat kGridLightThemeCellCloseButtonTintColor = 0x3C4043;
+const int kGridLightThemeCellTitleColor = 0x000000;
+const int kGridLightThemeCellHeaderColor = 0xF8F9FA;
+const int kGridLightThemeCellSelectionColor = 0x1A73E8;
+const int kGridLightThemeCellCloseButtonTintColor = 0x3C4043;
 // Dark theme colors.
-const CGFloat kGridDarkThemeCellTitleColor = 0xFFFFFF;
-const CGFloat kGridDarkThemeCellHeaderColor = 0x5F6368;
-const CGFloat kGridDarkThemeCellSelectionColor = 0x9AA0A6;
-const CGFloat kGridDarkThemeCellCloseButtonTintColor = 0xFFFFFF;
+const int kGridDarkThemeCellTitleColor = 0xFFFFFF;
+const int kGridDarkThemeCellHeaderColor = 0x5F6368;
+const int kGridDarkThemeCellSelectionColor = 0x9AA0A6;
+const int kGridDarkThemeCellCloseButtonTintColor = 0xFFFFFF;
+
+// GridCell dimensions.
+const CGFloat kGridCellCornerRadius = 13.0f;
+const CGFloat kGridCellIconCornerRadius = 3.0f;
+// The cell header contains the icon, title, and close button.
+const CGFloat kGridCellHeaderHeight = 32.0f;
+const CGFloat kGridCellHeaderLeadingInset = 5.0f;
+const CGFloat kGridCellHeaderTrailingInset = 8.5f;
+const CGFloat kGridCellIconDiameter = 22.0f;
+const CGFloat kGridCellSelectionRingGapWidth = 2.0f;
+const CGFloat kGridCellSelectionRingTintWidth = 5.0f;
diff --git a/ios/chrome/browser/ui/tab_grid/grid_view_controller.h b/ios/chrome/browser/ui/tab_grid/grid_view_controller.h
index 7f2bb0b37..6523f6d 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_view_controller.h
+++ b/ios/chrome/browser/ui/tab_grid/grid_view_controller.h
@@ -16,20 +16,18 @@
 
 // Protocol used to relay relevant user interactions from a grid UI.
 @protocol GridViewControllerDelegate
-// Tells the receiver that the item at |index| was selected in
+// Tells the delegate that the item at |index| was selected in
 // |gridViewController|.
 - (void)gridViewController:(GridViewController*)gridViewController
       didSelectItemAtIndex:(NSUInteger)index;
-// Tells the receiver that the item at |index| was closed in
+// Tells the delegate that the item at |index| was closed in
 // |gridViewController|.
 - (void)gridViewController:(GridViewController*)gridViewController
        didCloseItemAtIndex:(NSUInteger)index;
-// Tells the receiver that the last item was closed in |gridViewController|.
-- (void)lastItemWasClosedInGridViewController:
-    (GridViewController*)gridViewController;
-// Tells the receiver that the first item was added in |gridViewController|.
-- (void)firstItemWasAddedInGridViewController:
-    (GridViewController*)gridViewController;
+// Tells the delegate that the the number of items in |gridViewController|
+// changed to |count|.
+- (void)gridViewController:(GridViewController*)gridViewController
+        didChangeItemCount:(NSUInteger)count;
 @end
 
 // A view controller that contains a grid of items.
diff --git a/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm
index b32d0e5c..b764819 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm
@@ -82,6 +82,8 @@
   [self.collectionView selectItemAtIndexPath:CreateIndexPath(self.selectedIndex)
                                     animated:animated
                               scrollPosition:UICollectionViewScrollPositionTop];
+  // Update the delegate, in case it wasn't set when |items| was populated.
+  [self.delegate gridViewController:self didChangeItemCount:self.items.count];
 }
 
 #pragma mark - Public
@@ -201,6 +203,7 @@
   [self.collectionView selectItemAtIndexPath:CreateIndexPath(selectedIndex)
                                     animated:YES
                               scrollPosition:UICollectionViewScrollPositionTop];
+  [self.delegate gridViewController:self didChangeItemCount:self.items.count];
 }
 
 - (void)insertItem:(GridItem*)item
@@ -212,6 +215,7 @@
   };
   if (![self isViewVisible]) {
     performDataSourceUpdates();
+    [self.delegate gridViewController:self didChangeItemCount:self.items.count];
     return;
   }
   auto performAllUpdates = ^{
@@ -224,9 +228,7 @@
         selectItemAtIndexPath:CreateIndexPath(selectedIndex)
                      animated:YES
                scrollPosition:UICollectionViewScrollPositionNone];
-    if (self.items.count == 1) {
-      [self.delegate firstItemWasAddedInGridViewController:self];
-    }
+    [self.delegate gridViewController:self didChangeItemCount:self.items.count];
   };
   [self.collectionView performBatchUpdates:performAllUpdates
                                 completion:completion];
@@ -240,6 +242,7 @@
   };
   if (![self isViewVisible]) {
     performDataSourceUpdates();
+    [self.delegate gridViewController:self didChangeItemCount:self.items.count];
     return;
   }
   auto performAllUpdates = ^{
@@ -254,8 +257,8 @@
                  scrollPosition:UICollectionViewScrollPositionNone];
     } else {
       self.collectionView.backgroundView.hidden = NO;
-      [self.delegate lastItemWasClosedInGridViewController:self];
     }
+    [self.delegate gridViewController:self didChangeItemCount:self.items.count];
   };
   [self.collectionView performBatchUpdates:performAllUpdates
                                 completion:completion];
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h
index 98dd7966..0b17be703 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h
@@ -16,11 +16,6 @@
 @property(nonatomic, weak, readonly) UIButton* leadingButton;
 @property(nonatomic, weak, readonly) UIButton* trailingButton;
 @property(nonatomic, weak, readonly) UIButton* centerButton;
-
-- (instancetype)init NS_DESIGNATED_INITIALIZER;
-- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
-- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_BOTTOM_TOOLBAR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
index 8be165a..1740665f 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
@@ -4,77 +4,87 @@
 
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h"
 
-#include "base/logging.h"
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-namespace {
-// Height of the toolbar.
-const CGFloat kToolbarHeight = 44.0f;
-}  // namespace
-
 @implementation TabGridBottomToolbar
 @synthesize leadingButton = _leadingButton;
 @synthesize trailingButton = _trailingButton;
 @synthesize centerButton = _centerButton;
 
-- (instancetype)init {
-  if (self = [super initWithFrame:CGRectZero]) {
-    UIVisualEffect* blurEffect =
-        [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
-    UIVisualEffectView* toolbar =
-        [[UIVisualEffectView alloc] initWithEffect:blurEffect];
-    toolbar.translatesAutoresizingMaskIntoConstraints = NO;
-    [self addSubview:toolbar];
-
-    UIButton* leadingButton = [UIButton buttonWithType:UIButtonTypeSystem];
-    leadingButton.translatesAutoresizingMaskIntoConstraints = NO;
-    leadingButton.titleLabel.font =
-        [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
-    leadingButton.titleLabel.adjustsFontForContentSizeCategory = YES;
-    leadingButton.tintColor = [UIColor whiteColor];
-    UIButton* trailingButton = [UIButton buttonWithType:UIButtonTypeSystem];
-    trailingButton.translatesAutoresizingMaskIntoConstraints = NO;
-    trailingButton.titleLabel.font =
-        [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
-    trailingButton.titleLabel.adjustsFontForContentSizeCategory = YES;
-    trailingButton.tintColor = [UIColor whiteColor];
-    UIButton* centerButton = [UIButton buttonWithType:UIButtonTypeSystem];
-    centerButton.translatesAutoresizingMaskIntoConstraints = NO;
-
-    [toolbar.contentView addSubview:leadingButton];
-    [toolbar.contentView addSubview:trailingButton];
-    [toolbar.contentView addSubview:centerButton];
-    _leadingButton = leadingButton;
-    _trailingButton = trailingButton;
-    _centerButton = centerButton;
-
-    NSArray* constraints = @[
-      [toolbar.topAnchor constraintEqualToAnchor:self.topAnchor],
-      [toolbar.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
-      [toolbar.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
-      [toolbar.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
-      [leadingButton.heightAnchor constraintEqualToConstant:kToolbarHeight],
-      [leadingButton.leadingAnchor
-          constraintEqualToAnchor:toolbar.layoutMarginsGuide.leadingAnchor],
-      [leadingButton.topAnchor constraintEqualToAnchor:toolbar.topAnchor],
-      [centerButton.centerXAnchor
-          constraintEqualToAnchor:toolbar.centerXAnchor],
-      [centerButton.topAnchor constraintEqualToAnchor:toolbar.topAnchor],
-      [trailingButton.heightAnchor constraintEqualToConstant:kToolbarHeight],
-      [trailingButton.trailingAnchor
-          constraintEqualToAnchor:toolbar.layoutMarginsGuide.trailingAnchor],
-      [trailingButton.topAnchor constraintEqualToAnchor:toolbar.topAnchor],
-    ];
-    [NSLayoutConstraint activateConstraints:constraints];
-  }
-  return self;
-}
+#pragma mark - UIView
 
 - (CGSize)intrinsicContentSize {
-  return CGSizeMake(UIViewNoIntrinsicMetric, kToolbarHeight);
+  return CGSizeMake(UIViewNoIntrinsicMetric, kTabGridBottomToolbarHeight);
+}
+
+- (void)willMoveToSuperview:(UIView*)newSuperview {
+  // The first time this moves to a superview, perform the view setup.
+  if (newSuperview && self.subviews.count == 0) {
+    [self setupViews];
+  }
+}
+
+#pragma mark - Private
+
+- (void)setupViews {
+  self.layoutMargins = UIEdgeInsetsMake(0, kTabGridToolbarHorizontalInset, 0,
+                                        kTabGridToolbarHorizontalInset);
+
+  UIVisualEffect* blurEffect =
+      [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
+  UIVisualEffectView* toolbar =
+      [[UIVisualEffectView alloc] initWithEffect:blurEffect];
+  toolbar.translatesAutoresizingMaskIntoConstraints = NO;
+  [self addSubview:toolbar];
+
+  UIButton* leadingButton = [UIButton buttonWithType:UIButtonTypeSystem];
+  leadingButton.translatesAutoresizingMaskIntoConstraints = NO;
+  leadingButton.titleLabel.font =
+      [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
+  leadingButton.titleLabel.adjustsFontForContentSizeCategory = YES;
+  leadingButton.tintColor = UIColorFromRGB(kTabGridToolbarTextButtonColor);
+  UIButton* trailingButton = [UIButton buttonWithType:UIButtonTypeSystem];
+  trailingButton.translatesAutoresizingMaskIntoConstraints = NO;
+  trailingButton.titleLabel.font =
+      [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+  trailingButton.titleLabel.adjustsFontForContentSizeCategory = YES;
+  trailingButton.tintColor = UIColorFromRGB(kTabGridToolbarTextButtonColor);
+  UIButton* centerButton = [UIButton buttonWithType:UIButtonTypeSystem];
+  centerButton.translatesAutoresizingMaskIntoConstraints = NO;
+
+  [toolbar.contentView addSubview:leadingButton];
+  [toolbar.contentView addSubview:trailingButton];
+  [toolbar.contentView addSubview:centerButton];
+  _leadingButton = leadingButton;
+  _trailingButton = trailingButton;
+  _centerButton = centerButton;
+
+  NSArray* constraints = @[
+    [toolbar.topAnchor constraintEqualToAnchor:self.topAnchor],
+    [toolbar.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
+    [toolbar.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
+    [toolbar.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
+    [leadingButton.heightAnchor
+        constraintEqualToConstant:kTabGridBottomToolbarHeight],
+    [leadingButton.leadingAnchor
+        constraintEqualToAnchor:self.layoutMarginsGuide.leadingAnchor],
+    [leadingButton.topAnchor constraintEqualToAnchor:toolbar.topAnchor],
+    [centerButton.centerXAnchor constraintEqualToAnchor:toolbar.centerXAnchor],
+    [centerButton.centerYAnchor
+        constraintEqualToAnchor:toolbar.topAnchor
+                       constant:kTabGridBottomToolbarHeight / 2.0f],
+    [trailingButton.heightAnchor
+        constraintEqualToConstant:kTabGridBottomToolbarHeight],
+    [trailingButton.trailingAnchor
+        constraintEqualToAnchor:self.layoutMarginsGuide.trailingAnchor],
+    [trailingButton.topAnchor constraintEqualToAnchor:toolbar.topAnchor],
+  ];
+  [NSLayoutConstraint activateConstraints:constraints];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_constants.h b/ios/chrome/browser/ui/tab_grid/tab_grid_constants.h
new file mode 100644
index 0000000..f7b3806
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_constants.h
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_CONSTANTS_H_
+#define IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_CONSTANTS_H_
+
+#import <UIKit/UIKit.h>
+
+// All kxxxColor constants are RGB values stored in a Hex integer. These will be
+// converted into UIColors using the UIColorFromRGB() function, from
+// uikit_ui_util.h
+
+// The color of the text buttons in the toolbars.
+extern const int kTabGridToolbarTextButtonColor;
+
+// The distance the toolbar content is inset from either side.
+extern const CGFloat kTabGridToolbarHorizontalInset;
+
+// The distance between the title and body of the empty state view.
+extern const CGFloat kTabGridEmptyStateVerticalMargin;
+
+// Intrinsic heights of the tab grid toolbars.
+extern const CGFloat kTabGridTopToolbarHeight;
+extern const CGFloat kTabGridBottomToolbarHeight;
+
+#endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_constants.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_constants.mm
new file mode 100644
index 0000000..2426a90
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_constants.mm
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// The color of the text buttons in the toolbars.
+const int kTabGridToolbarTextButtonColor = 0xFFFFFF;
+
+// The distance the toolbar content is inset from either side.
+const CGFloat kTabGridToolbarHorizontalInset = 16.0f;
+
+// The distance between the title and body of the empty state view.
+const CGFloat kTabGridEmptyStateVerticalMargin = 4.0f;
+
+// Intrinsic heights of the tab grid toolbars.
+const CGFloat kTabGridTopToolbarHeight = 52.0f;
+const CGFloat kTabGridBottomToolbarHeight = 44.0f;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h
index 2418fc4..8cc28e3 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h
@@ -30,11 +30,11 @@
 // Setting this property will *not* update the selected page.
 @property(nonatomic, assign) CGFloat sliderPosition;
 
-// Text displayed next to the incognito and inside the regular tabs icons. The
-// available space for text is small -- no wider than two numerals. Text wider
-// than this will be clipped.
-@property(nonatomic, copy) NSString* incognitoText;
-@property(nonatomic, copy) NSString* regularText;
+// The numbers that the control should display in the appropriate sections.
+// Numbers less than 1 are not displayed.
+// Numbers greated than 99 are displayed as ':-)'.
+@property(nonatomic, assign) NSUInteger incognitoTabCount;
+@property(nonatomic, assign) NSUInteger regularTabCount;
 
 // Create and return a new instance of this control. This is the preferred way
 // to create instances of this class.
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm
index 25525835..3a883a8c 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_page_control.mm
@@ -99,6 +99,15 @@
 CGPoint RectCenter(CGRect rect) {
   return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
 }
+
+// Returns the string to use for a numeric item count.
+NSString* StringForItemCount(long count) {
+  if (count == 0)
+    return @"";
+  if (count > 99)
+    return @":-)";
+  return [NSString stringWithFormat:@"%ld", count];
+}
 }
 
 // View class used for the background of this control; it draws the grey
@@ -138,8 +147,8 @@
 // Public properties
 @synthesize selectedPage = _selectedPage;
 @synthesize sliderPosition = _sliderPosition;
-@synthesize incognitoText = _incognitoText;
-@synthesize regularText = _regularText;
+@synthesize incognitoTabCount = _incognitoTabCount;
+@synthesize regularTabCount = _regularTabCount;
 // Private properties
 @synthesize incognitoGuide = _incognitoGuide;
 @synthesize regularGuide = _regularGuide;
@@ -192,16 +201,18 @@
 // the text in both labels (the regular and the  "selected" versions that's
 // visible when the slider is over a segment), and an ivar to store values that
 // are set before the labels are created.
-- (void)setIncognitoText:(NSString*)incognitoText {
+- (void)setIncognitoTabCount:(NSUInteger)incognitoTabCount {
+  NSString* incognitoText = StringForItemCount(incognitoTabCount);
   self.incognitoLabel.text = incognitoText;
   self.incognitoSelectedLabel.text = incognitoText;
-  _incognitoText = [incognitoText copy];
+  _incognitoTabCount = incognitoTabCount;
 }
 
-- (void)setRegularText:(NSString*)regularText {
+- (void)setRegularTabCount:(NSUInteger)regularTabCount {
+  NSString* regularText = StringForItemCount(regularTabCount);
   self.regularLabel.text = regularText;
   self.regularSelectedLabel.text = regularText;
-  _regularText = [regularText copy];
+  _regularTabCount = regularTabCount;
 }
 
 #pragma mark - Public methods
@@ -374,8 +385,8 @@
 
   // Update the label text, in case these properties have been set before the
   // views were set up.
-  self.regularText = _regularText;
-  self.incognitoText = _incognitoText;
+  self.regularTabCount = _regularTabCount;
+  self.incognitoTabCount = _incognitoTabCount;
 
   // Mark the control's layout as dirty so the the guides will be computed, then
   // force a layout now so it won't be triggered later (perhaps during an
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.h b/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.h
index a2906d3..701ef0c 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.h
@@ -18,11 +18,6 @@
 @property(nonatomic, weak, readonly) UIButton* leadingButton;
 @property(nonatomic, weak, readonly) UIButton* trailingButton;
 @property(nonatomic, weak, readonly) TabGridPageControl* pageControl;
-
-- (instancetype)init NS_DESIGNATED_INITIALIZER;
-- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
-- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_TOP_TOOLBAR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.mm
index 8e549ce7..20ab2c2 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.mm
@@ -4,81 +4,91 @@
 
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.h"
 
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-namespace {
-// Height of the toolbar.
-const CGFloat kToolbarHeight = 52.0f;
-}  // namespace
-
 @implementation TabGridTopToolbar
 @synthesize leadingButton = _leadingButton;
 @synthesize trailingButton = _trailingButton;
 @synthesize pageControl = _pageControl;
 
-- (instancetype)init {
-  if (self = [super initWithFrame:CGRectZero]) {
-    UIVisualEffect* blurEffect =
-        [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
-    UIVisualEffectView* toolbar =
-        [[UIVisualEffectView alloc] initWithEffect:blurEffect];
-    toolbar.translatesAutoresizingMaskIntoConstraints = NO;
-    [self addSubview:toolbar];
-
-    UIButton* leadingButton = [UIButton buttonWithType:UIButtonTypeSystem];
-    leadingButton.translatesAutoresizingMaskIntoConstraints = NO;
-    leadingButton.titleLabel.font =
-        [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
-    leadingButton.titleLabel.adjustsFontForContentSizeCategory = YES;
-    leadingButton.tintColor = [UIColor whiteColor];
-
-    // The segmented control has an intrinsic size.
-    TabGridPageControl* pageControl = [[TabGridPageControl alloc] init];
-    pageControl.translatesAutoresizingMaskIntoConstraints = NO;
-
-    UIButton* trailingButton = [UIButton buttonWithType:UIButtonTypeSystem];
-    trailingButton.translatesAutoresizingMaskIntoConstraints = NO;
-    trailingButton.titleLabel.font =
-        [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
-    trailingButton.titleLabel.adjustsFontForContentSizeCategory = YES;
-    trailingButton.tintColor = [UIColor whiteColor];
-
-    [toolbar.contentView addSubview:leadingButton];
-    [toolbar.contentView addSubview:trailingButton];
-    [toolbar.contentView addSubview:pageControl];
-    _leadingButton = leadingButton;
-    _trailingButton = trailingButton;
-    _pageControl = pageControl;
-
-    NSArray* constraints = @[
-      [toolbar.topAnchor constraintEqualToAnchor:self.topAnchor],
-      [toolbar.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
-      [toolbar.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
-      [toolbar.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
-      [leadingButton.heightAnchor constraintEqualToConstant:kToolbarHeight],
-      [leadingButton.leadingAnchor
-          constraintEqualToAnchor:toolbar.layoutMarginsGuide.leadingAnchor],
-      [leadingButton.bottomAnchor constraintEqualToAnchor:toolbar.bottomAnchor],
-      [pageControl.centerXAnchor constraintEqualToAnchor:toolbar.centerXAnchor],
-      [pageControl.bottomAnchor constraintEqualToAnchor:toolbar.bottomAnchor
-                                               constant:-7.0f],
-      [trailingButton.heightAnchor constraintEqualToConstant:kToolbarHeight],
-      [trailingButton.trailingAnchor
-          constraintEqualToAnchor:toolbar.layoutMarginsGuide.trailingAnchor],
-      [trailingButton.bottomAnchor
-          constraintEqualToAnchor:toolbar.bottomAnchor],
-    ];
-    [NSLayoutConstraint activateConstraints:constraints];
-  }
-  return self;
-}
+#pragma mark - UIView
 
 - (CGSize)intrinsicContentSize {
-  return CGSizeMake(UIViewNoIntrinsicMetric, kToolbarHeight);
+  return CGSizeMake(UIViewNoIntrinsicMetric, kTabGridTopToolbarHeight);
+}
+
+- (void)willMoveToSuperview:(UIView*)newSuperview {
+  // The first time this moves to a superview, perform the view setup.
+  if (newSuperview && self.subviews.count == 0) {
+    [self setupViews];
+  }
+}
+
+#pragma mark - Private
+
+- (void)setupViews {
+  self.layoutMargins = UIEdgeInsetsMake(0, kTabGridToolbarHorizontalInset, 0,
+                                        kTabGridToolbarHorizontalInset);
+
+  UIVisualEffect* blurEffect =
+      [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
+  UIVisualEffectView* toolbar =
+      [[UIVisualEffectView alloc] initWithEffect:blurEffect];
+  toolbar.translatesAutoresizingMaskIntoConstraints = NO;
+  [self addSubview:toolbar];
+
+  UIButton* leadingButton = [UIButton buttonWithType:UIButtonTypeSystem];
+  leadingButton.translatesAutoresizingMaskIntoConstraints = NO;
+  leadingButton.titleLabel.font =
+      [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
+  leadingButton.titleLabel.adjustsFontForContentSizeCategory = YES;
+  leadingButton.tintColor = UIColorFromRGB(kTabGridToolbarTextButtonColor);
+
+  // The segmented control has an intrinsic size.
+  TabGridPageControl* pageControl = [[TabGridPageControl alloc] init];
+  pageControl.translatesAutoresizingMaskIntoConstraints = NO;
+
+  UIButton* trailingButton = [UIButton buttonWithType:UIButtonTypeSystem];
+  trailingButton.translatesAutoresizingMaskIntoConstraints = NO;
+  trailingButton.titleLabel.font =
+      [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+  trailingButton.titleLabel.adjustsFontForContentSizeCategory = YES;
+  trailingButton.tintColor = UIColorFromRGB(kTabGridToolbarTextButtonColor);
+
+  [toolbar.contentView addSubview:leadingButton];
+  [toolbar.contentView addSubview:trailingButton];
+  [toolbar.contentView addSubview:pageControl];
+  _leadingButton = leadingButton;
+  _trailingButton = trailingButton;
+  _pageControl = pageControl;
+
+  NSArray* constraints = @[
+    [toolbar.topAnchor constraintEqualToAnchor:self.topAnchor],
+    [toolbar.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
+    [toolbar.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
+    [toolbar.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
+    [leadingButton.heightAnchor
+        constraintEqualToConstant:kTabGridTopToolbarHeight],
+    [leadingButton.leadingAnchor
+        constraintEqualToAnchor:self.layoutMarginsGuide.leadingAnchor],
+    [leadingButton.bottomAnchor constraintEqualToAnchor:toolbar.bottomAnchor],
+    [pageControl.centerXAnchor constraintEqualToAnchor:toolbar.centerXAnchor],
+    [pageControl.centerYAnchor
+        constraintEqualToAnchor:toolbar.bottomAnchor
+                       constant:-kTabGridTopToolbarHeight / 2.0f],
+    [trailingButton.heightAnchor
+        constraintEqualToConstant:kTabGridTopToolbarHeight],
+    [trailingButton.trailingAnchor
+        constraintEqualToAnchor:self.layoutMarginsGuide.trailingAnchor],
+    [trailingButton.bottomAnchor constraintEqualToAnchor:toolbar.bottomAnchor],
+  ];
+  [NSLayoutConstraint activateConstraints:constraints];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index 62dbe58..58eb30a5 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -5,13 +5,17 @@
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h"
 
 #import "base/logging.h"
+#include "base/strings/sys_string_conversions.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_commands.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_consumer.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_image_data_source.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_view_controller.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.h"
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_constants.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_page_control.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.h"
+#include "ios/chrome/grit/ios_strings.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -156,16 +160,20 @@
 #pragma mark - UIScrollViewAccessibilityDelegate
 
 - (NSString*)accessibilityScrollStatusForScrollView:(UIScrollView*)scrollView {
-  // TODO(crbug.com/818699) : Localize strings.
   // This reads the new page whenever the user scrolls in VoiceOver.
+  int stringID;
   switch (self.currentPage) {
     case TabGridPageIncognitoTabs:
-      return @"Incognito Tabs page";
+      stringID = IDS_IOS_TAB_GRID_INCOGNITO_TABS_TITLE;
+      break;
     case TabGridPageRegularTabs:
-      return @"Regular Tabs page";
+      stringID = IDS_IOS_TAB_GRID_REGULAR_TABS_TITLE;
+      break;
     case TabGridPageRemoteTabs:
-      return @"Remote Tabs page";
+      stringID = IDS_IOS_TAB_GRID_REMOTE_TABS_TITLE;
+      break;
   }
+  return l10n_util::GetNSString(stringID);
 }
 
 #pragma mark - GridTransitionStateProviding properties
@@ -298,11 +306,11 @@
   [self addChildViewController:viewController];
   [contentView addSubview:viewController.view];
   [viewController didMoveToParentViewController:self];
-  // TODO(crbug.com/818699) : Localize strings.
-  viewController.emptyStateView = [self
-      createEmptyStateViewWithTopText:@"No Incognito Tabs"
-                           bottomText:
-                               @"Open a tab to browse the web privately."];
+  int titleStringID = IDS_IOS_TAB_GRID_INCOGNITO_TABS_EMPTY_STATE_TITLE;
+  int bodyStringID = IDS_IOS_TAB_GRID_INCOGNITO_TABS_EMPTY_STATE_BODY;
+  viewController.emptyStateView =
+      [self createEmptyStateViewWithTitleStringID:titleStringID
+                                     bodyStringID:bodyStringID];
   viewController.theme = GridThemeDark;
   viewController.delegate = self;
   if (@available(iOS 11, *)) {
@@ -333,10 +341,11 @@
   [self addChildViewController:viewController];
   [contentView addSubview:viewController.view];
   [viewController didMoveToParentViewController:self];
-  // TODO(crbug.com/818699) : Localize strings.
+  int titleStringID = IDS_IOS_TAB_GRID_REGULAR_TABS_EMPTY_STATE_TITLE;
+  int bodyStringID = IDS_IOS_TAB_GRID_REGULAR_TABS_EMPTY_STATE_BODY;
   viewController.emptyStateView =
-      [self createEmptyStateViewWithTopText:@"No Open Tabs"
-                                 bottomText:@"Open a tab to browse the web."];
+      [self createEmptyStateViewWithTitleStringID:titleStringID
+                                     bodyStringID:bodyStringID];
   viewController.theme = GridThemeLight;
   viewController.delegate = self;
   if (@available(iOS 11, *)) {
@@ -386,12 +395,12 @@
 }
 
 // Creates an empty state view.
-- (UIView*)createEmptyStateViewWithTopText:(NSString*)topText
-                                bottomText:(NSString*)bottomText {
+- (UIView*)createEmptyStateViewWithTitleStringID:(int)titleStringID
+                                    bodyStringID:(int)bodyStringID {
   UIView* view = [[UIView alloc] init];
   UILabel* topLabel = [[UILabel alloc] init];
   topLabel.translatesAutoresizingMaskIntoConstraints = NO;
-  topLabel.text = topText;
+  topLabel.text = l10n_util::GetNSString(titleStringID);
   topLabel.textColor = [UIColor whiteColor];
   topLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleTitle2];
   topLabel.adjustsFontForContentSizeCategory = YES;
@@ -400,7 +409,7 @@
   [view addSubview:topLabel];
   UILabel* bottomLabel = [[UILabel alloc] init];
   bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;
-  bottomLabel.text = bottomText;
+  bottomLabel.text = l10n_util::GetNSString(bodyStringID);
   bottomLabel.textColor = [UIColor whiteColor];
   bottomLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
   bottomLabel.adjustsFontForContentSizeCategory = YES;
@@ -410,10 +419,12 @@
   NSArray* constraints = @[
     [topLabel.leadingAnchor constraintEqualToAnchor:view.leadingAnchor],
     [topLabel.trailingAnchor constraintEqualToAnchor:view.trailingAnchor],
-    [topLabel.bottomAnchor constraintEqualToAnchor:view.centerYAnchor
-                                          constant:-10.0f],
-    [bottomLabel.topAnchor constraintEqualToAnchor:view.centerYAnchor
-                                          constant:10.0f],
+    [topLabel.bottomAnchor
+        constraintEqualToAnchor:view.centerYAnchor
+                       constant:-kTabGridEmptyStateVerticalMargin / 2.0f],
+    [bottomLabel.topAnchor
+        constraintEqualToAnchor:view.centerYAnchor
+                       constant:kTabGridEmptyStateVerticalMargin / 2.0f],
     [bottomLabel.leadingAnchor constraintEqualToAnchor:view.leadingAnchor],
     [bottomLabel.trailingAnchor constraintEqualToAnchor:view.trailingAnchor],
   ];
@@ -427,6 +438,10 @@
   topToolbar.translatesAutoresizingMaskIntoConstraints = NO;
   [self.view addSubview:topToolbar];
   self.topToolbar = topToolbar;
+  // Configure and initialize the page control.
+  [self.topToolbar.pageControl addTarget:self
+                                  action:@selector(pageControlChanged:)
+                        forControlEvents:UIControlEventValueChanged];
   NSArray* constraints = @[
     [topToolbar.topAnchor constraintEqualToAnchor:self.view.topAnchor],
     [topToolbar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
@@ -537,9 +552,11 @@
     self.closeAllButton = self.topToolbar.leadingButton;
   }
 
-  // TODO(crbug.com/818699) : Localize strings.
-  [self.doneButton setTitle:@"Done" forState:UIControlStateNormal];
-  [self.closeAllButton setTitle:@"Close All" forState:UIControlStateNormal];
+  [self.doneButton setTitle:l10n_util::GetNSString(IDS_IOS_TAB_GRID_DONE_BUTTON)
+                   forState:UIControlStateNormal];
+  [self.closeAllButton
+      setTitle:l10n_util::GetNSString(IDS_IOS_TAB_GRID_CLOSE_ALL_BUTTON)
+      forState:UIControlStateNormal];
   self.doneButton.accessibilityIdentifier = kTabGridDoneButtonAccessibilityID;
   [self.doneButton addTarget:self
                       action:@selector(doneButtonTapped:)
@@ -550,12 +567,6 @@
   [self.newTabButton addTarget:self
                         action:@selector(newTabButtonTapped:)
               forControlEvents:UIControlEventTouchUpInside];
-  [self.topToolbar.pageControl addTarget:self
-                                  action:@selector(pageControlChanged:)
-                        forControlEvents:UIControlEventValueChanged];
-  // TODO(crbug.com/804501): Use the actual live tab counts.
-  self.topToolbar.pageControl.regularText = @"5";
-  self.topToolbar.pageControl.incognitoText = @"0";
   [self configureButtonsForCurrentPage];
 }
 
@@ -599,6 +610,8 @@
                                       imageWithRenderingMode:
                                           UIImageRenderingModeAlwaysOriginal]
                          forState:UIControlStateNormal];
+      self.newTabButton.accessibilityLabel =
+          l10n_util::GetNSString(IDS_IOS_TAB_GRID_CREATE_NEW_INCOGNITO_TAB);
       break;
     case TabGridPageRegularTabs:
       self.newTabButton.enabled = YES;
@@ -606,6 +619,8 @@
                                       imageWithRenderingMode:
                                           UIImageRenderingModeAlwaysOriginal]
                          forState:UIControlStateNormal];
+      self.newTabButton.accessibilityLabel =
+          l10n_util::GetNSString(IDS_IOS_TAB_GRID_CREATE_NEW_TAB);
       break;
     case TabGridPageRemoteTabs:
       self.newTabButton.enabled = NO;
@@ -679,14 +694,14 @@
   }
 }
 
-- (void)lastItemWasClosedInGridViewController:
-    (GridViewController*)gridViewController {
+- (void)gridViewController:(GridViewController*)gridViewController
+        didChangeItemCount:(NSUInteger)count {
   [self configureButtonsForCurrentPage];
-}
-
-- (void)firstItemWasAddedInGridViewController:
-    (GridViewController*)gridViewController {
-  [self configureButtonsForCurrentPage];
+  if (gridViewController == self.regularTabsViewController) {
+    self.topToolbar.pageControl.regularTabCount = count;
+  } else if (gridViewController == self.incognitoTabsViewController) {
+    self.topToolbar.pageControl.incognitoTabCount = count;
+  }
 }
 
 #pragma mark - Control actions
diff --git a/media/cast/net/udp_transport_impl.cc b/media/cast/net/udp_transport_impl.cc
index 4d2587a..22cae91 100644
--- a/media/cast/net/udp_transport_impl.cc
+++ b/media/cast/net/udp_transport_impl.cc
@@ -11,12 +11,10 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
-#include "base/rand_util.h"
 #include "build/build_config.h"
 #include "media/cast/net/udp_packet_pipe.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
 #include "net/log/net_log_source.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
@@ -71,7 +69,6 @@
       local_addr_(local_end_point),
       remote_addr_(remote_end_point),
       udp_socket_(new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND,
-                                     net::RandIntCallback(),
                                      net_log,
                                      net::NetLogSource())),
       send_pending_(false),
diff --git a/media/renderers/video_overlay_factory.cc b/media/renderers/video_overlay_factory.cc
index 71057d8..bc9432cc 100644
--- a/media/renderers/video_overlay_factory.cc
+++ b/media/renderers/video_overlay_factory.cc
@@ -25,11 +25,11 @@
     if (!gl)
       return;
     gpu_memory_buffer_ = gpu_factories_->CreateGpuMemoryBuffer(
-        gfx::Size(1, 1), gfx::BufferFormat::RGBA_8888,
+        gfx::Size(1, 1), gfx::BufferFormat::BGRA_8888,
         gfx::BufferUsage::SCANOUT);
     if (gpu_memory_buffer_) {
       image_id_ = gl->CreateImageCHROMIUM(gpu_memory_buffer_->AsClientBuffer(),
-                                          1, 1, GL_RGBA);
+                                          1, 1, GL_BGRA_EXT);
       }
       if (image_id_) {
         gl->GenTextures(1, &texture_id_);
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc
index 4c9a396..19a1f41 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -699,10 +699,9 @@
       ++copies;
   }
 
-  const base::Closure copies_done =
-      base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources);
-  const base::RepeatingClosure barrier =
-      base::BarrierClosure(copies, copies_done);
+  const base::RepeatingClosure barrier = base::BarrierClosure(
+      copies, base::BindOnce(&PoolImpl::OnCopiesDone, this, video_frame,
+                             frame_resources));
 
   // Map the buffers.
   for (size_t i = 0; i < NumGpuMemoryBuffers(output_format_); i++) {
@@ -840,25 +839,24 @@
   for (size_t i = 0; i < NumGpuMemoryBuffers(output_format_); i++)
     mailbox_holders[i].sync_token = sync_token;
 
-  auto release_mailbox_callback = BindToCurrentLoop(
-      base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources));
-
   VideoPixelFormat frame_format = VideoFormat(output_format_);
 
   // Create the VideoFrame backed by native textures.
   gfx::Size visible_size = video_frame->visible_rect().size();
   scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
-      frame_format, mailbox_holders, release_mailbox_callback, coded_size,
+      frame_format, mailbox_holders, VideoFrame::ReleaseMailboxCB(), coded_size,
       gfx::Rect(visible_size), video_frame->natural_size(),
       video_frame->timestamp());
 
   if (!frame) {
     frame_resources->MarkUnused(tick_clock_->NowTicks());
-    release_mailbox_callback.Run(gpu::SyncToken());
+    MailboxHoldersReleased(frame_resources, gpu::SyncToken());
     std::move(frame_copy_requests_.front().frame_ready_cb).Run(video_frame);
     frame_copy_requests_.pop_front();
     return;
   }
+  frame->SetReleaseMailboxCB(
+      base::BindOnce(&PoolImpl::MailboxHoldersReleased, this, frame_resources));
 
   frame->set_color_space(video_frame->ColorSpace());
 
@@ -913,6 +911,7 @@
 }
 
 void GpuMemoryBufferVideoFramePool::PoolImpl::Shutdown() {
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
   // Clients don't care about copies once shutdown has started, so abort them.
   Abort();
 
@@ -941,6 +940,7 @@
 GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResources(
     const gfx::Size& size,
     GpuVideoAcceleratorFactories::OutputFormat format) {
+  DCHECK(media_task_runner_->BelongsToCurrentThread());
 
   auto it = resources_pool_.begin();
   while (it != resources_pool_.end()) {
@@ -1001,7 +1001,6 @@
   // TODO(dcastagna): As soon as the context lost is dealt with in media,
   // make sure that we won't execute this callback (use a weak pointer to
   // the old context).
-
   gpu::gles2::GLES2Interface* gles2 = gpu_factories->ContextGL();
   if (!gles2)
     return;
@@ -1019,7 +1018,13 @@
 void GpuMemoryBufferVideoFramePool::PoolImpl::MailboxHoldersReleased(
     FrameResources* frame_resources,
     const gpu::SyncToken& release_sync_token) {
-  DCHECK(media_task_runner_->BelongsToCurrentThread());
+  if (!media_task_runner_->BelongsToCurrentThread()) {
+    media_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&PoolImpl::MailboxHoldersReleased, this,
+                                  frame_resources, release_sync_token));
+    return;
+  }
+
   if (in_shutdown_) {
     DeleteFrameResources(gpu_factories_, frame_resources);
     delete frame_resources;
diff --git a/net/dns/address_sorter_posix.cc b/net/dns/address_sorter_posix.cc
index 051bafe..37af8da 100644
--- a/net/dns/address_sorter_posix.cc
+++ b/net/dns/address_sorter_posix.cc
@@ -280,7 +280,7 @@
     // Each socket can only be bound once.
     std::unique_ptr<DatagramClientSocket> socket(
         socket_factory_->CreateDatagramClientSocket(
-            DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL /* NetLog */,
+            DatagramSocket::DEFAULT_BIND, nullptr /* NetLog */,
             NetLogSource()));
 
     // Even though no packets are sent, cannot use port 0 in Connect.
diff --git a/net/dns/address_sorter_posix_unittest.cc b/net/dns/address_sorter_posix_unittest.cc
index 1407ab4..80ba6d7 100644
--- a/net/dns/address_sorter_posix_unittest.cc
+++ b/net/dns/address_sorter_posix_unittest.cc
@@ -111,7 +111,6 @@
 
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType,
-      const RandIntCallback&,
       NetLog*,
       const NetLogSource&) override {
     return std::unique_ptr<DatagramClientSocket>(
diff --git a/net/dns/dns_session_unittest.cc b/net/dns/dns_session_unittest.cc
index a9afe2b..e2807241 100644
--- a/net/dns/dns_session_unittest.cc
+++ b/net/dns/dns_session_unittest.cc
@@ -31,7 +31,6 @@
 
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
-      const RandIntCallback& rand_int_cb,
       NetLog* net_log,
       const NetLogSource& source) override;
 
@@ -181,7 +180,6 @@
 std::unique_ptr<DatagramClientSocket>
 TestClientSocketFactory::CreateDatagramClientSocket(
     DatagramSocket::BindType bind_type,
-    const RandIntCallback& rand_int_cb,
     NetLog* net_log,
     const NetLogSource& source) {
   // We're not actually expecting to send or receive any data, so use the
diff --git a/net/dns/dns_socket_pool.cc b/net/dns/dns_socket_pool.cc
index e77a03a..4732a0c 100644
--- a/net/dns/dns_socket_pool.cc
+++ b/net/dns/dns_socket_pool.cc
@@ -74,8 +74,8 @@
   std::unique_ptr<DatagramClientSocket> socket;
 
   NetLogSource no_source;
-  socket = socket_factory_->CreateDatagramClientSocket(
-      kBindType, rand_int_callback_, net_log_, no_source);
+  socket = socket_factory_->CreateDatagramClientSocket(kBindType, net_log_,
+                                                       no_source);
 
   if (socket.get()) {
     int rv = socket->Connect((*nameservers_)[server_index]);
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index f61f0ff..2fd04787 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -229,7 +229,6 @@
 
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
-      const RandIntCallback& rand_int_cb,
       NetLog* net_log,
       const NetLogSource& source) override {
     if (fail_next_socket_) {
@@ -238,9 +237,7 @@
           new FailingUDPClientSocket(&empty_data_, net_log));
     }
     SocketDataProvider* data_provider = mock_data().GetNext();
-    std::unique_ptr<TestUDPClientSocket> socket(
-        new TestUDPClientSocket(this, data_provider, net_log));
-    return std::move(socket);
+    return std::make_unique<TestUDPClientSocket>(this, data_provider, net_log);
   }
 
   void OnConnect(const IPEndPoint& endpoint) {
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc
index f46c06a8..039fc9c1 100644
--- a/net/dns/host_resolver_impl.cc
+++ b/net/dns/host_resolver_impl.cc
@@ -2415,8 +2415,7 @@
                                            const NetLogWithSource& net_log) {
   std::unique_ptr<DatagramClientSocket> socket(
       ClientSocketFactory::GetDefaultFactory()->CreateDatagramClientSocket(
-          DatagramSocket::DEFAULT_BIND, RandIntCallback(), net_log.net_log(),
-          net_log.source()));
+          DatagramSocket::DEFAULT_BIND, net_log.net_log(), net_log.source()));
   int rv = socket->Connect(IPEndPoint(dest, 53));
   if (rv != OK)
     return false;
diff --git a/net/quic/chromium/quic_chromium_client_session_test.cc b/net/quic/chromium/quic_chromium_client_session_test.cc
index 7bcd392..4eb8e16e9 100644
--- a/net/quic/chromium/quic_chromium_client_session_test.cc
+++ b/net/quic/chromium/quic_chromium_client_session_test.cc
@@ -7,7 +7,6 @@
 #include "base/base64.h"
 #include "base/files/file_path.h"
 #include "base/memory/ptr_util.h"
-#include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/test/histogram_tester.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -132,7 +131,6 @@
       socket_factory_.AddSocketDataProvider(socket_data_.get());
     std::unique_ptr<DatagramClientSocket> socket =
         socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
-                                                   base::Bind(&base::RandInt),
                                                    &net_log_, NetLogSource());
     socket->Connect(kIpEndPoint);
     QuicChromiumPacketWriter* writer = new net::QuicChromiumPacketWriter(
@@ -1263,7 +1261,6 @@
   // Create connected socket.
   std::unique_ptr<DatagramClientSocket> new_socket =
       socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
-                                                 base::Bind(&base::RandInt),
                                                  &net_log_, NetLogSource());
   EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
 
@@ -1322,7 +1319,6 @@
     // Create connected socket.
     std::unique_ptr<DatagramClientSocket> new_socket =
         socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
-                                                   base::Bind(&base::RandInt),
                                                    &net_log_, NetLogSource());
     EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
 
@@ -1389,7 +1385,6 @@
   // Create connected socket.
   std::unique_ptr<DatagramClientSocket> new_socket =
       socket_factory_.CreateDatagramClientSocket(DatagramSocket::DEFAULT_BIND,
-                                                 base::Bind(&base::RandInt),
                                                  &net_log_, NetLogSource());
   EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
 
diff --git a/net/quic/chromium/quic_connectivity_probing_manager_test.cc b/net/quic/chromium/quic_connectivity_probing_manager_test.cc
index 7b7b0c5..6d77dead 100644
--- a/net/quic/chromium/quic_connectivity_probing_manager_test.cc
+++ b/net/quic/chromium/quic_connectivity_probing_manager_test.cc
@@ -4,7 +4,6 @@
 
 #include "net/quic/chromium/quic_connectivity_probing_manager.h"
 
-#include "base/rand_util.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "net/log/test_net_log.h"
 #include "net/quic/test_tools/mock_clock.h"
@@ -84,8 +83,7 @@
     socket_factory_.AddSocketDataProvider(socket_data_.get());
     // Create a connected socket for probing.
     socket_ = socket_factory_.CreateDatagramClientSocket(
-        DatagramSocket::DEFAULT_BIND, base::Bind(&base::RandInt), &net_log_,
-        NetLogSource());
+        DatagramSocket::DEFAULT_BIND, &net_log_, NetLogSource());
     EXPECT_THAT(socket_->Connect(kIpEndPoint), IsOk());
     IPEndPoint self_address;
     socket_->GetLocalAddress(&self_address);
diff --git a/net/quic/chromium/quic_stream_factory.cc b/net/quic/chromium/quic_stream_factory.cc
index 584f3737..9448749c 100644
--- a/net/quic/chromium/quic_stream_factory.cc
+++ b/net/quic/chromium/quic_stream_factory.cc
@@ -14,7 +14,6 @@
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/rand_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -1347,7 +1346,7 @@
     NetLog* net_log,
     const NetLogSource& source) {
   auto socket = client_socket_factory_->CreateDatagramClientSocket(
-      DatagramSocket::DEFAULT_BIND, RandIntCallback(), net_log, source);
+      DatagramSocket::DEFAULT_BIND, net_log, source);
   if (enable_socket_recv_optimization_)
     socket->EnableRecvOptimization();
   return socket;
diff --git a/net/quic/chromium/quic_stream_factory_test.cc b/net/quic/chromium/quic_stream_factory_test.cc
index fd26cb78..ec2eeed 100644
--- a/net/quic/chromium/quic_stream_factory_test.cc
+++ b/net/quic/chromium/quic_stream_factory_test.cc
@@ -190,7 +190,6 @@
 
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
-      const RandIntCallback& rand_int_cb,
       NetLog* net_log,
       const NetLogSource& source) override {
     SocketDataProvider* data_provider = mock_data().GetNext();
diff --git a/net/reporting/reporting_header_parser.cc b/net/reporting/reporting_header_parser.cc
index e482a55e..001fc0e 100644
--- a/net/reporting/reporting_header_parser.cc
+++ b/net/reporting/reporting_header_parser.cc
@@ -26,14 +26,15 @@
   DISCARDED_NO_REPORTING_SERVICE = 0,
   DISCARDED_INVALID_SSL_INFO = 1,
   DISCARDED_CERT_STATUS_ERROR = 2,
-  DISCARDED_INVALID_JSON = 3,
-  PARSED = 4,
+  DISCARDED_JSON_TOO_BIG = 3,
+  DISCARDED_JSON_INVALID = 4,
+  PARSED = 5,
 
   MAX
 };
 
 void RecordHeaderOutcome(HeaderOutcome outcome) {
-  UMA_HISTOGRAM_ENUMERATION("Reporting.HeaderOutcome", outcome,
+  UMA_HISTOGRAM_ENUMERATION("Net.Reporting.HeaderOutcome", outcome,
                             HeaderOutcome::MAX);
 }
 
@@ -45,38 +46,30 @@
   DISCARDED_TTL_NEGATIVE = 4,
   DISCARDED_ENDPOINTS_MISSING = 5,
   DISCARDED_ENDPOINTS_NOT_LIST = 6,
+
   PARSED = 7,
 
   MAX
 };
 
 void RecordHeaderEndpointGroupOutcome(HeaderEndpointGroupOutcome outcome) {
-  UMA_HISTOGRAM_ENUMERATION("Reporting.HeaderEndpointGroupOutcome", outcome,
+  UMA_HISTOGRAM_ENUMERATION("Net.Reporting.HeaderEndpointGroupOutcome", outcome,
                             HeaderEndpointGroupOutcome::MAX);
 }
 
 enum class HeaderEndpointOutcome {
   DISCARDED_NOT_DICTIONARY = 0,
-  DISCARDED_ENDPOINT_MISSING = 1,     // obsolete
-  DISCARDED_ENDPOINT_NOT_STRING = 2,  // obsolete
-  DISCARDED_ENDPOINT_INVALID = 3,     // obsolete
-  DISCARDED_ENDPOINT_INSECURE = 4,    // obsolete
-  DISCARDED_TTL_MISSING = 5,          // obsolete
-  DISCARDED_TTL_NOT_INTEGER = 6,      // obsolete
-  DISCARDED_TTL_NEGATIVE = 7,         // obsolete
-  DISCARDED_GROUP_NOT_STRING = 8,     // obsolete
-  REMOVED = 9,
-  SET_REJECTED_BY_DELEGATE = 10,
-  SET = 11,
+  DISCARDED_URL_MISSING = 1,
+  DISCARDED_URL_NOT_STRING = 2,
+  DISCARDED_URL_INVALID = 3,
+  DISCARDED_URL_INSECURE = 4,
+  DISCARDED_PRIORITY_NOT_INTEGER = 5,
+  DISCARDED_WEIGHT_NOT_INTEGER = 6,
+  DISCARDED_WEIGHT_NOT_POSITIVE = 7,
 
-  DISCARDED_PRIORITY_NOT_INTEGER = 12,
-  DISCARDED_WEIGHT_NOT_INTEGER = 13,
-  DISCARDED_WEIGHT_NOT_POSITIVE = 14,
-
-  DISCARDED_URL_MISSING = 15,
-  DISCARDED_URL_NOT_STRING = 16,
-  DISCARDED_URL_INVALID = 17,
-  DISCARDED_URL_INSECURE = 18,
+  REMOVED = 8,
+  SET_REJECTED_BY_DELEGATE = 9,
+  SET = 10,
 
   MAX
 };
@@ -88,7 +81,7 @@
 }
 
 void RecordHeaderEndpointOutcome(HeaderEndpointOutcome outcome) {
-  UMA_HISTOGRAM_ENUMERATION("Reporting.HeaderEndpointOutcome", outcome,
+  UMA_HISTOGRAM_ENUMERATION("Net.Reporting.HeaderEndpointOutcome", outcome,
                             HeaderEndpointOutcome::MAX);
 }
 
@@ -239,8 +232,13 @@
 }
 
 // static
-void ReportingHeaderParser::RecordHeaderDiscardedForInvalidJson() {
-  RecordHeaderOutcome(HeaderOutcome::DISCARDED_INVALID_JSON);
+void ReportingHeaderParser::RecordHeaderDiscardedForJsonInvalid() {
+  RecordHeaderOutcome(HeaderOutcome::DISCARDED_JSON_INVALID);
+}
+
+// static
+void ReportingHeaderParser::RecordHeaderDiscardedForJsonTooBig() {
+  RecordHeaderOutcome(HeaderOutcome::DISCARDED_JSON_TOO_BIG);
 }
 
 // static
diff --git a/net/reporting/reporting_header_parser.h b/net/reporting/reporting_header_parser.h
index 94a29be..7613add 100644
--- a/net/reporting/reporting_header_parser.h
+++ b/net/reporting/reporting_header_parser.h
@@ -25,7 +25,8 @@
   static void RecordHeaderDiscardedForNoReportingService();
   static void RecordHeaderDiscardedForInvalidSSLInfo();
   static void RecordHeaderDiscardedForCertStatusError();
-  static void RecordHeaderDiscardedForInvalidJson();
+  static void RecordHeaderDiscardedForJsonInvalid();
+  static void RecordHeaderDiscardedForJsonTooBig();
 
   static void ParseHeader(ReportingContext* context,
                           const GURL& url,
diff --git a/net/reporting/reporting_report.cc b/net/reporting/reporting_report.cc
index 37c4a22..2a594841 100644
--- a/net/reporting/reporting_report.cc
+++ b/net/reporting/reporting_report.cc
@@ -18,7 +18,7 @@
 namespace {
 
 void RecordReportOutcome(ReportingReport::Outcome outcome) {
-  UMA_HISTOGRAM_ENUMERATION("Reporting.ReportOutcome", outcome,
+  UMA_HISTOGRAM_ENUMERATION("Net.Reporting.ReportOutcome", outcome,
                             ReportingReport::Outcome::MAX);
 }
 
@@ -59,9 +59,9 @@
   RecordReportOutcome(outcome);
 
   if (outcome == Outcome::DELIVERED) {
-    UMA_HISTOGRAM_LONG_TIMES_100("Reporting.ReportDeliveredLatency",
+    UMA_HISTOGRAM_LONG_TIMES_100("Net.Reporting.ReportDeliveredLatency",
                                  now - queued);
-    UMA_HISTOGRAM_COUNTS_100("Reporting.ReportDeliveredAttempts", attempts);
+    UMA_HISTOGRAM_COUNTS_100("Net.Reporting.ReportDeliveredAttempts", attempts);
   }
 
   recorded_outcome = true;
diff --git a/net/reporting/reporting_report.h b/net/reporting/reporting_report.h
index 1621ab0..e7fba5d 100644
--- a/net/reporting/reporting_report.h
+++ b/net/reporting/reporting_report.h
@@ -33,7 +33,6 @@
     ERASED_BROWSING_DATA_REMOVED = 7,
     ERASED_REPORTING_SHUT_DOWN = 8,
     DELIVERED = 9,
-    ERASED_NO_BACKGROUND_SYNC_PERMISSION = 10,
 
     MAX
   };
diff --git a/net/reporting/reporting_service.cc b/net/reporting/reporting_service.cc
index 5137082..24be577 100644
--- a/net/reporting/reporting_service.cc
+++ b/net/reporting/reporting_service.cc
@@ -54,7 +54,7 @@
         base::BindRepeating(&ReportingServiceImpl::ProcessHeaderValue,
                             weak_factory_.GetWeakPtr(), url),
         base::BindRepeating(
-            &ReportingHeaderParser::RecordHeaderDiscardedForInvalidJson));
+            &ReportingHeaderParser::RecordHeaderDiscardedForJsonInvalid));
   }
 
   void RemoveBrowsingData(int data_type_mask,
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index 908e3191..c84685d 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -40,11 +40,10 @@
 
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
-      const RandIntCallback& rand_int_cb,
       NetLog* net_log,
       const NetLogSource& source) override {
     return std::unique_ptr<DatagramClientSocket>(
-        new UDPClientSocket(bind_type, rand_int_cb, net_log, source));
+        new UDPClientSocket(bind_type, net_log, source));
   }
 
   std::unique_ptr<StreamSocket> CreateTransportClientSocket(
diff --git a/net/socket/client_socket_factory.h b/net/socket/client_socket_factory.h
index 65490656..c17c342 100644
--- a/net/socket/client_socket_factory.h
+++ b/net/socket/client_socket_factory.h
@@ -9,7 +9,6 @@
 #include <string>
 
 #include "net/base/net_export.h"
-#include "net/base/rand_callback.h"
 #include "net/socket/datagram_socket.h"
 #include "net/socket/socket_performance_watcher.h"
 
@@ -36,7 +35,6 @@
   // if it has one.
   virtual std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
-      const RandIntCallback& rand_int_cb,
       NetLog* net_log,
       const NetLogSource& source) = 0;
 
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 91e0e68..3f3c08a 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -225,7 +225,6 @@
 
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
-      const RandIntCallback& rand_int_cb,
       NetLog* net_log,
       const NetLogSource& source) override {
     NOTREACHED();
diff --git a/net/socket/fuzzed_socket_factory.cc b/net/socket/fuzzed_socket_factory.cc
index ca158aea..dfff012 100644
--- a/net/socket/fuzzed_socket_factory.cc
+++ b/net/socket/fuzzed_socket_factory.cc
@@ -139,7 +139,6 @@
 std::unique_ptr<DatagramClientSocket>
 FuzzedSocketFactory::CreateDatagramClientSocket(
     DatagramSocket::BindType bind_type,
-    const RandIntCallback& rand_int_cb,
     NetLog* net_log,
     const NetLogSource& source) {
   return std::make_unique<FuzzedDatagramClientSocket>(data_provider_);
diff --git a/net/socket/fuzzed_socket_factory.h b/net/socket/fuzzed_socket_factory.h
index 788594b8..559d1465 100644
--- a/net/socket/fuzzed_socket_factory.h
+++ b/net/socket/fuzzed_socket_factory.h
@@ -37,7 +37,6 @@
 
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
-      const RandIntCallback& rand_int_cb,
       NetLog* net_log,
       const NetLogSource& source) override;
 
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index c66bedf..85d9fc67 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -20,6 +20,7 @@
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -725,15 +726,13 @@
 std::unique_ptr<DatagramClientSocket>
 MockClientSocketFactory::CreateDatagramClientSocket(
     DatagramSocket::BindType bind_type,
-    const RandIntCallback& rand_int_cb,
     NetLog* net_log,
     const NetLogSource& source) {
   SocketDataProvider* data_provider = mock_data_.GetNext();
   std::unique_ptr<MockUDPClientSocket> socket(
       new MockUDPClientSocket(data_provider, net_log));
   if (bind_type == DatagramSocket::RANDOM_BIND)
-    socket->set_source_port(
-        static_cast<uint16_t>(rand_int_cb.Run(1025, 65535)));
+    socket->set_source_port(static_cast<uint16_t>(base::RandInt(1025, 65535)));
   udp_client_socket_ports_.push_back(socket->source_port());
   return std::move(socket);
 }
@@ -1924,12 +1923,11 @@
 std::unique_ptr<DatagramClientSocket>
 MockTaggingClientSocketFactory::CreateDatagramClientSocket(
     DatagramSocket::BindType bind_type,
-    const RandIntCallback& rand_int_cb,
     NetLog* net_log,
     const NetLogSource& source) {
   std::unique_ptr<DatagramClientSocket> socket(
-      MockClientSocketFactory::CreateDatagramClientSocket(
-          bind_type, rand_int_cb, net_log, source));
+      MockClientSocketFactory::CreateDatagramClientSocket(bind_type, net_log,
+                                                          source));
   udp_socket_ = static_cast<MockUDPClientSocket*>(socket.get());
   return socket;
 }
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 65015f5..906d6be 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -528,7 +528,6 @@
   // ClientSocketFactory
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
-      const RandIntCallback& rand_int_cb,
       NetLog* net_log,
       const NetLogSource& source) override;
   std::unique_ptr<StreamSocket> CreateTransportClientSocket(
@@ -1145,7 +1144,6 @@
   // ClientSocketFactory implementation.
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
-      const RandIntCallback& rand_int_cb,
       NetLog* net_log,
       const NetLogSource& source) override;
   std::unique_ptr<StreamSocket> CreateTransportClientSocket(
diff --git a/net/socket/transport_client_socket_pool_test_util.cc b/net/socket/transport_client_socket_pool_test_util.cc
index 7f872c6..a516afd 100644
--- a/net/socket/transport_client_socket_pool_test_util.cc
+++ b/net/socket/transport_client_socket_pool_test_util.cc
@@ -372,7 +372,6 @@
 std::unique_ptr<DatagramClientSocket>
 MockTransportClientSocketFactory::CreateDatagramClientSocket(
     DatagramSocket::BindType bind_type,
-    const RandIntCallback& rand_int_cb,
     NetLog* net_log,
     const NetLogSource& source) {
   NOTREACHED();
diff --git a/net/socket/transport_client_socket_pool_test_util.h b/net/socket/transport_client_socket_pool_test_util.h
index e7c9e3ee..4e0820d6 100644
--- a/net/socket/transport_client_socket_pool_test_util.h
+++ b/net/socket/transport_client_socket_pool_test_util.h
@@ -75,7 +75,6 @@
 
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
-      const RandIntCallback& rand_int_cb,
       NetLog* net_log,
       const NetLogSource& source) override;
 
diff --git a/net/socket/udp_client_socket.cc b/net/socket/udp_client_socket.cc
index f84d28d..733670b 100644
--- a/net/socket/udp_client_socket.cc
+++ b/net/socket/udp_client_socket.cc
@@ -11,10 +11,9 @@
 namespace net {
 
 UDPClientSocket::UDPClientSocket(DatagramSocket::BindType bind_type,
-                                 const RandIntCallback& rand_int_cb,
                                  net::NetLog* net_log,
                                  const net::NetLogSource& source)
-    : socket_(bind_type, rand_int_cb, net_log, source),
+    : socket_(bind_type, net_log, source),
       network_(NetworkChangeNotifier::kInvalidNetworkHandle) {}
 
 UDPClientSocket::~UDPClientSocket() = default;
diff --git a/net/socket/udp_client_socket.h b/net/socket/udp_client_socket.h
index 9f4f1ea..ad2ebf1f 100644
--- a/net/socket/udp_client_socket.h
+++ b/net/socket/udp_client_socket.h
@@ -9,7 +9,6 @@
 
 #include "base/macros.h"
 #include "net/base/net_export.h"
-#include "net/base/rand_callback.h"
 #include "net/socket/datagram_client_socket.h"
 #include "net/socket/udp_socket.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -23,7 +22,6 @@
 class NET_EXPORT_PRIVATE UDPClientSocket : public DatagramClientSocket {
  public:
   UDPClientSocket(DatagramSocket::BindType bind_type,
-                  const RandIntCallback& rand_int_cb,
                   net::NetLog* net_log,
                   const net::NetLogSource& source);
   ~UDPClientSocket() override;
diff --git a/net/socket/udp_server_socket.cc b/net/socket/udp_server_socket.cc
index ca9d848..d2f18f4f 100644
--- a/net/socket/udp_server_socket.cc
+++ b/net/socket/udp_server_socket.cc
@@ -5,13 +5,12 @@
 #include "net/socket/udp_server_socket.h"
 
 #include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
 
 namespace net {
 
 UDPServerSocket::UDPServerSocket(net::NetLog* net_log,
                                  const net::NetLogSource& source)
-    : socket_(DatagramSocket::DEFAULT_BIND, RandIntCallback(), net_log, source),
+    : socket_(DatagramSocket::DEFAULT_BIND, net_log, source),
       allow_address_reuse_(false),
       allow_broadcast_(false) {}
 
diff --git a/net/socket/udp_socket_perftest.cc b/net/socket/udp_socket_perftest.cc
index 25f0ba3..c2c89ad 100644
--- a/net/socket/udp_socket_perftest.cc
+++ b/net/socket/udp_socket_perftest.cc
@@ -105,9 +105,8 @@
   // Setup the client.
   IPEndPoint server_address;
   CreateUDPAddress("127.0.0.1", kPort, &server_address);
-  std::unique_ptr<UDPClientSocket> client(
-      new UDPClientSocket(DatagramSocket::DEFAULT_BIND, RandIntCallback(),
-                          nullptr, NetLogSource()));
+  std::unique_ptr<UDPClientSocket> client(new UDPClientSocket(
+      DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource()));
   if (use_nonblocking_io)
     client->UseNonBlockingIO();
   rv = client->Connect(server_address);
diff --git a/net/socket/udp_socket_posix.cc b/net/socket/udp_socket_posix.cc
index e84a785..d5229972 100644
--- a/net/socket/udp_socket_posix.cc
+++ b/net/socket/udp_socket_posix.cc
@@ -192,7 +192,6 @@
 }  // namespace
 
 UDPSocketPosix::UDPSocketPosix(DatagramSocket::BindType bind_type,
-                               const RandIntCallback& rand_int_cb,
                                net::NetLog* net_log,
                                const net::NetLogSource& source)
     : socket_(kInvalidSocket),
@@ -203,7 +202,6 @@
       multicast_interface_(0),
       multicast_time_to_live_(1),
       bind_type_(bind_type),
-      rand_int_cb_(rand_int_cb),
       read_socket_watcher_(FROM_HERE),
       write_socket_watcher_(FROM_HERE),
       read_watcher_(this),
@@ -216,8 +214,6 @@
       experimental_recv_optimization_enabled_(false) {
   net_log_.BeginEvent(NetLogEventType::SOCKET_ALIVE,
                       source.ToEventParametersCallback());
-  if (bind_type == DatagramSocket::RANDOM_BIND)
-    DCHECK(!rand_int_cb.is_null());
 }
 
 UDPSocketPosix::~UDPSocketPosix() {
@@ -973,14 +969,14 @@
 }
 
 int UDPSocketPosix::RandomBind(const IPAddress& address) {
-  DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
+  DCHECK_EQ(bind_type_, DatagramSocket::RANDOM_BIND);
 
   for (int i = 0; i < kBindRetries; ++i) {
-    int rv = DoBind(IPEndPoint(address,
-                               rand_int_cb_.Run(kPortStart, kPortEnd)));
+    int rv = DoBind(IPEndPoint(address, base::RandInt(kPortStart, kPortEnd)));
     if (rv != ERR_ADDRESS_IN_USE)
       return rv;
   }
+
   return DoBind(IPEndPoint(address, 0));
 }
 
diff --git a/net/socket/udp_socket_posix.h b/net/socket/udp_socket_posix.h
index 77189fe..55d4a6ca 100644
--- a/net/socket/udp_socket_posix.h
+++ b/net/socket/udp_socket_posix.h
@@ -20,7 +20,6 @@
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_export.h"
 #include "net/base/network_change_notifier.h"
-#include "net/base/rand_callback.h"
 #include "net/log/net_log_with_source.h"
 #include "net/socket/datagram_socket.h"
 #include "net/socket/diff_serv_code_point.h"
@@ -80,7 +79,6 @@
   };
 
   UDPSocketPosix(DatagramSocket::BindType bind_type,
-                 const RandIntCallback& rand_int_cb,
                  net::NetLog* net_log,
                  const net::NetLogSource& source);
   virtual ~UDPSocketPosix();
@@ -372,9 +370,6 @@
   // UDPClientSocket, since UDPServerSocket provides Bind.
   DatagramSocket::BindType bind_type_;
 
-  // PRNG function for generating port numbers.
-  RandIntCallback rand_int_cb_;
-
   // These are mutable since they're just cached copies to make
   // GetPeerAddress/GetLocalAddress smarter.
   mutable std::unique_ptr<IPEndPoint> local_address_;
diff --git a/net/socket/udp_socket_unittest.cc b/net/socket/udp_socket_unittest.cc
index de48387..8f31f0b 100644
--- a/net/socket/udp_socket_unittest.cc
+++ b/net/socket/udp_socket_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "net/socket/udp_socket.h"
 
+#include <algorithm>
+
 #include "base/bind.h"
 #include "base/containers/circular_deque.h"
 #include "base/location.h"
@@ -46,6 +48,7 @@
 
 using net::test::IsError;
 using net::test::IsOk;
+using testing::Not;
 
 namespace net {
 
@@ -152,9 +155,8 @@
 
   // Setup the client.
   TestNetLog client_log;
-  std::unique_ptr<UDPClientSocket> client(
-      new UDPClientSocket(DatagramSocket::DEFAULT_BIND, RandIntCallback(),
-                          &client_log, NetLogSource()));
+  auto client = std::make_unique<UDPClientSocket>(DatagramSocket::DEFAULT_BIND,
+                                                  &client_log, NetLogSource());
   if (use_nonblocking_io)
     client->UseNonBlockingIO();
 
@@ -257,8 +259,8 @@
   IPEndPoint server_address;
   ASSERT_THAT(server_socket.GetLocalAddress(&server_address), IsOk());
 
-  UDPClientSocket client_socket(DatagramSocket::DEFAULT_BIND, RandIntCallback(),
-                                nullptr, NetLogSource());
+  UDPClientSocket client_socket(DatagramSocket::DEFAULT_BIND, nullptr,
+                                NetLogSource());
   ASSERT_THAT(client_socket.Connect(server_address), IsOk());
 
   std::string test_packet("hello world!");
@@ -337,106 +339,75 @@
   ASSERT_EQ(second_message, str);
 }
 
-// In this test, we verify that random binding logic works, which attempts
-// to bind to a random port and returns if succeeds, otherwise retries for
-// |kBindRetries| number of times.
-
-// To generate the scenario, we first create |kBindRetries| number of
-// UDPClientSockets with default binding policy and connect to the same
-// peer and save the used port numbers.  Then we get rid of the last
-// socket, making sure that the local port it was bound to is available.
-// Finally, we create a socket with random binding policy, passing it a
-// test PRNG that would serve used port numbers in the array, one after
-// another.  At the end, we make sure that the test socket was bound to the
-// port that became available after deleting the last socket with default
-// binding policy.
-
-// We do not test the randomness of bound ports, but that we are using
-// passed in PRNG correctly, thus, it's the duty of PRNG to produce strong
-// random numbers.
-static const int kBindRetries = 10;
-
-class TestPrng {
- public:
-  explicit TestPrng(const base::circular_deque<int>& numbers)
-      : numbers_(numbers) {}
-  int GetNext(int /* min */, int /* max */) {
-    DCHECK(!numbers_.empty());
-    int rv = numbers_.front();
-    numbers_.pop_front();
-    return rv;
-  }
- private:
-  base::circular_deque<int> numbers_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestPrng);
-};
-
+// ConnectRandomBind verifies RANDOM_BIND is handled correctly. It connects
+// 1000 sockets and then verifies that the allocated port numbers satisfy the
+// following 2 conditions:
+//  1. Range from min port value to max is greater than 10000.
+//  2. There is at least one port in the 5 buckets in the [min, max] range.
+//
+// These conditions are not enough to verify that the port numbers are truly
+// random, but they are enough to protect from most common non-random port
+// allocation strategies (e.g. counter, pool of available ports, etc.) False
+// positive result is theoretically possible, but its probability is negligible.
 TEST_F(UDPSocketTest, ConnectRandomBind) {
-  std::vector<std::unique_ptr<UDPClientSocket>> sockets;
-  IPEndPoint peer_address(IPAddress::IPv4Localhost(), 53);
+  const int kIterations = 1000;
 
-  // Create and connect sockets and save port numbers.
-  base::circular_deque<int> used_ports;
-  for (int i = 0; i < kBindRetries; ++i) {
-    UDPClientSocket* socket = new UDPClientSocket(
-        DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL, NetLogSource());
-    sockets.push_back(base::WrapUnique(socket));
-    EXPECT_THAT(socket->Connect(peer_address), IsOk());
+  std::vector<int> used_ports;
+  for (int i = 0; i < kIterations; ++i) {
+    UDPClientSocket socket(DatagramSocket::RANDOM_BIND, nullptr,
+                           NetLogSource());
+    EXPECT_THAT(socket.Connect(IPEndPoint(IPAddress::IPv4Localhost(), 53)),
+                IsOk());
 
     IPEndPoint client_address;
-    EXPECT_THAT(socket->GetLocalAddress(&client_address), IsOk());
+    EXPECT_THAT(socket.GetLocalAddress(&client_address), IsOk());
     used_ports.push_back(client_address.port());
   }
 
-  // Free the last socket, its local port is still in |used_ports|.
-  sockets.pop_back();
+  int min_port = *std::min_element(used_ports.begin(), used_ports.end());
+  int max_port = *std::max_element(used_ports.begin(), used_ports.end());
+  int range = max_port - min_port + 1;
 
-  TestPrng test_prng(used_ports);
-  RandIntCallback rand_int_cb =
-      base::Bind(&TestPrng::GetNext, base::Unretained(&test_prng));
+  // Verify that the range of ports used by the random port allocator is wider
+  // than 10k. Assuming that socket implementation limits port range to 16k
+  // ports (default on Fuchsia) probability of false negative is below
+  // 10^-200.
+  static int kMinRange = 10000;
+  EXPECT_GT(range, kMinRange);
 
-  // Create a socket with random binding policy and connect.
-  std::unique_ptr<UDPClientSocket> test_socket(new UDPClientSocket(
-      DatagramSocket::RANDOM_BIND, rand_int_cb, NULL, NetLogSource()));
-  EXPECT_THAT(test_socket->Connect(peer_address), IsOk());
+  static int kBuckets = 5;
+  std::vector<int> bucket_sizes(kBuckets, 0);
+  for (int port : used_ports) {
+    bucket_sizes[(port - min_port) * kBuckets / range] += 1;
+  }
 
-  // Make sure that the last port number in the |used_ports| was used.
-  IPEndPoint client_address;
-  EXPECT_THAT(test_socket->GetLocalAddress(&client_address), IsOk());
-  EXPECT_EQ(used_ports.back(), client_address.port());
+  // Verify that there is at least one value in each bucket. Probability of
+  // false negative is below (kBuckets * (1 - 1 / kBuckets) ^ kIterations),
+  // which is less than 10^-96.
+  for (int size : bucket_sizes) {
+    EXPECT_GT(size, 0);
+  }
 }
 
-// Return a privileged port (under 1024) so binding will fail.
-int PrivilegedRand(int min, int max) {
-  // Chosen by fair dice roll.  Guaranteed to be random.
-  return 4;
-}
-
-#if defined(OS_IOS) && !TARGET_IPHONE_SIMULATOR || defined(OS_FUCHSIA)
-// On iOS this test fails on device (but passes on simulator). See
-// http://crbug.com/227760.
-//
-// On Fuchsia the tests run in an emulator and have permissions to bind to
-// privileged ports.
+#if defined(OS_FUCHSIA)
+// Currently the test fails on Fuchsia because netstack allows to connect IPv4
+// socket to IPv6 address. This issue is tracked by NET-596.
 #define MAYBE_ConnectFail DISABLED_ConnectFail
 #else
 #define MAYBE_ConnectFail ConnectFail
 #endif
 TEST_F(UDPSocketTest, MAYBE_ConnectFail) {
-  IPEndPoint peer_address;
-  CreateUDPAddress("0.0.0.0", 53, &peer_address);
+  UDPSocket socket(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource());
 
-  std::unique_ptr<UDPSocket> socket(new UDPSocket(DatagramSocket::RANDOM_BIND,
-                                                  base::Bind(&PrivilegedRand),
-                                                  NULL, NetLogSource()));
-  int rv = socket->Open(peer_address.GetFamily());
-  EXPECT_THAT(rv, IsOk());
-  rv = socket->Connect(peer_address);
-  // Connect should have failed since we couldn't bind to that port,
-  EXPECT_NE(OK, rv);
+  EXPECT_THAT(socket.Open(ADDRESS_FAMILY_IPV4), IsOk());
+
+  // Connect to an IPv6 address should fail since the socket was created for
+  // IPv4.
+  EXPECT_THAT(socket.Connect(net::IPEndPoint(IPAddress::IPv6Localhost(), 53)),
+              Not(IsOk()));
+
   // Make sure that UDPSocket actually closed the socket.
-  EXPECT_FALSE(socket->is_connected());
+  EXPECT_FALSE(socket.is_connected());
 }
 
 // In this test, we verify that connect() on a socket will have the effect
@@ -455,21 +426,20 @@
 
   // Setup the first server to listen.
   IPEndPoint server1_address(IPAddress::IPv4Localhost(), kPort1);
-  UDPServerSocket server1(NULL, NetLogSource());
+  UDPServerSocket server1(nullptr, NetLogSource());
   server1.AllowAddressReuse();
   int rv = server1.Listen(server1_address);
   ASSERT_THAT(rv, IsOk());
 
   // Setup the second server to listen.
   IPEndPoint server2_address(IPAddress::IPv4Localhost(), kPort2);
-  UDPServerSocket server2(NULL, NetLogSource());
+  UDPServerSocket server2(nullptr, NetLogSource());
   server2.AllowAddressReuse();
   rv = server2.Listen(server2_address);
   ASSERT_THAT(rv, IsOk());
 
   // Setup the client, connected to server 1.
-  UDPClientSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL,
-                         NetLogSource());
+  UDPClientSocket client(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource());
   rv = client.Connect(server1_address);
   EXPECT_THAT(rv, IsOk());
 
@@ -526,8 +496,8 @@
     EXPECT_TRUE(ip_address.AssignFromIPLiteral(tests[i].local_address));
     IPEndPoint local_address(ip_address, 80);
 
-    UDPClientSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(),
-                           NULL, NetLogSource());
+    UDPClientSocket client(DatagramSocket::DEFAULT_BIND, nullptr,
+                           NetLogSource());
     int rv = client.Connect(remote_address);
     if (tests[i].may_fail && rv == ERR_ADDRESS_UNREACHABLE) {
       // Connect() may return ERR_ADDRESS_UNREACHABLE for IPv6
@@ -583,8 +553,8 @@
 
 TEST_F(UDPSocketTest, ClientSetDoNotFragment) {
   for (std::string ip : {"127.0.0.1", "::1"}) {
-    UDPClientSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(),
-                           nullptr, NetLogSource());
+    UDPClientSocket client(DatagramSocket::DEFAULT_BIND, nullptr,
+                           NetLogSource());
     IPAddress ip_address;
     EXPECT_TRUE(ip_address.AssignFromIPLiteral(ip));
     IPEndPoint remote_address(ip_address, 80);
@@ -659,8 +629,7 @@
   IPAddress group_ip;
   EXPECT_TRUE(group_ip.AssignFromIPLiteral(kGroup));
 
-  UDPSocket socket(DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL,
-                   NetLogSource());
+  UDPSocket socket(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource());
   EXPECT_THAT(socket.Open(bind_address.GetFamily()), IsOk());
 
 #if defined(OS_FUCHSIA)
@@ -686,8 +655,7 @@
   IPEndPoint bind_address;
   CreateUDPAddress("0.0.0.0", kPort, &bind_address);
 
-  UDPSocket socket(DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL,
-                   NetLogSource());
+  UDPSocket socket(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource());
   // Before binding.
   EXPECT_THAT(socket.SetMulticastLoopbackMode(false), IsOk());
   EXPECT_THAT(socket.SetMulticastLoopbackMode(true), IsOk());
@@ -711,8 +679,7 @@
 TEST_F(UDPSocketTest, SetDSCP) {
   // Setup the server to listen.
   IPEndPoint bind_address;
-  UDPSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL,
-                   NetLogSource());
+  UDPSocket client(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource());
   // We need a real IP, but we won't actually send anything to it.
   CreateUDPAddress("8.8.8.8", 9999, &bind_address);
   int rv = client.Open(bind_address.GetFamily());
@@ -736,8 +703,7 @@
 }
 
 TEST_F(UDPSocketTest, TestBindToNetwork) {
-  UDPSocket socket(DatagramSocket::RANDOM_BIND, base::Bind(&PrivilegedRand),
-                   NULL, NetLogSource());
+  UDPSocket socket(DatagramSocket::RANDOM_BIND, nullptr, NetLogSource());
 #if defined(OS_ANDROID)
   NetworkChangeNotifierFactoryAndroid ncn_factory;
   NetworkChangeNotifier::DisableForTest ncn_disable_for_test;
@@ -870,8 +836,7 @@
   IPEndPoint bind_address;
   // We need a real IP, but we won't actually send anything to it.
   CreateUDPAddress("8.8.8.8", 9999, &bind_address);
-  UDPSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL,
-                   NetLogSource());
+  UDPSocket client(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource());
   int rv = client.SetDiffServCodePoint(DSCP_AF41);
   EXPECT_THAT(rv, IsError(ERR_SOCKET_NOT_CONNECTED));
 
@@ -924,8 +889,7 @@
 
   // Setup the client, enable experimental optimization and connected to the
   // server.
-  UDPClientSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL,
-                         NetLogSource());
+  UDPClientSocket client(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource());
   client.EnableRecvOptimization();
   rv = client.Connect(server_address);
   EXPECT_THAT(rv, IsOk());
@@ -967,8 +931,7 @@
 
   // Setup the client, enable experimental optimization and connected to the
   // server.
-  UDPClientSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(), NULL,
-                         NetLogSource());
+  UDPClientSocket client(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource());
   client.EnableRecvOptimization();
   rv = client.Connect(server_address);
   EXPECT_THAT(rv, IsOk());
@@ -1035,8 +998,7 @@
   IPEndPoint server_address;
   ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
 
-  UDPClientSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(),
-                         nullptr, NetLogSource());
+  UDPClientSocket client(DatagramSocket::DEFAULT_BIND, nullptr, NetLogSource());
   ASSERT_THAT(client.Connect(server_address), IsOk());
 
   // Verify UDP packets are tagged and counted properly.
diff --git a/net/socket/udp_socket_win.cc b/net/socket/udp_socket_win.cc
index b848b54..a7e686e 100644
--- a/net/socket/udp_socket_win.cc
+++ b/net/socket/udp_socket_win.cc
@@ -246,7 +246,6 @@
 //-----------------------------------------------------------------------------
 
 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type,
-                           const RandIntCallback& rand_int_cb,
                            net::NetLog* net_log,
                            const net::NetLogSource& source)
     : socket_(INVALID_SOCKET),
@@ -256,7 +255,6 @@
       multicast_interface_(0),
       multicast_time_to_live_(1),
       bind_type_(bind_type),
-      rand_int_cb_(rand_int_cb),
       use_non_blocking_io_(false),
       read_iobuffer_len_(0),
       write_iobuffer_len_(0),
@@ -268,8 +266,6 @@
   EnsureWinsockInit();
   net_log_.BeginEvent(NetLogEventType::SOCKET_ALIVE,
                       source.ToEventParametersCallback());
-  if (bind_type == DatagramSocket::RANDOM_BIND)
-    DCHECK(!rand_int_cb.is_null());
 }
 
 UDPSocketWin::~UDPSocketWin() {
@@ -999,11 +995,11 @@
 }
 
 int UDPSocketWin::RandomBind(const IPAddress& address) {
-  DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
+  DCHECK_EQ(bind_type_, DatagramSocket::RANDOM_BIND);
 
   for (int i = 0; i < kBindRetries; ++i) {
-    int rv = DoBind(IPEndPoint(address, static_cast<uint16_t>(rand_int_cb_.Run(
-                                            kPortStart, kPortEnd))));
+    int rv = DoBind(IPEndPoint(
+        address, static_cast<uint16_t>(base::RandInt(kPortStart, kPortEnd))));
     if (rv != ERR_ADDRESS_IN_USE)
       return rv;
   }
diff --git a/net/socket/udp_socket_win.h b/net/socket/udp_socket_win.h
index 09d8196..c1f3cb42 100644
--- a/net/socket/udp_socket_win.h
+++ b/net/socket/udp_socket_win.h
@@ -24,7 +24,6 @@
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_export.h"
 #include "net/base/network_change_notifier.h"
-#include "net/base/rand_callback.h"
 #include "net/log/net_log_with_source.h"
 #include "net/socket/datagram_socket.h"
 #include "net/socket/diff_serv_code_point.h"
@@ -40,7 +39,6 @@
 class NET_EXPORT UDPSocketWin : public base::win::ObjectWatcher::Delegate {
  public:
   UDPSocketWin(DatagramSocket::BindType bind_type,
-               const RandIntCallback& rand_int_cb,
                net::NetLog* net_log,
                const net::NetLogSource& source);
   ~UDPSocketWin() override;
@@ -288,9 +286,6 @@
   // UDPClientSocket, since UDPServerSocket provides Bind.
   DatagramSocket::BindType bind_type_;
 
-  // PRNG function for generating port numbers.
-  RandIntCallback rand_int_cb_;
-
   // These are mutable since they're just cached copies to make
   // GetPeerAddress/GetLocalAddress smarter.
   mutable std::unique_ptr<IPEndPoint> local_address_;
diff --git a/net/tools/quic/quic_client_message_loop_network_helper.cc b/net/tools/quic/quic_client_message_loop_network_helper.cc
index 6c524fa..b60ba04 100644
--- a/net/tools/quic/quic_client_message_loop_network_helper.cc
+++ b/net/tools/quic/quic_client_message_loop_network_helper.cc
@@ -45,9 +45,8 @@
     QuicSocketAddress server_address,
     QuicIpAddress bind_to_address,
     int bind_to_port) {
-  std::unique_ptr<UDPClientSocket> socket(
-      new UDPClientSocket(DatagramSocket::DEFAULT_BIND, RandIntCallback(),
-                          &net_log_, NetLogSource()));
+  auto socket = std::make_unique<UDPClientSocket>(DatagramSocket::DEFAULT_BIND,
+                                                  &net_log_, NetLogSource());
 
   if (bind_to_address.IsInitialized()) {
     client_address_ = QuicSocketAddress(bind_to_address, client_->local_port());
diff --git a/services/network/chunked_data_pipe_upload_data_stream.cc b/services/network/chunked_data_pipe_upload_data_stream.cc
index 4718cde..d125d547 100644
--- a/services/network/chunked_data_pipe_upload_data_stream.cc
+++ b/services/network/chunked_data_pipe_upload_data_stream.cc
@@ -102,8 +102,12 @@
   // The pipe was closed. If the size isn't known yet, could be a success or a
   // failure.
   if (!size_) {
+    // Need to keep the buffer around because its presence is used to indicate
+    // that there's a pending UploadDataStream read.
     buf_ = buf;
     buf_len_ = buf_len;
+
+    handle_watcher_.Cancel();
     data_pipe_.reset();
     return net::ERR_IO_PENDING;
   }
diff --git a/services/network/public/cpp/network_param.typemap b/services/network/public/cpp/network_param.typemap
index e674db3..823f1d12 100644
--- a/services/network/public/cpp/network_param.typemap
+++ b/services/network/public/cpp/network_param.typemap
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-mojom = "//services/network/public/mojom/url_loader.mojom"
+mojom = "//services/network/public/mojom/network_param.mojom"
 public_headers = [
   "//net/base/auth.h",
   "//net/base/host_port_pair.h",
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn
index 6700d93..835461c 100644
--- a/services/network/public/mojom/BUILD.gn
+++ b/services/network/public/mojom/BUILD.gn
@@ -63,6 +63,7 @@
     "fetch_api.mojom",
     "http_request_headers.mojom",
     "network_change_manager.mojom",
+    "network_param.mojom",
     "network_service.mojom",
     "network_service_test.mojom",
     "network_types.mojom",
@@ -73,7 +74,6 @@
     "tcp_socket.mojom",
     "url_loader.mojom",
     "url_loader_factory.mojom",
-    "websocket.mojom",
   ]
 
   public_deps = [
diff --git a/services/network/public/mojom/network_param.mojom b/services/network/public/mojom/network_param.mojom
new file mode 100644
index 0000000..e68c575
--- /dev/null
+++ b/services/network/public/mojom/network_param.mojom
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module network.mojom;
+
+[Native]
+struct AuthChallengeInfo;
+
+[Native]
+struct AuthCredentials;
+
+[Native]
+struct CertVerifyResult;
+
+[Native]
+struct HostPortPair;
+
+[Native]
+struct X509Certificate;
+
+[Native]
+struct SSLCertRequestInfo;
+
+[Native]
+struct SSLInfo;
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom
index 01962d8..d980ba6 100644
--- a/services/network/public/mojom/network_service.mojom
+++ b/services/network/public/mojom/network_service.mojom
@@ -16,18 +16,13 @@
 import "services/network/public/mojom/tcp_socket.mojom";
 import "services/network/public/mojom/udp_socket.mojom";
 import "services/network/public/mojom/url_loader.mojom";
+import "services/network/public/mojom/network_param.mojom";
 import "services/network/public/mojom/url_loader_factory.mojom";
 import "services/proxy_resolver/public/mojom/proxy_resolver.mojom";
 import "services/network/public/mojom/restricted_cookie_manager.mojom";
 import "url/mojom/origin.mojom";
 import "url/mojom/url.mojom";
 
-[Native]
-struct AuthChallengeInfo;
-
-[Native]
-struct AuthCredentials;
-
 // Parameters for constructing a network context.
 struct NetworkContextParams {
   // Name used by memory tools to identify the context.
diff --git a/services/network/public/mojom/network_service_test.mojom b/services/network/public/mojom/network_service_test.mojom
index 9bf1cee..0050c00 100644
--- a/services/network/public/mojom/network_service_test.mojom
+++ b/services/network/public/mojom/network_service_test.mojom
@@ -5,12 +5,7 @@
 module network.mojom;
 
 import "services/network/public/mojom/network_change_manager.mojom";
-
-[Native]
-struct CertVerifyResult;
-
-[Native]
-struct X509Certificate;
+import "services/network/public/mojom/network_param.mojom";
 
 struct Rule {
   string host_pattern;
diff --git a/services/network/public/mojom/url_loader.mojom b/services/network/public/mojom/url_loader.mojom
index 52b1164..c3e99031 100644
--- a/services/network/public/mojom/url_loader.mojom
+++ b/services/network/public/mojom/url_loader.mojom
@@ -4,6 +4,8 @@
 
 module network.mojom;
 
+import "services/network/public/mojom/network_param.mojom";
+
 [Native]
 struct URLRequest;
 
@@ -11,12 +13,6 @@
 struct URLResponseHead;
 
 [Native]
-struct SSLCertRequestInfo;
-
-[Native]
-struct SSLInfo;
-
-[Native]
 struct URLRequestRedirectInfo;
 
 [Native]
@@ -25,9 +21,6 @@
 [Native]
 struct URLLoaderCompletionStatus;
 
-[Native]
-struct X509Certificate;
-
 // This enum corresponds to net::RequestPriority. See its comments for details.
 enum RequestPriority {
   kThrottled = 0,
diff --git a/services/network/tcp_socket_unittest.cc b/services/network/tcp_socket_unittest.cc
index dfb9bb1..95ec05e 100644
--- a/services/network/tcp_socket_unittest.cc
+++ b/services/network/tcp_socket_unittest.cc
@@ -477,8 +477,7 @@
   }
 }
 
-// TODO(xunjieli): This test is flaky on MacOS crbug.com/821224.
-TEST_F(TCPSocketTest, DISABLED_ServerReceivesMultipleAccept) {
+TEST_F(TCPSocketTest, ServerReceivesMultipleAccept) {
   uint32_t backlog = 10;
   TestServer server;
   server.Start(backlog);
@@ -496,6 +495,7 @@
   EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, callback.WaitForResult());
 
   // After handling incoming connections, all callbacks should now complete.
+  std::vector<mojom::TCPConnectedSocketPtr> client_sockets;
   for (size_t i = 0; i < backlog; ++i) {
     TestTCPConnectedSocketObserver observer;
     mojo::ScopedDataPipeConsumerHandle client_socket_receive_handle;
@@ -506,6 +506,7 @@
                   mojo::MakeRequest(&client_socket), observer.GetObserverPtr(),
                   base::nullopt /*local_addr*/, server.server_addr(),
                   &client_socket_receive_handle, &client_socket_send_handle));
+    client_sockets.push_back(std::move(client_socket));
   }
   for (const auto& callback : accept_callbacks) {
     EXPECT_EQ(net::OK, callback->WaitForResult());
diff --git a/services/network/udp_socket.cc b/services/network/udp_socket.cc
index e43690f..b396ae9b 100644
--- a/services/network/udp_socket.cc
+++ b/services/network/udp_socket.cc
@@ -12,10 +12,8 @@
 #include "base/numerics/checked_math.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/optional.h"
-#include "base/rand_util.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
 #include "net/log/net_log.h"
 #include "net/socket/udp_socket.h"
 
@@ -31,10 +29,9 @@
 class SocketWrapperImpl : public UDPSocket::SocketWrapper {
  public:
   SocketWrapperImpl(net::DatagramSocket::BindType bind_type,
-                    const net::RandIntCallback& rand_int_cb,
                     net::NetLog* net_log,
                     const net::NetLogSource& source)
-      : socket_(bind_type, rand_int_cb, net_log, source) {}
+      : socket_(bind_type, net_log, source) {}
   ~SocketWrapperImpl() override {}
 
   int Connect(const net::IPEndPoint& remote_addr,
@@ -286,9 +283,8 @@
 
 std::unique_ptr<UDPSocket::SocketWrapper> UDPSocket::CreateSocketWrapper()
     const {
-  return std::make_unique<SocketWrapperImpl>(
-      net::DatagramSocket::RANDOM_BIND, base::BindRepeating(&base::RandInt),
-      net_log_, net::NetLogSource());
+  return std::make_unique<SocketWrapperImpl>(net::DatagramSocket::RANDOM_BIND,
+                                             nullptr, net::NetLogSource());
 }
 
 bool UDPSocket::IsConnectedOrBound() const {
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc
index 10f06011..f58676e 100644
--- a/services/ui/ws/frame_generator.cc
+++ b/services/ui/ws/frame_generator.cc
@@ -178,9 +178,8 @@
   hit_test_region_list->bounds.set_size(pixel_size_);
 
   auto hit_test_region = viz::mojom::HitTestRegion::New();
-  viz::SurfaceId surface_id = window_manager_surface_info_.id();
-  hit_test_region->frame_sink_id = surface_id.frame_sink_id();
-  hit_test_region->local_surface_id = surface_id.local_surface_id();
+  hit_test_region->frame_sink_id =
+      window_manager_surface_info_.id().frame_sink_id();
   hit_test_region->flags = viz::mojom::kHitTestChildSurface;
   hit_test_region->rect = gfx::Rect(pixel_size_);
 
diff --git a/services/viz/public/interfaces/hit_test/hit_test_region_list.mojom b/services/viz/public/interfaces/hit_test/hit_test_region_list.mojom
index acfa39f6d..2b95dfb9 100644
--- a/services/viz/public/interfaces/hit_test/hit_test_region_list.mojom
+++ b/services/viz/public/interfaces/hit_test/hit_test_region_list.mojom
@@ -5,7 +5,6 @@
 module viz.mojom;
 
 import "services/viz/public/interfaces/compositing/frame_sink_id.mojom";
-import "services/viz/public/interfaces/compositing/local_surface_id.mojom";
 import "services/viz/public/interfaces/compositing/surface_id.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "ui/gfx/mojo/transform.mojom";
@@ -37,9 +36,6 @@
   // FrameSinkId of this region.
   FrameSinkId frame_sink_id;
 
-  // LocalSurfaceId is required when flags include kHitTestChildSurface.
-  LocalSurfaceId? local_surface_id;
-
   // The rect of the region in the coordinate space of the embedder.
   gfx.mojom.Rect rect;
 
diff --git a/storage/browser/blob/blob_entry.cc b/storage/browser/blob/blob_entry.cc
index 08a6877..496af8e 100644
--- a/storage/browser/blob/blob_entry.cc
+++ b/storage/browser/blob/blob_entry.cc
@@ -40,13 +40,13 @@
   DCHECK(!transport_quota_request);
 }
 
-void BlobEntry::BuildingState::CancelRequests() {
-  if (copy_quota_request) {
+void BlobEntry::BuildingState::CancelRequestsAndAbort() {
+  if (copy_quota_request)
     copy_quota_request->Cancel();
-  }
-  if (transport_quota_request) {
+  if (transport_quota_request)
     transport_quota_request->Cancel();
-  }
+  if (build_aborted_callback)
+    std::move(build_aborted_callback).Run();
 }
 
 BlobEntry::BlobEntry(const std::string& content_type,
diff --git a/storage/browser/blob/blob_entry.h b/storage/browser/blob/blob_entry.h
index 8fd89e1..9611b425 100644
--- a/storage/browser/blob/blob_entry.h
+++ b/storage/browser/blob/blob_entry.h
@@ -28,6 +28,7 @@
  public:
   using TransportAllowedCallback = base::OnceCallback<
       void(BlobStatus, std::vector<BlobMemoryController::FileCreationInfo>)>;
+  using BuildAbortedCallback = base::OnceClosure;
 
   // Records a copy from a referenced blob. Copies happen after referenced blobs
   // are complete & quota for the copies is granted.
@@ -60,8 +61,9 @@
                   size_t num_building_dependent_blobs);
     ~BuildingState();
 
-    // Cancels pending memory or file requests.
-    void CancelRequests();
+    // Cancels pending memory or file requests, and calls aborted callback if it
+    // is set.
+    void CancelRequestsAndAbort();
 
     const bool transport_items_present;
     // We can have trasnport data that's either populated or unpopulated. If we
@@ -69,6 +71,8 @@
     TransportAllowedCallback transport_allowed_callback;
     std::vector<ShareableBlobDataItem*> transport_items;
 
+    BuildAbortedCallback build_aborted_callback;
+
     // Stores all blobs that we're depending on for building. This keeps the
     // blobs alive while we build our blob.
     std::vector<std::unique_ptr<BlobDataHandle>> dependent_blobs;
diff --git a/storage/browser/blob/blob_impl.cc b/storage/browser/blob/blob_impl.cc
index 46db19c7..ae0d555 100644
--- a/storage/browser/blob/blob_impl.cc
+++ b/storage/browser/blob/blob_impl.cc
@@ -39,6 +39,47 @@
  private:
   mojo::ScopedDataPipeProducerHandle handle_;
   blink::mojom::BlobReaderClientPtr client_;
+
+  DISALLOW_COPY_AND_ASSIGN(ReaderDelegate);
+};
+
+class DataPipeGetterReaderDelegate : public MojoBlobReader::Delegate {
+ public:
+  DataPipeGetterReaderDelegate(
+      mojo::ScopedDataPipeProducerHandle handle,
+      network::mojom::DataPipeGetter::ReadCallback callback)
+      : handle_(std::move(handle)), callback_(std::move(callback)) {}
+
+  mojo::ScopedDataPipeProducerHandle PassDataPipe() override {
+    return std::move(handle_);
+  }
+
+  MojoBlobReader::Delegate::RequestSideData DidCalculateSize(
+      uint64_t total_size,
+      uint64_t content_size) override {
+    // Check if null since it's conceivable OnComplete() was already called
+    // with error.
+    if (!callback_.is_null())
+      std::move(callback_).Run(net::OK, content_size);
+    return MojoBlobReader::Delegate::DONT_REQUEST_SIDE_DATA;
+  }
+
+  void OnComplete(net::Error result, uint64_t total_written_bytes) override {
+    // Check if null since DidCalculateSize() may have already been called
+    // and an error occurred later.
+    if (!callback_.is_null() && result != net::OK) {
+      // On error, signal failure immediately. On success, OnCalculatedSize()
+      // is guaranteed to be called, and the result will be signaled from
+      // there.
+      std::move(callback_).Run(result, 0);
+    }
+  }
+
+ private:
+  mojo::ScopedDataPipeProducerHandle handle_;
+  network::mojom::DataPipeGetter::ReadCallback callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(DataPipeGetterReaderDelegate);
 };
 
 }  // namespace
@@ -54,6 +95,10 @@
   bindings_.AddBinding(this, std::move(request));
 }
 
+void BlobImpl::AsDataPipeGetter(network::mojom::DataPipeGetterRequest request) {
+  data_pipe_getter_bindings_.AddBinding(this, std::move(request));
+}
+
 void BlobImpl::ReadRange(uint64_t offset,
                          uint64_t length,
                          mojo::ScopedDataPipeProducerHandle handle,
@@ -74,9 +119,21 @@
   std::move(callback).Run(handle_->uuid());
 }
 
+void BlobImpl::Clone(network::mojom::DataPipeGetterRequest request) {
+  data_pipe_getter_bindings_.AddBinding(this, std::move(request));
+}
+
+void BlobImpl::Read(mojo::ScopedDataPipeProducerHandle pipe,
+                    ReadCallback callback) {
+  MojoBlobReader::Create(handle_.get(), net::HttpByteRange(),
+                         std::make_unique<DataPipeGetterReaderDelegate>(
+                             std::move(pipe), std::move(callback)));
+}
+
 void BlobImpl::FlushForTesting() {
   bindings_.FlushForTesting();
-  if (bindings_.empty())
+  data_pipe_getter_bindings_.FlushForTesting();
+  if (bindings_.empty() && data_pipe_getter_bindings_.empty())
     delete this;
 }
 
@@ -85,8 +142,10 @@
     : handle_(std::move(handle)), weak_ptr_factory_(this) {
   DCHECK(handle_);
   bindings_.AddBinding(this, std::move(request));
-  bindings_.set_connection_error_handler(
-      base::Bind(&BlobImpl::OnConnectionError, base::Unretained(this)));
+  bindings_.set_connection_error_handler(base::BindRepeating(
+      &BlobImpl::OnConnectionError, base::Unretained(this)));
+  data_pipe_getter_bindings_.set_connection_error_handler(base::BindRepeating(
+      &BlobImpl::OnConnectionError, base::Unretained(this)));
 }
 
 BlobImpl::~BlobImpl() = default;
@@ -94,6 +153,8 @@
 void BlobImpl::OnConnectionError() {
   if (!bindings_.empty())
     return;
+  if (!data_pipe_getter_bindings_.empty())
+    return;
   delete this;
 }
 
diff --git a/storage/browser/blob/blob_impl.h b/storage/browser/blob/blob_impl.h
index c1b6fc52..1cd5aea4 100644
--- a/storage/browser/blob/blob_impl.h
+++ b/storage/browser/blob/blob_impl.h
@@ -6,6 +6,7 @@
 #define STORAGE_BROWSER_BLOB_BLOB_IMPL_H_
 
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/network/public/mojom/data_pipe_getter.mojom.h"
 #include "storage/browser/storage_browser_export.h"
 #include "third_party/WebKit/public/mojom/blob/blob.mojom.h"
 
@@ -14,12 +15,15 @@
 class BlobDataHandle;
 
 // Self destroys when no more bindings exist.
-class STORAGE_EXPORT BlobImpl : public blink::mojom::Blob {
+class STORAGE_EXPORT BlobImpl : public blink::mojom::Blob,
+                                public network::mojom::DataPipeGetter {
  public:
   static base::WeakPtr<BlobImpl> Create(std::unique_ptr<BlobDataHandle> handle,
                                         blink::mojom::BlobRequest request);
 
+  // blink::mojom::Blob:
   void Clone(blink::mojom::BlobRequest request) override;
+  void AsDataPipeGetter(network::mojom::DataPipeGetterRequest request) override;
   void ReadRange(uint64_t offset,
                  uint64_t length,
                  mojo::ScopedDataPipeProducerHandle handle,
@@ -28,6 +32,11 @@
                blink::mojom::BlobReaderClientPtr client) override;
   void GetInternalUUID(GetInternalUUIDCallback callback) override;
 
+  // network::mojom::DataPipeGetter:
+  void Clone(network::mojom::DataPipeGetterRequest request) override;
+  void Read(mojo::ScopedDataPipeProducerHandle pipe,
+            ReadCallback callback) override;
+
   void FlushForTesting();
 
  private:
@@ -39,6 +48,7 @@
   std::unique_ptr<BlobDataHandle> handle_;
 
   mojo::BindingSet<blink::mojom::Blob> bindings_;
+  mojo::BindingSet<network::mojom::DataPipeGetter> data_pipe_getter_bindings_;
 
   base::WeakPtrFactory<BlobImpl> weak_ptr_factory_;
 
diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc
index 08166b9c..f29a3df 100644
--- a/storage/browser/blob/blob_registry_impl.cc
+++ b/storage/browser/blob/blob_registry_impl.cc
@@ -89,6 +89,9 @@
                     const std::string& bad_message_reason = "") {
     DCHECK(BlobStatusIsError(reason));
     DCHECK_EQ(bad_message_reason.empty(), !BlobStatusIsBadIPC(reason));
+    // Cancelling would also try to delete |this| by removing it from
+    // blobs_under_construction_, so preemptively own |this|.
+    auto self = std::move(blob_registry_->blobs_under_construction_[uuid()]);
     // The blob might no longer have any references, in which case it may no
     // longer exist. If that happens just skip calling cancel.
     if (context() && context()->registry().HasEntry(uuid()))
@@ -526,8 +529,10 @@
       this, uuid, content_type, content_disposition, std::move(elements),
       bindings_.GetBadMessageCallback());
 
-  std::unique_ptr<BlobDataHandle> handle =
-      context_->AddFutureBlob(uuid, content_type, content_disposition);
+  std::unique_ptr<BlobDataHandle> handle = context_->AddFutureBlob(
+      uuid, content_type, content_disposition,
+      base::BindOnce(&BlobRegistryImpl::BlobBuildAborted,
+                     weak_ptr_factory_.GetWeakPtr(), uuid));
   BlobImpl::Create(std::move(handle), std::move(blob));
 
   blobs_under_construction_[uuid]->StartTransportation();
@@ -596,6 +601,10 @@
   g_url_store_creation_hook = hook;
 }
 
+void BlobRegistryImpl::BlobBuildAborted(const std::string& uuid) {
+  blobs_under_construction_.erase(uuid);
+}
+
 void BlobRegistryImpl::StreamingBlobDone(
     RegisterFromStreamCallback callback,
     BlobBuilderFromStream* builder,
diff --git a/storage/browser/blob/blob_registry_impl.h b/storage/browser/blob/blob_registry_impl.h
index e3d09281..5b8c9ad1 100644
--- a/storage/browser/blob/blob_registry_impl.h
+++ b/storage/browser/blob/blob_registry_impl.h
@@ -70,6 +70,8 @@
  private:
   class BlobUnderConstruction;
 
+  void BlobBuildAborted(const std::string& uuid);
+
   void StreamingBlobDone(RegisterFromStreamCallback callback,
                          BlobBuilderFromStream* builder,
                          std::unique_ptr<BlobDataHandle> result);
diff --git a/storage/browser/blob/blob_registry_impl_unittest.cc b/storage/browser/blob/blob_registry_impl_unittest.cc
index 108031de..3e772f55 100644
--- a/storage/browser/blob/blob_registry_impl_unittest.cc
+++ b/storage/browser/blob/blob_registry_impl_unittest.cc
@@ -47,6 +47,11 @@
                             std::move(request));
   }
 
+  void AsDataPipeGetter(
+      network::mojom::DataPipeGetterRequest request) override {
+    NOTREACHED();
+  }
+
   void ReadRange(uint64_t offset,
                  uint64_t size,
                  mojo::ScopedDataPipeProducerHandle,
@@ -917,7 +922,8 @@
   const std::string kDepId = "dep-id";
 
   // Create future blob.
-  auto blob_handle = context_->AddFutureBlob(kDepId, "", "");
+  auto blob_handle = context_->AddFutureBlob(
+      kDepId, "", "", BlobStorageContext::BuildAbortedCallback());
   blink::mojom::BlobPtrInfo referenced_blob_info;
   mojo::MakeStrongBinding(std::make_unique<MockBlob>(kDepId),
                           MakeRequest(&referenced_blob_info));
@@ -988,6 +994,42 @@
   EXPECT_EQ(0u, BlobsUnderConstruction());
 }
 
+TEST_F(BlobRegistryImplTest,
+       Register_DefereferencedWhileBuildingBeforeTransportingByFile) {
+  const std::string kId = "id";
+  const std::string kData =
+      base::RandBytesAsString(kTestBlobStorageMaxBlobMemorySize + 42);
+
+  blink::mojom::BytesProviderPtrInfo bytes_provider_info;
+  auto request = MakeRequest(&bytes_provider_info);
+
+  std::vector<blink::mojom::DataElementPtr> elements;
+  elements.push_back(
+      blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New(
+          kData.size(), base::nullopt, std::move(bytes_provider_info))));
+
+  blink::mojom::BlobPtr blob;
+  EXPECT_TRUE(registry_->Register(MakeRequest(&blob), kId, "", "",
+                                  std::move(elements)));
+  EXPECT_TRUE(bad_messages_.empty());
+
+  EXPECT_TRUE(context_->registry().HasEntry(kId));
+  EXPECT_TRUE(context_->GetBlobDataFromUUID(kId)->IsBeingBuilt());
+  EXPECT_EQ(1u, BlobsUnderConstruction());
+
+  // Now drop all references to the blob.
+  blob.reset();
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_FALSE(context_->registry().HasEntry(kId));
+
+  // Now cause construction to complete, if it would still be going on.
+  CreateBytesProvider(kData, std::move(request));
+  scoped_task_environment_.RunUntilIdle();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(0u, BlobsUnderConstruction());
+}
+
 TEST_F(BlobRegistryImplTest, RegisterFromStream) {
   const std::string kData = "hello world, this is a blob";
   const std::string kContentType = "content/type";
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc
index e16eed8..f7592ad4 100644
--- a/storage/browser/blob/blob_storage_context.cc
+++ b/storage/browser/blob/blob_storage_context.cc
@@ -157,7 +157,8 @@
 std::unique_ptr<BlobDataHandle> BlobStorageContext::AddFutureBlob(
     const std::string& uuid,
     const std::string& content_type,
-    const std::string& content_disposition) {
+    const std::string& content_disposition,
+    BuildAbortedCallback build_aborted_callback) {
   DCHECK(!registry_.HasEntry(uuid));
 
   BlobEntry* entry =
@@ -166,6 +167,8 @@
   entry->set_status(BlobStatus::PENDING_CONSTRUCTION);
   entry->set_building_state(std::make_unique<BlobEntry::BuildingState>(
       false, TransportAllowedCallback(), 0));
+  entry->building_state_->build_aborted_callback =
+      std::move(build_aborted_callback);
   return CreateHandle(uuid, entry);
 }
 
@@ -315,6 +318,8 @@
     DCHECK(previous_building_state->copies.empty());
     std::swap(building_state->build_completion_callbacks,
               previous_building_state->build_completion_callbacks);
+    building_state->build_aborted_callback =
+        std::move(previous_building_state->build_aborted_callback);
     auto runner = base::ThreadTaskRunnerHandle::Get();
     for (auto& callback : previous_building_state->build_started_callbacks)
       runner->PostTask(FROM_HERE,
@@ -652,7 +657,7 @@
 
 void BlobStorageContext::ClearAndFreeMemory(BlobEntry* entry) {
   if (entry->building_state_)
-    entry->building_state_->CancelRequests();
+    entry->building_state_->CancelRequestsAndAbort();
   entry->ClearItems();
   entry->ClearOffsets();
   entry->set_size(0);
diff --git a/storage/browser/blob/blob_storage_context.h b/storage/browser/blob/blob_storage_context.h
index c286643..e79e609 100644
--- a/storage/browser/blob/blob_storage_context.h
+++ b/storage/browser/blob/blob_storage_context.h
@@ -48,6 +48,7 @@
     : public base::trace_event::MemoryDumpProvider {
  public:
   using TransportAllowedCallback = BlobEntry::TransportAllowedCallback;
+  using BuildAbortedCallback = BlobEntry::BuildAbortedCallback;
 
   // Initializes the context without disk support.
   BlobStorageContext();
@@ -115,7 +116,8 @@
   std::unique_ptr<BlobDataHandle> AddFutureBlob(
       const std::string& uuid,
       const std::string& content_type,
-      const std::string& content_disposition);
+      const std::string& content_disposition,
+      BuildAbortedCallback build_aborted_callback);
 
   // Same as BuildBlob, but for a blob that was previously registered by calling
   // AddFutureBlob.
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 780198e..b3bc9f05 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -48150,8 +48150,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48182,8 +48182,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48212,8 +48212,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48244,8 +48244,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48274,8 +48274,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48306,8 +48306,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48336,8 +48336,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48368,8 +48368,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48398,8 +48398,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48430,8 +48430,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48460,8 +48460,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48492,8 +48492,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48522,8 +48522,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48554,8 +48554,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48584,8 +48584,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48616,8 +48616,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48646,8 +48646,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48678,8 +48678,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48708,8 +48708,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48740,8 +48740,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48770,8 +48770,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48802,8 +48802,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48832,8 +48832,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48864,8 +48864,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48894,8 +48894,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48926,8 +48926,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48956,8 +48956,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -48988,8 +48988,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49018,8 +49018,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49050,8 +49050,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49080,8 +49080,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49112,8 +49112,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49142,8 +49142,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49174,8 +49174,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49204,8 +49204,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49236,8 +49236,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49266,8 +49266,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49296,8 +49296,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49328,8 +49328,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49349,8 +49349,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49379,8 +49379,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49411,8 +49411,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49441,8 +49441,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49473,8 +49473,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49503,8 +49503,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49535,8 +49535,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49565,8 +49565,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49597,8 +49597,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49627,8 +49627,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49659,8 +49659,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49689,8 +49689,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49719,8 +49719,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49751,8 +49751,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49781,8 +49781,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49813,8 +49813,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49843,8 +49843,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49875,8 +49875,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49905,8 +49905,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49937,8 +49937,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49967,8 +49967,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -49999,8 +49999,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50029,8 +50029,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50061,8 +50061,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50091,8 +50091,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50123,8 +50123,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50153,8 +50153,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50185,8 +50185,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50215,8 +50215,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50247,8 +50247,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50277,8 +50277,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50309,8 +50309,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50339,8 +50339,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50371,8 +50371,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50401,8 +50401,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50433,8 +50433,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50463,8 +50463,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50495,8 +50495,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50525,8 +50525,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50557,8 +50557,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50587,8 +50587,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50619,8 +50619,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50649,8 +50649,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50681,8 +50681,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50711,8 +50711,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50743,8 +50743,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50773,8 +50773,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50805,8 +50805,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50835,8 +50835,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50867,8 +50867,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50897,8 +50897,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50929,8 +50929,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50959,8 +50959,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -50991,8 +50991,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51021,8 +51021,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51053,8 +51053,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51083,8 +51083,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51113,8 +51113,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51145,8 +51145,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51177,8 +51177,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51207,8 +51207,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51237,8 +51237,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51269,8 +51269,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51301,8 +51301,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51331,8 +51331,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51363,8 +51363,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build136-m1",
+              "gpu": "8086:5912",
+              "id": "build193-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51393,8 +51393,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51425,8 +51425,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51455,8 +51455,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51487,8 +51487,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51517,8 +51517,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51549,8 +51549,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51579,8 +51579,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51611,8 +51611,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51641,8 +51641,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51673,8 +51673,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51703,8 +51703,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51733,8 +51733,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51765,8 +51765,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51797,8 +51797,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51827,8 +51827,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51859,8 +51859,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build192-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51889,8 +51889,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build132-m1",
+              "gpu": "8086:5912",
+              "id": "build189-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51910,8 +51910,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build135-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51940,8 +51940,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -51972,8 +51972,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build134-m1",
+              "gpu": "8086:5912",
+              "id": "build191-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -52002,8 +52002,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
@@ -52034,8 +52034,8 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "102b:0534",
-              "id": "build133-m1",
+              "gpu": "8086:5912",
+              "id": "build190-a9",
               "os": "Windows-10",
               "pool": "Chrome-perf"
             }
diff --git a/testing/buildbot/chromium.webrtc.fyi.json b/testing/buildbot/chromium.webrtc.fyi.json
index b6506ef..9572ed7 100644
--- a/testing/buildbot/chromium.webrtc.fyi.json
+++ b/testing/buildbot/chromium.webrtc.fyi.json
@@ -3,27 +3,47 @@
   "AAAAA2 See generate_buildbot_json.py to make changes": {},
   "Android Builder": {
     "additional_compile_targets": [
-      "all"
+      "browser_tests",
+      "capture_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "jingle_unittests",
+      "remoting_unittests"
     ]
   },
   "Android Builder (dbg)": {
     "additional_compile_targets": [
-      "content_browsertests"
+      "browser_tests",
+      "capture_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "jingle_unittests",
+      "remoting_unittests"
     ]
   },
   "Android Builder ARM64 (dbg)": {
     "additional_compile_targets": [
-      "content_browsertests"
+      "browser_tests",
+      "capture_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "jingle_unittests",
+      "remoting_unittests"
     ]
   },
   "Linux Builder": {
     "additional_compile_targets": [
-      "all"
+      "browser_tests",
+      "capture_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "frame_analyzer",
+      "jingle_unittests",
+      "remoting_unittests"
     ]
   },
   "Linux Builder (dbg)": {
     "additional_compile_targets": [
-      "all",
       "browser_tests",
       "capture_unittests",
       "content_browsertests",
@@ -55,12 +75,17 @@
   },
   "Win Builder": {
     "additional_compile_targets": [
-      "all"
+      "browser_tests",
+      "capture_unittests",
+      "content_browsertests",
+      "content_unittests",
+      "frame_analyzer",
+      "jingle_unittests",
+      "remoting_unittests"
     ]
   },
   "Win Builder (dbg)": {
     "additional_compile_targets": [
-      "all",
       "browser_tests",
       "capture_unittests",
       "content_browsertests",
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index a5337ab..d4e456f 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -1940,28 +1940,47 @@
     'machines': {
       'Android Builder': {
         'additional_compile_targets': [
-          'all',
+          'browser_tests',
+          'capture_unittests',
+          'content_browsertests',
+          'content_unittests',
+          'jingle_unittests',
+          'remoting_unittests',
         ],
       },
       'Android Builder (dbg)': {
         'additional_compile_targets': [
+          'browser_tests',
+          'capture_unittests',
           'content_browsertests',
+          'content_unittests',
+          'jingle_unittests',
+          'remoting_unittests',
         ],
       },
       'Android Builder ARM64 (dbg)': {
         'additional_compile_targets': [
+          'browser_tests',
+          'capture_unittests',
           'content_browsertests',
+          'content_unittests',
+          'jingle_unittests',
+          'remoting_unittests',
         ],
       },
       'Linux Builder': {
         'additional_compile_targets': [
-          'all',
+          'browser_tests',
+          'capture_unittests',
+          'content_browsertests',
+          'content_unittests',
+          'frame_analyzer',
+          'jingle_unittests',
+          'remoting_unittests',
         ],
       },
       'Linux Builder (dbg)': {
         'additional_compile_targets': [
-          'all',
-          # TODO(dpranke): Specifying these additional targets is pointless :).
           'browser_tests',
           'capture_unittests',
           'content_browsertests',
@@ -1993,12 +2012,17 @@
       },
       'Win Builder': {
         'additional_compile_targets': [
-          'all',
+          'browser_tests',
+          'capture_unittests',
+          'content_browsertests',
+          'content_unittests',
+          'frame_analyzer',
+          'jingle_unittests',
+          'remoting_unittests',
         ],
       },
       'Win Builder (dbg)': {
         'additional_compile_targets': [
-          'all',
           'browser_tests',
           'capture_unittests',
           'content_browsertests',
diff --git a/third_party/.gitignore b/third_party/.gitignore
index 3e34f62..255183b 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -122,6 +122,7 @@
 /llvm
 /llvm-allocated-type
 /llvm-bootstrap
+/llvm-bootstrap-install
 /llvm-build
 /llvm-build-tools
 /lss
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 501461c..f64f120 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -99,7 +99,7 @@
 crbug.com/591099 animations/interpolation/backdrop-filter-interpolation.html [ Timeout ]
 crbug.com/591099 animations/interpolation/line-height-interpolation.html [ Timeout ]
 crbug.com/591099 animations/interpolation/svg-stroke-dasharray-interpolation.html [ Timeout ]
-crbug.com/591099 animations/interpolation/webkit-clip-path-interpolation.html [ Pass Timeout ]
+crbug.com/591099 animations/interpolation/webkit-clip-path-interpolation.html [ Timeout ]
 crbug.com/591099 animations/interpolation/webkit-column-width-interpolation.html [ Pass ]
 crbug.com/591099 animations/rotate-transform-equivalent.html [ Failure ]
 crbug.com/591099 animations/timing/timing-model.html [ Timeout ]
@@ -131,7 +131,7 @@
 crbug.com/591099 compositing/scrollbars/nested-overlay-scrollbars.html [ Failure ]
 crbug.com/591099 compositing/squashing/add-remove-squashed-layers.html [ Failure ]
 crbug.com/591099 compositing/squashing/selection-repaint-with-gaps.html [ Failure ]
-crbug.com/591099 compositing/squashing/squash-onto-distant-relative.html [ Crash ]
+crbug.com/591099 compositing/squashing/squash-onto-distant-relative.html [ Crash Pass ]
 crbug.com/591099 compositing/squashing/vertical-writing-mode-squashed.html [ Failure ]
 crbug.com/591099 crypto/subtle/hkdf/cloneKey.html [ Timeout ]
 crbug.com/591099 crypto/subtle/hmac/cloneKey.html [ Timeout ]
@@ -141,13 +141,14 @@
 crbug.com/591099 css1/box_properties/float_on_text_elements.html [ Failure ]
 crbug.com/591099 css1/classification/list_style.html [ Failure ]
 crbug.com/591099 css1/classification/list_style_image.html [ Failure ]
-crbug.com/591099 css1/pseudo/multiple_pseudo_elements.html [ Crash ]
+crbug.com/591099 css1/font_properties/font_variant.html [ Failure ]
+crbug.com/591099 css1/pseudo/multiple_pseudo_elements.html [ Crash Failure ]
 crbug.com/591099 css2.1/20110323/margin-applies-to-008.htm [ Failure ]
 crbug.com/714962 css2.1/20110323/overflow-applies-to-012.htm [ Failure ]
 crbug.com/591099 css2.1/20110323/table-caption-margins-001.htm [ Failure ]
 crbug.com/591099 css2.1/t0510-c25-pseudo-elmnt-00-c.html [ Failure ]
-crbug.com/591099 css2.1/t051201-c23-first-line-00-b.html [ Crash ]
-crbug.com/591099 css2.1/t051202-c26-psudo-nest-00-c.html [ Crash ]
+crbug.com/591099 css2.1/t051201-c23-first-line-00-b.html [ Crash Failure ]
+crbug.com/591099 css2.1/t051202-c26-psudo-nest-00-c.html [ Crash Failure ]
 crbug.com/591099 css2.1/t0905-c414-flt-wrap-01-d-g.html [ Failure ]
 crbug.com/591099 css2.1/t100801-c544-valgn-00-a-ag.html [ Failure ]
 crbug.com/591099 css2.1/t100801-c544-valgn-03-d-agi.html [ Failure ]
@@ -156,6 +157,7 @@
 crbug.com/591099 css2.1/t1202-counters-04-b.html [ Failure ]
 crbug.com/591099 css2.1/t1205-c564-list-img-00-b-g.html [ Failure ]
 crbug.com/591099 css2.1/t1205-c566-list-stl-01-c-g.html [ Failure ]
+crbug.com/591099 css2.1/t1505-c524-font-var-00-b.html [ Failure ]
 crbug.com/591099 css3/blending/background-blend-mode-overlapping-accelerated-elements.html [ Failure ]
 crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ]
 crbug.com/591099 css3/filters/effect-reference-subregion-nested.html [ Pass ]
@@ -320,7 +322,6 @@
 crbug.com/591099 editing/unsupported-content/table-type-after.html [ Failure ]
 crbug.com/591099 editing/unsupported-content/table-type-before.html [ Failure ]
 crbug.com/591099 external/wpt/2dcontext/drawing-images-to-the-canvas/drawimage_html_image_11.html [ Pass ]
-crbug.com/591099 external/wpt/FileAPI/url/url-with-fetch.any.html [ Failure Pass ]
 crbug.com/591099 external/wpt/WebCryptoAPI/derive_bits_keys/hkdf.https.worker.html [ Timeout ]
 crbug.com/591099 external/wpt/WebCryptoAPI/derive_bits_keys/test_hkdf.https.html [ Timeout ]
 crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures.worker.html [ Timeout ]
@@ -339,10 +340,10 @@
 crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.html [ Timeout ]
 crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.html [ Timeout ]
 crbug.com/591099 external/wpt/WebCryptoAPI/generateKey/successes.worker.html [ Timeout ]
-crbug.com/591099 external/wpt/WebCryptoAPI/import_export/rsa_importKey.https.worker.html [ Pass Timeout ]
+crbug.com/591099 external/wpt/WebCryptoAPI/import_export/rsa_importKey.https.worker.html [ Timeout ]
 crbug.com/591099 external/wpt/WebCryptoAPI/import_export/rsa_importKey.worker.html [ Timeout ]
 crbug.com/709227 external/wpt/WebCryptoAPI/import_export/symmetric_importKey.worker.html [ Failure ]
-crbug.com/714962 external/wpt/WebCryptoAPI/import_export/test_rsa_importKey.https.html [ Pass Timeout ]
+crbug.com/714962 external/wpt/WebCryptoAPI/import_export/test_rsa_importKey.https.html [ Timeout ]
 crbug.com/591099 external/wpt/acid/acid3/numbered-tests.html [ Crash ]
 crbug.com/591099 external/wpt/acid/acid3/test.html [ Crash ]
 crbug.com/591099 external/wpt/compat/webkit-text-fill-color-property-005.html [ Pass ]
@@ -357,7 +358,7 @@
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-nested-002.xht [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-percents-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-remove-006.xht [ Pass ]
-crbug.com/591099 external/wpt/css/CSS2/normal-flow/max-height-percentage-002.xht [ Failure ]
+crbug.com/591099 external/wpt/css/CSS2/normal-flow/max-height-percentage-002.xht [ Failure Pass ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/max-width-applies-to-005.xht [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/root-box-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/positioning/abspos-007.xht [ Pass ]
@@ -679,7 +680,7 @@
 crbug.com/591099 external/wpt/css/css-tables/fixup-dynamic-anonymous-table-001.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-tables/floats/floats-wrap-bfc-006c.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-children.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-tables/table-model-fixup-2.html [ Failure Pass ]
+crbug.com/591099 external/wpt/css/css-tables/table-model-fixup-2.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-color-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-above-left-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-above-left-002.xht [ Failure ]
@@ -1040,7 +1041,7 @@
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-001-table.xhtml [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-001.xhtml [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-vert-rtl-001.xhtml [ Pass ]
-crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001b.html [ Failure Pass ]
+crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001b.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-break-request-horiz-001a.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003v.html [ Pass ]
 crbug.com/714962 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-items-as-stacking-contexts-002.html [ Failure ]
@@ -1052,9 +1053,6 @@
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-014.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-015.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/selectors4/dir-style-03a.html [ Pass ]
-crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-declaration-15.html [ Failure Pass ]
-crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-01.html [ Failure Pass ]
-crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-02.html [ Failure Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-break-inside-001.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-007.html [ Failure ]
 crbug.com/591099 external/wpt/dom/interfaces.html [ Timeout ]
@@ -1199,8 +1197,7 @@
 crbug.com/591099 external/wpt/encoding/textdecoder-fatal-single-byte.html [ Timeout ]
 crbug.com/591099 external/wpt/feature-policy/payment-allowed-by-feature-policy.https.sub.html [ Pass ]
 crbug.com/591099 external/wpt/feature-policy/payment-disabled-by-feature-policy.https.sub.html [ Pass ]
-crbug.com/591099 external/wpt/fetch/api/request/request-cache-default-conditional.html [ Pass Timeout ]
-crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ]
+crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ]
 crbug.com/591099 external/wpt/html-media-capture/capture_audio_cancel-manual.html [ Failure ]
 crbug.com/591099 external/wpt/html-media-capture/capture_image_cancel-manual.html [ Failure ]
 crbug.com/591099 external/wpt/html-media-capture/capture_video_cancel-manual.html [ Failure ]
@@ -1265,7 +1262,7 @@
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html [ Timeout ]
 crbug.com/591099 external/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Timeout ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-keyboard-manual.html [ Timeout ]
-crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Pass Timeout ]
+crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Timeout ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-left-css_touch-manual.html [ Pass ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-right-css_touch-manual.html [ Failure ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html [ Timeout ]
@@ -1647,6 +1644,7 @@
 crbug.com/591099 fast/css/containment/size-and-layout-containment.html [ Failure ]
 crbug.com/591099 fast/css/content-counter-010.htm [ Failure ]
 crbug.com/591099 fast/css/css-properties-position-relative-as-parent-fixed.html [ Failure ]
+crbug.com/591099 fast/css/dumpAsText/xml-stylesheet-pi-not-in-prolog.xml [ Failure ]
 crbug.com/591099 fast/css/first-child-pseudo-class.html [ Failure ]
 crbug.com/714962 fast/css/first-letter-before-hit-test.html [ Failure ]
 crbug.com/714962 fast/css/first-letter-hit-test.html [ Failure ]
@@ -1670,7 +1668,7 @@
 crbug.com/714962 fast/css/hover-pseudo-element-quirks.html [ Failure ]
 crbug.com/591099 fast/css/hover-subselector.html [ Failure ]
 crbug.com/591099 fast/css/ignore-empty-focus-ring-rects.html [ Failure ]
-crbug.com/591099 fast/css/import_with_baseurl.html [ Failure Pass ]
+crbug.com/591099 fast/css/import_with_baseurl.html [ Failure ]
 crbug.com/591099 fast/css/large-numbers.html [ Timeout ]
 crbug.com/591099 fast/css/last-child-pseudo-class.html [ Failure ]
 crbug.com/591099 fast/css/last-of-type-pseudo-class.html [ Failure ]
@@ -1799,7 +1797,7 @@
 crbug.com/591099 fast/events/wheel/mouse-wheel-scroll-latching.html [ Pass ]
 crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ]
 crbug.com/714962 fast/events/wheel/wheelevent-basic.html [ Failure ]
-crbug.com/591099 fast/forms/calendar-picker/calendar-picker-key-operations.html [ Timeout ]
+crbug.com/591099 fast/forms/calendar-picker/calendar-picker-key-operations.html [ Pass Timeout ]
 crbug.com/714962 fast/forms/calendar-picker/calendar-picker-mouse-operations.html [ Failure ]
 crbug.com/591099 fast/forms/calendar-picker/month-picker-key-operations.html [ Timeout ]
 crbug.com/714962 fast/forms/calendar-picker/month-picker-mouse-operations.html [ Failure ]
@@ -1843,6 +1841,7 @@
 crbug.com/714962 fast/forms/textarea/textarea-resize-below-min-intrinsic-size.html [ Pass ]
 crbug.com/591099 fast/forms/textarea/textarea-resize-orthogonal-containing-block.html [ Pass ]
 crbug.com/591099 fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html [ Timeout ]
+crbug.com/591099 fast/forms/validation-bubble-appearance-rtl-ui.html [ Failure ]
 crbug.com/591099 fast/frames/iframe-with-frameborder.html [ Failure ]
 crbug.com/591099 fast/gradients/list-item-gradient.html [ Failure ]
 crbug.com/591099 fast/gradients/radial-centered.html [ Failure ]
@@ -1861,7 +1860,7 @@
 crbug.com/591099 fast/inline-block/contenteditable-baseline.html [ Failure ]
 crbug.com/714962 fast/inline-block/tricky-baseline.html [ Failure ]
 crbug.com/591099 fast/inline-block/vertical-align-top-and-bottom-2.html [ Failure ]
-crbug.com/591099 fast/inline/absolute-positioned-inline-in-centred-block.html [ Crash ]
+crbug.com/591099 fast/inline/absolute-positioned-inline-in-centred-block.html [ Crash Failure ]
 crbug.com/591099 fast/inline/bpm-inline-ancestors.html [ Failure ]
 crbug.com/714962 fast/inline/continuation-outlines-with-layers-2.html [ Failure ]
 crbug.com/591099 fast/inline/continuation-outlines-with-layers.html [ Failure ]
@@ -1936,22 +1935,23 @@
 crbug.com/591099 fast/multicol/client-rects-crossing-boundaries.html [ Failure ]
 crbug.com/591099 fast/multicol/client-rects-rtl.html [ Failure ]
 crbug.com/591099 fast/multicol/client-rects.html [ Failure ]
+crbug.com/591099 fast/multicol/column-break-with-balancing.html [ Pass ]
 crbug.com/591099 fast/multicol/column-count-with-rules.html [ Failure ]
 crbug.com/591099 fast/multicol/column-rules.html [ Failure ]
 crbug.com/591099 fast/multicol/columns-shorthand-parsing.html [ Failure ]
 crbug.com/591099 fast/multicol/composited-inner-multicol.html [ Failure ]
 crbug.com/591099 fast/multicol/composited-layer.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-opacity-2nd-and-3rd-column.html [ Crash Failure ]
-crbug.com/591099 fast/multicol/composited-relpos-clipped.html [ Crash Failure ]
-crbug.com/591099 fast/multicol/composited-relpos-in-clipped.html [ Failure Pass ]
-crbug.com/591099 fast/multicol/composited-relpos-overlapping-will-change.html [ Crash Failure ]
-crbug.com/591099 fast/multicol/composited-relpos-resize.html [ Crash Failure ]
-crbug.com/591099 fast/multicol/composited-relpos.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/composited-opacity-2nd-and-3rd-column.html [ Failure ]
+crbug.com/591099 fast/multicol/composited-relpos-clipped.html [ Failure ]
+crbug.com/591099 fast/multicol/composited-relpos-in-clipped.html [ Failure ]
+crbug.com/591099 fast/multicol/composited-relpos-overlapping-will-change.html [ Failure ]
+crbug.com/591099 fast/multicol/composited-relpos-resize.html [ Failure ]
+crbug.com/591099 fast/multicol/composited-relpos.html [ Failure ]
 crbug.com/591099 fast/multicol/composited-with-child-layer-in-next-column.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-with-overflow-in-next-column.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/composited-with-overflow-in-next-column.html [ Failure ]
 crbug.com/714962 fast/multicol/content-change-same-height.html [ Failure ]
 crbug.com/591099 fast/multicol/doubly-nested-with-top-padding-crossing-row-boundaries.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/abspos-becomes-spanner.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/dynamic/abspos-becomes-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/abspos-multicol-with-spanner-becomes-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/block-becomes-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/change-second-row-height.html [ Failure ]
@@ -1964,8 +1964,8 @@
 crbug.com/591099 fast/multicol/dynamic/insert-block-between-spanners.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/insert-block-into-content.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/insert-block-into-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-float-after-content-in-spanner.html [ Failure Pass ]
-crbug.com/591099 fast/multicol/dynamic/insert-float-before-content-in-spanner.html [ Failure Pass ]
+crbug.com/591099 fast/multicol/dynamic/insert-float-after-content-in-spanner.html [ Failure ]
+crbug.com/591099 fast/multicol/dynamic/insert-float-before-content-in-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/insert-spanner-after-content.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/insert-spanner-after-inner-multicol-crash.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/insert-spanner-after-spanner-before-content.html [ Failure ]
@@ -1981,7 +1981,6 @@
 crbug.com/591099 fast/multicol/dynamic/insert-spanner-pseudo-before-following-content.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/insert-spanner-pseudo-before.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/invalid-spanner-container-becomes-valid.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/relayout-abspos-in-relpos-spanner.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/dynamic/relpos-becomes-static-has-abspos.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/remove-abspos-next-to-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/dynamic/remove-and-insert-block-after-spanner.html [ Failure ]
@@ -2007,9 +2006,10 @@
 crbug.com/714962 fast/multicol/event-offset-complex-tree.html [ Failure ]
 crbug.com/591099 fast/multicol/event-offset-in-nested.html [ Failure ]
 crbug.com/714962 fast/multicol/event-offset.html [ Failure ]
+crbug.com/591099 fast/multicol/filter-in-second-column.html [ Pass ]
 crbug.com/591099 fast/multicol/first-line-in-float-below-next-column-top.html [ Failure ]
 crbug.com/591099 fast/multicol/first-line-in-float-with-margin.html [ Failure ]
-crbug.com/591099 fast/multicol/fixedpos-child-becomes-static.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/fixedpos-child-becomes-static.html [ Failure ]
 crbug.com/591099 fast/multicol/flexbox-starts-at-column-boundary-with-block.html [ Failure ]
 crbug.com/591099 fast/multicol/flexbox-starts-at-column-boundary.html [ Failure ]
 crbug.com/591099 fast/multicol/flexbox-with-overflow-auto-child-crash.html [ Crash ]
@@ -2033,20 +2033,19 @@
 crbug.com/591099 fast/multicol/float-with-margin-moved-by-child-line-and-unbreakable.html [ Failure ]
 crbug.com/591099 fast/multicol/float-with-margin-moved-by-child-line.html [ Failure ]
 crbug.com/591099 fast/multicol/float-with-margin-moved-unbreakable.html [ Failure ]
-crbug.com/591099 fast/multicol/flowthread-with-floats-destroyed-crash.html [ Crash Pass ]
 crbug.com/591099 fast/multicol/forced-break-after-block-with-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/forced-break-after-empty-block-after-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/forced-break-after-last-block-before-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/forced-break-in-nested-columns.html [ Failure ]
 crbug.com/591099 fast/multicol/forced-break-too-short-column.html [ Failure ]
+crbug.com/591099 fast/multicol/foreignObject.html [ Pass ]
 crbug.com/591099 fast/multicol/hit-test-above-or-below.html [ Failure ]
 crbug.com/591099 fast/multicol/hit-test-end-of-column-with-line-height.html [ Failure ]
 crbug.com/591099 fast/multicol/hit-test-end-of-column.html [ Failure ]
 crbug.com/591099 fast/multicol/hit-test-gap-between-pages-flipped.html [ Failure ]
-crbug.com/812457 fast/multicol/huge-column-count.html [ Timeout Failure ]
+crbug.com/812457 fast/multicol/huge-column-count.html [ Failure ]
 crbug.com/714962 fast/multicol/huge-column-gap-crash.html [ Failure ]
 crbug.com/591099 fast/multicol/image-inside-nested-blocks-with-border.html [ Failure ]
-crbug.com/591099 fast/multicol/infinitely-tall-content-in-outer-crash.html [ Pass Timeout ]
 crbug.com/591099 fast/multicol/inline-block-baseline.html [ Failure ]
 crbug.com/591099 fast/multicol/inline-getclientrects.html [ Failure ]
 crbug.com/591099 fast/multicol/inner-multicol-in-second-column.html [ Failure ]
@@ -2061,8 +2060,9 @@
 crbug.com/591099 fast/multicol/many-lines-overflow-in-single-row-inner.html [ Failure ]
 crbug.com/591099 fast/multicol/mixed-opacity-fixed-test.html [ Pass ]
 crbug.com/591099 fast/multicol/mixed-opacity-test.html [ Failure ]
-crbug.com/591099 fast/multicol/mixed-positioning-stacking-order.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/mixed-positioning-stacking-order.html [ Failure ]
 crbug.com/714962 fast/multicol/multicol-becomes-abspos-crash.html [ Failure ]
+crbug.com/591099 fast/multicol/multicol-becomes-paged-fixed-height.html [ Pass ]
 crbug.com/591099 fast/multicol/multicol-svg.html [ Failure ]
 crbug.com/591099 fast/multicol/multicol-with-child-renderLayer-for-input.html [ Failure ]
 crbug.com/591099 fast/multicol/nested-3-multicols-fixed-height.html [ Failure ]
@@ -2100,36 +2100,43 @@
 crbug.com/714962 fast/multicol/newmulticol/balance5.html [ Failure ]
 crbug.com/591099 fast/multicol/newmulticol/break-before.html [ Failure ]
 crbug.com/591099 fast/multicol/newmulticol/breaks-2-columns-3-no-balancing.html [ Failure ]
+crbug.com/591099 fast/multicol/newmulticol/breaks-2-columns-3.html [ Pass ]
 crbug.com/591099 fast/multicol/newmulticol/breaks-3-columns-3.html [ Failure ]
 crbug.com/591099 fast/multicol/newmulticol/fixed-height-fill-balance-2.html [ Failure ]
 crbug.com/591099 fast/multicol/newmulticol/hide-box-vertical-lr.html [ Failure ]
 crbug.com/591099 fast/multicol/newmulticol/hide-box-vertical-rl.html [ Failure ]
 crbug.com/591099 fast/multicol/newmulticol/list-item.html [ Failure ]
 crbug.com/591099 fast/multicol/newmulticol/orphans-and-widows-balance.html [ Failure ]
+crbug.com/591099 fast/multicol/newmulticol/regular-block-becomes-multicol.html [ Pass ]
 crbug.com/591099 fast/multicol/newmulticol/table-cell.html [ Failure ]
+crbug.com/591099 fast/multicol/newmulticol/unresolvable-percent-max-height-2.html [ Pass ]
 crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-left-right.html [ Pass ]
-crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-on-line-at-boundary.html [ Crash Failure ]
-crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-on-line-rtl.html [ Crash Failure ]
-crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-on-line.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-on-line-at-boundary.html [ Failure ]
+crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-on-line-rtl.html [ Failure ]
+crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-on-line.html [ Failure ]
 crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-small-on-line-at-boundary.html [ Failure ]
-crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position.html [ Failure ]
 crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-top-bottom.html [ Pass ]
-crbug.com/591099 fast/multicol/out-of-flow/nested-multicol.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/out-of-flow/nested-multicol.html [ Failure ]
 crbug.com/591099 fast/multicol/out-of-flow/offset-properties.html [ Pass ]
 crbug.com/591099 fast/multicol/outlines-at-column-boundaries.html [ Failure ]
 crbug.com/591099 fast/multicol/overflow-across-columns.html [ Failure ]
 crbug.com/591099 fast/multicol/overflow-content.html [ Failure ]
 crbug.com/591099 fast/multicol/overflow-unsplittable.html [ Failure ]
 crbug.com/591099 fast/multicol/pageLogicalOffset-vertical.html [ Failure ]
+crbug.com/591099 fast/multicol/paged-becomes-multicol-auto-height.html [ Pass ]
+crbug.com/591099 fast/multicol/paged-becomes-multicol-fixed-height.html [ Pass ]
 crbug.com/591099 fast/multicol/paginate-block-replaced.html [ Failure ]
 crbug.com/591099 fast/multicol/positioned-outside-of-columns.html [ Failure ]
 crbug.com/591099 fast/multicol/positioned-split.html [ Failure ]
 crbug.com/591099 fast/multicol/positioned-with-constrained-height.html [ Failure ]
 crbug.com/591099 fast/multicol/pushed-line-affected-by-float.html [ Failure ]
+crbug.com/591099 fast/multicol/regular-block-becomes-multicol.html [ Pass ]
 crbug.com/591099 fast/multicol/relayout-and-push-float.html [ Failure ]
 crbug.com/591099 fast/multicol/renderer-positioned-assert-crash.html [ Failure ]
 crbug.com/591099 fast/multicol/rule-in-nested-with-too-tall-line.html [ Failure ]
 crbug.com/714962 fast/multicol/scale-transform-text.html [ Failure ]
+crbug.com/591099 fast/multicol/scrollable-basic.html [ Pass ]
 crbug.com/591099 fast/multicol/scrolling-overflow.html [ Failure ]
 crbug.com/591099 fast/multicol/shadow-breaking.html [ Failure ]
 crbug.com/591099 fast/multicol/single-line.html [ Failure ]
@@ -2171,7 +2178,7 @@
 crbug.com/591099 fast/multicol/span/outer-column-break-after-inner-spanner-and-float.html [ Failure ]
 crbug.com/591099 fast/multicol/span/outer-column-break-after-inner-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/span/outline.html [ Failure ]
-crbug.com/591099 fast/multicol/span/overflow-on-multicol.html [ Failure Pass ]
+crbug.com/591099 fast/multicol/span/overflow-on-multicol.html [ Failure ]
 crbug.com/591099 fast/multicol/span/overflow-on-viewport.html [ Failure ]
 crbug.com/591099 fast/multicol/span/percent-margins.html [ Failure ]
 crbug.com/591099 fast/multicol/span/preferred-widths-with-column-content.html [ Failure ]
@@ -2190,13 +2197,12 @@
 crbug.com/591099 fast/multicol/span/span-between-text.html [ Failure ]
 crbug.com/591099 fast/multicol/span/spanner-first.html [ Failure ]
 crbug.com/591099 fast/multicol/span/spanner-img.html [ Failure ]
-crbug.com/591099 fast/multicol/span/spanner-inline-block.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/span/spanner-last.html [ Failure ]
 crbug.com/591099 fast/multicol/span/spanner-table.html [ Failure ]
 crbug.com/591099 fast/multicol/span/spanner-with-margin.html [ Failure ]
 crbug.com/591099 fast/multicol/span/spanner-with-margins-between-margins.html [ Failure ]
 crbug.com/591099 fast/multicol/span/spanner-with-relpos-child.html [ Failure ]
-crbug.com/591099 fast/multicol/span/summary-split.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/span/summary-split.html [ Failure ]
 crbug.com/591099 fast/multicol/span/trailing-margin-before-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/span/two-rows-then-spanner-then-two-rows.html [ Failure ]
 crbug.com/591099 fast/multicol/span/underflow-after-spanner.html [ Failure ]
@@ -2213,22 +2219,20 @@
 crbug.com/591099 fast/multicol/table-margin-collapse.html [ Failure ]
 crbug.com/591099 fast/multicol/tall-content-in-inner-with-fixed-height.html [ Failure ]
 crbug.com/591099 fast/multicol/tall-float2.html [ Failure ]
-crbug.com/591099 fast/multicol/text-shadow-at-column-boundaries.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/three-inner-rows.html [ Failure ]
-crbug.com/591099 fast/multicol/transform-inside-opacity.html [ Failure Pass ]
 crbug.com/714962 fast/multicol/unbreakable-content-taller-than-height-crash.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/abspos-auto-position-on-line.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/vertical-lr/abspos-auto-position-on-line.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/break-properties.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/caret-range-anonymous-block-rtl.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/caret-range-anonymous-block.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/caret-range-outside-columns-rtl.html [ Failure Timeout ]
+crbug.com/591099 fast/multicol/vertical-lr/caret-range-outside-columns-rtl.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/caret-range-outside-columns.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/client-rect-after-spanner.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/client-rects-crossing-boundaries-nested.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/column-break-with-balancing.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/column-count-with-rules.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/column-rules.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/composited-relpos-overlapping-will-change.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/vertical-lr/composited-relpos-overlapping-will-change.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/float-avoidance.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/float-big-line.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/float-break.html [ Failure ]
@@ -2242,7 +2246,7 @@
 crbug.com/591099 fast/multicol/vertical-lr/offset-top-and-left-at-boundaries.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/offset-top-and-left-nested.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/unsplittable-inline-block.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/abspos-auto-position-on-line.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/vertical-rl/abspos-auto-position-on-line.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-rl/break-properties.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-rl/caret-range-anonymous-block-rtl.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-rl/caret-range-anonymous-block.html [ Failure ]
@@ -2253,7 +2257,7 @@
 crbug.com/591099 fast/multicol/vertical-rl/column-break-with-balancing.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-rl/column-count-with-rules.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-rl/column-rules.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/composited-relpos-overlapping-will-change.html [ Crash Failure ]
+crbug.com/591099 fast/multicol/vertical-rl/composited-relpos-overlapping-will-change.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-rl/float-avoidance.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-rl/float-big-line.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-rl/float-break.html [ Failure ]
@@ -2265,7 +2269,6 @@
 crbug.com/591099 fast/multicol/vertical-rl/offset-top-and-left-at-boundaries-nested.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-rl/offset-top-and-left-at-boundaries.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-rl/offset-top-and-left-nested.html [ Failure ]
-crbug.com/714962 fast/multicol/vertical-rl/rule-style.html [ Failure Pass ]
 crbug.com/591099 fast/multicol/vertical-rl/unsplittable-inline-block.html [ Failure ]
 crbug.com/591099 fast/multicol/widows-and-orphans.html [ Failure ]
 crbug.com/591099 fast/multicol/widows.html [ Failure ]
@@ -2523,8 +2526,8 @@
 crbug.com/591099 fast/table/percent-height-content-in-fixed-height-border-box-sized-cell-with-collapsed-border-on-table.html [ Failure ]
 crbug.com/591099 fast/table/percent-height-content-in-fixed-height-border-box-sized-cell-with-collapsed-border.html [ Failure ]
 crbug.com/591099 fast/table/percent-height-content-in-fixed-height-content-box-sized-cell.html [ Failure ]
-crbug.com/591099 fast/table/percent-height-overflow-auto-content-in-cell.html [ Failure Pass ]
-crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure Pass ]
+crbug.com/591099 fast/table/percent-height-overflow-auto-content-in-cell.html [ Failure ]
+crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure ]
 crbug.com/591099 fast/table/percent-widths-stretch-vertical.html [ Failure ]
 crbug.com/714962 fast/table/split-table-section-before-anonymous-block-2.html [ Failure ]
 crbug.com/714962 fast/table/split-table-section-before-anonymous-block-3.html [ Failure ]
@@ -2812,8 +2815,8 @@
 crbug.com/591099 fullscreen/full-screen-css.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-element-stack.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-iframe-not-allowed.html [ Failure ]
-crbug.com/591099 fullscreen/full-screen-remove-ancestor-after.html [ Crash ]
-crbug.com/591099 fullscreen/full-screen-ruleset-crash.html [ Crash Pass ]
+crbug.com/591099 fullscreen/full-screen-remove-ancestor-after.html [ Crash Pass ]
+crbug.com/591099 fullscreen/full-screen-ruleset-crash.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-twice-newapi.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-with-css-reference-filter.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-with-flex-item.html [ Crash ]
@@ -2838,7 +2841,6 @@
 crbug.com/591099 html/marquee/marquee-scroll.html [ Failure ]
 crbug.com/591099 html/marquee/marquee-scrollamount.html [ Failure ]
 crbug.com/591099 http/tests/css/css-image-valued-shape.html [ Failure ]
-crbug.com/591099 http/tests/css/missing-repaint-after-slow-style-sheet.pl [ Failure Pass ]
 crbug.com/591099 http/tests/css/shape-image-file.html [ Failure ]
 crbug.com/591099 http/tests/csspaint/invalidation-background-image.html [ Timeout ]
 crbug.com/591099 http/tests/csspaint/invalidation-border-image.html [ Timeout ]
@@ -3012,7 +3014,7 @@
 crbug.com/591099 paint/invalidation/clip/outline-clip-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/clip/repaint-tile-clipped.html [ Crash ]
 crbug.com/591099 paint/invalidation/clip/replaced-clipped-positioned-not-wrong-incremental-repainting.html [ Failure ]
-crbug.com/591099 paint/invalidation/compositing/column-span-under-composited-column-child.html [ Crash ]
+crbug.com/591099 paint/invalidation/compositing/column-span-under-composited-column-child.html [ Crash Pass ]
 crbug.com/714962 paint/invalidation/compositing/composited-inline-change-text-data-keep-geometry.html [ Crash ]
 crbug.com/591099 paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll.html [ Failure ]
 crbug.com/591099 paint/invalidation/compositing/iframe-clip-removed.html [ Failure ]
@@ -3352,7 +3354,9 @@
 crbug.com/591099 payments/payment-request-in-iframe-nested-not-allowed.html [ Failure ]
 crbug.com/591099 payments/payment-request-in-iframe.html [ Failure ]
 crbug.com/591099 plugins/mouse-click-plugin-clears-selection.html [ Failure ]
+crbug.com/591099 plugins/plugin-scroll.html [ Failure ]
 crbug.com/591099 plugins/webview-plugin-nested-iframe-scroll.html [ Failure ]
+crbug.com/591099 plugins/webview-plugin-scroll.html [ Failure ]
 crbug.com/591099 printing/absolute-position-headers-and-footers.html [ Failure ]
 crbug.com/591099 printing/absolute-positioned.html [ Failure ]
 crbug.com/591099 printing/allowed-page-breaks.html [ Failure ]
@@ -3436,17 +3440,19 @@
 crbug.com/591099 svg/custom/transformed-text-pattern.html [ Failure ]
 crbug.com/591099 svg/custom/use-event-retargeting.html [ Failure ]
 crbug.com/591099 svg/custom/use-font-face-crash.svg [ Failure ]
-crbug.com/591099 svg/dom/svgangle-units.html [ Timeout ]
+crbug.com/591099 svg/dom/svgangle-units.html [ Pass Timeout ]
 crbug.com/591099 svg/filters/feTurbulence-bad-seeds.html [ Failure ]
 crbug.com/591099 svg/foreign-object-under-shadow-root-under-hidden.html [ Failure ]
 crbug.com/591099 svg/hixie/error/012.xml [ Failure ]
 crbug.com/591099 svg/hixie/error/013.xml [ Failure ]
+crbug.com/591099 svg/hixie/error/dumpAsText/004.xml [ Failure ]
+crbug.com/591099 svg/hixie/error/dumpAsText/005.xml [ Failure ]
 crbug.com/591099 svg/in-html/sizing/svg-inline.html [ Timeout ]
 crbug.com/714962 svg/overflow/overflow-on-outermost-svg-element-horizontal-auto.svg [ Failure ]
 crbug.com/591099 svg/overflow/overflow-on-outermost-svg-element-in-xhtml-defaults.xhtml [ Failure ]
 crbug.com/591099 svg/parser/whitespace-length-invalid-1.html [ Pass Timeout ]
 crbug.com/591099 svg/parser/whitespace-length-invalid-2.html [ Pass Timeout ]
-crbug.com/591099 svg/parser/whitespace-length-invalid-3.html [ Timeout ]
+crbug.com/591099 svg/parser/whitespace-length-invalid-3.html [ Pass Timeout ]
 crbug.com/591099 svg/parser/whitespace-length-invalid-4.html [ Pass Timeout ]
 crbug.com/591099 svg/parser/whitespace-number.html [ Timeout ]
 crbug.com/714962 svg/text/columns-do-not-apply.html [ Failure ]
@@ -3618,7 +3624,7 @@
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/event-on-culled_inline.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/keyboardevent-getModifierState.html [ Timeout ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/menu-key-context-menu-document-pinch-zoom.html [ Failure ]
-crbug.com/714962 virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-latching.html [ Timeout ]
+crbug.com/714962 virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-latching.html [ Pass Timeout ]
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/mouse-down-on-pseudo-element-remove-crash.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/mouse-event-buttons-attribute.html [ Timeout ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/mouse-relative-position.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
index 9372748a..8156ec3d 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -90,7 +90,6 @@
 Bug(none) http/tests/websocket/cookie-document-to-ws.html [ Failure ]
 Bug(none) http/tests/websocket/cookie-http-to-ws.pl [ Failure ]
 Bug(none) http/tests/websocket/httponly-cookie.pl [ Failure ]
-Bug(none) http/tests/xmlhttprequest/xmlhttprequest-data-url.html [ Failure ]
 Bug(none) http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-xhr.js [ Timeout ]
 Bug(none) plugins/iframe-plugin-bgcolor.html [ Timeout ]
 
@@ -112,12 +111,6 @@
 # Started flaking after test was rewritten in r517585.
 Bug(none) http/tests/devtools/service-workers/service-worker-agents.js [ Crash Pass ]
 
-crbug.com/777879 external/wpt/FileAPI/file/send-file-form-iso-2022-jp.tentative.html [ Crash ]
-crbug.com/777879 external/wpt/FileAPI/file/send-file-form-utf-8.html [ Crash ]
-crbug.com/777879 external/wpt/FileAPI/file/send-file-form-windows-1252.tentative.html [ Crash ]
-crbug.com/777879 external/wpt/FileAPI/file/send-file-form-x-user-defined.tentative.html [ Crash ]
-crbug.com/777879 external/wpt/FileAPI/file/send-file-form.html [ Crash ]
-
 # Started flaking after https://chromium-review.googlesource.com/864265.
 # Text-diff: total-byte-weight: {{true => false}}
 Bug(none) http/tests/devtools/audits2/audits2-limited-run.js [ Failure ]
@@ -134,5 +127,3 @@
 crbug.com/803958 external/wpt/websockets/cookies/007.html?wss [ Failure ]
 
 crbug.com/816556 external/wpt/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html [ Failure ]
-
-crbug.com/821878 external/wpt/html/semantics/forms/form-submission-0/submit-file.sub.html [ Crash ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
index d1048f1..503f29f2 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
@@ -132,6 +132,10 @@
 Bug(none) virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html [ Skip ]
 Bug(none) virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html [ Skip ]
 
+# Layout tests don't work for printing cross-site frames.
+crbug.com/822372 http/tests/printing/cross-site-frame.html [ Crash ]
+crbug.com/822372 http/tests/printing/cross-site-frame-scrolled.html [ Crash ]
+
 # TODO(lukasza, alexmos): Triage these failures.
 Bug(none) external/wpt/html/browsers/browsing-the-web/navigating-across-documents/004.html [ Timeout ]
 
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index fb4373d..70023d8 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -617,7 +617,6 @@
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/upload-onprogress-event.html [ Crash ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/upload-progress-events.html [ Crash Timeout Pass ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/workers/upload-onprogress-event.html [ Pass Crash ]
-crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/xmlhttprequest-data-url.html [ Crash ]
 
 # Timeout tests in dictionary order.
 crbug.com/736308 virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-preflight-status.any.html [ Pass Timeout ]
@@ -702,7 +701,6 @@
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/simple-cross-origin-denied-events-post-sync.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/simple-cross-origin-denied-events-sync.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/workers/xmlhttprequest-allowed-with-disabled-web-security.html [ Failure ]
-crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/xhr-to-blob-in-isolated-world.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/xmlhttprequest-allowed-with-disabled-web-security.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/xmlhttprequest-sync-no-progress-events.html [ Failure ]
 # ====== Out of Blink CORS related tests END ======
@@ -1540,6 +1538,8 @@
 # were matched on pass/fail but not exact error messages.
 crbug.com/626703 external/wpt/resource-timing/resource_TAO_space.htm [ Pass Failure ]
 
+crbug.com/822757 external/wpt/resource-timing/resource_initiator_types.html [ Pass Failure ]
+
 # Working on getting the CSP tests going:
 crbug.com/694525 external/wpt/content-security-policy/object-src [ Skip ]
 crbug.com/694525 external/wpt/content-security-policy/connect-src/connect-src-eventsource-blocked.sub.html [ Skip ]
@@ -1696,6 +1696,8 @@
 crbug.com/805463 external/wpt/acid/acid3/numbered-tests.html [ Skip ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 virtual/incremental-shadow-dom/external/wpt/css/css-scoping/shadow-fallback-dynamic-001.html [ Failure ]
+crbug.com/626703 [ Android ] virtual/media-gpu-accelerated/external/wpt/media-source/mediasource-config-change-mp4-av-framesize.html [ Crash ]
 crbug.com/626703 external/wpt/payment-request/payment-request-show-method-manual.https.html [ Skip ]
 crbug.com/626703 external/wpt/payment-request/payment-request-abort-method-manual.https.html [ Skip ]
 crbug.com/626703 external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index 8c77331..c2f941c 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -305,9 +305,7 @@
 external/wpt/svg/linking/scripted [ Skip ]
 
 # Manual tests that fail as TIMEOUT or NOTRUN. Consider adding wpt_automation.
-external/wpt/FileAPI/BlobURL/test1-manual.html [ Skip ]
 external/wpt/FileAPI/BlobURL/test2-manual.html [ Skip ]
-external/wpt/FileAPI/BlobURL/test3-manual.html [ Skip ]
 external/wpt/FileAPI/FileReader/test_errors-manual.html [ Skip ]
 external/wpt/FileAPI/filelist-section/filelist_multiple_selected_files-manual.html [ Skip ]
 external/wpt/FileAPI/filelist-section/filelist_selected_file-manual.html [ Skip ]
@@ -389,7 +387,6 @@
 external/wpt/pointerevents/pointerevent_releasepointercapture_release_right_after_capture-manual.html [ Skip ]
 external/wpt/pointerevents/pointerevent_setpointercapture_override_pending_capture_element-manual.html [ Skip ]
 external/wpt/pointerevents/pointerevent_setpointercapture_to_same_element_twice-manual.html [ Skip ]
-external/wpt/quirks-mode/active-and-hover-manual.html [ Skip ]
 external/wpt/touch-events/multi-touch-interactions-manual.html [ Skip ]
 external/wpt/touch-events/multi-touch-interfaces-manual.html [ Skip ]
 external/wpt/touch-events/single-touch-manual.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 90a12ae..f8d6465 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -47785,6 +47785,66 @@
      {}
     ]
    ],
+   "css/css-scoping/shadow-fallback-dynamic-001.html": [
+    [
+     "/css/css-scoping/shadow-fallback-dynamic-001.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-scoping/shadow-fallback-dynamic-002.html": [
+    [
+     "/css/css-scoping/shadow-fallback-dynamic-002.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-scoping/shadow-fallback-dynamic-003.html": [
+    [
+     "/css/css-scoping/shadow-fallback-dynamic-003.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-scoping/shadow-fallback-dynamic-004.html": [
+    [
+     "/css/css-scoping/shadow-fallback-dynamic-004.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-scoping/shadow-fallback-dynamic-005.html": [
+    [
+     "/css/css-scoping/shadow-fallback-dynamic-005.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-scoping/slotted-with-pseudo-element.html": [
     [
      "/css/css-scoping/slotted-with-pseudo-element.html",
@@ -116400,6 +116460,11 @@
      {}
     ]
    ],
+   "css/css-grid/abspos/support/grid.css": [
+    [
+     {}
+    ]
+   ],
    "css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-009-expected.txt": [
     [
      {}
@@ -116440,6 +116505,11 @@
      {}
     ]
    ],
+   "css/css-grid/grid-definition/support/grid.css": [
+    [
+     {}
+    ]
+   ],
    "css/css-grid/grid-definition/support/testing-utils.js": [
     [
      {}
@@ -116485,6 +116555,16 @@
      {}
     ]
    ],
+   "css/css-grid/grid-items/support/grid.css": [
+    [
+     {}
+    ]
+   ],
+   "css/css-grid/grid-model/support/grid.css": [
+    [
+     {}
+    ]
+   ],
    "css/css-grid/reference/display-grid-ref.html": [
     [
      {}
@@ -116575,11 +116655,6 @@
      {}
     ]
    ],
-   "css/css-grid/support/grid.css": [
-    [
-     {}
-    ]
-   ],
    "css/css-grid/test-plan/index.html": [
     [
      {}
@@ -128930,11 +129005,6 @@
      {}
     ]
    ],
-   "css/cssom/stylesheet-same-origin.sub-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "css/cssom/support/1x1-green.png": [
     [
      {}
@@ -152440,6 +152510,11 @@
      {}
     ]
    ],
+   "presentation-api/controlling-ua/PresentationRequest_error.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "presentation-api/controlling-ua/common.js": [
     [
      {}
@@ -155270,11 +155345,21 @@
      {}
     ]
    ],
+   "resource-timing/resources/empty.py": [
+    [
+     {}
+    ]
+   ],
    "resource-timing/resources/empty_script.js": [
     [
      {}
     ]
    ],
+   "resource-timing/resources/eventsource.py": [
+    [
+     {}
+    ]
+   ],
    "resource-timing/resources/fake_responses.html": [
     [
      {}
@@ -158390,31 +158475,11 @@
      {}
     ]
    ],
-   "streams/piping/error-propagation-backward-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/piping/error-propagation-backward.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/piping/error-propagation-backward.js": [
     [
      {}
     ]
    ],
-   "streams/piping/error-propagation-backward.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/piping/error-propagation-backward.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/piping/error-propagation-forward-expected.txt": [
     [
      {}
@@ -158450,31 +158515,11 @@
      {}
     ]
    ],
-   "streams/piping/multiple-propagation-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/piping/multiple-propagation.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/piping/multiple-propagation.js": [
     [
      {}
     ]
    ],
-   "streams/piping/multiple-propagation.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/piping/multiple-propagation.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/piping/pipe-through.js": [
     [
      {}
@@ -158690,6 +158735,11 @@
      {}
     ]
    ],
+   "streams/readable-streams/general-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "streams/readable-streams/general.dedicatedworker-expected.txt": [
     [
      {}
@@ -158860,61 +158910,21 @@
      {}
     ]
    ],
-   "streams/writable-streams/aborting-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/aborting.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/writable-streams/aborting.js": [
     [
      {}
     ]
    ],
-   "streams/writable-streams/aborting.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/aborting.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/writable-streams/bad-strategies.js": [
     [
      {}
     ]
    ],
-   "streams/writable-streams/bad-underlying-sinks-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/bad-underlying-sinks.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/writable-streams/bad-underlying-sinks.js": [
     [
      {}
     ]
    ],
-   "streams/writable-streams/bad-underlying-sinks.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/bad-underlying-sinks.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/writable-streams/brand-checks.js": [
     [
      {}
@@ -158925,31 +158935,11 @@
      {}
     ]
    ],
-   "streams/writable-streams/close-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/close.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/writable-streams/close.js": [
     [
      {}
     ]
    ],
-   "streams/writable-streams/close.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/close.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/writable-streams/constructor.js": [
     [
      {}
@@ -158970,81 +158960,21 @@
      {}
     ]
    ],
-   "streams/writable-streams/general-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/general.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/writable-streams/general.js": [
     [
      {}
     ]
    ],
-   "streams/writable-streams/general.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/general.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/properties-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/properties.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/writable-streams/properties.js": [
     [
      {}
     ]
    ],
-   "streams/writable-streams/properties.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/properties.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/reentrant-strategy-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/reentrant-strategy.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/writable-streams/reentrant-strategy.js": [
     [
      {}
     ]
    ],
-   "streams/writable-streams/reentrant-strategy.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/writable-streams/reentrant-strategy.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/writable-streams/start.js": [
     [
      {}
@@ -160275,6 +160205,16 @@
      {}
     ]
    ],
+   "web-animations/interfaces/Animatable/getAnimations-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "web-animations/interfaces/Animation/cancel-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "web-animations/interfaces/Animation/constructor-expected.txt": [
     [
      {}
@@ -160300,6 +160240,16 @@
      {}
     ]
    ],
+   "web-animations/interfaces/AnimationEffect/getComputedTiming-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "web-animations/interfaces/AnimationEffect/updateTiming-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "web-animations/interfaces/AnimationEffectTiming/getComputedTiming-expected.txt": [
     [
      {}
@@ -160320,6 +160270,11 @@
      {}
     ]
    ],
+   "web-animations/interfaces/KeyframeEffect/copy-constructor-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "web-animations/interfaces/KeyframeEffect/idlharness-expected.txt": [
     [
      {}
@@ -160365,6 +160320,16 @@
      {}
     ]
    ],
+   "web-animations/resources/timing-tests.js": [
+    [
+     {}
+    ]
+   ],
+   "web-animations/resources/timing-utils.js": [
+    [
+     {}
+    ]
+   ],
    "web-animations/resources/xhr-doc.py": [
     [
      {}
@@ -160690,6 +160655,11 @@
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-audioworklet-interface/processors/input-length-processor.js": [
+    [
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-audioworklet-interface/processors/one-pole-processor.js": [
     [
      {}
@@ -188183,6 +188153,12 @@
      {}
     ]
    ],
+   "domxpath/document.tentative.html": [
+    [
+     "/domxpath/document.tentative.html",
+     {}
+    ]
+   ],
    "domxpath/evaluator-constructor.html": [
     [
      "/domxpath/evaluator-constructor.html",
@@ -190105,6 +190081,12 @@
      {}
     ]
    ],
+   "eventsource/dedicated-worker/eventsource-close2.htm": [
+    [
+     "/eventsource/dedicated-worker/eventsource-close2.htm",
+     {}
+    ]
+   ],
    "eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm": [
     [
      "/eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm",
@@ -202093,6 +202075,12 @@
      {}
     ]
    ],
+   "html/syntax/parsing/html-integration-point.html": [
+    [
+     "/html/syntax/parsing/html-integration-point.html",
+     {}
+    ]
+   ],
    "html/syntax/parsing/html5lib_adoption01.html": [
     [
      "/html/syntax/parsing/html5lib_adoption01.html?run_type=uri",
@@ -224813,12 +224801,6 @@
      {}
     ]
    ],
-   "resource-timing/resource_frame_initiator_type.html": [
-    [
-     "/resource-timing/resource_frame_initiator_type.html",
-     {}
-    ]
-   ],
    "resource-timing/resource_ignore_data_url.html": [
     [
      "/resource-timing/resource_ignore_data_url.html",
@@ -227153,12 +227135,6 @@
      {}
     ]
    ],
-   "staticrange/idlharness.html": [
-    [
-     "/staticrange/idlharness.html",
-     {}
-    ]
-   ],
    "storage/estimate-indexeddb-worker.https.html": [
     [
      "/storage/estimate-indexeddb-worker.https.html",
@@ -229763,63 +229739,15 @@
      {}
     ]
    ],
-   "web-animations/interfaces/AnimationEffectTiming/delay.html": [
+   "web-animations/interfaces/AnimationEffect/getComputedTiming.html": [
     [
-     "/web-animations/interfaces/AnimationEffectTiming/delay.html",
+     "/web-animations/interfaces/AnimationEffect/getComputedTiming.html",
      {}
     ]
    ],
-   "web-animations/interfaces/AnimationEffectTiming/direction.html": [
+   "web-animations/interfaces/AnimationEffect/updateTiming.html": [
     [
-     "/web-animations/interfaces/AnimationEffectTiming/direction.html",
-     {}
-    ]
-   ],
-   "web-animations/interfaces/AnimationEffectTiming/duration.html": [
-    [
-     "/web-animations/interfaces/AnimationEffectTiming/duration.html",
-     {}
-    ]
-   ],
-   "web-animations/interfaces/AnimationEffectTiming/easing.html": [
-    [
-     "/web-animations/interfaces/AnimationEffectTiming/easing.html",
-     {}
-    ]
-   ],
-   "web-animations/interfaces/AnimationEffectTiming/endDelay.html": [
-    [
-     "/web-animations/interfaces/AnimationEffectTiming/endDelay.html",
-     {}
-    ]
-   ],
-   "web-animations/interfaces/AnimationEffectTiming/fill.html": [
-    [
-     "/web-animations/interfaces/AnimationEffectTiming/fill.html",
-     {}
-    ]
-   ],
-   "web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html": [
-    [
-     "/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html",
-     {}
-    ]
-   ],
-   "web-animations/interfaces/AnimationEffectTiming/idlharness.html": [
-    [
-     "/web-animations/interfaces/AnimationEffectTiming/idlharness.html",
-     {}
-    ]
-   ],
-   "web-animations/interfaces/AnimationEffectTiming/iterationStart.html": [
-    [
-     "/web-animations/interfaces/AnimationEffectTiming/iterationStart.html",
-     {}
-    ]
-   ],
-   "web-animations/interfaces/AnimationEffectTiming/iterations.html": [
-    [
-     "/web-animations/interfaces/AnimationEffectTiming/iterations.html",
+     "/web-animations/interfaces/AnimationEffect/updateTiming.html",
      {}
     ]
    ],
@@ -230249,6 +230177,12 @@
      {}
     ]
    ],
+   "webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-disconnected-input.https.html": [
+    [
+     "/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-disconnected-input.https.html",
+     {}
+    ]
+   ],
    "webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-onerror.https.html": [
     [
      "/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-onerror.https.html",
@@ -250941,7 +250875,7 @@
    "testharness"
   ],
   "bluetooth/resources/bluetooth-helpers.js": [
-   "1944dc57df774ad737179dd22fb3cc9de842bc21",
+   "9d2b233c511627f6a4fe93bdaf16ba28c4a6ead9",
    "support"
   ],
   "bluetooth/resources/health-thermometer-iframe.html": [
@@ -284589,11 +284523,11 @@
    "testharness"
   ],
   "css/css-grid/abspos/absolute-positioning-grid-container-containing-block-001.html": [
-   "f35bf44f588c631cf85021df55d34b5726ceff03",
+   "308d1e747e91bd4d3cbeab33f53e549d380fa716",
    "testharness"
   ],
   "css/css-grid/abspos/absolute-positioning-grid-container-parent-001.html": [
-   "4f65457310c6f1127c10821159a37b89caf26abd",
+   "8623dfe31fc392230376d52382baff1e527d84eb",
    "testharness"
   ],
   "css/css-grid/abspos/grid-item-absolute-positioning-dynamic-001.html": [
@@ -284605,15 +284539,15 @@
    "support"
   ],
   "css/css-grid/abspos/grid-paint-positioned-children-001.html": [
-   "1093709bd8e0cbbbbdc02032e1e4771cd9ab53e3",
+   "c79700e65dccba02c03ef54c6b1ab65b9f8bc19d",
    "reftest"
   ],
   "css/css-grid/abspos/grid-positioned-children-writing-modes-001-ref.html": [
-   "8baf87330e4005ddb664f5fc71c972e4e1c00f40",
+   "27b26b1a72d83b1b870b11194ce42f6a329b885c",
    "support"
   ],
   "css/css-grid/abspos/grid-positioned-children-writing-modes-001.html": [
-   "45d1fbeb11504621afa26f82ff0819d4c8659962",
+   "2d123622147a051ee3a3727ea3d029b2922973b1",
    "reftest"
   ],
   "css/css-grid/abspos/grid-positioned-item-dynamic-change-001.html": [
@@ -284621,31 +284555,31 @@
    "reftest"
   ],
   "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html": [
-   "b15d1db43efd2b8f15aab17dbbcf3afc262baa76",
+   "4f909aa983223a1a8b103b6e3adc014513dbb6eb",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html": [
-   "6efd2dfea5027aca510f7a92e8cec16b3fddef2d",
+   "9c66af91c308c50dfdb9d811357b2241a5665412",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html": [
-   "d485183a7ea0bfcf92503a3e420ae68470593995",
+   "c3ba40cd174cb2a2588898e6643ca2a489a27c25",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html": [
-   "aacc2daef0aae211a8ffa433ff6684d037afd4c8",
+   "60cd2f1b1a78e0be1d08ed04433e8db765dd1f90",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html": [
-   "fc2cfee0c523129d8cb0bbee1685786a72031e84",
+   "2ba2d79cbee6c6e388c98245ccd96da9a4f186e5",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html": [
-   "7408735464c2da7fa7916ee5a739518866e5b7a2",
+   "d78e6df343046ae4361fddac1a5c38a1d18de5a1",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html": [
-   "4c50565bb7adf5074f57da937954c3e95ee00d7a",
+   "5f21384b56ed7e51c55896249e6a8dc69c8c15f5",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-background-001-ref.html": [
@@ -284653,7 +284587,7 @@
    "support"
   ],
   "css/css-grid/abspos/grid-positioned-items-background-001.html": [
-   "1776e1042cf1712a86906e6e8b56faf9d80bb143",
+   "f4b76880ffd08a2879354d63862533532e0acb68",
    "reftest"
   ],
   "css/css-grid/abspos/grid-positioned-items-background-rtl-001-ref.html": [
@@ -284661,47 +284595,47 @@
    "support"
   ],
   "css/css-grid/abspos/grid-positioned-items-background-rtl-001.html": [
-   "581116474bdd4214f803dd7c6375104308c245e8",
+   "90fdc98fa243436d0dd1c83fcacfbbafe756f69f",
    "reftest"
   ],
   "css/css-grid/abspos/grid-positioned-items-content-alignment-001.html": [
-   "d9f5abb41f8fb479c37f0d364b9cd73cb9008829",
+   "53bba04085d038dfb81d1f9323915a24e1bf477e",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-content-alignment-rtl-001.html": [
-   "81cd5622a02ae3bdccd609d6e409241b9ba92117",
+   "fcce72ee35dd8d3fb7ee6be0b6f44bf025abf5a1",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-gaps-001.html": [
-   "29cc4d5bb2a27e59907b6f2e1c32fe260cd3f4c8",
+   "59ad78731845efdee151a7db5f963484505e9b49",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-gaps-rtl-001.html": [
-   "662bd6d9451786ba0da556c3049e7747f2d9d3e7",
+   "618bf5f6b8ca90359e9df147f201ad4ba5d84e8e",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-implicit-grid-001.html": [
-   "dfeb40d25bf666ce73fda44e3cc5ad152cc55116",
+   "2666a4caa94fb56a17cc197f67a8572185b01514",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-implicit-grid-line-001.html": [
-   "4e687882f7721dae22c1a65789fe1cfbfcfa86e2",
+   "1b1dee594c037e5ee8966331e8fc2d60b4e847d9",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-padding-001.html": [
-   "9f1dfe2b066d9df4bbce276a16849de8779d8b6e",
+   "6cfe2450ba28b501f1421c04c274976f63ee3494",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-unknown-named-grid-line-001.html": [
-   "92fa645b99f912e38c55d7a8f6a8c7983e0960d8",
+   "4ad027f1a382a9414ce0d34826aa877d9915d458",
    "testharness"
   ],
   "css/css-grid/abspos/grid-positioned-items-within-grid-implicit-track-001.html": [
-   "1a198448681696a8fed8c8240af0d069b34a50ad",
+   "cc16a7b4ffc4da30a2dc47b4bb627c40b611d425",
    "testharness"
   ],
   "css/css-grid/abspos/grid-sizing-positioned-items-001.html": [
-   "a626f8ac567d7577d7f0a8b27c7104fda7bb7d86",
+   "80f385933b5380bb0e476db4f089b6064195c535",
    "testharness"
   ],
   "css/css-grid/abspos/orthogonal-positioned-grid-items-001-ref.html": [
@@ -284945,21 +284879,25 @@
    "reftest"
   ],
   "css/css-grid/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html": [
-   "7f5640648062fe8b02e98b67d48c1af1914cdab7",
+   "6fc9fc8a452476ae5234e67d87b06aee99b32194",
    "testharness"
   ],
   "css/css-grid/abspos/positioned-grid-items-should-not-take-up-space-001.html": [
-   "8f048f2cfc368d45263fac24ab8e64ef6db0a163",
+   "02ea3621a3e3189181de74c7e1393db58d499181",
    "testharness"
   ],
   "css/css-grid/abspos/positioned-grid-items-sizing-001-ref.html": [
-   "de3401d0edd3dbb428066d5fa85f5235d083aa18",
+   "5b07f605970df1d5de7e3e44e4cac3d8c7450198",
    "support"
   ],
   "css/css-grid/abspos/positioned-grid-items-sizing-001.html": [
-   "053c2ad3fe2edfd36dc8743c01cf098af91c026c",
+   "831ab1249db84ddc90344f2c9fa38bbf8b5dd403",
    "reftest"
   ],
+  "css/css-grid/abspos/support/grid.css": [
+   "6bb300b8baebf700481ea162fb7b41913fcca29c",
+   "support"
+  ],
   "css/css-grid/alignment/grid-alignment-implies-size-change-001.html": [
    "6a98b19084f09099a83cd1e150dcc99e58967596",
    "testharness"
@@ -285889,7 +285827,7 @@
    "reftest"
   ],
   "css/css-grid/grid-definition/grid-change-fit-content-argument-001.html": [
-   "409d4b815307264b17581975f0f121f40946d932",
+   "d00e8651be933262d7f64d22f6e8ce68d23d44eb",
    "testharness"
   ],
   "css/css-grid/grid-definition/grid-inline-support-flexible-lengths-001.html": [
@@ -285953,11 +285891,11 @@
    "testharness"
   ],
   "css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html": [
-   "5f2f68b7cf046593760e6668a3d7fca58bae263e",
+   "f97320fd878e74ef93435ceeaf8117acde1c0e00",
    "support"
   ],
   "css/css-grid/grid-definition/grid-template-columns-fit-content-001.html": [
-   "adffbd4b734ae719675cb5bee7fd6bc3fbde5d5b",
+   "f0b39f517dbf4ceb7649c99863ca3cbb44549446",
    "reftest"
   ],
   "css/css-grid/grid-definition/grid-template-columns-rows-resolved-values-001.html": [
@@ -285965,13 +285903,17 @@
    "testharness"
   ],
   "css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html": [
-   "0599be38ec7525b925d2c42dad8f6c09efff1612",
+   "fe5c6aad4b42792b63e609c9f17a1d26918e68cc",
    "support"
   ],
   "css/css-grid/grid-definition/grid-template-rows-fit-content-001.html": [
-   "a6ea0c0330b667d86c54933875e5cfda9d3f2162",
+   "57659c467b0abc12fc953edd6e96a07d2f15786e",
    "reftest"
   ],
+  "css/css-grid/grid-definition/support/grid.css": [
+   "6bb300b8baebf700481ea162fb7b41913fcca29c",
+   "support"
+  ],
   "css/css-grid/grid-definition/support/testing-utils.js": [
    "7d6dc5106777942ad83e6bc570368af113f32d5f",
    "support"
@@ -286121,35 +286063,35 @@
    "reftest"
   ],
   "css/css-grid/grid-items/grid-items-minimum-width-001.html": [
-   "b966e131ea84ee815ac866c43000dc785aec7976",
+   "8eb22226f25e529fdfa1e904760dc9d9572cb8c5",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-items-minimum-width-002.html": [
-   "9000f0fa00c17e9c5f00346709f3a0a87cbb1e51",
+   "46d62c774bdfa47a0aa11692a5b42ba032d3c35a",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-items-minimum-width-orthogonal-001.html": [
-   "c02833f09f5b3b66a5807d7c0145044cf244f2fb",
+   "012848f739cb0ac5aaf53de9f6137d87e52dac57",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-items-minimum-width-orthogonal-002.html": [
-   "79cb2aad0f70c532ede28367db867c3abdae716d",
+   "e366eed5aa25cdcc88510dc70b55cfe1ebd410d4",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-items-minimum-width-vertical-lr-001.html": [
-   "989908844f12f99ccd7862818a31778a8786217b",
+   "ad2a7bfe6c02682b9d8907234df2f28c7c6e825d",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-items-minimum-width-vertical-lr-002.html": [
-   "240f06eb9af9d5e94d5d4ddd1fbecf6b46f3e92c",
+   "5ef51897c6b890ac9508917bfcb5187406e0420b",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-items-minimum-width-vertical-rl-001.html": [
-   "482e8cd355affd797af1983490a2b56824d6c5be",
+   "0295b15da5707dcd4b44cd95c66edbd19c08c1b8",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-items-minimum-width-vertical-rl-002.html": [
-   "456df30ce85f22ab081b498b3300cb31cc55233a",
+   "3d9ee014d1341bae70de86de585658f7432f76ef",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-items-sizing-alignment-001-ref.html": [
@@ -286257,19 +286199,19 @@
    "testharness"
   ],
   "css/css-grid/grid-items/grid-minimum-size-grid-items-022.html": [
-   "7a5be2e6b0adbbf048efb0cb19c35be913729ba8",
+   "2baacdd3bf98a6084105e70168dbe276579b226f",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-minimum-size-grid-items-023.html": [
-   "cc51bc269d23ae345c91f91368b5a57d99a4606e",
+   "30f45639bea629c3db5a616a408eb6a0e5eb5f81",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-minimum-size-grid-items-024.html": [
-   "5eb13653b1d9fe889cd6bb8423e47eed207ac69d",
+   "36c73749ac60f7589928e9b96a2722946de3e63c",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-minimum-size-grid-items-025.html": [
-   "15a29d967b7e543edeebd6bb37a597741b79bf50",
+   "4b0da168ad2dc39fb9e057d39e566bd4dadc9553",
    "testharness"
   ],
   "css/css-grid/grid-items/grid-order-property-auto-placement-001.html": [
@@ -286384,6 +286326,10 @@
    "928556fc1f503c821581032a2288a08f8aa07021",
    "support"
   ],
+  "css/css-grid/grid-items/support/grid.css": [
+   "6bb300b8baebf700481ea162fb7b41913fcca29c",
+   "support"
+  ],
   "css/css-grid/grid-layout-properties.html": [
    "d30ee96245cf3d25bffc64347a4ee60bfb2b2049",
    "testharness"
@@ -286405,11 +286351,11 @@
    "testharness"
   ],
   "css/css-grid/grid-model/grid-container-ignores-first-letter-001.html": [
-   "e46492228ce6fdf83d9661c06db745e9c6689bb4",
+   "157c7945bc8f6e020f3e123789489269f318d91e",
    "testharness"
   ],
   "css/css-grid/grid-model/grid-container-ignores-first-line-001.html": [
-   "8e8895681b8f7e8f5d416faedf5b081f7fc42243",
+   "aec98e4e7bf245637903a1f06d2e5d5519b8da66",
    "testharness"
   ],
   "css/css-grid/grid-model/grid-display-grid-001.html": [
@@ -286497,11 +286443,11 @@
    "reftest"
   ],
   "css/css-grid/grid-model/grid-item-accepts-first-letter-001.html": [
-   "bc3aa0022584b2dc6253aeb1bbca50b6b7c05f54",
+   "0ab0d1b9446d4ccaeba6778bdc65ef7d4adbd6a1",
    "testharness"
   ],
   "css/css-grid/grid-model/grid-item-accepts-first-line-001.html": [
-   "0af2d39207188e1398e69f1e2d81848ba1bee2ee",
+   "9025d7543cfff53833f783d19b3f56333ac5fef3",
    "testharness"
   ],
   "css/css-grid/grid-model/grid-margins-no-collapse-001.html": [
@@ -286520,6 +286466,10 @@
    "adfa657da1bb65a313894a8b5010a62d7c629c34",
    "reftest"
   ],
+  "css/css-grid/grid-model/support/grid.css": [
+   "6bb300b8baebf700481ea162fb7b41913fcca29c",
+   "support"
+  ],
   "css/css-grid/implicit-grids/grid-support-grid-auto-columns-rows-001.html": [
    "85a397623ccb6b2ced1450af19f0eaf3a2f6df22",
    "reftest"
@@ -286636,10 +286586,6 @@
    "feb53485e24aeaf9a5f27be5e42cc4a6fc5b8df0",
    "support"
   ],
-  "css/css-grid/support/grid.css": [
-   "6bb300b8baebf700481ea162fb7b41913fcca29c",
-   "support"
-  ],
   "css/css-grid/test-plan/index.html": [
    "e633dc7584fbc7bfe99177aa5dd9fbd107a2d3f5",
    "support"
@@ -289420,6 +289366,26 @@
    "46913ea7e47811b11be898de5c3bd0a330ea6637",
    "testharness"
   ],
+  "css/css-scoping/shadow-fallback-dynamic-001.html": [
+   "062c99df18077a0205d0170d641b1d1e61199657",
+   "reftest"
+  ],
+  "css/css-scoping/shadow-fallback-dynamic-002.html": [
+   "2f66c8bca48c2ce5c9e82c5d67b152e2d143f4c6",
+   "reftest"
+  ],
+  "css/css-scoping/shadow-fallback-dynamic-003.html": [
+   "f054b0974277fbee38a96a26559c9a15400266db",
+   "reftest"
+  ],
+  "css/css-scoping/shadow-fallback-dynamic-004.html": [
+   "fc33527eaaa7711ecb2c7cd9523e793bce2503f2",
+   "reftest"
+  ],
+  "css/css-scoping/shadow-fallback-dynamic-005.html": [
+   "46d78b6d6931505bbc4bfc2f83e2bd0bac0d3472",
+   "reftest"
+  ],
   "css/css-scoping/slotted-invalidation.html": [
    "c500e1ceba1b293d45df5f66fd89d4a5d9ceb952",
    "testharness"
@@ -313816,10 +313782,6 @@
    "268fb9a72d33b3d18bbb82aaaac48bb15c89a88e",
    "support"
   ],
-  "css/cssom/stylesheet-same-origin.sub-expected.txt": [
-   "a97ac3f245a813470bb6d58b70590d70739535bc",
-   "support"
-  ],
   "css/cssom/stylesheet-same-origin.sub.html": [
    "cab23bdf8b92c8194cc71b1a8ce34155f89f42cf",
    "testharness"
@@ -319717,7 +319679,7 @@
    "testharness"
   ],
   "dom/interfaces-expected.txt": [
-   "09e2ecc16bdb310f2ffab5b51a69d0f2b2fe40da",
+   "3cacec14f027e5864ea398db96eb2960d28f30d4",
    "support"
   ],
   "dom/interfaces.html": [
@@ -321216,6 +321178,10 @@
    "279341d850642f62ea0b3de1b15da87884413516",
    "support"
   ],
+  "domxpath/document.tentative.html": [
+   "c1b93714b14b822c55d3f784e0520d91c6cc46c4",
+   "testharness"
+  ],
   "domxpath/evaluator-constructor.html": [
    "4842d40e22e25ee72536946d785a3cd03bc6a11d",
    "testharness"
@@ -323752,6 +323718,10 @@
    "700107771158b22fa280f30a5a52d1aac617ff6e",
    "testharness"
   ],
+  "eventsource/dedicated-worker/eventsource-close2.htm": [
+   "dc79b53506150f4877a36c6c0d54ccebeecf87ba",
+   "testharness"
+  ],
   "eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm": [
    "9614ac5ce1967bbbcae6a1cc8d64465579f6410d",
    "testharness"
@@ -344704,6 +344674,10 @@
    "78e72ad26b9df9b3f32f1cf00acb6eb051dc86c5",
    "support"
   ],
+  "html/syntax/parsing/html-integration-point.html": [
+   "cd2686abb45f08150a13c887959fa0e8e26753a5",
+   "testharness"
+  ],
   "html/syntax/parsing/html5lib_adoption01.html": [
    "90f39dae58f37f2f8d786a617fcc5804e6235ae0",
    "testharness"
@@ -346417,7 +346391,7 @@
    "support"
   ],
   "interfaces/dom.idl": [
-   "2d65a8029a80cfc97398d18f911f1ae65067e765",
+   "f5881beeeaa7e990e9b889182989d6d0fb0ba8a3",
    "support"
   ],
   "interfaces/encoding.idl": [
@@ -347569,7 +347543,7 @@
    "testharness"
   ],
   "mediacapture-streams/MediaDevices-enumerateDevices.https.html": [
-   "1fb376d675c685d5de76fef0e840e440de3e3268",
+   "892229b737d157845d9b2e24170f3bc820b10036",
    "testharness"
   ],
   "mediacapture-streams/MediaDevices-getUserMedia.https.html": [
@@ -356980,8 +356954,12 @@
    "4f34387b135ee40a6f8fc363659096409a1eb0bd",
    "manual"
   ],
+  "presentation-api/controlling-ua/PresentationRequest_error.https-expected.txt": [
+   "e32aa84c3134096e8d073d52a4e90bc46d5c3fce",
+   "support"
+  ],
   "presentation-api/controlling-ua/PresentationRequest_error.https.html": [
-   "8d8a2a77b5735cfe4dc6d0eeb3c5bdf7f13c4148",
+   "c1156f81c778b871e741d55eed332e441c0cda1d",
    "testharness"
   ],
   "presentation-api/controlling-ua/PresentationRequest_mixedcontent.https.html": [
@@ -357005,7 +356983,7 @@
    "testharness"
   ],
   "presentation-api/controlling-ua/PresentationRequest_success.https.html": [
-   "74cc007c2472f11bdc08410f870f270e8e4b0f4a",
+   "91cc64f165493d46bf3e9f0a303c9794bff78854",
    "testharness"
   ],
   "presentation-api/controlling-ua/common.js": [
@@ -364892,10 +364870,6 @@
    "a6cd75583f6363a83b18f1bc77d89821de344ff7",
    "testharness"
   ],
-  "resource-timing/resource_frame_initiator_type.html": [
-   "dcea1111a2c9a40a1d3de7246a5295e84dcf08b5",
-   "testharness"
-  ],
   "resource-timing/resource_ignore_data_url.html": [
    "f8513b4ae7cc26c07cea1c16d872e0594f05041c",
    "testharness"
@@ -364905,7 +364879,7 @@
    "testharness"
   ],
   "resource-timing/resource_initiator_types.html": [
-   "70ab5e0b5d8d684fc420e9242a273e948edbb1ba",
+   "11ad45e383c110eee2496c481abbff9642f6e6ee",
    "testharness"
   ],
   "resource-timing/resource_memory_cached.sub.html": [
@@ -364969,7 +364943,7 @@
    "support"
   ],
   "resource-timing/resources/all_resource_types.htm": [
-   "c7f698888c64e5b750fac45e22dbb85e5979b3c5",
+   "63a40f0ab7e27536448a7624bb632332c9d0aae4",
    "support"
   ],
   "resource-timing/resources/blank_page_green.htm": [
@@ -364984,10 +364958,18 @@
    "51e0050cf1bdeb051d0d7ab6f23a7a2173cb40db",
    "support"
   ],
+  "resource-timing/resources/empty.py": [
+   "3638ba60904616a2bf551fef1fb81b08db9e172f",
+   "support"
+  ],
   "resource-timing/resources/empty_script.js": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
+  "resource-timing/resources/eventsource.py": [
+   "e53940d9844b03cd06b425530e2e23e20aa31bdb",
+   "support"
+  ],
   "resource-timing/resources/fake_responses.html": [
    "c942abc1e8c1672935ffc8ce34821891345bacb9",
    "support"
@@ -364997,7 +364979,7 @@
    "support"
   ],
   "resource-timing/resources/green_frame.htm": [
-   "08f8ca19b61ab0ac68014d5b406a952669fbe104",
+   "710159d2dcfce2cdc2f98449ec7a516fdc739079",
    "support"
   ],
   "resource-timing/resources/gzip_xml.py": [
@@ -369060,10 +369042,6 @@
    "4a751ed955527472b3c130870c8fbc7b79868290",
    "support"
   ],
-  "staticrange/idlharness.html": [
-   "16f30a68d97edf19c5255328fd1460ac54a4c025",
-   "testharness"
-  ],
   "storage/OWNERS": [
    "858262a742df1d152d85b55cb47df59464d68809",
    "support"
@@ -369256,14 +369234,6 @@
    "277a94372fc8359b631b46ea79778ce2ec0e928c",
    "testharness"
   ],
-  "streams/piping/error-propagation-backward-expected.txt": [
-   "b4baf4a5a15dfc90ee64514fc66f6d42c1925244",
-   "support"
-  ],
-  "streams/piping/error-propagation-backward.dedicatedworker-expected.txt": [
-   "b4baf4a5a15dfc90ee64514fc66f6d42c1925244",
-   "support"
-  ],
   "streams/piping/error-propagation-backward.dedicatedworker.html": [
    "2f7ad2bf616e612f8cae9c61264d1ea012be2561",
    "testharness"
@@ -369276,18 +369246,10 @@
    "a9ed4065bf5512937a60f85e18ee0b4312994506",
    "support"
   ],
-  "streams/piping/error-propagation-backward.serviceworker.https-expected.txt": [
-   "62860e3eff83009cc89c7bd40f6a55889a21c540",
-   "support"
-  ],
   "streams/piping/error-propagation-backward.serviceworker.https.html": [
    "3502f6514992dab5662a5088c518d3a775863770",
    "testharness"
   ],
-  "streams/piping/error-propagation-backward.sharedworker-expected.txt": [
-   "b4baf4a5a15dfc90ee64514fc66f6d42c1925244",
-   "support"
-  ],
   "streams/piping/error-propagation-backward.sharedworker.html": [
    "464dbfc87804e207057de70b2dcbb0aacf03b92e",
    "testharness"
@@ -369368,14 +369330,6 @@
    "44f9ceaa3bfc9d8b92885997d322486bd0f237a6",
    "testharness"
   ],
-  "streams/piping/multiple-propagation-expected.txt": [
-   "7268cb2b8cf18bc230c612acd617627fb5f14eaf",
-   "support"
-  ],
-  "streams/piping/multiple-propagation.dedicatedworker-expected.txt": [
-   "7268cb2b8cf18bc230c612acd617627fb5f14eaf",
-   "support"
-  ],
   "streams/piping/multiple-propagation.dedicatedworker.html": [
    "ef3d8a0ab031c3e25c6fcd083e7361a449ed671d",
    "testharness"
@@ -369388,18 +369342,10 @@
    "a4f9df6a5da581c14aae0d489bc73972873f2b7d",
    "support"
   ],
-  "streams/piping/multiple-propagation.serviceworker.https-expected.txt": [
-   "6c910a0b45fd2812a7ae60dfe4cf475d8208d091",
-   "support"
-  ],
   "streams/piping/multiple-propagation.serviceworker.https.html": [
    "b1ec8a36de6b683fcfc9b3af35f7544d4806bdb6",
    "testharness"
   ],
-  "streams/piping/multiple-propagation.sharedworker-expected.txt": [
-   "7268cb2b8cf18bc230c612acd617627fb5f14eaf",
-   "support"
-  ],
   "streams/piping/multiple-propagation.sharedworker.html": [
    "a2aaf43f0d2eb831bd9f8e379fbf0076eee76633",
    "testharness"
@@ -369816,6 +369762,10 @@
    "d22e9b8bc231b3c00be2de557c0f91dbb76dcd81",
    "testharness"
   ],
+  "streams/readable-streams/general-expected.txt": [
+   "e2846b3e93c1b0e46f1f8176042a98d4b66982b6",
+   "support"
+  ],
   "streams/readable-streams/general.dedicatedworker-expected.txt": [
    "e2846b3e93c1b0e46f1f8176042a98d4b66982b6",
    "support"
@@ -369965,11 +369915,11 @@
    "testharness"
   ],
   "streams/transform-streams/errors-expected.txt": [
-   "04242cf6f4be6cad6f37641138dc7613066e99c8",
+   "2ba9233fbbde4f44203326fdfd7909125814bf8f",
    "support"
   ],
   "streams/transform-streams/errors.dedicatedworker-expected.txt": [
-   "04242cf6f4be6cad6f37641138dc7613066e99c8",
+   "2ba9233fbbde4f44203326fdfd7909125814bf8f",
    "support"
   ],
   "streams/transform-streams/errors.dedicatedworker.html": [
@@ -369985,7 +369935,7 @@
    "support"
   ],
   "streams/transform-streams/errors.serviceworker.https-expected.txt": [
-   "c83621c9c2f0ebf2a1f4a156b762d35dcf71acb3",
+   "8f5bac390f21f8b729d3741b936c7d365e5c7f84",
    "support"
   ],
   "streams/transform-streams/errors.serviceworker.https.html": [
@@ -369993,7 +369943,7 @@
    "testharness"
   ],
   "streams/transform-streams/errors.sharedworker-expected.txt": [
-   "04242cf6f4be6cad6f37641138dc7613066e99c8",
+   "2ba9233fbbde4f44203326fdfd7909125814bf8f",
    "support"
   ],
   "streams/transform-streams/errors.sharedworker.html": [
@@ -370192,14 +370142,6 @@
    "9f545c6d51b877e399fd5e484a5ce5052c607346",
    "testharness"
   ],
-  "streams/writable-streams/aborting-expected.txt": [
-   "3737adb2f1046d5905cff920098c04617108e4f7",
-   "support"
-  ],
-  "streams/writable-streams/aborting.dedicatedworker-expected.txt": [
-   "3737adb2f1046d5905cff920098c04617108e4f7",
-   "support"
-  ],
   "streams/writable-streams/aborting.dedicatedworker.html": [
    "89cfc3ba5cfbb426b6ac60c32aa5cfe9dd0ad8b4",
    "testharness"
@@ -370212,18 +370154,10 @@
    "24615519115cde901b8cac1a19c23cd0d9244a17",
    "support"
   ],
-  "streams/writable-streams/aborting.serviceworker.https-expected.txt": [
-   "37a2bf9ef2a34f5bfc1f4609e8b1b38dbd321910",
-   "support"
-  ],
   "streams/writable-streams/aborting.serviceworker.https.html": [
    "b69530ebf51ccaf781ff78172be2f4607ee22c86",
    "testharness"
   ],
-  "streams/writable-streams/aborting.sharedworker-expected.txt": [
-   "3737adb2f1046d5905cff920098c04617108e4f7",
-   "support"
-  ],
   "streams/writable-streams/aborting.sharedworker.html": [
    "9e792fad19cd10a96440478cb7e0486f41b70bf4",
    "testharness"
@@ -370248,14 +370182,6 @@
    "a4692c839ca53134bc5036b2f813e2311db3f2d0",
    "testharness"
   ],
-  "streams/writable-streams/bad-underlying-sinks-expected.txt": [
-   "82b2db30ed3d823d52e2150b1a4e0849d2ed292f",
-   "support"
-  ],
-  "streams/writable-streams/bad-underlying-sinks.dedicatedworker-expected.txt": [
-   "82b2db30ed3d823d52e2150b1a4e0849d2ed292f",
-   "support"
-  ],
   "streams/writable-streams/bad-underlying-sinks.dedicatedworker.html": [
    "1b17838179df4a18b4a2d06a1d977cbb26d3b4b9",
    "testharness"
@@ -370268,18 +370194,10 @@
    "9a9f0b9eb7a93e9809c549e983c4052648157592",
    "support"
   ],
-  "streams/writable-streams/bad-underlying-sinks.serviceworker.https-expected.txt": [
-   "2d1d50e62e29c73d3e39c583106c7b8972e46928",
-   "support"
-  ],
   "streams/writable-streams/bad-underlying-sinks.serviceworker.https.html": [
    "fbddba953d4b50ed43b1e03cab6eb8931db71ffe",
    "testharness"
   ],
-  "streams/writable-streams/bad-underlying-sinks.sharedworker-expected.txt": [
-   "82b2db30ed3d823d52e2150b1a4e0849d2ed292f",
-   "support"
-  ],
   "streams/writable-streams/bad-underlying-sinks.sharedworker.html": [
    "b20a95798586eb4c1d9ba9d2413038fa37316c5e",
    "testharness"
@@ -370324,14 +370242,6 @@
    "3c576d902e34976313357126d3688a4639a4e5a7",
    "testharness"
   ],
-  "streams/writable-streams/close-expected.txt": [
-   "fab6269fe331fc6334513e035734beba590727b7",
-   "support"
-  ],
-  "streams/writable-streams/close.dedicatedworker-expected.txt": [
-   "fab6269fe331fc6334513e035734beba590727b7",
-   "support"
-  ],
   "streams/writable-streams/close.dedicatedworker.html": [
    "cccf37e3bcc4be858fb41be465c38e7785db4508",
    "testharness"
@@ -370344,18 +370254,10 @@
    "45a448b31a40388f277ecf064339f6858f032cc1",
    "support"
   ],
-  "streams/writable-streams/close.serviceworker.https-expected.txt": [
-   "9fc6e420ecb221f1dcb62405e299450d921c0028",
-   "support"
-  ],
   "streams/writable-streams/close.serviceworker.https.html": [
    "5461a766e8047c6d50b7943d99f8ebb4c140a547",
    "testharness"
   ],
-  "streams/writable-streams/close.sharedworker-expected.txt": [
-   "fab6269fe331fc6334513e035734beba590727b7",
-   "support"
-  ],
   "streams/writable-streams/close.sharedworker.html": [
    "b2aeb127d5ae7087b42e3fc08faaa113c84e6fd8",
    "testharness"
@@ -370440,14 +370342,6 @@
    "00af09f46d126d6d2944d13831896e648094d1a8",
    "testharness"
   ],
-  "streams/writable-streams/general-expected.txt": [
-   "09aa178c5f9caef1a7ea93e5a5ae93f70c2e3e3c",
-   "support"
-  ],
-  "streams/writable-streams/general.dedicatedworker-expected.txt": [
-   "09aa178c5f9caef1a7ea93e5a5ae93f70c2e3e3c",
-   "support"
-  ],
   "streams/writable-streams/general.dedicatedworker.html": [
    "8583d80450b090c16ed0795170340d040449bbc1",
    "testharness"
@@ -370460,30 +370354,14 @@
    "af1848e49d119ba4e57b8354052e161ac8e80632",
    "support"
   ],
-  "streams/writable-streams/general.serviceworker.https-expected.txt": [
-   "b48d49828246a8e000f6687006188d136add06b3",
-   "support"
-  ],
   "streams/writable-streams/general.serviceworker.https.html": [
    "1792d6c45a5687777291a4dab031a954aa053752",
    "testharness"
   ],
-  "streams/writable-streams/general.sharedworker-expected.txt": [
-   "09aa178c5f9caef1a7ea93e5a5ae93f70c2e3e3c",
-   "support"
-  ],
   "streams/writable-streams/general.sharedworker.html": [
    "44f9ceaa3bfc9d8b92885997d322486bd0f237a6",
    "testharness"
   ],
-  "streams/writable-streams/properties-expected.txt": [
-   "47b37dbd643ef29a774b9633a016a9ce219ba7b7",
-   "support"
-  ],
-  "streams/writable-streams/properties.dedicatedworker-expected.txt": [
-   "47b37dbd643ef29a774b9633a016a9ce219ba7b7",
-   "support"
-  ],
   "streams/writable-streams/properties.dedicatedworker.html": [
    "0d766237560b16ddb1bfcd02e701089132f1b3ec",
    "testharness"
@@ -370496,30 +370374,14 @@
    "81af0a954d0c12677f28ea55636a3de5bf8d3cfa",
    "support"
   ],
-  "streams/writable-streams/properties.serviceworker.https-expected.txt": [
-   "a82719e10add91cec0119e77fb38084bcc79d794",
-   "support"
-  ],
   "streams/writable-streams/properties.serviceworker.https.html": [
    "2ef8fc878249c429a89e0748e6a98fac47c1a99a",
    "testharness"
   ],
-  "streams/writable-streams/properties.sharedworker-expected.txt": [
-   "47b37dbd643ef29a774b9633a016a9ce219ba7b7",
-   "support"
-  ],
   "streams/writable-streams/properties.sharedworker.html": [
    "5c855e897d1143092ecc10b58268e6a576882184",
    "testharness"
   ],
-  "streams/writable-streams/reentrant-strategy-expected.txt": [
-   "f94c1d8432e8295d70cd175691ec831baecab4d6",
-   "support"
-  ],
-  "streams/writable-streams/reentrant-strategy.dedicatedworker-expected.txt": [
-   "f94c1d8432e8295d70cd175691ec831baecab4d6",
-   "support"
-  ],
   "streams/writable-streams/reentrant-strategy.dedicatedworker.html": [
    "5d9e5a6b69fbe79183ac6e0d2c8559f13be6e386",
    "testharness"
@@ -370532,18 +370394,10 @@
    "87a02a0d0b66c3fe571ca106379da254a4e2869f",
    "support"
   ],
-  "streams/writable-streams/reentrant-strategy.serviceworker.https-expected.txt": [
-   "3af8efee5c70450d4950e3026603714c69f7e67f",
-   "support"
-  ],
   "streams/writable-streams/reentrant-strategy.serviceworker.https.html": [
    "663075ee687ea54010f76d0e37191e46f37b9a49",
    "testharness"
   ],
-  "streams/writable-streams/reentrant-strategy.sharedworker-expected.txt": [
-   "f94c1d8432e8295d70cd175691ec831baecab4d6",
-   "support"
-  ],
   "streams/writable-streams/reentrant-strategy.sharedworker.html": [
    "5dabe1367481c57c58fe208ba66d8c13d4e2b796",
    "testharness"
@@ -372489,7 +372343,7 @@
    "support"
   ],
   "web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html": [
-   "bda186b311457e58c48ca5cf4619f485a41f8e2d",
+   "2c424570af86e1a4541d4f0a67c7693cfcac8abc",
    "testharness"
   ],
   "web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html": [
@@ -372501,7 +372355,7 @@
    "testharness"
   ],
   "web-animations/interfaces/Animatable/animate-expected.txt": [
-   "ce65bd1b17f53d2d89f0d28e596ba93f1e6a6387",
+   "9e83cf9fad363d76e829ad098b333e37247572f2",
    "support"
   ],
   "web-animations/interfaces/Animatable/animate-no-browsing-context-expected.txt": [
@@ -372513,15 +372367,23 @@
    "testharness"
   ],
   "web-animations/interfaces/Animatable/animate.html": [
-   "8d76a26de47494600da40e756a26de61329ff3aa",
+   "4cd816ad368f1dae077f601022f9b57d9cb931ae",
    "testharness"
   ],
+  "web-animations/interfaces/Animatable/getAnimations-expected.txt": [
+   "65cd4e69b57d415eeebf2dac2a4d4de76d1f8dcf",
+   "support"
+  ],
   "web-animations/interfaces/Animatable/getAnimations.html": [
-   "9c03f9a6410dc8463a3e3acb3b6e38c26d79b097",
+   "a11049c78d2ca16a9df9d0f21b3a3d0fd35e29f3",
    "testharness"
   ],
+  "web-animations/interfaces/Animation/cancel-expected.txt": [
+   "f3b8e000f0f6b383c3742c4f8ea6aaf63a9a31c6",
+   "support"
+  ],
   "web-animations/interfaces/Animation/cancel.html": [
-   "38d509e24fa224fc8b937e4a63dd1c404e72b466",
+   "105313dffbe7953ca6b413e860ba8b47e316e0b7",
    "testharness"
   ],
   "web-animations/interfaces/Animation/constructor-expected.txt": [
@@ -372529,19 +372391,19 @@
    "support"
   ],
   "web-animations/interfaces/Animation/constructor.html": [
-   "f4dc4fdca61255557ed346412e134745bce1a3ed",
+   "75e8dd9d9d3c96a87cec1abc2c1373537c6e0f77",
    "testharness"
   ],
   "web-animations/interfaces/Animation/effect.html": [
-   "4445fc8bd2120fb1e212dfc6a1fcf786a531ee6f",
+   "db36e79cf6839cda7d6940f21afe2f56d4d9a115",
    "testharness"
   ],
   "web-animations/interfaces/Animation/finished-expected.txt": [
-   "bbf5319f8bf5d347fa37c9ca885133bdef7380e8",
+   "3f9f416b1976aae8b2cccde1778139234f5c5c85",
    "support"
   ],
   "web-animations/interfaces/Animation/finished.html": [
-   "ffcba3379db7094455a7798e4d5972d8e52caec5",
+   "a944518bdd0151534f0172ac58034ac613a70249",
    "testharness"
   ],
   "web-animations/interfaces/Animation/id.html": [
@@ -372553,7 +372415,7 @@
    "support"
   ],
   "web-animations/interfaces/Animation/idlharness.html": [
-   "d61aa2d95ea31809a275183408e822c8c1eec87d",
+   "b049999bb0512bfa0c3eb8b60176eb9213d663f7",
    "testharness"
   ],
   "web-animations/interfaces/Animation/oncancel.html": [
@@ -372592,50 +372454,26 @@
    "01f669542434f03d37e9f148a4f3135fe3122d46",
    "testharness"
   ],
-  "web-animations/interfaces/AnimationEffectTiming/delay.html": [
-   "4de5b0a692d645961de27df67efa8257adb0a031",
+  "web-animations/interfaces/AnimationEffect/getComputedTiming-expected.txt": [
+   "ed031dc998b9bbd6d9483fa69f213f5a2233e46d",
+   "support"
+  ],
+  "web-animations/interfaces/AnimationEffect/getComputedTiming.html": [
+   "e0d4ba4c0f1a5da4d126c501eca733e00adbef1a",
    "testharness"
   ],
-  "web-animations/interfaces/AnimationEffectTiming/direction.html": [
-   "642207ce454fb816cc47d14fbe29f65d92ddf6ed",
-   "testharness"
+  "web-animations/interfaces/AnimationEffect/updateTiming-expected.txt": [
+   "a7182805f6450e1efd7e99c4c1cf8294d264a51d",
+   "support"
   ],
-  "web-animations/interfaces/AnimationEffectTiming/duration.html": [
-   "14abe09cb19080585a315115e387b85784c7d862",
-   "testharness"
-  ],
-  "web-animations/interfaces/AnimationEffectTiming/easing.html": [
-   "b3ad4c78c9bce0e17db0ce780cd1260de1ce7cb0",
-   "testharness"
-  ],
-  "web-animations/interfaces/AnimationEffectTiming/endDelay.html": [
-   "a8609f22672b092178c2391d7ba7ef804112bef4",
-   "testharness"
-  ],
-  "web-animations/interfaces/AnimationEffectTiming/fill.html": [
-   "1cef601cde33eea3b591a0826ad52f379bb31d0d",
+  "web-animations/interfaces/AnimationEffect/updateTiming.html": [
+   "5daa5580c2d34e992f3560bf5b85419498b6c5ee",
    "testharness"
   ],
   "web-animations/interfaces/AnimationEffectTiming/getComputedTiming-expected.txt": [
    "ed031dc998b9bbd6d9483fa69f213f5a2233e46d",
    "support"
   ],
-  "web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html": [
-   "020e9faaae05de5a25829a05558ea72672b04f63",
-   "testharness"
-  ],
-  "web-animations/interfaces/AnimationEffectTiming/idlharness.html": [
-   "aa9823e5a06c76921b49aa5f5e61fd1dedfac3af",
-   "testharness"
-  ],
-  "web-animations/interfaces/AnimationEffectTiming/iterationStart.html": [
-   "393b37098ab470e75b1254b53875901e705d8d1b",
-   "testharness"
-  ],
-  "web-animations/interfaces/AnimationEffectTiming/iterations.html": [
-   "1e8bb46b5a1eef496edda32b16c856baa16e9b30",
-   "testharness"
-  ],
   "web-animations/interfaces/AnimationPlaybackEvent/constructor-expected.txt": [
    "9f5f2918d1c87c03c88105706ea87e85063d7e7c",
    "support"
@@ -372653,7 +372491,7 @@
    "support"
   ],
   "web-animations/interfaces/Document/getAnimations.html": [
-   "12fdbce3e75f5a7d7771d9337089255ef73f9712",
+   "7fbd5eed47955fdaeccd329f82f0884b86654784",
    "testharness"
   ],
   "web-animations/interfaces/Document/timeline.html": [
@@ -372673,23 +372511,27 @@
    "testharness"
   ],
   "web-animations/interfaces/KeyframeEffect/constructor-expected.txt": [
-   "dc192d2b1ff0c5623a18bf088c85bcb09d8f69c2",
+   "5733d115900aa50624e04ac84051348ef8ade012",
    "support"
   ],
   "web-animations/interfaces/KeyframeEffect/constructor.html": [
-   "2f6449cbf2b47ae457efb23fb52b8fd1709837ac",
+   "38ff2a4b64e7318fa96eb867aae7f25bed53e67b",
    "testharness"
   ],
+  "web-animations/interfaces/KeyframeEffect/copy-constructor-expected.txt": [
+   "74353cf40fdb42a530fbf516148268b4d61f1747",
+   "support"
+  ],
   "web-animations/interfaces/KeyframeEffect/copy-constructor.html": [
-   "6ef462ddc696269f132d596188ffd5e8da1e1164",
+   "0e3d893d7b8e438b279f087846df596256ccbe84",
    "testharness"
   ],
   "web-animations/interfaces/KeyframeEffect/idlharness-expected.txt": [
-   "cafe0b8e746cadffc2da5ef45450d633e66c3b71",
+   "50927a9f477c0a410188f65d0091c53d1134905f",
    "support"
   ],
   "web-animations/interfaces/KeyframeEffect/idlharness.html": [
-   "f05c9bd1cdee77ff6be143b0eb4f982c7218908b",
+   "ffe493133d4029820f8b27389a15157706b738e8",
    "testharness"
   ],
   "web-animations/interfaces/KeyframeEffect/iterationComposite-expected.txt": [
@@ -372697,7 +372539,7 @@
    "support"
   ],
   "web-animations/interfaces/KeyframeEffect/iterationComposite.html": [
-   "65cd746596a6770d1101b030769712be433bf6f3",
+   "c5ce17faeb355f1e9efae516d6272a88c46daa1f",
    "testharness"
   ],
   "web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001-expected.txt": [
@@ -372705,7 +372547,7 @@
    "support"
   ],
   "web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html": [
-   "f54c7c0da5728f88f37a067761af7ad815fea005",
+   "ca5efb8556aff617bef957be315ea2fd01e756d8",
    "testharness"
   ],
   "web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html": [
@@ -372744,12 +372586,20 @@
    "08da0c81847809328bda0d6e0581711f7838916e",
    "support"
   ],
+  "web-animations/resources/timing-tests.js": [
+   "2da06d9e7ace5947141165284697c4ea9be5b9d5",
+   "support"
+  ],
+  "web-animations/resources/timing-utils.js": [
+   "e0918d83187c0fbdadaebb14be72c6f34f8dfc03",
+   "support"
+  ],
   "web-animations/resources/xhr-doc.py": [
    "de68c45fc1d38a49946f9046f34031e9278a1531",
    "support"
   ],
   "web-animations/testcommon.js": [
-   "6f3e85e7ae7786ad9ff3aaec8c6343642d2510c5",
+   "8f593cc9211bcc0f8f99579e8a3475528f837969",
    "support"
   ],
   "web-animations/timing-model/animation-effects/active-time.html": [
@@ -372773,11 +372623,11 @@
    "testharness"
   ],
   "web-animations/timing-model/animation-effects/phases-and-states-expected.txt": [
-   "dfd52899f36d48cd23e8323b04d359be59c8b1f3",
+   "a99653f0b75182cc5406ff502f134e7522de7d24",
    "support"
   ],
   "web-animations/timing-model/animation-effects/phases-and-states.html": [
-   "3edd2c4bdd8409c2c12f08bc998dd8d532e0fd7d",
+   "b8cc580e3e8d17961ffff4b693857f6c333dd57f",
    "testharness"
   ],
   "web-animations/timing-model/animation-effects/simple-iteration-progress-expected.txt": [
@@ -372801,7 +372651,7 @@
    "support"
   ],
   "web-animations/timing-model/animations/finishing-an-animation.html": [
-   "4c1cf823a81e72541abcafaa08950cf87424ae55",
+   "afe654435332e798b3771b6ec6ca13bcca99e421",
    "testharness"
   ],
   "web-animations/timing-model/animations/pausing-an-animation-expected.txt": [
@@ -372877,7 +372727,7 @@
    "support"
   ],
   "web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html": [
-   "5575a251b9c265d98471e758b3cf9b218e381cba",
+   "f4e50b805229e0170bff67530b694ee5d6dd1f1a",
    "testharness"
   ],
   "web-animations/timing-model/animations/setting-the-timeline-of-an-animation-expected.txt": [
@@ -372893,7 +372743,7 @@
    "testharness"
   ],
   "web-animations/timing-model/animations/updating-the-finished-state.html": [
-   "59e7ed8e4eac5c9edf2526ef748b22e1877b7016",
+   "8eea7caf9f0bf8b9a87b5a6574a28b378054c8db",
    "testharness"
   ],
   "web-animations/timing-model/time-transformations/transformed-progress-expected.txt": [
@@ -373304,6 +373154,10 @@
    "99284ab790c09dd7a23a6fa5022e8b08b9e3947d",
    "testharness"
   ],
+  "webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-disconnected-input.https.html": [
+   "bf3ebb3a403b24078b7e8c2ff7073dcbc486bb27",
+   "testharness"
+  ],
   "webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-onerror.https.html": [
    "a1cd969fe32a5aca7cd90d0d0955132fd1660b9c",
    "testharness"
@@ -373328,6 +373182,10 @@
    "1561b9eede1ee15126fdd9674a6d9d63194b66c2",
    "support"
   ],
+  "webaudio/the-audio-api/the-audioworklet-interface/processors/input-length-processor.js": [
+   "bd6e7a669a2c445ecfd3de4dd6b48a4d84b214cc",
+   "support"
+  ],
   "webaudio/the-audio-api/the-audioworklet-interface/processors/one-pole-processor.js": [
    "80b817db4e8d3f49e4f5fe6e97f8e687d16f3159",
    "support"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/absolute-positioning-grid-container-containing-block-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/absolute-positioning-grid-container-containing-block-001.html
index a447ead..e456af8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/absolute-positioning-grid-container-containing-block-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/absolute-positioning-grid-container-containing-block-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <meta name="assert" content="This test checks the behavior of the absolutely positioned elements with a grid container as containing block.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/absolute-positioning-grid-container-parent-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/absolute-positioning-grid-container-parent-001.html
index 82e6063..e798b80 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/absolute-positioning-grid-container-parent-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/absolute-positioning-grid-container-parent-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <meta name="assert" content="This test checks the behavior of the absolutely positioned elements with a grid container as parent.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-paint-positioned-children-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-paint-positioned-children-001.html
index 7528b084..ae074da 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-paint-positioned-children-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-paint-positioned-children-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="match" href="grid-paint-positioned-children-001-ref.html">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   border: 2px solid black;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-children-writing-modes-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-children-writing-modes-001-ref.html
index 3610cd3..e8ab242 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-children-writing-modes-001-ref.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-children-writing-modes-001-ref.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8">
 <title>CSS Grid Layout Test: Grid positioned children writing modes reference test</title>
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-children-writing-modes-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-children-writing-modes-001.html
index b922639..eb85527 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-children-writing-modes-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-children-writing-modes-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="match" href="grid-positioned-children-writing-modes-001-ref.html">
 <meta name="assert" content="This test checks the behavior of the positioned grid children in combination with the writing modes and text direction properties.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html
index 849567c..81ea909d0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html
@@ -6,7 +6,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
 <meta name="assert" content="This test checks that positioned items don't avoid auto-fit tracks to collapse.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .container {
   width: 200px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html
index 7271081..27fc722 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html
@@ -6,7 +6,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
 <meta name="assert" content="This test checks tracks before the first in-flow item also collapse and positioned items don't have any impact.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .container {
   width: 200px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html
index 05ac15d..1c893392 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html
@@ -6,7 +6,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
 <meta name="assert" content="This test checks that positioned items will use the area defined by the in-flow items, ignoring any collapsed track.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .container {
   width: 200px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html
index 13b29ea9..54b2ff7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html
@@ -6,7 +6,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
 <meta name="assert" content="This test checks that positioned items ignore collapsed gaps.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .container {
   width: 200px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html
index 70695c4..56f870f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html
@@ -6,7 +6,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
 <meta name="assert" content="This test checks that positioned items ignore collapsed gaps, both before and after the first in-flow item .">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .container {
   width: 200px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html
index 5b79220..e301d349 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html
@@ -6,7 +6,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
 <meta name="assert" content="This test checks that positioned items ignore collapsed gaps but consider those between in-flow items inside their grid area.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .container {
   width: 200px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html
index 1f995802..8c46216 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html
@@ -6,7 +6,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
 <meta name="assert" content="This test checks that positioned items ignore collapsed gaps even with non-empty tracks before and after.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .container {
   width: 250px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-background-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-background-001.html
index 2b299cd..19ee662e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-background-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-background-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="match" href="grid-positioned-items-background-001-ref.html">
 <meta name="assert" content="This test checks that the background of positioned items is painted in the right position">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-background-rtl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-background-rtl-001.html
index 50741e2f..9ed046b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-background-rtl-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-background-rtl-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="match" href="grid-positioned-items-background-rtl-001-ref.html">
 <meta name="assert" content="This test checks that the background of positioned items is painted in the right position using RTL direction.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-content-alignment-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-content-alignment-001.html
index 80b795d..ebff62aa 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-content-alignment-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-content-alignment-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-align" title="10.5. Aligning the Grid: the justify-content and align-content properties">
 <meta name="assert" content="This test checks the behavior of the positioned items in a grid using content alignment.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <link rel="stylesheet" href="../../support/alignment.css">
 <style>
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-content-alignment-rtl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-content-alignment-rtl-001.html
index ad9147e2..628a63c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-content-alignment-rtl-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-content-alignment-rtl-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-align" title="10.5. Aligning the Grid: the justify-content and align-content properties">
 <meta name="assert" content="This test checks the behavior of the positioned items in a grid using content alignment in RTL.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <link rel="stylesheet" href="../../support/alignment.css">
 <style>
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-001.html
index e1adc6b..b9f3343e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#gutters" title="10.1. Gutters: the row-gap, column-gap, and gap properties">
 <meta name="assert" content="This test checks the behavior of the positioned items in a grid container with gaps.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-rtl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-rtl-001.html
index 4a6cd88..16ab39d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-rtl-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-rtl-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#gutters" title="10.1. Gutters: the row-gap, column-gap, and gap properties">
 <meta name="assert" content="This test checks the behavior of the positioned items in a grid container with gaps in RTL.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-001.html
index 6d62088..71f096a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#implicit-grids" title="7.5. The Implicit Grid">
 <meta name="assert" content="This test checks the behavior of the absolutely positioned grid items placed on the implicit grid.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-line-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-line-001.html
index f0f98d2..7b8fa4e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-line-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-line-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#implicit-grids" title="7.5. The Implicit Grid">
 <meta name="assert" content="This test checks that grid placement properties of absolutely positioned items using implicit grid lines are treated as 'auto'.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-padding-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-padding-001.html
index a0ccd1ef..4941d77 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-padding-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-padding-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <meta name="assert" content="This test checks that positioned grid items can be placed directly on the padding.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-unknown-named-grid-line-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-unknown-named-grid-line-001.html
index a50e12ab..24d9d76 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-unknown-named-grid-line-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-unknown-named-grid-line-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <meta name="assert" content="This test checks that grid placement properties of absolutely positioned items using unknown named grid lines are treated as 'auto'.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-within-grid-implicit-track-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-within-grid-implicit-track-001.html
index fb9cad1..5a31c35 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-within-grid-implicit-track-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-positioned-items-within-grid-implicit-track-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#implicit-grids" title="7.5. The Implicit Grid">
 <meta name="assert" content="This test checks that positioned grid items are placed properly (including implicit tracks) even if the grid has implicit tracks.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-sizing-positioned-items-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-sizing-positioned-items-001.html
index 2acae44e..0e8cd33 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-sizing-positioned-items-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/grid-sizing-positioned-items-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <meta name="assert" content="This test checks the different size options for absolutely positioned grid items.">
-<link href="../support/grid.css" rel="stylesheet">
+<link href="support/grid.css" rel="stylesheet">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html
index 56aa0e1..5ef006ae 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <meta name="assert" content="This test checks that positioned items shouldn't create implicit tracks on the grid.">
-<link href="../support/grid.css" rel="stylesheet">
+<link href="support/grid.css" rel="stylesheet">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-should-not-take-up-space-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-should-not-take-up-space-001.html
index a6834cb0..597e7780 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-should-not-take-up-space-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-should-not-take-up-space-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
 <meta name="assert" content="This test checks that positioned items shouldn't take up space or otherwise participate in the layout of the grid.">
-<link href="../support/grid.css" rel="stylesheet">
+<link href="support/grid.css" rel="stylesheet">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-sizing-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-sizing-001-ref.html
index a468863..2ded937a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-sizing-001-ref.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-sizing-001-ref.html
@@ -3,7 +3,7 @@
 <title>CSS Grid Layout Test: Positioned grid items sizing reference file</title>
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <meta name="flags" content="ahem">
-<link href="../support/grid.css" rel="stylesheet">
+<link href="support/grid.css" rel="stylesheet">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-sizing-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-sizing-001.html
index ae12806..4f84957 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-sizing-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/positioned-grid-items-sizing-001.html
@@ -6,7 +6,7 @@
 <link rel="match" href="positioned-grid-items-sizing-001-ref.html">
 <meta name="assert" content="This test checks that the sizing of positioned grid items without specific dimensions or offsets is equivalent to the size of regular items.">
 <meta name="flags" content="ahem">
-<link href="../support/grid.css" rel="stylesheet">
+<link href="support/grid.css" rel="stylesheet">
 <style>
 
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/support/grid.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/support/grid.css
similarity index 100%
rename from third_party/WebKit/LayoutTests/external/wpt/css/css-grid/support/grid.css
rename to third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/support/grid.css
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-change-fit-content-argument-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-change-fit-content-argument-001.html
index d08712d3..9441b0a4 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-change-fit-content-argument-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-change-fit-content-argument-001.html
@@ -6,7 +6,7 @@
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#track-sizing">
 <meta name="assert" content="This test checks that grid-template-{rows|columns} with fit-content() tracks recomputes the tracks when the fit-content() argument is modified.">
 <meta name="flags" content="ahem">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   width: fit-content;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html
index cb7a582..f90bd047 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html
@@ -3,7 +3,7 @@
 <meta charset="utf-8">
 <title>CSS Grid Layout Test: grid-template-columns fit-content() reference file</title>
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <meta name="flags" content="ahem">
 <style>
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-columns-fit-content-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-columns-fit-content-001.html
index d492d45..c594d805 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-columns-fit-content-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-columns-fit-content-001.html
@@ -7,7 +7,7 @@
 <link rel="match" href="grid-template-columns-fit-content-001-ref.html">
 <meta name="assert" content="This test checks that 'fit-content()' works as expected in grid-template-columns, i.e., it's similar to 'auto' ('minmax(auto, max-content)') except that the growth limit is clamped at the argument of 'fit-content' (if greater than the 'auto' minimum).">
 <meta name="flags" content="ahem">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   justify-content: start;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html
index a1f83dc8..a6785fc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html
@@ -3,7 +3,7 @@
 <meta charset="utf-8">
 <title>CSS Grid Layout Test: grid-template-rows fit-content() reference file</title>
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <meta name="flags" content="ahem">
 <style>
 .grid {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-rows-fit-content-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-rows-fit-content-001.html
index 6d406c3f..2931960 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-rows-fit-content-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-template-rows-fit-content-001.html
@@ -7,7 +7,7 @@
 <link rel="match" href="grid-template-rows-fit-content-001-ref.html">
 <meta name="assert" content="This test checks that 'fit-content()' works as expected in grid-template-rows, i.e., it's similar to 'auto' ('minmax(auto, max-content)') except that the growth limit is clamped at the argument of 'fit-content' (if greater than the 'auto' minimum).">
 <meta name="flags" content="ahem">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   justify-content: start;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/support/grid.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/support/grid.css
similarity index 100%
copy from third_party/WebKit/LayoutTests/external/wpt/css/css-grid/support/grid.css
copy to third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/support/grid.css
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-001.html
index 26374115..00487f76 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-items">
 <meta name="assert" content="Checks that grid items minimum width takes into account borders, padding and margins for grid containers with definite width.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   width: 100px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-002.html
index 3775479b..c9f77a6e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-002.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-items">
 <meta name="assert" content="Checks that grid items minimum width takes into account borders, padding and margins for grid containers with indefinite width.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   display: inline-grid;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-orthogonal-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-orthogonal-001.html
index e3128d9..943837d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-orthogonal-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-orthogonal-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-items">
 <meta name="assert" content="Checks that orthogonal grid items minimum width takes into account borders, padding and margins for grid containers with definite width.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   width: 100px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-orthogonal-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-orthogonal-002.html
index 37aab4e0..25ad710 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-orthogonal-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-orthogonal-002.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-items">
 <meta name="assert" content="Checks that orthogonal grid items minimum width takes into account borders, padding and margins for grid containers with indefinite width.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   display: inline-grid;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-lr-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-lr-001.html
index d72c0668..1afe6df 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-lr-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-lr-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-items">
 <meta name="assert" content="Checks that grid items minimum width takes into account borders, padding and margins for grid containers with definite width in vertical-lr.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   width: 100px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-lr-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-lr-002.html
index 6eb3b0ab..a239369e4 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-lr-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-lr-002.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-items">
 <meta name="assert" content="Checks that grid items minimum width takes into account borders, padding and margins for grid containers with indefinite width in vertical-lr.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   display: inline-grid;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-rl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-rl-001.html
index 48e6461f..df3fe9b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-rl-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-rl-001.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-items">
 <meta name="assert" content="Checks that grid items minimum width takes into account borders, padding and margins for grid containers with definite width in vertical-rl.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   width: 100px;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-rl-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-rl-002.html
index e534ec9..3978ed60 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-rl-002.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-items-minimum-width-vertical-rl-002.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-items">
 <meta name="assert" content="Checks that grid items minimum width takes into account borders, padding and margins for grid containers with indefinite width in vertical-rl.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   display: inline-grid;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html
index 127ea8d..ce1db93 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="http://www.w3.org/TR/css-grid-1/#min-size-auto" title="6.5. Implied Minimum Size of Grid Items">
 <meta name="assert" content="Checks that automatic minimum size is clamped with different column sizes.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   border: solid thick;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-023.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-023.html
index 636a40fc..c5e6da55 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-023.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-023.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="http://www.w3.org/TR/css-grid-1/#min-size-auto" title="6.5. Implied Minimum Size of Grid Items">
 <meta name="assert" content="Checks that automatic minimum size is clamped with different row sizes.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   border: solid thick;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-024.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-024.html
index fb706bf..c77556c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-024.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-024.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="http://www.w3.org/TR/css-grid-1/#min-size-auto" title="6.5. Implied Minimum Size of Grid Items">
 <meta name="assert" content="Checks that automatic minimum size is clamped with different column sizes and spaning items.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   border: solid thick;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-025.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-025.html
index 722426e..a3c35a5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-025.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/grid-minimum-size-grid-items-025.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
 <link rel="help" href="http://www.w3.org/TR/css-grid-1/#min-size-auto" title="6.5. Implied Minimum Size of Grid Items">
 <meta name="assert" content="Checks that automatic minimum size is clamped with different row sizes and spaning items.">
-<link rel="stylesheet" href="../support/grid.css">
+<link rel="stylesheet" href="support/grid.css">
 <style>
 .grid {
   border: solid thick;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/support/grid.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/support/grid.css
similarity index 100%
copy from third_party/WebKit/LayoutTests/external/wpt/css/css-grid/support/grid.css
copy to third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-items/support/grid.css
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html
index f94fdcfe..b8e344e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="http://www.w3.org/TR/css-grid-1/#grid-containers">
 <link rel="help" href="http://www.w3.org/TR/css3-selectors/#first-letter">
 <meta name="assert" content="The test checks that grid item should ignore grid container's first-letter pseudo-element.">
-<link href="../support/grid.css" rel="stylesheet">
+<link href="support/grid.css" rel="stylesheet">
 <style>
   body { line-height: 20px; }
   .grid-first-letter::first-letter { line-height: 100px; color: red; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-ignores-first-line-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-ignores-first-line-001.html
index b491298..140d7bf 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-ignores-first-line-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-ignores-first-line-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="http://www.w3.org/TR/css-grid-1/#grid-containers">
 <link rel="help" href="http://www.w3.org/TR/css3-selectors/#first-formatted-line">
 <meta name="assert" content="The test checks that grid item should ignore grid container's first-line pseudo-element.">
-<link href="../support/grid.css" rel="stylesheet">
+<link href="support/grid.css" rel="stylesheet">
 <style>
   body { line-height: 20px; }
   .grid-first-line::first-line { line-height: 100px; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-item-accepts-first-letter-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-item-accepts-first-letter-001.html
index c9454fe..b6914eb5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-item-accepts-first-letter-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-item-accepts-first-letter-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="http://www.w3.org/TR/css-grid-1/#grid-containers">
 <link rel="help" href="http://www.w3.org/TR/css3-selectors/#first-letter">
 <meta name="assert" content="The test checks that grid items accept first-letter pseudo-element.">
-<link href="../support/grid.css" rel="stylesheet">
+<link href="support/grid.css" rel="stylesheet">
 <style>
   .item::first-letter { line-height: 100px; }
 </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-item-accepts-first-line-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-item-accepts-first-line-001.html
index 1330b376..8bf8c653 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-item-accepts-first-line-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-item-accepts-first-line-001.html
@@ -5,7 +5,7 @@
 <link rel="help" href="http://www.w3.org/TR/css-grid-1/#grid-containers">
 <link rel="help" href="http://www.w3.org/TR/css3-selectors/#first-formatted-line">
 <meta name="assert" content="The test checks that grid items accept first-line pseudo-element.">
-<link href="../support/grid.css" rel="stylesheet">
+<link href="support/grid.css" rel="stylesheet">
 <style>
   .item::first-line { line-height: 100px; }
 </style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/support/grid.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/support/grid.css
similarity index 100%
copy from third_party/WebKit/LayoutTests/external/wpt/css/css-grid/support/grid.css
copy to third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/support/grid.css
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-001.html
new file mode 100644
index 0000000..6bf12aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-001.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>CSS Scoping Module Level 1 - Dynamic fallback content</title>
+<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
+<link rel="match" href="reference/green-box.html"/>
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<div id="host">
+  <span slot="myslot">FAIL</span>
+</div>
+<script>
+  let root = host.attachShadow({ mode: "open" });
+  root.innerHTML = `
+    <slot name="myslot">
+      <div style="width: 100px; height: 100px; background: green"></div>
+    </slot>
+  `;
+  document.body.offsetTop;
+  host.firstElementChild.remove();
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-002.html
new file mode 100644
index 0000000..7553049e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-002.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>CSS Scoping Module Level 1 - Dynamic fallback content</title>
+<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
+<link rel="match" href="reference/green-box.html"/>
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<div id="host">
+  <span slot="myslot">FAIL</span>
+</div>
+<script>
+  let root = host.attachShadow({ mode: "open" });
+  root.innerHTML = `
+    <slot name="myslot">
+      <div style="width: 100px; height: 100px; background: green"></div>
+    </slot>
+  `;
+  document.body.offsetTop;
+  host.firstElementChild.removeAttribute("slot");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-003.html
new file mode 100644
index 0000000..59f8b53
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-003.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>CSS Scoping Module Level 1 - Dynamic fallback content</title>
+<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
+<link rel="match" href="reference/green-box.html"/>
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<div id="host">
+</div>
+<script>
+  let root = host.attachShadow({ mode: "open" });
+  root.innerHTML = `
+    <slot name="myslot">FAIL</slot>
+  `;
+  document.body.offsetTop;
+  host.innerHTML = `
+    <div slot="myslot" style="width: 100px; height: 100px; background: green"></div>
+  `;
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-004.html
new file mode 100644
index 0000000..b301741
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-004.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>CSS Scoping Module Level 1 - Dynamic fallback content</title>
+<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
+<link rel="match" href="reference/green-box.html"/>
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<div id="host">
+  <div slot="myslot" style="width: 100px; height: 100px; background: green"></div>
+</div>
+<script>
+  let root = host.attachShadow({ mode: "open" });
+  root.innerHTML = `
+    <slot name="myslot"></slot>
+  `;
+  document.body.offsetTop;
+  let newSlot = document.createElement('slot');
+  newSlot.appendChild(document.createTextNode("FAIL"));
+  newSlot.setAttribute("name", "myslot");
+  root.insertBefore(newSlot, root.firstChild);
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-005.html
new file mode 100644
index 0000000..ff030c0c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-fallback-dynamic-005.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>CSS Scoping Module Level 1 - Dynamic fallback content</title>
+<link rel="author" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-scoping/#selectors-data-model">
+<link rel="match" href="reference/green-box.html"/>
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<div id="host">
+  <div slot="myslot" style="width: 100px; height: 100px; background: green"></div>
+</div>
+<script>
+  let root = host.attachShadow({ mode: "open" });
+  root.innerHTML = `
+    <slot name="myslot"></slot>
+    <slot name="myotherslot">
+      FAIL
+    </slot>
+  `;
+  document.body.offsetTop;
+  host.firstElementChild.setAttribute("slot", "myotherslot");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes/shape-outside/formatting-context/reference/shape-outside-formatting-context-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes/shape-outside/formatting-context/reference/shape-outside-formatting-context-ref.html
new file mode 100644
index 0000000..2fd6df9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes/shape-outside/formatting-context/reference/shape-outside-formatting-context-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<style>
+.test {
+  width: 200px;
+  overflow: hidden;
+}
+
+.float {
+  float: left;
+  width: 50%;
+  height: 100px;
+
+  background: orange;
+  clip-path: polygon(0 0, 100% 100%, 0 100%);
+}
+
+.flex {
+  display: flex;
+  height: 50px;
+  background: rebeccapurple;
+}
+</style>
+<div class="test">
+  <div class="float"></div>
+  <div class="flex"></div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes/shape-outside/formatting-context/shape-outside-formatting-context.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes/shape-outside/formatting-context/shape-outside-formatting-context.tentative.html
new file mode 100644
index 0000000..cfb5d46a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-shapes/shape-outside/formatting-context/shape-outside-formatting-context.tentative.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<link rel="match" href="reference/shape-outside-formatting-context-ref.html">
+<link rel="help" href="https://drafts.csswg.org/css-shapes/">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/1970">
+<meta name="assert" content="The test verifies that a new formatting context does *not* get sized and positioned based off the float area (defined by shape outside).">
+<style>
+.test {
+  width: 200px;
+  overflow: hidden;
+}
+
+.float {
+  float: left;
+  width: 50%;
+  height: 100px;
+
+  background: orange;
+  shape-outside: polygon(0 0, 100% 100%, 0 100%);
+  clip-path: polygon(0 0, 100% 100%, 0 100%);
+}
+
+.flex {
+  display: flex;
+  height: 50px;
+  background: rebeccapurple;
+}
+</style>
+<div class="test">
+  <div class="float"></div>
+  <div class="flex"></div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
index e4324a7d..c6a73d0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 1945 tests; 1940 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1957 tests; 1937 PASS, 20 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver
 PASS WorkerGlobalScope interface: existence and properties of interface object
 PASS DedicatedWorkerGlobalScope interface: existence and properties of interface object
@@ -1629,22 +1629,34 @@
 PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError
 PASS EventTarget interface: document.createComment("abc") must inherit property "dispatchEvent(Event)" with the proper type
 PASS EventTarget interface: calling dispatchEvent(Event) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Range interface: existence and properties of interface object
+FAIL AbstractRange interface: existence and properties of interface object assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+FAIL AbstractRange interface object length assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+FAIL AbstractRange interface object name assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+FAIL AbstractRange interface: existence and properties of interface prototype object assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+FAIL AbstractRange interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+FAIL AbstractRange interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+FAIL AbstractRange interface: attribute startContainer assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+PASS Unscopable handled correctly for startContainer property on AbstractRange
+FAIL AbstractRange interface: attribute startOffset assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+PASS Unscopable handled correctly for startOffset property on AbstractRange
+FAIL AbstractRange interface: attribute endContainer assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+PASS Unscopable handled correctly for endContainer property on AbstractRange
+FAIL AbstractRange interface: attribute endOffset assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+PASS Unscopable handled correctly for endOffset property on AbstractRange
+FAIL AbstractRange interface: attribute collapsed assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
+PASS Unscopable handled correctly for collapsed property on AbstractRange
+FAIL StaticRange interface: existence and properties of interface object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing
+PASS StaticRange interface object length
+PASS StaticRange interface object name
+FAIL StaticRange interface: existence and properties of interface prototype object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing
+PASS StaticRange interface: existence and properties of interface prototype object's "constructor" property
+PASS StaticRange interface: existence and properties of interface prototype object's @@unscopables property
+FAIL Range interface: existence and properties of interface object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing
 PASS Range interface object length
 PASS Range interface object name
-PASS Range interface: existence and properties of interface prototype object
+FAIL Range interface: existence and properties of interface prototype object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing
 PASS Range interface: existence and properties of interface prototype object's "constructor" property
 PASS Range interface: existence and properties of interface prototype object's @@unscopables property
-PASS Range interface: attribute startContainer
-PASS Unscopable handled correctly for startContainer property on Range
-PASS Range interface: attribute startOffset
-PASS Unscopable handled correctly for startOffset property on Range
-PASS Range interface: attribute endContainer
-PASS Unscopable handled correctly for endContainer property on Range
-PASS Range interface: attribute endOffset
-PASS Unscopable handled correctly for endOffset property on Range
-PASS Range interface: attribute collapsed
-PASS Unscopable handled correctly for collapsed property on Range
 PASS Range interface: attribute commonAncestorContainer
 PASS Unscopable handled correctly for commonAncestorContainer property on Range
 PASS Range interface: operation setStart(Node, unsigned long)
@@ -1698,11 +1710,6 @@
 PASS Range interface: stringifier
 PASS Range must be primary interface of document.createRange()
 PASS Stringification of document.createRange()
-PASS Range interface: document.createRange() must inherit property "startContainer" with the proper type
-PASS Range interface: document.createRange() must inherit property "startOffset" with the proper type
-PASS Range interface: document.createRange() must inherit property "endContainer" with the proper type
-PASS Range interface: document.createRange() must inherit property "endOffset" with the proper type
-PASS Range interface: document.createRange() must inherit property "collapsed" with the proper type
 PASS Range interface: document.createRange() must inherit property "commonAncestorContainer" with the proper type
 PASS Range interface: document.createRange() must inherit property "setStart(Node, unsigned long)" with the proper type
 PASS Range interface: calling setStart(Node, unsigned long) on document.createRange() with too few arguments must throw TypeError
@@ -1743,13 +1750,13 @@
 PASS Range interface: calling comparePoint(Node, unsigned long) on document.createRange() with too few arguments must throw TypeError
 PASS Range interface: document.createRange() must inherit property "intersectsNode(Node)" with the proper type
 PASS Range interface: calling intersectsNode(Node) on document.createRange() with too few arguments must throw TypeError
+PASS AbstractRange interface: document.createRange() must inherit property "startContainer" with the proper type
+PASS AbstractRange interface: document.createRange() must inherit property "startOffset" with the proper type
+PASS AbstractRange interface: document.createRange() must inherit property "endContainer" with the proper type
+PASS AbstractRange interface: document.createRange() must inherit property "endOffset" with the proper type
+PASS AbstractRange interface: document.createRange() must inherit property "collapsed" with the proper type
 PASS Range must be primary interface of detachedRange
 PASS Stringification of detachedRange
-PASS Range interface: detachedRange must inherit property "startContainer" with the proper type
-PASS Range interface: detachedRange must inherit property "startOffset" with the proper type
-PASS Range interface: detachedRange must inherit property "endContainer" with the proper type
-PASS Range interface: detachedRange must inherit property "endOffset" with the proper type
-PASS Range interface: detachedRange must inherit property "collapsed" with the proper type
 PASS Range interface: detachedRange must inherit property "commonAncestorContainer" with the proper type
 PASS Range interface: detachedRange must inherit property "setStart(Node, unsigned long)" with the proper type
 PASS Range interface: calling setStart(Node, unsigned long) on detachedRange with too few arguments must throw TypeError
@@ -1790,6 +1797,11 @@
 PASS Range interface: calling comparePoint(Node, unsigned long) on detachedRange with too few arguments must throw TypeError
 PASS Range interface: detachedRange must inherit property "intersectsNode(Node)" with the proper type
 PASS Range interface: calling intersectsNode(Node) on detachedRange with too few arguments must throw TypeError
+PASS AbstractRange interface: detachedRange must inherit property "startContainer" with the proper type
+PASS AbstractRange interface: detachedRange must inherit property "startOffset" with the proper type
+PASS AbstractRange interface: detachedRange must inherit property "endContainer" with the proper type
+PASS AbstractRange interface: detachedRange must inherit property "endOffset" with the proper type
+PASS AbstractRange interface: detachedRange must inherit property "collapsed" with the proper type
 PASS NodeIterator interface: existence and properties of interface object
 PASS NodeIterator interface object length
 PASS NodeIterator interface object name
diff --git a/third_party/WebKit/LayoutTests/external/wpt/domxpath/document.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/domxpath/document.tentative.html
new file mode 100644
index 0000000..c44ebd99
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/domxpath/document.tentative.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>XPath parent of documentElement</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<body>
+<script>
+test(function() {
+  var result = document.evaluate("..", // expression
+                                document.documentElement, // context node
+                                null, // resolver
+                                XPathResult.ANY_TYPE, // type
+                                null); // result
+  var matched = [];
+  var cur;
+  while ((cur = result.iterateNext()) !== null) {
+    matched.push(cur);
+  }
+  assert_array_equals(matched, [document]);
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/eventsource/dedicated-worker/eventsource-close2.htm b/third_party/WebKit/LayoutTests/external/wpt/eventsource/dedicated-worker/eventsource-close2.htm
new file mode 100644
index 0000000..b1b74e8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/eventsource/dedicated-worker/eventsource-close2.htm
@@ -0,0 +1,29 @@
+<!--
+self.close()
+var source = new EventSource("../resources/message.py")
+postMessage(source.readyState)
+/*-->
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>dedicated worker - EventSource created after: worker.close()</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+  </head>
+  <body>
+    <div id="log"></div>
+    <script>
+      var test = async_test();
+      test.step(function() {
+        var worker = new Worker('#')
+        worker.onmessage = function(e) {
+          test.step(function() {
+            assert_equals(e.data, EventSource.CONNECTING, 'this.readyState')
+          })
+          test.done()
+        }
+      })
+    </script>
+  </body>
+</html>
+<!--*/ //-->
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/dom.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/dom.idl
index ae65018..4186f1d2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/dom.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/dom.idl
@@ -440,14 +440,22 @@
 };
 
 
-[Constructor,
- Exposed=Window]
-interface Range {
+[Exposed=Window]
+interface AbstractRange {
   readonly attribute Node startContainer;
   readonly attribute unsigned long startOffset;
   readonly attribute Node endContainer;
   readonly attribute unsigned long endOffset;
   readonly attribute boolean collapsed;
+};
+
+[Exposed=Window]
+interface StaticRange : AbstractRange {
+};
+
+[Constructor,
+ Exposed=Window]
+interface Range : AbstractRange {
   readonly attribute Node commonAncestorContainer;
 
   void setStart(Node node, unsigned long offset);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_error.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_error.https-expected.txt
new file mode 100644
index 0000000..8bc4e328
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_error.https-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+FAIL Constructing a PresentationRequest (Error) assert_throws: Call PresentationRequest constructor with an unsupported URL. NotSupportedError expected. function "() => {
+        new PresentationRequest('unsupported://example.com');
+    }" did not throw
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_error.https.html b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_error.https.html
index d6324ea56b..c5ab466 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_error.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_error.https.html
@@ -1,33 +1,36 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>Presentation API PresentationRequest for Controlling User Agent (Error)</title>
+<title>Constructing a PresentationRequest (Error)</title>
 <link rel="author" title="Franck William Taffo" href="http://www.fokus.fraunhofer.de">
-<link rel="help" href="http://w3c.github.io/presentation-api/#dfn-controlling-user-agent">
+<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs">
+<link rel="help" href="http://w3c.github.io/presentation-api/#constructing-a-presentationrequest">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
 
-    test(function() {
-        assert_throws(new TypeError(), function() {
-            new PresentationRequest();
-        });
+  test(() => {
+    assert_throws(new TypeError(), () => {
+      new PresentationRequest();
     }, 'Call PresentationRequest() constructor without presentation URL. TypeError Exception expected.');
 
-    test(function() {
-        assert_throws('NotSupportedError', function() {
-            new PresentationRequest([]);
-        });
+    assert_throws('NotSupportedError', () => {
+      new PresentationRequest([]);
     }, 'Call PresentationRequest constructor with an empty sequence. NotSupportedError Exception expected.');
 
-    test(function() {
-        assert_throws('SyntaxError', function() {
-            new PresentationRequest('http://@');
-        });
+    assert_throws('SyntaxError', () => {
+      new PresentationRequest('http://@');
     }, 'Call PresentationRequest constructor with an invalid URL. SyntaxError Exception expected.');
 
-    test(function() {
-        assert_throws('SyntaxError', function() {
-            new PresentationRequest(['presentation.html', 'http://@']);
-        });
+    assert_throws('NotSupportedError', () => {
+        new PresentationRequest('unsupported://example.com');
+    }, 'Call PresentationRequest constructor with an unsupported URL. NotSupportedError expected.');
+
+    assert_throws('SyntaxError', function() {
+      new PresentationRequest(['presentation.html', 'http://@']);
     }, 'Call PresentationRequest constructor with a sequence of URLs, one of them invalid. SyntaxError Exception expected.');
+
+    assert_throws('NotSupportedError', function() {
+      new PresentationRequest(['unsupported://example.com', 'invalid://example.com']);
+    }, 'Call PresentationRequest constructor only with a sequence of unsupported URLs. NotSupportedError Exception expected.');
+  });
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_success.https.html b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_success.https.html
index 70ea5a80..890e0ed6 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_success.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/presentation-api/controlling-ua/PresentationRequest_success.https.html
@@ -8,17 +8,24 @@
 <script src="/resources/testharnessreport.js"></script>
 
 <script>
-    test(() => {
-        let request = new PresentationRequest('presentation.html');
-        assert_true(request instanceof PresentationRequest, 'An instance of PresentationRequest with a relative presentation URL is constructed successfully.');
+  test(() => {
+    let request = new PresentationRequest('presentation.html');
+    assert_true(request instanceof PresentationRequest, 'An instance of PresentationRequest with a relative presentation URL is constructed successfully.');
 
-        request = new PresentationRequest('https://example.org/');
-        assert_true(request instanceof PresentationRequest, 'An instance of PresentationRequest with an absolute presentation URL is constructed successfully.');
+    request = new PresentationRequest('https://example.org/');
+    assert_true(request instanceof PresentationRequest, 'An instance of PresentationRequest with an absolute presentation URL is constructed successfully.');
 
-        request = new PresentationRequest([
-            'presentation.html',
-            'https://example.org/presentation/'
-        ]);
-        assert_true(request instanceof PresentationRequest, 'An instance of PresentationRequest with an array of presentation URLs is constructed successfully.');
-    });
+    request = new PresentationRequest([
+      'presentation.html',
+      'https://example.org/presentation/'
+    ]);
+    assert_true(request instanceof PresentationRequest, 'An instance of PresentationRequest with an array of presentation URLs is constructed successfully.');
+
+    request = new PresentationRequest([
+      'unsupported://example.com',
+      'presentation.html',
+      'https://example.org/presentation/'
+    ]);
+    assert_true(request instanceof PresentationRequest, 'An unsupported URL in an array of presentation URLs is ignored successfully.');
+  });
 </script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resource_frame_initiator_type.html b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resource_frame_initiator_type.html
deleted file mode 100644
index f647198..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resource_frame_initiator_type.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8" />
-<title>Resource Timing frame initiator type</title>
-<link rel="author" title="Google" href="http://www.google.com/" />
-<link rel="help" href="http://www.w3.org/TR/resource-timing/#dom-performanceresourcetiming-initiatortype"/>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/webperftestharness.js"></script>
-<script src="resources/webperftestharnessextension.js"></script>
-<script>
-setup({explicit_done: true});
-
-function onload_test() {
-    const iframe = document.getElementById('frameContext');
-    const context = new PerformanceContext(iframe.contentWindow.performance);
-    const entries = context.getEntriesByType('resource');
-
-    const index = window.location.pathname.lastIndexOf('/');
-    const pathname = window.location.pathname.substring(0, index) +
-      '/resources/blank_page_green.htm';
-    const expected_entries = {};
-    expected_entries[pathname] = 'frame';
-
-    test_resource_entries(entries, expected_entries);
-    done();
-}
-</script>
-</head>
-<body>
-<h1>Description</h1>
-<p>This test validates that the frame initiator type is represented.</p>
-<div id="log"></div>
-<iframe id="frameContext" onload="onload_test();" src="resources/green_frame.htm" style="width: 250px; height: 250px;"></iframe>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resource_initiator_types.html b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resource_initiator_types.html
index 30f8c0c0..69cb23b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resource_initiator_types.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resource_initiator_types.html
@@ -18,6 +18,7 @@
 let ul_font_loaded = false;
 let xhr_loaded = false;
 let tests_run = false;
+let frameset_loaded = false;
 
 function check_finished() {
     if (!ul_font_loaded) {
@@ -26,7 +27,7 @@
     if (!ol_font_loaded) {
         ol_font_loaded = check_font_loaded('ol');
     }
-    if (page_loaded && ol_font_loaded && ul_font_loaded && background_loaded && xhr_loaded) {
+    if (page_loaded && ol_font_loaded && ul_font_loaded && background_loaded && xhr_loaded && frameset_loaded) {
         perform_test();
     } else {
         step_timeout(check_finished, 100);
@@ -64,40 +65,88 @@
     step_timeout(check_finished, 100);
 }
 
+function frameset_onload() {
+    frameset_loaded = true;
+
+    step_timeout(check_finished, 100);
+}
+
 function perform_test() {
     if (tests_run) {
         return;
     }
     tests_run = true;
     const context = new PerformanceContext(document.getElementById('frameContext').contentWindow.performance);
-    const entries = context.getEntriesByType('resource');
+    let entries = context.getEntriesByType('resource');
+
+    // check for frameset
+    if (document.getElementById('frameContext2') &&
+        document.getElementById('frameContext2').contentWindow) {
+        const context2 = new PerformanceContext(document.getElementById('frameContext2').contentWindow.performance);
+        entries = entries.concat(context2.getEntriesByType('resource'));
+    }
 
     const index = window.location.pathname.lastIndexOf('/');
     const pathname = window.location.pathname.substring(0, index) + '/resources/';
     const font_pathname = window.location.pathname.substring(0, index - 15) + 'fonts/Ahem.ttf';
 
     let expected_entries = {};
-    expected_entries[font_pathname] = 'css';
-    expected_entries[pathname + 'resource_timing_test0.png'] = 'img';
-    expected_entries[pathname + 'blank_page_green.htm'] = 'iframe';
-    expected_entries[pathname + 'empty_script.js'] = 'script';
-    expected_entries[pathname + 'resource_timing_test0.css?id=embed'] = 'embed';
-    expected_entries[pathname + 'resource_timing_test0.css?id=n1'] = 'css';
-    expected_entries[font_pathname + '?id=n1'] = 'css';
-    expected_entries[pathname + 'blue.png?id=1'] = 'css';
-    expected_entries[pathname + 'blue.png?id=2'] = 'css';
-    expected_entries[pathname + 'blue.png?id=async_xhr'] = 'xmlhttprequest';
-    expected_entries[pathname + 'blue.png?id=body'] = 'body';
-    expected_entries[pathname + 'blue.png?id=input'] = 'input';
-    expected_entries[pathname + 'blue.png?id=n1'] = 'css';
-    expected_entries[pathname + 'blue.png?id=object'] = 'object';
-    expected_entries[pathname + 'blue.png?id=poster'] = 'video';
-    expected_entries[pathname + 'nested.css'] = 'link';
+    addEntryIfExists(entries, expected_entries, font_pathname, 'css');
+    addEntryIfExists(entries, expected_entries, pathname + 'resource_timing_test0.png', 'img');
+    addEntryIfExists(entries, expected_entries, pathname + 'resource_timing_test0.png?id=srcset-srcset', 'img');
+    addEntryIfExists(entries, expected_entries, pathname + 'resource_timing_test0.png?id=srcset-src', 'img');
+    addEntryIfExists(entries, expected_entries, pathname + 'blank_page_green.htm', 'iframe');
+    addEntryIfExists(entries, expected_entries, pathname + 'blank_page_green.htm?id=frame', 'frame');
+    addEntryIfExists(entries, expected_entries, pathname + 'empty_script.js', 'script');
+    addEntryIfExists(entries, expected_entries, pathname + 'resource_timing_test0.css?id=embed', 'embed');
+    addEntryIfExists(entries, expected_entries, pathname + 'resource_timing_test0.css?id=n1', 'css');
+    addEntryIfExists(entries, expected_entries, font_pathname + '?id=n1', 'css');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=cursor', 'css');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=1', 'css');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=2', 'css');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=async_xhr', 'xmlhttprequest');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=body', 'body');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=input', 'input');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=n1', 'css');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=object', 'object');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=video-poster', 'video');
+    addEntryIfExists(entries, expected_entries, '/media/test.mp4?id=video-src', 'video');
+    addEntryIfExists(entries, expected_entries, '/media/test.mp4?id=video-source', 'source');
+    addEntryIfExists(entries, expected_entries, '/media/test.ogg?id=video-source', 'source');
+    addEntryIfExists(entries, expected_entries, pathname + 'empty.py?id=video-track', 'track');
+    addEntryIfExists(entries, expected_entries, pathname + 'empty.py?id=audio-src', 'audio');
+    addEntryIfExists(entries, expected_entries, pathname + 'empty.py?id=audio-source-wav', 'source');
+    addEntryIfExists(entries, expected_entries, pathname + 'empty.py?id=audio-source-mpeg', 'source');
+    addEntryIfExists(entries, expected_entries, pathname + 'empty.py?id=audio-source-ogg', 'source');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=picture-source', 'source');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=picture-img', 'img');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=picture-notsupported-img', 'img');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=picture-img-src', 'img');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=picture-img-srcset', 'img');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=picture-99x-img-src', 'img');
+    addEntryIfExists(entries, expected_entries, pathname + 'blue.png?id=svg-image', 'image');
+    addEntryIfExists(entries, expected_entries, pathname + 'nested.css', 'link');
+    addEntryIfExists(entries, expected_entries, pathname + 'nested.css?id=prefetch', 'link');
+    addEntryIfExists(entries, expected_entries, pathname + 'nested.css?id=preload', 'link');
+    addEntryIfExists(entries, expected_entries, pathname + 'blank_page_green.htm?id=prerender', 'link');
+    addEntryIfExists(entries, expected_entries, pathname + 'manifest.json', 'link');
+    addEntryIfExists(entries, expected_entries, pathname + 'empty.py?id=beacon', 'beacon');
+    addEntryIfExists(entries, expected_entries, pathname + 'empty.py?id=fetch', 'fetch');
+    addEntryIfExists(entries, expected_entries, pathname + 'empty.py?favicon', 'link');
+    addEntryIfExists(entries, expected_entries, pathname + 'eventsource.py?id=eventsource', 'eventsource');
 
     test_resource_entries(entries, expected_entries);
     done();
 }
 
+function addEntryIfExists(entries, expected_entries, path, initiatorType) {
+    const url = window.location.protocol + "//" + window.location.host + path;
+
+    if (entries.find(function(entry) { return entry.name === url; })) {
+        expected_entries[path] = initiatorType;
+    }
+}
+
 window.on_test_body_created = check_finished;
 window.on_async_xhr_done = function() {
     xhr_loaded = true;
@@ -110,5 +159,6 @@
 <p>This test validates that all of the initiator types are represented.</p>
 <div id="log"></div>
 <iframe id="frameContext" onload="onload_test();" src="resources/all_resource_types.htm" style="width: 250px; height: 250px;"></iframe>
+<iframe id="frameContext2" onload="frameset_onload();" src="resources/green_frame.htm" style="width: 250px; height: 250px;"></iframe>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/all_resource_types.htm b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/all_resource_types.htm
index 41789d8..bc7101c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/all_resource_types.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/all_resource_types.htm
@@ -3,6 +3,7 @@
     <head>
         <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
         <title>All Resource Types Test Page</title>
+        <link rel="shortcut icon" href="empty.py?favicon">
     </head>
     <body background='blue.png?id=body'>
         <script>
@@ -10,7 +11,14 @@
                 window.parent.on_test_body_created();
         </script>
         <link rel="stylesheet" href="nested.css"></link>
+        <link rel="prefetch" href="nested.css?id=prefetch"></link>
+        <link rel="preload" href="nested.css?id=preload" as="style"></link>
+        <link rel="prerender" href="blank_page_green.htm?id=prerender"></link>
+        <link rel="manifest" href="manifest.json"></link>
         <img src="resource_timing_test0.png"></img>
+        <img src="resource_timing_test0.png?id=srcset-src"
+            srcset="resource_timing_test0.png?id=srcset-srcset 67w"
+            sizes="67px"></img>
         <iframe src="blank_page_green.htm" width="100px" height="100px"></iframe>
         <script src="empty_script.js"></script>
         <script>
@@ -21,6 +29,18 @@
                     parent.on_async_xhr_done();
             }
             async_xhr.send();
+
+            if (window.navigator && navigator.sendBeacon) {
+                navigator.sendBeacon('empty.py?id=beacon');
+            }
+
+            if (window.fetch) {
+                fetch('empty.py?id=fetch');
+            }
+
+            if (window.EventSource) {
+                var evtSource = new EventSource('eventsource.py?id=eventsource');
+            }
         </script>
         <style>
             @font-face {
@@ -30,6 +50,9 @@
             iframe {
                 background: url('blue.png?id=1');
             }
+            body {
+                cursor: url('blue.png?id=cursor'), pointer;
+            }
             ul {
                 font-family: remoteFontAhem;
                 list-style-image: url('blue.png?id=2');
@@ -44,6 +67,41 @@
         <embed src="resource_timing_test0.css?id=embed" type="text/css"></embed>
         <input type="image" src="blue.png?id=input"></input>
         <object type="image/png" data="blue.png?id=object"></object>
-        <video poster="blue.png?id=poster"></video>
+        <video poster="blue.png?id=video-poster"></video>
+        <video src="/media/test.mp4?id=video-src" autoplay="true"></video>
+        <video autoplay="true">
+            <source src="/media/test.mp4?id=video-source" type="video/mp4">
+            <source src="/media/test.ogv?id=video-source" type="video/ogg">
+            <track kind="subtitles" src="empty.py?id=video-track" srclang="en" default>
+        </video>
+        <audio src="empty.py?id=audio-src"></audio>
+        <audio>
+            <source src="empty.py?id=audio-source-wav" type="audio/wav" />
+            <source src="empty.py?id=audio-source-mpeg" type="audio/mpeg" />
+            <source src="empty.py?id=audio-source-ogg" type="audio/ogg" />
+        </audio>
+        <svg width=200 height=200
+            xmlns="http://www.w3.org/2000/svg"
+            xmlns:xlink="http://www.w3.org/1999/xlink">
+            <image href="blue.png?id=svg-image" height="200" width="200"/>
+        </svg>
+        <picture>
+            <source srcset="blue.png?id=picture-source" type="image/png" />
+            <img src="blue.png?id=picture-img" />
+        </picture>
+        <picture>
+            <source srcset="blue.png?id=picture-notsupported-source" type="image/notsupported" />
+            <img src="blue.png?id=picture-notsupported-img" />
+        </picture>
+        <picture>
+            <img src="blue.png?id=picture-img-src"
+                srcset="blue.png?id=picture-img-srcset"
+                sizes="67px"></img>
+        </picture>
+        <picture>
+            <img src="blue.png?id=picture-99x-img-src"
+                srcset="blue.png?id=picture-99x-img-srcset 99x"
+                sizes="67px"></img>
+        </picture>
     </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/empty.py b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/empty.py
new file mode 100644
index 0000000..e5ccfbe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/empty.py
@@ -0,0 +1,3 @@
+def main(request, response):
+    response.headers.set("Content-Type", "text/plain")
+    return ""
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/eventsource.py b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/eventsource.py
new file mode 100644
index 0000000..5095ea9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/eventsource.py
@@ -0,0 +1,3 @@
+def main(request, response):
+    response.headers.set("Content-Type", "text/event-stream")
+    return ""
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/green_frame.htm b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/green_frame.htm
index c91f44a..f3f0324 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/green_frame.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/resource-timing/resources/green_frame.htm
@@ -1,7 +1,7 @@
 <html>
   <head>
     <frameset>
-      <frame src="blank_page_green.htm">
+      <frame src="blank_page_green.htm?id=frame">
     </frameset>
   </head>
 </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/staticrange/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/staticrange/idlharness.html
deleted file mode 100644
index e35bca1e..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/staticrange/idlharness.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<title>Static Range IDL tests</title>
-<link rel="help" href="http://garykac.github.io/staticrange/index.html#interface-staticrange"/>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-
-<pre id="untested_idl">
-interface Node {
-};
-</pre>
-
-<pre id='idl'>
-interface StaticRange {
-    readonly attribute Node startContainer;
-    readonly attribute unsigned long startOffset;
-    readonly attribute Node endContainer;
-    readonly attribute unsigned long endOffset;
-    readonly attribute boolean collapsed;
-};
-</pre>
-
-<script>
-(function(){
-    "use strict";
-    const idl_array = new IdlArray();
-    idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
-    idl_array.add_idls(document.getElementById("idl").textContent);
-    idl_array.test();
-})();
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html
index c2e9702..142d49d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html
@@ -20,13 +20,13 @@
                   iterations: 10,
                   iterationComposite: 'accumulate' });
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).alignContent, 'flex-end',
     'Animated align-content style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).alignContent, 'flex-start',
     'Animated align-content style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).alignContent, 'flex-end',
     'Animated align-content style at 50s of the third iteration');
 }, 'iteration composition of discrete type animation (align-content)');
@@ -41,13 +41,13 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).marginLeft, '5px',
     'Animated margin-left style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).marginLeft, '20px',
     'Animated margin-left style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).marginLeft, '25px',
     'Animated margin-left style at 50s of the third iteration');
 }, 'iteration composition of <length> type animation');
@@ -66,13 +66,13 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).width, '25px',
     'Animated width style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).width, '100px',
     'Animated width style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).width, '125px',
     'Animated width style at 50s of the third iteration');
 }, 'iteration composition of <percentage> type animation');
@@ -87,13 +87,13 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).color, 'rgb(60, 60, 60)',
     'Animated color style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).color, 'rgb(240, 240, 240)',
     'Animated color style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).color, 'rgb(255, 255, 255)',
     'Animated color style at 50s of the third iteration');
 }, 'iteration composition of <color> type animation');
@@ -108,13 +108,13 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).color, 'rgb(30, 90, 30)',
     'Animated color style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).color, 'rgb(120, 240, 120)',
     'Animated color style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   // The green color is (240 + 180) / 2 = 210
   assert_equals(getComputedStyle(div).color, 'rgb(150, 210, 150)',
     'Animated color style at 50s of the third iteration');
@@ -131,13 +131,13 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).flexGrow, '5',
     'Animated flex-grow style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).flexGrow, '20',
     'Animated flex-grow style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).flexGrow, '25',
     'Animated flex-grow style at 50s of the third iteration');
 }, 'iteration composition of <number> type animation');
@@ -154,13 +154,13 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).clip, 'rect(5px, 5px, 5px, 5px)',
     'Animated clip style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).clip, 'rect(20px, 20px, 20px, 20px)',
     'Animated clip style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).clip, 'rect(25px, 25px, 25px, 25px)',
     'Animated clip style at 50s of the third iteration');
 }, 'iteration composition of <shape> type animation');
@@ -175,13 +175,13 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).width, '5px',
     'Animated calc width style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).width, '20px',
     'Animated calc width style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).width, '25px',
     'Animated calc width style at 50s of the third iteration');
 }, 'iteration composition of <calc()> value animation');
@@ -200,15 +200,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).width, '10px',
     // 100px * 5% + 5px
     'Animated calc width style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).width,
     '40px', // 100px * (10% + 10%) + (10px + 10px)
     'Animated calc width style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).width,
     '50px', // (40px + 60px) / 2
     'Animated calc width style at 50s of the third iteration');
@@ -225,13 +225,13 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).opacity, '0.2',
     'Animated opacity style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).opacity, '0.8',
     'Animated opacity style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).opacity, '1', // (0.8 + 1.2) * 0.5
     'Animated opacity style at 50s of the third iteration');
 }, 'iteration composition of opacity animation');
@@ -247,15 +247,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).boxShadow,
     'rgb(60, 60, 60) 5px 5px 5px 0px',
     'Animated box-shadow style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).boxShadow,
     'rgb(240, 240, 240) 20px 20px 20px 0px',
     'Animated box-shadow style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).boxShadow,
     'rgb(255, 255, 255) 25px 25px 25px 0px',
     'Animated box-shadow style at 50s of the third iteration');
@@ -271,13 +271,13 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter, 'blur(5px)',
     'Animated filter blur style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).filter, 'blur(20px)',
     'Animated filter blur style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter, 'blur(25px)',
     'Animated filter blur style at 50s of the third iteration');
 }, 'iteration composition of filter blur animation');
@@ -293,15 +293,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'brightness(1.4)',
     'Animated filter brightness style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).filter,
     'brightness(2.6)', // brightness(1) + brightness(0.8) + brightness(0.8)
     'Animated filter brightness style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'brightness(3)', // (brightness(2.6) + brightness(3.4)) * 0.5
     'Animated filter brightness style at 50s of the third iteration');
@@ -318,15 +318,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'brightness(0.5)',
     'Animated filter brightness style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).filter,
     'brightness(0)', // brightness(1) is an identity element, not accumulated.
     'Animated filter brightness style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'brightness(0.5)', // brightness(1) is an identity element, not accumulated.
     'Animated filter brightness style at 50s of the third iteration');
@@ -343,15 +343,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'drop-shadow(rgb(60, 60, 60) 5px 5px 5px)',
     'Animated filter drop-shadow style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).filter,
     'drop-shadow(rgb(240, 240, 240) 20px 20px 20px)',
     'Animated filter drop-shadow style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'drop-shadow(rgb(255, 255, 255) 25px 25px 25px)',
     'Animated filter drop-shadow style at 50s of the third iteration');
@@ -368,15 +368,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'brightness(1.5) contrast(1.5)',
     'Animated filter list at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).filter,
     'brightness(3) contrast(3)',
     'Animated filter list at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'brightness(3.5) contrast(3.5)',
     'Animated filter list at 50s of the third iteration');
@@ -393,18 +393,18 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'contrast(2) brightness(2)', // discrete
     'Animated filter list at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).filter,
     // We can't accumulate 'contrast(2) brightness(2)' onto
     // the first list 'brightness(1) contrast(1)' because of
     // mismatch of the order.
     'brightness(1) contrast(1)',
     'Animated filter list at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     // We *can* accumulate 'contrast(2) brightness(2)' onto
     // the same list 'contrast(2) brightness(2)' here.
@@ -424,15 +424,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'sepia(0.5) contrast(1.5)',
     'Animated filter list at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).filter,
     'sepia(2) contrast(3)',
     'Animated filter list at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).filter,
     'sepia(2.5) contrast(3.5)',
     'Animated filter list at 50s of the third iteration');
@@ -448,15 +448,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(0, 1, -1, 0, 0, 0)', // rotate(90deg)
     'Animated transform(rotate) style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(1, 0, 0, 1, 0, 0)', // rotate(360deg)
     'Animated transform(rotate) style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(0, 1, -1, 0, 0, 0)', // rotate(450deg)
     'Animated transform(rotate) style at 50s of the third iteration');
@@ -472,16 +472,16 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5)
     'Animated transform(scale) style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(0, 0, 0, 0, 0, 0)', // scale(0); scale(1) is an identity element,
                                 // not accumulated.
     'Animated transform(scale) style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5); scale(1) an identity
                                     // element, not accumulated.
@@ -498,15 +498,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(1.5, 0, 0, 1.5, 0, 0)', // scale(1.5)
     'Animated transform(scale) style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(3, 0, 0, 3, 0, 0)', // scale(1 + (2 -1) + (2 -1))
     'Animated transform(scale) style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(3.5, 0, 0, 3.5, 0, 0)', // (scale(3) + scale(4)) * 0.5
     'Animated transform(scale) style at 50s of the third iteration');
@@ -522,15 +522,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(1, 0, 0, 1, 0, 0)', // scale(1)
     'Animated transform(scale) style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(2, 0, 0, 2, 0, 0)', // (scale(0) + scale(2-1)*2)
     'Animated transform(scale) style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(3, 0, 0, 3, 0, 0)', // (scale(2) + scale(4)) * 0.5
     'Animated transform(scale) style at 50s of the third iteration');
@@ -547,15 +547,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(0, 1, -1, 0, 0, 5)', // rotate(90deg) translateX(5px)
     'Animated transform list at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(1, 0, 0, 1, 20, 0)', // rotate(360deg) translateX(20px)
     'Animated transform list at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(0, 1, -1, 0, 0, 25)', // rotate(450deg) translateX(25px)
     'Animated transform list at 50s of the third iteration');
@@ -572,16 +572,16 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(2.5, 0, 0, 2.5, 15, 0)',
     'Animated transform of matrix function at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // scale(2) + (scale(3-1)*2) + translateX(30px)*2
     'matrix(6, 0, 0, 6, 60, 0)',
     'Animated transform of matrix function at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // from: matrix(6, 0, 0, 6, 60, 0)
     // to:   matrix(7, 0, 0, 7, 90, 0)
@@ -601,20 +601,20 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // Interpolate between matrix(2, 0, 0, 2,  0, 0) = translateX(0px) scale(2)
     //                 and matrix(3, 0, 0, 3, 30, 0) = scale(3) translateX(10px)
     'matrix(2.5, 0, 0, 2.5, 15, 0)',
     'Animated transform list at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // 'from' and 'to' value are mismatched, so accumulate
     // matrix(2, 0, 0, 2, 0, 0) onto matrix(3, 0, 0, 3, 30, 0) * 2
     //  = scale(2) + (scale(3-1)*2) + translateX(30px)*2
     'matrix(6, 0, 0, 6, 60, 0)',
     'Animated transform list at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // Interpolate between matrix(6, 0, 0, 6, 60, 0)
     //                 and matrix(7, 0, 0, 7, 210, 0) = scale(7) translate(30px)
@@ -636,20 +636,20 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // Interpolate between matrix(1, 0, 0, 1,  0, 0) = translateX(0px)
     //                 and matrix(2, 0, 0, 2, 20, 0) = scale(2) translateX(10px)
     'matrix(1.5, 0, 0, 1.5, 10, 0)',
     'Animated transform list at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // 'from' and 'to' value are mismatched, so accumulate
     // matrix(1, 0, 0, 1, 0, 0) onto matrix(2, 0, 0, 2, 20, 0) * 2
     //  = scale(1) + (scale(2-1)*2) + translateX(20px)*2
     'matrix(3, 0, 0, 3, 40, 0)',
     'Animated transform list at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // Interpolate between matrix(3, 0, 0, 3, 40, 0)
     //                 and matrix(4, 0, 0, 4, 120, 0) =
@@ -670,17 +670,17 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // translateX(none) -> translateX(10px) @ 50%
     'matrix(1, 0, 0, 1, 5, 0)',
     'Animated transform list at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 0%
     'matrix(1, 0, 0, 1, 20, 0)',
     'Animated transform list at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 50%
     'matrix(1, 0, 0, 1, 25, 0)',
@@ -704,16 +704,16 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 40, 1)',
     'Animated transform of matrix3d function at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // translateZ(30px) + (translateZ(50px)*2)
     'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)',
     'Animated transform of matrix3d function at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     // from: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)
     // to:   matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 150, 1)
@@ -736,11 +736,11 @@
   assert_matrix_equals(getComputedStyle(div).transform,
     'matrix(1, 0, 0, 1, 0, 0)', // Actually not rotated at all.
     'Animated transform of rotate3d function at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     rotate3dToMatrix3d(1, 1, 0, Math.PI), // 180deg
     'Animated transform of rotate3d function at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_matrix_equals(getComputedStyle(div).transform,
     rotate3dToMatrix3d(1, 1, 0, 225 * Math.PI / 180), //((270 + 180) * 0.5)deg
     'Animated transform of rotate3d function at 50s of the third iteration');
@@ -756,13 +756,13 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).marginLeft, '15px',
     'Animated margin-left style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).marginLeft, '50px', // 10px + 20px + 20px
     'Animated margin-left style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).marginLeft, '55px', // (50px + 60px) * 0.5
     'Animated margin-left style at 50s of the third iteration');
 }, 'iteration composition starts with non-zero value animation');
@@ -777,15 +777,15 @@
                   iterationComposite: 'accumulate' });
   anim.pause();
 
-  anim.currentTime = anim.effect.timing.duration / 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).marginLeft,
     '0px',
     'Animated margin-left style at 50s of the first iteration');
-  anim.currentTime = anim.effect.timing.duration * 2;
+  anim.currentTime = anim.effect.getComputedTiming().duration * 2;
   assert_equals(getComputedStyle(div).marginLeft,
     '-10px', // 10px + -10px + -10px
     'Animated margin-left style at 0s of the third iteration');
-  anim.currentTime += anim.effect.timing.duration / 2;
+  anim.currentTime += anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).marginLeft,
     '-20px', // (-10px + -30px) * 0.5
     'Animated margin-left style at 50s of the third iteration');
@@ -801,17 +801,22 @@
   anim.pause();
 
   anim.currentTime =
-    anim.effect.timing.duration * 2 + anim.effect.timing.duration / 2;
+    anim.effect.getComputedTiming().duration * 2 +
+    anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).marginLeft, '25px',
     'Animated style at 50s of the third iteration');
 
   // double its duration.
-  anim.effect.timing.duration = anim.effect.timing.duration * 2;
+  anim.effect.updateTiming({
+    duration: anim.effect.getComputedTiming().duration * 2
+  });
   assert_equals(getComputedStyle(div).marginLeft, '12.5px',
     'Animated style at 25s of the first iteration');
 
   // half of original.
-  anim.effect.timing.duration = anim.effect.timing.duration / 4;
+  anim.effect.updateTiming({
+    duration: anim.effect.getComputedTiming().duration / 4
+  });
   assert_equals(getComputedStyle(div).marginLeft, '50px',
       'Animated style at 50s of the fourth iteration');
 }, 'duration changes with an iteration composition operation of accumulate');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt
index 537e299..cb71bf3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt
@@ -1,10 +1,9 @@
 This is a testharness.js-based test.
-Found 121 tests; 111 PASS, 10 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 140 tests; 126 PASS, 14 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Element.animate() creates an Animation object
 PASS Element.animate() creates an Animation object in the relevant realm of the target element
 PASS Element.animate() creates an Animation object with a KeyframeEffect
 PASS Element.animate() creates an Animation object with a KeyframeEffect that is created in the relevant realm of the target element
-PASS Element.animate() creates an Animation object with a KeyframeEffect whose AnimationEffectTiming object is created in the relevant realm of the target element
 PASS Element.animate() accepts empty keyframe lists (input: [])
 PASS Element.animate() accepts empty keyframe lists (input: null)
 PASS Element.animate() accepts empty keyframe lists (input: undefined)
@@ -82,6 +81,22 @@
 PASS Element.animate() does not accept property-indexed keyframes with an invalid composite value
 PASS Element.animate() does not accept property-indexed keyframes with an invalid composite value as one of the array values
 PASS Element.animate() does not accept keyframes with an invalid composite value
+FAIL Element.animate() accepts a double as an options argument anim.effect.getTiming is not a function
+FAIL Element.animate() accepts a KeyframeAnimationOptions argument anim.effect.getTiming is not a function
+FAIL Element.animate() accepts an absent options argument effect.getTiming is not a function
+PASS Element.animate() does not accept invalid delay value: NaN
+PASS Element.animate() does not accept invalid delay value: Infinity
+PASS Element.animate() does not accept invalid delay value: -Infinity
+FAIL Element.animate() accepts a duration of 'auto' using a dictionary object anim.effect.getTiming is not a function
+PASS Element.animate() does not accept invalid duration value: -1
+PASS Element.animate() does not accept invalid duration value: NaN
+PASS Element.animate() does not accept invalid duration value: -Infinity
+PASS Element.animate() does not accept invalid duration value: "abc"
+PASS Element.animate() does not accept invalid duration value: -1 using a dictionary object
+PASS Element.animate() does not accept invalid duration value: NaN using a dictionary object
+PASS Element.animate() does not accept invalid duration value: -Infinity using a dictionary object
+PASS Element.animate() does not accept invalid duration value: "abc" using a dictionary object
+PASS Element.animate() does not accept invalid duration value: "100" using a dictionary object
 PASS Element.animate() does not accept invalid easing: ''
 PASS Element.animate() does not accept invalid easing: '7'
 PASS Element.animate() does not accept invalid easing: 'test'
@@ -111,9 +126,13 @@
 PASS Element.animate() does not accept invalid easing: 'frames(2.0)'
 PASS Element.animate() does not accept invalid easing: 'frames(2.5)'
 PASS Element.animate() does not accept invalid easing: 'frames(2 3)'
-PASS Element.animate() accepts a double as an options argument
-PASS Element.animate() accepts a KeyframeAnimationOptions argument
-PASS Element.animate() accepts an absent options argument
+PASS Element.animate() does not accept invalid iterationStart value: -1
+PASS Element.animate() does not accept invalid iterationStart value: NaN
+PASS Element.animate() does not accept invalid iterationStart value: Infinity
+PASS Element.animate() does not accept invalid iterationStart value: -Infinity
+PASS Element.animate() does not accept invalid iterations value: -1
+PASS Element.animate() does not accept invalid iterations value: -Infinity
+PASS Element.animate() does not accept invalid iterations value: NaN
 PASS Element.animate() correctly sets the id attribute when no id is specified
 PASS Element.animate() correctly sets the id attribute
 PASS Element.animate() correctly sets the Animation's timeline
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate.html
index 36c4ee1..c7b7b25 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/animate.html
@@ -8,6 +8,8 @@
 <script src="../../resources/easing-tests.js"></script>
 <script src="../../resources/keyframe-utils.js"></script>
 <script src="../../resources/keyframe-tests.js"></script>
+<script src="../../resources/timing-utils.js"></script>
+<script src="../../resources/timing-tests.js"></script>
 <body>
 <div id="log"></div>
 <iframe width="10" height="10" id="iframe"></iframe>
@@ -17,8 +19,7 @@
 // Tests on Element
 
 test(t => {
-  const div = createDiv(t);
-  const anim = div.animate(null);
+  const anim = createDiv(t).animate(null);
   assert_class_string(anim, 'Animation', 'Returned object is an Animation');
 }, 'Element.animate() creates an Animation object');
 
@@ -57,26 +58,9 @@
 }, 'Element.animate() creates an Animation object with a KeyframeEffect'
    + ' that is created in the relevant realm of the target element');
 
-test(t => {
-  const iframe = window.frames[0];
-  const div = createDiv(t, iframe.document);
-  const anim = div.animate(null);
-  assert_equals(Object.getPrototypeOf(anim.effect.timing),
-                iframe.AnimationEffectTiming.prototype,
-                'The prototype of the created AnimationEffectTiming is that'
-                + ' defined on the relevant global for the target element');
-  assert_not_equals(Object.getPrototypeOf(anim.effect.timing),
-                    AnimationEffectTiming.prototype,
-                    'The prototype of the created AnimationEffectTiming is NOT'
-                    + ' that of the current global');
-}, 'Element.animate() creates an Animation object with a KeyframeEffect'
-   + ' whose AnimationEffectTiming object is created in the relevant realm'
-   + ' of the target element');
-
 for (const subtest of gEmptyKeyframeListTests) {
   test(t => {
-    const div = createDiv(t);
-    const anim = div.animate(subtest, 2000);
+    const anim = createDiv(t).animate(subtest, 2000);
     assert_not_equals(anim, null);
   }, 'Element.animate() accepts empty keyframe lists ' +
      `(input: ${JSON.stringify(subtest)})`);
@@ -84,8 +68,7 @@
 
 for (const subtest of gKeyframesTests) {
   test(t => {
-    const div = createDiv(t);
-    const anim = div.animate(subtest.input, 2000);
+    const anim = createDiv(t).animate(subtest.input, 2000);
     assert_frame_lists_equal(anim.effect.getKeyframes(), subtest.output);
   }, `Element.animate() accepts ${subtest.desc}`);
 }
@@ -99,54 +82,101 @@
   }, `Element.animate() does not accept ${subtest.desc}`);
 }
 
+test(t => {
+  const anim = createDiv(t).animate(null, 2000);
+  assert_equals(anim.effect.getTiming().duration, 2000);
+  assert_default_timing_except(anim.effect, ['duration']);
+}, 'Element.animate() accepts a double as an options argument');
+
+test(t => {
+  const anim = createDiv(t).animate(null,
+                                    { duration: Infinity, fill: 'forwards' });
+  assert_equals(anim.effect.getTiming().duration, Infinity);
+  assert_equals(anim.effect.getTiming().fill, 'forwards');
+  assert_default_timing_except(anim.effect, ['duration', 'fill']);
+}, 'Element.animate() accepts a KeyframeAnimationOptions argument');
+
+test(t => {
+  const anim = createDiv(t).animate(null);
+  assert_default_timing_except(anim.effect, []);
+}, 'Element.animate() accepts an absent options argument');
+
+for (const invalid of gBadDelayValues) {
+  test(t => {
+    assert_throws(new TypeError, () => {
+      createDiv(t).animate(null, { delay: invalid });
+    });
+  }, `Element.animate() does not accept invalid delay value: ${invalid}`);
+}
+
+test(t => {
+  const anim = createDiv(t).animate(null, { duration: 'auto' });
+  assert_equals(anim.effect.getTiming().duration, 'auto', 'set duration \'auto\'');
+  assert_equals(anim.effect.getComputedTiming().duration, 0,
+                'getComputedTiming() after set duration \'auto\'');
+}, 'Element.animate() accepts a duration of \'auto\' using a dictionary'
+   + ' object');
+
+for (const invalid of gBadDurationValues) {
+  if (typeof invalid === 'string' && !isNaN(parseFloat(invalid))) {
+    continue;
+  }
+  test(t => {
+    assert_throws(new TypeError, () => {
+      createDiv(t).animate(null, invalid);
+    });
+  }, 'Element.animate() does not accept invalid duration value: '
+     + (typeof invalid === 'string' ? `"${invalid}"` : invalid));
+}
+
+for (const invalid of gBadDurationValues) {
+  test(t => {
+    assert_throws(new TypeError, () => {
+      createDiv(t).animate(null, { duration: invalid });
+    });
+  }, 'Element.animate() does not accept invalid duration value: '
+     + (typeof invalid === 'string' ? `"${invalid}"` : invalid)
+     + ' using a dictionary object');
+}
+
 for (const invalidEasing of gInvalidEasings) {
   test(t => {
-    const div = createDiv(t);
     assert_throws(new TypeError, () => {
-      div.animate({ easing: invalidEasing }, 2000);
+      createDiv(t).animate({ easing: invalidEasing }, 2000);
     });
   }, `Element.animate() does not accept invalid easing: '${invalidEasing}'`);
 }
 
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_equals(anim.effect.timing.duration, 2000);
-  // Also check that unspecified parameters receive their default values
-  assert_equals(anim.effect.timing.fill, 'auto');
-}, 'Element.animate() accepts a double as an options argument');
+for (const invalid of gBadIterationStartValues) {
+  test(t => {
+    assert_throws(new TypeError, () => {
+      createDiv(t).animate(null, { iterationStart: invalid });
+    });
+  }, 'Element.animate() does not accept invalid iterationStart value: ' +
+     invalid);
+}
+
+for (const invalid of gBadIterationsValues) {
+  test(t => {
+    assert_throws(new TypeError, () => {
+      createDiv(t).animate(null, { iterations: invalid });
+    });
+  }, 'Element.animate() does not accept invalid iterations value: ' +
+     invalid);
+}
 
 test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { duration: Infinity, fill: 'forwards' });
-  assert_equals(anim.effect.timing.duration, Infinity);
-  assert_equals(anim.effect.timing.fill, 'forwards');
-  // Also check that unspecified parameters receive their default values
-  assert_equals(anim.effect.timing.direction, 'normal');
-}, 'Element.animate() accepts a KeyframeAnimationOptions argument');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] });
-  assert_equals(anim.effect.timing.duration, 'auto');
-}, 'Element.animate() accepts an absent options argument');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+  const anim = createDiv(t).animate(null, 2000);
   assert_equals(anim.id, '');
 }, 'Element.animate() correctly sets the id attribute when no id is specified');
 
 test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, { id: 'test' });
+  const anim = createDiv(t).animate(null, { id: 'test' });
   assert_equals(anim.id, 'test');
 }, 'Element.animate() correctly sets the id attribute');
 
 test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+  const anim = createDiv(t).animate(null, 2000);
   assert_equals(anim.timeline, document.timeline);
 }, 'Element.animate() correctly sets the Animation\'s timeline');
 
@@ -157,7 +187,7 @@
 
   iframe.addEventListener('load', t.step_func(() => {
     const div = createDiv(t, iframe.contentDocument);
-    const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+    const anim = div.animate(null, 2000);
     assert_equals(anim.timeline, iframe.contentDocument.timeline);
     iframe.remove();
     t.done();
@@ -168,8 +198,7 @@
    'triggered on an element in a different document');
 
 test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+  const anim = createDiv(t).animate(null, 2000);
   assert_equals(anim.playState, 'running');
 }, 'Element.animate() calls play on the Animation');
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt
new file mode 100644
index 0000000..a168718c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+PASS Returns an empty array for an element with no animations
+PASS Returns both animations for an element with two animations
+PASS Returns only the animations specific to each sibling element
+PASS Returns only the animations specific to each parent/child element
+PASS Does not return finished animations that do not fill forwards
+PASS Returns finished animations that fill forwards
+PASS Returns animations in their delay phase
+FAIL Returns animations based on dynamic changes to individual animations' duration animation.effect.getTiming is not a function
+FAIL Returns animations based on dynamic changes to individual animations' end delay animation.effect.updateTiming is not a function
+FAIL Returns animations based on dynamic changes to individual animations' iteration count animation.effect.updateTiming is not a function
+PASS Returns animations based on dynamic changes to individual animations' current time
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations.html
index d05e2aa..182b5cbe 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animatable/getAnimations.html
@@ -75,12 +75,14 @@
   assert_array_equals(div.getAnimations(), [],
                       'Animation should not be returned when it is finished');
 
-  animation.effect.timing.duration += 100 * MS_PER_SEC;
+  animation.effect.updateTiming({
+    duration: animation.effect.getTiming().duration + 100 * MS_PER_SEC,
+  });
   assert_array_equals(div.getAnimations(), [animation],
                       'Animation should be returned after extending the'
                       + ' duration');
 
-  animation.effect.timing.duration = 0;
+  animation.effect.updateTiming({ duration: 0 });
   assert_array_equals(div.getAnimations(), [],
                       'Animation should not be returned after setting the'
                       + ' duration to zero');
@@ -91,13 +93,13 @@
   const div = createDiv(t);
   const animation = div.animate(null, 100 * MS_PER_SEC);
 
-  animation.effect.timing.endDelay = -200 * MS_PER_SEC;
+  animation.effect.updateTiming({ endDelay: -200 * MS_PER_SEC });
   assert_array_equals(div.getAnimations(), [],
                       'Animation should not be returned after setting a'
                       + ' negative end delay such that the end time is less'
                       + ' than the current time');
 
-  animation.effect.timing.endDelay = 100 * MS_PER_SEC;
+  animation.effect.updateTiming({ endDelay: 100 * MS_PER_SEC });
   assert_array_equals(div.getAnimations(), [animation],
                       'Animation should be returned after setting a positive'
                       + ' end delay such that the end time is more than the'
@@ -113,17 +115,17 @@
   assert_array_equals(div.getAnimations(), [],
                       'Animation should not be returned when it is finished');
 
-  animation.effect.timing.iterations = 10;
+  animation.effect.updateTiming({ iterations: 10 });
   assert_array_equals(div.getAnimations(), [animation],
                       'Animation should be returned after inreasing the'
                       + ' number of iterations');
 
-  animation.effect.timing.iterations = 0;
+  animation.effect.updateTiming({ iterations: 0 });
   assert_array_equals(div.getAnimations(), [],
                       'Animations should not be returned after setting the'
                       + ' iteration count to zero');
 
-  animation.effect.timing.iterations = Infinity;
+  animation.effect.updateTiming({ iterations: Infinity });
   assert_array_equals(div.getAnimations(), [animation],
                       'Animation should be returned after inreasing the'
                       + ' number of iterations to infinity');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel-expected.txt
new file mode 100644
index 0000000..84aff28d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel-expected.txt
@@ -0,0 +1,6 @@
+This is a testharness.js-based test.
+PASS Animated style is cleared after calling Animation.cancel()
+FAIL After cancelling an animation, it can still be seeked animation.effect.updateTiming is not a function
+PASS After cancelling an animation, it can still be re-used
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel.html
index be1bb5d..711a339 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/cancel.html
@@ -29,7 +29,7 @@
   const div = createDiv(t);
   const animation = div.animate({ marginLeft: ['100px', '200px'] },
                                 100 * MS_PER_SEC);
-  animation.effect.timing.easing = 'linear';
+  animation.effect.updateTiming({ easing: 'linear' });
   animation.cancel();
   assert_equals(getComputedStyle(div).marginLeft, '0px',
                 'margin-left style is not animated after cancelling');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/constructor.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/constructor.html
index c00c66ea..fcbaab1e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/constructor.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/constructor.html
@@ -14,7 +14,7 @@
 const gTarget = document.getElementById('target');
 
 function createEffect() {
-  return new KeyframeEffectReadOnly(gTarget, { opacity: [0, 1] });
+  return new KeyframeEffect(gTarget, { opacity: [0, 1] });
 }
 
 function createNull() {
@@ -82,10 +82,9 @@
 }
 
 test(t => {
-  const effect = new KeyframeEffectReadOnly(null,
-                                            { left: ['10px', '20px'] },
-                                            { duration: 10000,
-                                              fill: 'forwards' });
+  const effect = new KeyframeEffect(null,
+                                    { left: ['10px', '20px'] },
+                                    { duration: 10000, fill: 'forwards' });
   const anim = new Animation(effect, document.timeline);
   anim.pause();
   assert_equals(effect.getComputedTiming().progress, 0.0);
@@ -100,7 +99,7 @@
 
   iframe.addEventListener('load', t.step_func(() => {
     const div = createDiv(t, iframe.contentDocument);
-    const effect = new KeyframeEffectReadOnly(div, null, 10000);
+    const effect = new KeyframeEffect(div, null, 10000);
     const anim = new Animation(effect);
     assert_equals(anim.timeline, document.timeline);
     iframe.remove();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/effect.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/effect.html
index 175fc31..cb8bc09c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/effect.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/effect.html
@@ -14,7 +14,7 @@
   const anim = new Animation();
   assert_equals(anim.effect, null, 'initial effect is null');
 
-  const newEffect = new KeyframeEffectReadOnly(createDiv(t), null);
+  const newEffect = new KeyframeEffect(createDiv(t), null);
   anim.effect = newEffect;
   assert_equals(anim.effect, newEffect, 'new effect is set');
 }, 'effect is set correctly.');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished-expected.txt
index 32a633f..4332a1e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished-expected.txt
@@ -8,7 +8,7 @@
 PASS The finished promise is fulfilled with its Animation
 PASS finished promise is rejected when an animation is canceled by calling cancel()
 PASS canceling an already-finished animation replaces the finished promise
-FAIL Test finished promise changes for animation duration changes assert_false: shortening of the animation duration should resolve the finished promise expected false got true
+FAIL Test finished promise changes for animation duration changes promise_test: Unhandled rejection with value: object "TypeError: animation.effect.updateTiming is not a function"
 PASS Test finished promise changes when playbackRate == 0
 PASS Test finished promise resolves when reaching to the natural boundary.
 PASS Test finished promise changes when a prior finished promise resolved and the animation falls out finished state
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished.html
index 79700f31..563d4ba 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/finished.html
@@ -189,7 +189,7 @@
   animation.currentTime = HALF_DUR;
   return animation.ready.then(() => {
     currentTimeBeforeShortening = animation.currentTime;
-    animation.effect.timing.duration = QUARTER_DUR;
+    animation.effect.updateTiming({ duration: QUARTER_DUR });
     // Below we use gotNextFrame to check that shortening of the animation
     // duration causes the finished promise to resolve, rather than it just
     // getting resolved on the next animation frame. This relies on the fact
@@ -206,7 +206,7 @@
     assert_equals(animation.currentTime, currentTimeBeforeShortening,
                   'currentTime should be unchanged when duration shortened');
     const previousFinishedPromise = animation.finished;
-    animation.effect.timing.duration = 100 * MS_PER_SEC;
+    animation.effect.updateTiming({ duration: 100 * MS_PER_SEC });
     assert_not_equals(animation.finished, previousFinishedPromise,
                       'Finished promise should change after lengthening the ' +
                       'duration causes the animation to become active');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/idlharness.html
index bf7c9f3..20fca13 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/idlharness.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Animation/idlharness.html
@@ -10,11 +10,11 @@
 <script type="text/plain" id="Animation-IDL">
 enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" };
 
-[Constructor (optional AnimationEffectReadOnly? effect = null,
+[Constructor (optional AnimationEffect? effect = null,
               optional AnimationTimeline? timeline)]
 interface Animation : EventTarget {
              attribute DOMString                id;
-             attribute AnimationEffectReadOnly? effect;
+             attribute AnimationEffect?         effect;
              attribute AnimationTimeline?       timeline;
              attribute double?                  startTime;
              attribute double?                  currentTime;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/getComputedTiming-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/getComputedTiming-expected.txt
new file mode 100644
index 0000000..e6c52da
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/getComputedTiming-expected.txt
@@ -0,0 +1,39 @@
+This is a testharness.js-based test.
+PASS values of getComputedTiming() when a KeyframeEffect is constructed without any KeyframeEffectOptions object
+PASS values of getComputedTiming() when a KeyframeEffect is constructed by an empty KeyframeEffectOptions object
+PASS values of getComputedTiming() when a KeyframeEffect is constructed by a normal KeyframeEffectOptions object
+PASS values of getComputedTiming() when a KeyframeEffect is constructed by a double value
+PASS values of getComputedTiming() when a KeyframeEffect is constructed by +Infinity
+PASS values of getComputedTiming() when a KeyframeEffect is constructed by an Infinity duration
+PASS values of getComputedTiming() when a KeyframeEffect is constructed by an auto duration
+PASS values of getComputedTiming() when a KeyframeEffect is constructed by an Infinity iterations
+PASS values of getComputedTiming() when a KeyframeEffect is constructed by an auto fill
+PASS values of getComputedTiming() when a KeyframeEffect is constructed by a forwards fill
+PASS getComputedTiming().activeDuration for an empty KeyframeEffectOptions object
+PASS getComputedTiming().activeDuration for a non-zero duration and default iteration count
+PASS getComputedTiming().activeDuration for a non-zero duration and integral iteration count
+PASS getComputedTiming().activeDuration for a non-zero duration and fractional iteration count
+PASS getComputedTiming().activeDuration for an non-zero duration and infinite iteration count
+PASS getComputedTiming().activeDuration for an non-zero duration and zero iteration count
+PASS getComputedTiming().activeDuration for a zero duration and default iteration count
+PASS getComputedTiming().activeDuration for a zero duration and fractional iteration count
+PASS getComputedTiming().activeDuration for a zero duration and infinite iteration count
+PASS getComputedTiming().activeDuration for a zero duration and zero iteration count
+PASS getComputedTiming().activeDuration for an infinite duration and default iteration count
+PASS getComputedTiming().activeDuration for an infinite duration and zero iteration count
+PASS getComputedTiming().activeDuration for an infinite duration and fractional iteration count
+PASS getComputedTiming().activeDuration for an infinite duration and infinite iteration count
+PASS getComputedTiming().endTime for an empty KeyframeEffectOptions object
+PASS getComputedTiming().endTime for a non-zero duration and default iteration count
+PASS getComputedTiming().endTime for a non-zero duration and non-default iteration count
+PASS getComputedTiming().endTime for a non-zero duration and non-zero delay
+PASS getComputedTiming().endTime for a non-zero duration, non-zero delay and non-default iteration
+PASS getComputedTiming().endTime for an infinite iteration count
+PASS getComputedTiming().endTime for an infinite duration
+PASS getComputedTiming().endTime for an infinite duration and delay
+PASS getComputedTiming().endTime for an infinite duration and negative delay
+PASS getComputedTiming().endTime for an non-zero duration and negative delay
+FAIL getComputedTiming().endTime for an non-zero duration and negative delay greater than active duration assert_equals: expected 0 but got -1000
+FAIL getComputedTiming().endTime for a zero duration and negative delay assert_equals: expected 0 but got -1000
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/getComputedTiming.html
similarity index 99%
rename from third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html
rename to third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/getComputedTiming.html
index 9a92880a6..e0e4fc2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/getComputedTiming.html
@@ -195,7 +195,5 @@
 
   }, `getComputedTiming().endTime for ${stest.desc}`);
 }
-
-done();
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/updateTiming-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/updateTiming-expected.txt
new file mode 100644
index 0000000..79e1427
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/updateTiming-expected.txt
@@ -0,0 +1,74 @@
+This is a testharness.js-based test.
+Found 70 tests; 17 PASS, 53 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL Allows setting the delay to a positive number anim.effect.updateTiming is not a function
+FAIL Allows setting the delay to a negative number anim.effect.updateTiming is not a function
+FAIL Allows setting the delay of an animation in progress: positive delay that causes the animation to be no longer in-effect anim.effect.updateTiming is not a function
+FAIL Allows setting the delay of an animation in progress: negative delay that seeks into the active interval anim.effect.updateTiming is not a function
+FAIL Allows setting the delay of an animation in progress: large negative delay that causes the animation to be finished anim.effect.updateTiming is not a function
+PASS Throws when setting invalid delay value: NaN
+PASS Throws when setting invalid delay value: Infinity
+PASS Throws when setting invalid delay value: -Infinity
+FAIL Allows setting the endDelay to a positive number anim.effect.updateTiming is not a function
+FAIL Allows setting the endDelay to a negative number anim.effect.updateTiming is not a function
+PASS Throws when setting the endDelay to infinity
+PASS Throws when setting the endDelay to negative infinity
+FAIL Allows setting the fill to 'none' anim.effect.updateTiming is not a function
+FAIL Allows setting the fill to 'forwards' anim.effect.updateTiming is not a function
+FAIL Allows setting the fill to 'backwards' anim.effect.updateTiming is not a function
+FAIL Allows setting the fill to 'both' anim.effect.updateTiming is not a function
+FAIL Allows setting the iterationStart of an animation in progress: backwards-filling anim.effect.updateTiming is not a function
+FAIL Allows setting the iterationStart of an animation in progress: active phase anim.effect.updateTiming is not a function
+FAIL Allows setting the iterationStart of an animation in progress: forwards-filling anim.effect.updateTiming is not a function
+PASS Throws when setting invalid iterationStart value: -1
+PASS Throws when setting invalid iterationStart value: NaN
+PASS Throws when setting invalid iterationStart value: Infinity
+PASS Throws when setting invalid iterationStart value: -Infinity
+FAIL Allows setting iterations to a double value anim.effect.updateTiming is not a function
+FAIL Allows setting iterations to infinity anim.effect.updateTiming is not a function
+PASS Throws when setting invalid iterations value: -1
+PASS Throws when setting invalid iterations value: -Infinity
+PASS Throws when setting invalid iterations value: NaN
+FAIL Allows setting the iterations of an animation in progress anim.effect.updateTiming is not a function
+FAIL Allows setting the duration to 123.45 anim.effect.updateTiming is not a function
+FAIL Allows setting the duration to auto anim.effect.updateTiming is not a function
+FAIL Allows setting the duration to Infinity anim.effect.updateTiming is not a function
+PASS Throws when setting invalid duration: -1
+PASS Throws when setting invalid duration: NaN
+PASS Throws when setting invalid duration: -Infinity
+PASS Throws when setting invalid duration: "abc"
+PASS Throws when setting invalid duration: "100"
+FAIL Allows setting the duration of an animation in progress anim.effect.getTiming is not a function
+FAIL Allows setting the duration of an animation in progress such that the the start and current time do not change promise_test: Unhandled rejection with value: object "TypeError: anim.effect.updateTiming is not a function"
+FAIL Allows setting the direction to each of the possible keywords anim.effect.updateTiming is not a function
+FAIL Allows setting the direction of an animation in progress from 'normal' to 'reverse' anim.effect.updateTiming is not a function
+FAIL Allows setting the direction of an animation in progress from 'normal' to 'reverse' while at start of active interval anim.effect.updateTiming is not a function
+FAIL Allows setting the direction of an animation in progress from 'normal' to 'reverse' while filling backwards anim.effect.updateTiming is not a function
+FAIL Allows setting the direction of an animation in progress from 'normal' to 'alternate' anim.effect.updateTiming is not a function
+FAIL Allows setting the direction of an animation in progress from 'alternate' to 'alternate-reverse' anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a step-start function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a steps(1, start) function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a steps(2, start) function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a step-end function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a steps(1) function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a steps(1, end) function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a steps(2, end) function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a frames function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a linear function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a ease function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a ease-in function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a ease-in-out function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a ease-out function anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a easing function which produces values greater than 1 anim.effect.updateTiming is not a function
+FAIL Allows setting the easing to a easing function which produces values less than 1 anim.effect.updateTiming is not a function
+FAIL Updates the specified value when setting the easing to 'ease' anim.effect.updateTiming is not a function
+FAIL Updates the specified value when setting the easing to 'linear' anim.effect.updateTiming is not a function
+FAIL Updates the specified value when setting the easing to 'ease-in' anim.effect.updateTiming is not a function
+FAIL Updates the specified value when setting the easing to 'ease-out' anim.effect.updateTiming is not a function
+FAIL Updates the specified value when setting the easing to 'ease-in-out' anim.effect.updateTiming is not a function
+FAIL Updates the specified value when setting the easing to 'cubic-bezier(0.1, 5, 0.23, 0)' anim.effect.updateTiming is not a function
+FAIL Updates the specified value when setting the easing to 'steps(3, start)' anim.effect.updateTiming is not a function
+FAIL Updates the specified value when setting the easing to 'steps(3)' anim.effect.updateTiming is not a function
+FAIL Updates the specified value when setting the easing to 'frames(3)' anim.effect.updateTiming is not a function
+FAIL Allows setting the easing of an animation in progress anim.effect.updateTiming is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/updateTiming.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/updateTiming.html
new file mode 100644
index 0000000..746f0d7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffect/updateTiming.html
@@ -0,0 +1,475 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>AnimationEffect.updateTiming</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations-1/#dom-animationeffect-updatetiming">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<script src="../../resources/easing-tests.js"></script>
+<script src="../../resources/timing-tests.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+// ------------------------------
+//  delay
+// ------------------------------
+
+test(t => {
+  const anim = createDiv(t).animate(null, 100);
+  anim.effect.updateTiming({ delay: 100 });
+  assert_equals(anim.effect.getTiming().delay, 100, 'set delay 100');
+  assert_equals(anim.effect.getComputedTiming().delay, 100,
+                  'getComputedTiming() after set delay 100');
+}, 'Allows setting the delay to a positive number');
+
+test(t => {
+  const anim = createDiv(t).animate(null, 100);
+  anim.effect.updateTiming({ delay: -100 });
+  assert_equals(anim.effect.getTiming().delay, -100, 'set delay -100');
+  assert_equals(anim.effect.getComputedTiming().delay, -100,
+                'getComputedTiming() after set delay -100');
+}, 'Allows setting the delay to a negative number');
+
+test(t => {
+  const anim = createDiv(t).animate(null, 100);
+  anim.effect.updateTiming({ delay: 100 });
+  assert_equals(anim.effect.getComputedTiming().progress, null);
+  assert_equals(anim.effect.getComputedTiming().currentIteration, null);
+}, 'Allows setting the delay of an animation in progress: positive delay that'
+   + ' causes the animation to be no longer in-effect');
+
+test(t => {
+  const anim = createDiv(t).animate(null, { fill: 'both', duration: 100 });
+  anim.effect.updateTiming({ delay: -50 });
+  assert_equals(anim.effect.getComputedTiming().progress, 0.5);
+}, 'Allows setting the delay of an animation in progress: negative delay that'
+   + ' seeks into the active interval');
+
+test(t => {
+  const anim = createDiv(t).animate(null, { fill: 'both', duration: 100 });
+  anim.effect.updateTiming({ delay: -100 });
+  assert_equals(anim.effect.getComputedTiming().progress, 1);
+  assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
+}, 'Allows setting the delay of an animation in progress: large negative delay'
+   + ' that causes the animation to be finished');
+
+for (const invalid of gBadDelayValues) {
+  test(t => {
+    const anim = createDiv(t).animate(null);
+    assert_throws({ name: 'TypeError' }, () => {
+      anim.effect.updateTiming({ delay: invalid });
+    });
+  }, `Throws when setting invalid delay value: ${invalid}`);
+}
+
+
+// ------------------------------
+//  endDelay
+// ------------------------------
+
+test(t => {
+  const anim = createDiv(t).animate(null, 2000);
+  anim.effect.updateTiming({ endDelay: 123.45 });
+  assert_time_equals_literal(anim.effect.getTiming().endDelay, 123.45,
+                             'set endDelay 123.45');
+  assert_time_equals_literal(anim.effect.getComputedTiming().endDelay, 123.45,
+                             'getComputedTiming() after set endDelay 123.45');
+}, 'Allows setting the endDelay to a positive number');
+
+test(t => {
+  const anim = createDiv(t).animate(null, 2000);
+  anim.effect.updateTiming({ endDelay: -1000 });
+  assert_equals(anim.effect.getTiming().endDelay, -1000, 'set endDelay -1000');
+  assert_equals(anim.effect.getComputedTiming().endDelay, -1000,
+                'getComputedTiming() after set endDelay -1000');
+}, 'Allows setting the endDelay to a negative number');
+
+test(t => {
+  const anim = createDiv(t).animate(null, 2000);
+  assert_throws({ name: 'TypeError' }, () => {
+    anim.effect.updateTiming({ endDelay: Infinity });
+  });
+}, 'Throws when setting the endDelay to infinity');
+
+test(t => {
+  const anim = createDiv(t).animate(null, 2000);
+  assert_throws({ name: 'TypeError' }, () => {
+    anim.effect.updateTiming({ endDelay: -Infinity });
+  });
+}, 'Throws when setting the endDelay to negative infinity');
+
+
+// ------------------------------
+//  fill
+// ------------------------------
+
+for (const fill of ['none', 'forwards', 'backwards', 'both']) {
+  test(t => {
+    const anim = createDiv(t).animate(null, 100);
+    anim.effect.updateTiming({ fill });
+    assert_equals(anim.effect.getTiming().fill, fill, 'set fill ' + fill);
+    assert_equals(anim.effect.getComputedTiming().fill, fill,
+                  'getComputedTiming() after set fill ' + fill);
+  }, `Allows setting the fill to '${fill}'`);
+}
+
+
+// ------------------------------
+//  iterationStart
+// ------------------------------
+
+test(t => {
+  const anim = createDiv(t).animate(null,
+                                    { iterationStart: 0.2,
+                                      iterations: 1,
+                                      fill: 'both',
+                                      duration: 100,
+                                      delay: 1 });
+  anim.effect.updateTiming({ iterationStart: 2.5 });
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
+  assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
+}, 'Allows setting the iterationStart of an animation in progress:'
+   + ' backwards-filling');
+
+test(t => {
+  const anim = createDiv(t).animate(null,
+                                    { iterationStart: 0.2,
+                                      iterations: 1,
+                                      fill: 'both',
+                                      duration: 100,
+                                      delay: 0 });
+  anim.effect.updateTiming({ iterationStart: 2.5 });
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
+  assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
+}, 'Allows setting the iterationStart of an animation in progress:'
+   + ' active phase');
+
+test(t => {
+  const anim = createDiv(t).animate(null,
+                                    { iterationStart: 0.2,
+                                      iterations: 1,
+                                      fill: 'both',
+                                      duration: 100,
+                                      delay: 0 });
+  anim.finish();
+  anim.effect.updateTiming({ iterationStart: 2.5 });
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
+  assert_equals(anim.effect.getComputedTiming().currentIteration, 3);
+}, 'Allows setting the iterationStart of an animation in progress:'
+   + ' forwards-filling');
+
+for (const invalid of gBadIterationStartValues) {
+  test(t => {
+    const anim = createDiv(t).animate(null);
+    assert_throws({ name: 'TypeError' }, () => {
+      anim.effect.updateTiming({ iterationStart: invalid });
+    }, `setting ${invalid}`);
+  }, `Throws when setting invalid iterationStart value: ${invalid}`);
+}
+
+// ------------------------------
+//  iterations
+// ------------------------------
+
+test(t => {
+  const anim = createDiv(t).animate(null, 2000);
+  anim.effect.updateTiming({ iterations: 2 });
+  assert_equals(anim.effect.getTiming().iterations, 2, 'set duration 2');
+  assert_equals(anim.effect.getComputedTiming().iterations, 2,
+                       'getComputedTiming() after set iterations 2');
+}, 'Allows setting iterations to a double value');
+
+test(t => {
+  const anim = createDiv(t).animate(null, 2000);
+  anim.effect.updateTiming({ iterations: Infinity });
+  assert_equals(anim.effect.getTiming().iterations, Infinity,
+                'set duration Infinity');
+  assert_equals(anim.effect.getComputedTiming().iterations, Infinity,
+                       'getComputedTiming() after set iterations Infinity');
+}, 'Allows setting iterations to infinity');
+
+for (const invalid of gBadIterationsValues) {
+  test(t => {
+    const anim = createDiv(t).animate(null);
+    assert_throws({ name: 'TypeError' }, () => {
+      anim.effect.updateTiming({ iterations: invalid });
+    });
+  }, `Throws when setting invalid iterations value: ${invalid}`);
+}
+
+test(t => {
+  const anim = createDiv(t).animate(null, { duration: 100000, fill: 'both' });
+
+  anim.finish();
+
+  assert_equals(anim.effect.getComputedTiming().progress, 1,
+                'progress when animation is finished');
+  assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
+                'current iteration when animation is finished');
+
+  anim.effect.updateTiming({ iterations: 2 });
+
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress,
+                             0,
+                             'progress after adding an iteration');
+  assert_time_equals_literal(anim.effect.getComputedTiming().currentIteration,
+                             1,
+                             'current iteration after adding an iteration');
+
+  anim.effect.updateTiming({ iterations: 0 });
+
+  assert_equals(anim.effect.getComputedTiming().progress, 0,
+                'progress after setting iterations to zero');
+  assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
+                'current iteration after setting iterations to zero');
+
+  anim.effect.updateTiming({ iterations: Infinity });
+
+  assert_equals(anim.effect.getComputedTiming().progress, 0,
+                'progress after setting iterations to Infinity');
+  assert_equals(anim.effect.getComputedTiming().currentIteration, 1,
+                'current iteration after setting iterations to Infinity');
+}, 'Allows setting the iterations of an animation in progress');
+
+
+// ------------------------------
+//  duration
+// ------------------------------
+
+for (const duration of gGoodDurationValues) {
+  test(t => {
+    const anim = createDiv(t).animate(null, 2000);
+    anim.effect.updateTiming({ duration: duration.specified });
+    if (typeof duration.specified === 'number') {
+      assert_time_equals_literal(anim.effect.getTiming().duration,
+                                 duration.specified,
+                                 'Updates specified duration');
+    } else {
+      assert_equals(anim.effect.getTiming().duration, duration.specified,
+                    'Updates specified duration');
+    }
+    assert_time_equals_literal(anim.effect.getComputedTiming().duration,
+                               duration.computed,
+                               'Updates computed duration');
+  }, `Allows setting the duration to ${duration.specified}`);
+}
+
+for (const invalid of gBadDurationValues) {
+  test(t => {
+    assert_throws(new TypeError, () => {
+      createDiv(t).animate(null, { duration: invalid });
+    });
+  }, 'Throws when setting invalid duration: '
+     + (typeof invalid === 'string' ? `"${invalid}"` : invalid));
+}
+
+test(t => {
+  const anim = createDiv(t).animate(null, { duration: 100000, fill: 'both' });
+  anim.finish();
+  assert_equals(anim.effect.getComputedTiming().progress, 1,
+                'progress when animation is finished');
+  anim.effect.updateTiming({ duration: anim.effect.getTiming().duration * 2 });
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5,
+                             'progress after doubling the duration');
+  anim.effect.updateTiming({ duration: 0 });
+  assert_equals(anim.effect.getComputedTiming().progress, 1,
+                'progress after setting duration to zero');
+  anim.effect.updateTiming({ duration: 'auto' });
+  assert_equals(anim.effect.getComputedTiming().progress, 1,
+                'progress after setting duration to \'auto\'');
+}, 'Allows setting the duration of an animation in progress');
+
+promise_test(t => {
+  const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+  return anim.ready.then(() => {
+    const originalStartTime   = anim.startTime;
+    const originalCurrentTime = anim.currentTime;
+    assert_time_equals_literal(
+      anim.effect.getComputedTiming().duration,
+      100 * MS_PER_SEC,
+      'Initial duration should be as set on KeyframeEffect'
+    );
+
+    anim.effect.updateTiming({ duration: 200 * MS_PER_SEC });
+    assert_time_equals_literal(
+      anim.effect.getComputedTiming().duration,
+      200 * MS_PER_SEC,
+      'Effect duration should have been updated'
+    );
+    assert_times_equal(anim.startTime, originalStartTime,
+                       'startTime should be unaffected by changing effect ' +
+                       'duration');
+    assert_times_equal(anim.currentTime, originalCurrentTime,
+                       'currentTime should be unaffected by changing effect ' +
+                       'duration');
+  });
+}, 'Allows setting the duration of an animation in progress such that the' +
+   ' the start and current time do not change');
+
+
+// ------------------------------
+//  direction
+// ------------------------------
+
+test(t => {
+  const anim = createDiv(t).animate(null, 2000);
+
+  const directions = ['normal', 'reverse', 'alternate', 'alternate-reverse'];
+  for (const direction of directions) {
+    anim.effect.updateTiming({ direction: direction });
+    assert_equals(anim.effect.getTiming().direction, direction,
+                  `set direction to ${direction}`);
+  }
+}, 'Allows setting the direction to each of the possible keywords');
+
+test(t => {
+  const anim = createDiv(t).animate(null, {
+    duration: 10000,
+    direction: 'normal',
+  });
+  anim.currentTime = 7000;
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
+                             'progress before updating direction');
+
+  anim.effect.updateTiming({ direction: 'reverse' });
+
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
+                             'progress after updating direction');
+}, 'Allows setting the direction of an animation in progress from \'normal\' to'
+   + ' \'reverse\'');
+
+test(t => {
+  const anim = createDiv(t).animate(null,
+                                    { duration: 10000, direction: 'normal' });
+  assert_equals(anim.effect.getComputedTiming().progress, 0,
+                'progress before updating direction');
+
+  anim.effect.updateTiming({ direction: 'reverse' });
+
+  assert_equals(anim.effect.getComputedTiming().progress, 1,
+                'progress after updating direction');
+}, 'Allows setting the direction of an animation in progress from \'normal\' to'
+   + ' \'reverse\' while at start of active interval');
+
+test(t => {
+  const anim = createDiv(t).animate(null,
+                                    { fill: 'backwards',
+                                      duration: 10000,
+                                      delay: 10000,
+                                      direction: 'normal' });
+  assert_equals(anim.effect.getComputedTiming().progress, 0,
+                'progress before updating direction');
+
+  anim.effect.updateTiming({ direction: 'reverse' });
+
+  assert_equals(anim.effect.getComputedTiming().progress, 1,
+                'progress after updating direction');
+}, 'Allows setting the direction of an animation in progress from \'normal\' to'
+   + ' \'reverse\' while filling backwards');
+
+test(t => {
+  const anim = createDiv(t).animate(null,
+                                    { iterations: 2,
+                                      duration: 10000,
+                                      direction: 'normal' });
+  anim.currentTime = 17000;
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
+                             'progress before updating direction');
+
+  anim.effect.updateTiming({ direction: 'alternate' });
+
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
+                             'progress after updating direction');
+}, 'Allows setting the direction of an animation in progress from \'normal\' to'
+   + ' \'alternate\'');
+
+test(t => {
+  const anim = createDiv(t).animate(null,
+                                    { iterations: 2,
+                                      duration: 10000,
+                                      direction: 'alternate' });
+  anim.currentTime = 17000;
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
+                             'progress before updating direction');
+
+  anim.effect.updateTiming({ direction: 'alternate-reverse' });
+
+  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
+                             'progress after updating direction');
+}, 'Allows setting the direction of an animation in progress from \'alternate\''
+   + ' to \'alternate-reverse\'');
+
+
+// ------------------------------
+//  easing
+// ------------------------------
+
+function assert_progress(animation, currentTime, easingFunction) {
+  animation.currentTime = currentTime;
+  const portion = currentTime / animation.effect.getTiming().duration;
+  assert_approx_equals(animation.effect.getComputedTiming().progress,
+                       easingFunction(portion),
+                       0.01,
+                       'The progress of the animation should be approximately'
+                       + ` ${easingFunction(portion)} at ${currentTime}ms`);
+}
+
+for (const options of gEasingTests) {
+  test(t => {
+    const target = createDiv(t);
+    const anim = target.animate(null,
+                                { duration: 1000 * MS_PER_SEC,
+                                  fill: 'forwards' });
+    anim.effect.updateTiming({ easing: options.easing });
+    assert_equals(anim.effect.getTiming().easing,
+                  options.serialization || options.easing);
+
+    const easing = options.easingFunction;
+    assert_progress(anim, 0, easing);
+    assert_progress(anim, 250 * MS_PER_SEC, easing);
+    assert_progress(anim, 500 * MS_PER_SEC, easing);
+    assert_progress(anim, 750 * MS_PER_SEC, easing);
+    assert_progress(anim, 1000 * MS_PER_SEC, easing);
+  }, `Allows setting the easing to a ${options.desc}`);
+}
+
+for (const easing of gRoundtripEasings) {
+  test(t => {
+    const anim = createDiv(t).animate(null);
+    anim.effect.updateTiming({ easing: easing });
+    assert_equals(anim.effect.getTiming().easing, easing);
+  }, `Updates the specified value when setting the easing to '${easing}'`);
+}
+
+test(t => {
+  const delay = 1000 * MS_PER_SEC;
+
+  const target = createDiv(t);
+  const anim = target.animate(null,
+                              { duration: 1000 * MS_PER_SEC,
+                                fill: 'both',
+                                delay: delay,
+                                easing: 'steps(2, start)' });
+
+  anim.effect.updateTiming({ easing: 'steps(2, end)' });
+  assert_equals(anim.effect.getComputedTiming().progress, 0,
+                'easing replace to steps(2, end) at before phase');
+
+  anim.currentTime = delay + 750 * MS_PER_SEC;
+  assert_equals(anim.effect.getComputedTiming().progress, 0.5,
+                'change currentTime to active phase');
+
+  anim.effect.updateTiming({ easing: 'steps(2, start)' });
+  assert_equals(anim.effect.getComputedTiming().progress, 1,
+                'easing replace to steps(2, start) at active phase');
+
+  anim.currentTime = delay + 1500 * MS_PER_SEC;
+  anim.effect.updateTiming({ easing: 'steps(2, end)' });
+  assert_equals(anim.effect.getComputedTiming().progress, 1,
+                'easing replace to steps(2, end) again at after phase');
+}, 'Allows setting the easing of an animation in progress');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/delay.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/delay.html
deleted file mode 100644
index 41f099b..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/delay.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.delay</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-delay">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
-  const anim = createDiv(t).animate(null);
-  assert_equals(anim.effect.timing.delay, 0);
-}, 'Has the default value 0');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
-  anim.effect.timing.delay = 100;
-  assert_equals(anim.effect.timing.delay, 100, 'set delay 100');
-  assert_equals(anim.effect.getComputedTiming().delay, 100,
-                  'getComputedTiming() after set delay 100');
-}, 'Can be set to a positive number');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
-  anim.effect.timing.delay = -100;
-  assert_equals(anim.effect.timing.delay, -100, 'set delay -100');
-  assert_equals(anim.effect.getComputedTiming().delay, -100,
-                'getComputedTiming() after set delay -100');
-}, 'Can be set to a negative number');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
-  anim.effect.timing.delay = 100;
-  assert_equals(anim.effect.getComputedTiming().progress, null);
-  assert_equals(anim.effect.getComputedTiming().currentIteration, null);
-}, 'Can set a positive delay on an animation without a backwards fill to'
-   + ' make it no longer active');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { fill: 'both',
-                             duration: 100 });
-  anim.effect.timing.delay = -50;
-  assert_equals(anim.effect.getComputedTiming().progress, 0.5);
-}, 'Can set a negative delay to seek into the active interval');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { fill: 'both',
-                             duration: 100 });
-  anim.effect.timing.delay = -100;
-  assert_equals(anim.effect.getComputedTiming().progress, 1);
-  assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
-}, 'Can set a large negative delay to finishing an animation');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate(null);
-  for (let invalid of [NaN, Infinity]) {
-    assert_throws({ name: 'TypeError' }, () => {
-      anim.effect.timing.delay = invalid;
-    }, `setting ${invalid}`);
-    assert_throws({ name: 'TypeError' }, () => {
-      div.animate({}, { delay: invalid });
-    }, `animate() with ${invalid}`);
-  }
-}, 'Throws when setting invalid values');
-
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/direction.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/direction.html
deleted file mode 100644
index 3238f5d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/direction.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.direction</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-direction">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
-  const anim = createDiv(t).animate(null);
-  assert_equals(anim.effect.timing.direction, 'normal');
-}, 'Has the default value \'normal\'');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-
-  const directions = ['normal', 'reverse', 'alternate', 'alternate-reverse'];
-  for (const direction of directions) {
-    anim.effect.timing.direction = direction;
-    assert_equals(anim.effect.timing.direction, direction,
-                  `set direction to ${direction}`);
-  }
-}, 'Can be set to each of the possible keywords');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate(null, { duration: 10000, direction: 'normal' });
-  anim.currentTime = 7000;
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
-                             'progress before updating direction');
-
-  anim.effect.timing.direction = 'reverse';
-
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
-                             'progress after updating direction');
-}, 'Can be changed from \'normal\' to \'reverse\' while in progress');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { duration: 10000,
-                             direction: 'normal' });
-  assert_equals(anim.effect.getComputedTiming().progress, 0,
-                'progress before updating direction');
-
-  anim.effect.timing.direction = 'reverse';
-
-  assert_equals(anim.effect.getComputedTiming().progress, 1,
-                'progress after updating direction');
-}, 'Can be changed from \'normal\' to \'reverse\' while at start of active'
-   + ' interval');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { fill: 'backwards',
-                             duration: 10000,
-                             delay: 10000,
-                             direction: 'normal' });
-  assert_equals(anim.effect.getComputedTiming().progress, 0,
-                'progress before updating direction');
-
-  anim.effect.timing.direction = 'reverse';
-
-  assert_equals(anim.effect.getComputedTiming().progress, 1,
-                'progress after updating direction');
-}, 'Can be changed from \'normal\' to \'reverse\' while filling backwards');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { iterations: 2,
-                             duration: 10000,
-                             direction: 'normal' });
-  anim.currentTime = 17000;
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
-                             'progress before updating direction');
-
-  anim.effect.timing.direction = 'alternate';
-
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
-                             'progress after updating direction');
-}, 'Can be changed from \'normal\' to \'alternate\' while in progress');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { iterations: 2,
-                             duration: 10000,
-                             direction: 'alternate' });
-  anim.currentTime = 17000;
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.3,
-                             'progress before updating direction');
-
-  anim.effect.timing.direction = 'alternate-reverse';
-
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.7,
-                             'progress after updating direction');
-}, 'Can be changed from \'alternate\' to \'alternate-reverse\' while in'
-   + ' progress');
-
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/duration.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/duration.html
deleted file mode 100644
index 42913f5..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/duration.html
+++ /dev/null
@@ -1,190 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.duration</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-duration">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
-  const anim = createDiv(t).animate(null);
-  assert_equals(anim.effect.timing.duration, 'auto');
-}, 'Has the default value \'auto\'');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  anim.effect.timing.duration = 123.45;
-  assert_time_equals_literal(anim.effect.timing.duration, 123.45,
-                             'set duration 123.45');
-  assert_time_equals_literal(anim.effect.getComputedTiming().duration, 123.45,
-                             'getComputedTiming() after set duration 123.45');
-}, 'Can be set to a double value');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  anim.effect.timing.duration = 'auto';
-  assert_equals(anim.effect.timing.duration, 'auto', 'set duration \'auto\'');
-  assert_equals(anim.effect.getComputedTiming().duration, 0,
-                'getComputedTiming() after set duration \'auto\'');
-}, 'Can be set to the string \'auto\'');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, { duration: 'auto' });
-  assert_equals(anim.effect.timing.duration, 'auto', 'set duration \'auto\'');
-  assert_equals(anim.effect.getComputedTiming().duration, 0,
-                'getComputedTiming() after set duration \'auto\'');
-}, 'Can be set to \'auto\' using a dictionary object');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  anim.effect.timing.duration = Infinity;
-  assert_equals(anim.effect.timing.duration, Infinity, 'set duration Infinity');
-  assert_equals(anim.effect.getComputedTiming().duration, Infinity,
-                'getComputedTiming() after set duration Infinity');
-}, 'Can be set to Infinity');
-
-test(t => {
-  const div = createDiv(t);
-  assert_throws({ name: 'TypeError' }, () => {
-    div.animate({ opacity: [ 0, 1 ] }, -1);
-  });
-}, 'animate() throws when passed a negative number');
-
-test(t => {
-  const div = createDiv(t);
-  assert_throws({ name: 'TypeError' }, () => {
-    div.animate({ opacity: [ 0, 1 ] }, -Infinity);
-  });
-}, 'animate() throws when passed negative Infinity');
-
-test(t => {
-  const div = createDiv(t);
-  assert_throws({ name: 'TypeError' }, () => {
-    div.animate({ opacity: [ 0, 1 ] }, NaN);
-  });
-}, 'animate() throws when passed a NaN value');
-
-test(t => {
-  const div = createDiv(t);
-  assert_throws({ name: 'TypeError' }, () => {
-    div.animate({ opacity: [ 0, 1 ] }, { duration: -1 });
-  });
-}, 'animate() throws when passed a negative number using a dictionary object');
-
-test(t => {
-  const div = createDiv(t);
-  assert_throws({ name: 'TypeError' }, () => {
-    div.animate({ opacity: [ 0, 1 ] }, { duration: -Infinity });
-  });
-}, 'animate() throws when passed negative Infinity using a dictionary object');
-
-test(t => {
-  const div = createDiv(t);
-  assert_throws({ name: 'TypeError' }, () => {
-    div.animate({ opacity: [ 0, 1 ] }, { duration: NaN });
-  });
-}, 'animate() throws when passed a NaN value using a dictionary object');
-
-test(t => {
-  const div = createDiv(t);
-  assert_throws({ name: 'TypeError' }, () => {
-    div.animate({ opacity: [ 0, 1 ] }, { duration: 'abc' });
-  });
-}, 'animate() throws when passed a string other than \'auto\' using a'
-   + ' dictionary object');
-
-test(t => {
-  const div = createDiv(t);
-  assert_throws({ name: 'TypeError' }, () => {
-    div.animate({ opacity: [ 0, 1 ] }, { duration: '100' });
-  });
-}, 'animate() throws when passed a string containing a number using a'
-   + ' dictionary object');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_throws({ name: 'TypeError' }, () => {
-    anim.effect.timing.duration = -1;
-  });
-}, 'Throws when setting a negative number');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_throws({ name: 'TypeError' }, () => {
-    anim.effect.timing.duration = -Infinity;
-  });
-}, 'Throws when setting negative infinity');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_throws({ name: 'TypeError' }, () => {
-    anim.effect.timing.duration = NaN;
-  });
-}, 'Throws when setting a NaN value');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_throws({ name: 'TypeError' }, () => {
-    anim.effect.timing.duration = 'abc';
-  });
-}, 'Throws when setting a string other than \'auto\'');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_throws({ name: 'TypeError' }, () => {
-    anim.effect.timing.duration = '100';
-  });
-}, 'Throws when setting a string containing a number');
-
-promise_test(t => {
-  const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
-  return anim.ready.then(() => {
-    const originalStartTime   = anim.startTime;
-    const originalCurrentTime = anim.currentTime;
-    assert_equals(anim.effect.getComputedTiming().duration, 100 * MS_PER_SEC,
-                  'Initial duration should be as set on KeyframeEffect');
-
-    anim.effect.timing.duration = 200 * MS_PER_SEC;
-    assert_equals(anim.effect.getComputedTiming().duration, 200 * MS_PER_SEC,
-                  'Effect duration should have been updated');
-    assert_times_equal(anim.startTime, originalStartTime,
-                       'startTime should be unaffected by changing effect ' +
-                       'duration');
-    assert_times_equal(anim.currentTime, originalCurrentTime,
-                       'currentTime should be unaffected by changing effect ' +
-                       'duration');
-  });
-}, 'Extending an effect\'s duration does not change the start or current time');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate(null, { duration: 100000, fill: 'both' });
-  anim.finish();
-  assert_equals(anim.effect.getComputedTiming().progress, 1,
-                'progress when animation is finished');
-  anim.effect.timing.duration *= 2;
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5,
-                             'progress after doubling the duration');
-  anim.effect.timing.duration = 0;
-  assert_equals(anim.effect.getComputedTiming().progress, 1,
-                'progress after setting duration to zero');
-  anim.effect.timing.duration = 'auto';
-  assert_equals(anim.effect.getComputedTiming().progress, 1,
-                'progress after setting duration to \'auto\'');
-}, 'Can be updated while the animation is in progress');
-
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/easing.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/easing.html
deleted file mode 100644
index ec2b239..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/easing.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.easing</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-easing">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<script src="../../resources/easing-tests.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
-  const anim = createDiv(t).animate(null);
-  assert_equals(anim.effect.timing.easing, 'linear');
-}, 'Has the default value \'linear\'');
-
-function assert_progress(animation, currentTime, easingFunction) {
-  animation.currentTime = currentTime;
-  const portion = currentTime / animation.effect.timing.duration;
-  assert_approx_equals(animation.effect.getComputedTiming().progress,
-                       easingFunction(portion),
-                       0.01,
-                       'The progress of the animation should be approximately'
-                       + ` ${easingFunction(portion)} at ${currentTime}ms`);
-}
-
-for (const options of gEasingTests) {
-  test(t => {
-    const target = createDiv(t);
-    const anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
-                                { duration: 1000 * MS_PER_SEC,
-                                  fill: 'forwards' });
-    anim.effect.timing.easing = options.easing;
-    assert_equals(anim.effect.timing.easing,
-                  options.serialization || options.easing);
-
-    const easing = options.easingFunction;
-    assert_progress(anim, 0, easing);
-    assert_progress(anim, 250 * MS_PER_SEC, easing);
-    assert_progress(anim, 500 * MS_PER_SEC, easing);
-    assert_progress(anim, 750 * MS_PER_SEC, easing);
-    assert_progress(anim, 1000 * MS_PER_SEC, easing);
-  }, options.desc);
-}
-
-for (const invalidEasing of gInvalidEasings) {
-  test(t => {
-    const div = createDiv(t);
-    const anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
-    assert_throws({ name: 'TypeError' },
-                  () => {
-                    anim.effect.timing.easing = invalidEasing;
-                  });
-  }, `Throws on invalid easing: '${invalidEasing}'`);
-}
-
-for (const easing of gRoundtripEasings) {
-  test(t => {
-    const anim = createDiv(t).animate(null);
-    anim.effect.timing.easing = easing;
-    assert_equals(anim.effect.timing.easing, easing);
-  }, `Canonical easing '${easing}' is returned as set`);
-}
-
-test(t => {
-  const delay = 1000 * MS_PER_SEC;
-
-  const target = createDiv(t);
-  const anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
-                              { duration: 1000 * MS_PER_SEC,
-                                fill: 'both',
-                                delay: delay,
-                                easing: 'steps(2, start)' });
-
-  anim.effect.timing.easing = 'steps(2, end)';
-  assert_equals(anim.effect.getComputedTiming().progress, 0,
-                'easing replace to steps(2, end) at before phase');
-
-  anim.currentTime = delay + 750 * MS_PER_SEC;
-  assert_equals(anim.effect.getComputedTiming().progress, 0.5,
-                'change currentTime to active phase');
-
-  anim.effect.timing.easing = 'steps(2, start)';
-  assert_equals(anim.effect.getComputedTiming().progress, 1,
-                'easing replace to steps(2, start) at active phase');
-
-  anim.currentTime = delay + 1500 * MS_PER_SEC;
-  anim.effect.timing.easing = 'steps(2, end)';
-  assert_equals(anim.effect.getComputedTiming().progress, 1,
-                'easing replace to steps(2, end) again at after phase');
-}, 'Allows the easing to be changed while the animation is in progress');
-
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/endDelay.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/endDelay.html
deleted file mode 100644
index 3062c8c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/endDelay.html
+++ /dev/null
@@ -1,89 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.endDelay</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-enddelay">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
-  const anim = createDiv(t).animate(null);
-  assert_equals(anim.effect.timing.endDelay, 0);
-}, 'Has the default value 0');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  anim.effect.timing.endDelay = 123.45;
-  assert_time_equals_literal(anim.effect.timing.endDelay, 123.45,
-                             'set endDelay 123.45');
-  assert_time_equals_literal(anim.effect.getComputedTiming().endDelay, 123.45,
-                             'getComputedTiming() after set endDelay 123.45');
-}, 'Can be set to a positive number');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  anim.effect.timing.endDelay = -1000;
-  assert_equals(anim.effect.timing.endDelay, -1000, 'set endDelay -1000');
-  assert_equals(anim.effect.getComputedTiming().endDelay, -1000,
-                'getComputedTiming() after set endDelay -1000');
-}, 'Can be set to a negative number');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_throws({ name: 'TypeError' }, () => {
-    anim.effect.timing.endDelay = Infinity;
-  }, 'we can not assign Infinity to timing.endDelay');
-}, 'Throws when setting infinity');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_throws({ name: 'TypeError' }, () => {
-    anim.effect.timing.endDelay = -Infinity;
-  }, 'we can not assign negative Infinity to timing.endDelay');
-}, 'Throws when setting negative infinity');
-
-async_test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { duration: 100000, endDelay: 50000 });
-  anim.onfinish = t.step_func(event => {
-    assert_unreached('finish event should not be fired');
-  });
-
-  anim.ready.then(() => {
-    anim.currentTime = 100000;
-    return waitForAnimationFrames(2);
-  }).then(t.step_func(() => {
-    t.done();
-  }));
-}, 'finish event is not fired at the end of the active interval when the'
-   + ' endDelay has not expired');
-
-async_test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { duration: 100000, endDelay: 30000 });
-  anim.ready.then(() => {
-    anim.currentTime = 110000; // during endDelay
-    anim.onfinish = t.step_func(event => {
-      assert_unreached('onfinish event should not be fired during endDelay');
-    });
-    return waitForAnimationFrames(2);
-  }).then(t.step_func(() => {
-    anim.onfinish = t.step_func(event => {
-      t.done();
-    });
-    anim.currentTime = 130000; // after endTime
-  }));
-}, 'finish event is fired after the endDelay has expired');
-
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/fill.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/fill.html
deleted file mode 100644
index 01739478..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/fill.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.fill</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-fill">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
-  const anim = createDiv(t).animate(null);
-  assert_equals(anim.effect.timing.fill, 'auto');
-}, 'Has the default value \'auto\'');
-
-for (const fill of ['none', 'forwards', 'backwards', 'both']) {
-  test(t => {
-    const div = createDiv(t);
-    const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
-    anim.effect.timing.fill = fill;
-    assert_equals(anim.effect.timing.fill, fill, 'set fill ' + fill);
-    assert_equals(anim.effect.getComputedTiming().fill, fill,
-                  'getComputedTiming() after set fill ' + fill);
-  }, `Can set fill to ${fill}`);
-}
-
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/idlharness.html
deleted file mode 100644
index 7e537d1..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/idlharness.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming and AnimationEffectTimingReadOnly IDL</title>
-<link rel="help"
-      href="https://drafts.csswg.org/web-animations/#animationeffecttiming">
-<link rel="help"
-      href="https://drafts.csswg.org/web-animations/#animationeffecttimingreadonly">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-<div id="log"></div>
-<script type="text/plain" id="AnimationEffectTimingReadOnly-IDL">
-enum FillMode { "none", "forwards", "backwards", "both", "auto" };
-enum PlaybackDirection {
-  "normal",
-  "reverse",
-  "alternate",
-  "alternate-reverse"
-};
-
-dictionary AnimationEffectTimingProperties {
-  double                             delay = 0.0;
-  double                             endDelay = 0.0;
-  FillMode                           fill = "auto";
-  double                             iterationStart = 0.0;
-  unrestricted double                iterations = 1.0;
-  (unrestricted double or DOMString) duration = "auto";
-  PlaybackDirection                  direction = "normal";
-  DOMString                          easing = "linear";
-};
-
-[Exposed=Window]
-interface AnimationEffectTimingReadOnly {
-  readonly attribute double                             delay;
-  readonly attribute double                             endDelay;
-  readonly attribute FillMode                           fill;
-  readonly attribute double                             iterationStart;
-  readonly attribute unrestricted double                iterations;
-  readonly attribute (unrestricted double or DOMString) duration;
-  readonly attribute PlaybackDirection                  direction;
-  readonly attribute DOMString                          easing;
-};
-</script>
-<script type="text/plain" id="AnimationEffectTiming-IDL">
-[Exposed=Window]
-interface AnimationEffectTiming : AnimationEffectTimingReadOnly {
-  inherit attribute double                             delay;
-  inherit attribute double                             endDelay;
-  inherit attribute FillMode                           fill;
-  inherit attribute double                             iterationStart;
-  inherit attribute unrestricted double                iterations;
-  inherit attribute (unrestricted double or DOMString) duration;
-  inherit attribute PlaybackDirection                  direction;
-  inherit attribute DOMString                          easing;
-};
-</script>
-<script>
-'use strict';
-
-const idlArray = new IdlArray();
-
-idlArray.add_idls(
-  document.getElementById('AnimationEffectTimingReadOnly-IDL').textContent
-);
-idlArray.add_idls(
-  document.getElementById('AnimationEffectTiming-IDL').textContent
-);
-
-idlArray.add_objects({
-  AnimationEffectTiming: [
-    '(new KeyframeEffect(null, null)).timing'
-  ],
-  AnimationEffectTimingReadOnly: [
-    '(new KeyframeEffectReadOnly(null, null)).timing'
-  ],
-});
-idlArray.test();
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterationStart.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterationStart.html
deleted file mode 100644
index 73bc481..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterationStart.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.iterationStart</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-iterationstart">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
-  const anim = createDiv(t).animate(null);
-  assert_equals(anim.effect.timing.iterationStart, 0);
-}, 'Has the default value 0');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { iterationStart: 0.2,
-                             iterations: 1,
-                             fill: 'both',
-                             duration: 100,
-                             delay: 1 });
-  anim.effect.timing.iterationStart = 2.5;
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
-  assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
-}, 'Changing the value updates computed timing when backwards-filling');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { iterationStart: 0.2,
-                             iterations: 1,
-                             fill: 'both',
-                             duration: 100,
-                             delay: 0 });
-  anim.effect.timing.iterationStart = 2.5;
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
-  assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
-}, 'Changing the value updates computed timing during the active phase');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] },
-                           { iterationStart: 0.2,
-                             iterations: 1,
-                             fill: 'both',
-                             duration: 100,
-                             delay: 0 });
-  anim.finish();
-  anim.effect.timing.iterationStart = 2.5;
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress, 0.5);
-  assert_equals(anim.effect.getComputedTiming().currentIteration, 3);
-}, 'Changing the value updates computed timing when forwards-filling');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate(null);
-  for (let invalid of [-1, NaN, Infinity]) {
-    assert_throws({ name: 'TypeError' }, () => {
-      anim.effect.timing.iterationStart = invalid;
-    }, `setting ${invalid}`);
-    assert_throws({ name: 'TypeError' }, () => {
-      div.animate({}, { iterationStart: invalid });
-    }, `animate() with ${invalid}`);
-  }
-}, 'Throws when setting invalid values');
-
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterations.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterations.html
deleted file mode 100644
index 3bfaf8e..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/AnimationEffectTiming/iterations.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>AnimationEffectTiming.iterations</title>
-<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-iterations">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(t => {
-  const anim = createDiv(t).animate(null);
-  assert_equals(anim.effect.timing.iterations, 1);
-}, 'Has the default value 1');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  anim.effect.timing.iterations = 2;
-  assert_equals(anim.effect.timing.iterations, 2, 'set duration 2');
-  assert_equals(anim.effect.getComputedTiming().iterations, 2,
-                       'getComputedTiming() after set iterations 2');
-}, 'Can be set to a double value');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  anim.effect.timing.iterations = Infinity;
-  assert_equals(anim.effect.timing.iterations, Infinity, 'set duration Infinity');
-  assert_equals(anim.effect.getComputedTiming().iterations, Infinity,
-                       'getComputedTiming() after set iterations Infinity');
-}, 'Can be set to infinity');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_throws({ name: 'TypeError' }, () => {
-    anim.effect.timing.iterations = -1;
-  });
-}, 'Throws when setting a negative number');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_throws({ name: 'TypeError' }, () => {
-    anim.effect.timing.iterations = -Infinity;
-  });
-}, 'Throws when setting negative infinity');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-  assert_throws({ name: 'TypeError' }, () => {
-    anim.effect.timing.iterations = NaN;
-  });
-}, 'Throws when setting a NaN value');
-
-test(t => {
-  const div = createDiv(t);
-  const anim = div.animate(null, { duration: 100000, fill: 'both' });
-
-  anim.finish();
-
-  assert_equals(anim.effect.getComputedTiming().progress, 1,
-                'progress when animation is finished');
-  assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
-                'current iteration when animation is finished');
-
-  anim.effect.timing.iterations = 2;
-
-  assert_time_equals_literal(anim.effect.getComputedTiming().progress,
-                             0,
-                             'progress after adding an iteration');
-  assert_time_equals_literal(anim.effect.getComputedTiming().currentIteration,
-                             1,
-                             'current iteration after adding an iteration');
-
-  anim.effect.timing.iterations = 0;
-
-  assert_equals(anim.effect.getComputedTiming().progress, 0,
-                'progress after setting iterations to zero');
-  assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
-                'current iteration after setting iterations to zero');
-
-  anim.effect.timing.iterations = Infinity;
-
-  assert_equals(anim.effect.getComputedTiming().progress, 0,
-                'progress after setting iterations to Infinity');
-  assert_equals(anim.effect.getComputedTiming().currentIteration, 1,
-                'current iteration after setting iterations to Infinity');
-}, 'Can be updated while the animation is in progress');
-
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations.html
index 165626de..3a1d7be 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/Document/getAnimations.html
@@ -42,7 +42,7 @@
 }, 'Test the order of document.getAnimations with script generated animations')
 
 test(t => {
-  const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
+  const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
   const anim = new Animation(effect, document.timeline);
   anim.play();
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor-expected.txt
index 131b57c..b1ecb41 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor-expected.txt
@@ -1,171 +1,171 @@
 This is a testharness.js-based test.
-Found 167 tests; 154 PASS, 13 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS A KeyframeEffectReadOnly can be constructed with no frames
-PASS easing values are parsed correctly when passed to the KeyframeEffectReadOnly constructor in KeyframeEffectOptions
-PASS Invalid easing values are correctly rejected when passed to the KeyframeEffectReadOnly constructor in KeyframeEffectOptions
-FAIL composite values are parsed correctly when passed to the KeyframeEffectReadOnly constructor in property-indexed keyframes assert_equals: resulting composite for 'accumulate' expected "accumulate" but got "replace"
-FAIL composite values are parsed correctly when passed to the KeyframeEffectReadOnly constructor in regular keyframes assert_equals: resulting composite for 'accumulate' expected "accumulate" but got "replace"
+Found 167 tests; 144 PASS, 23 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS A KeyframeEffect can be constructed with no frames
+FAIL easing values are parsed correctly when passed to the KeyframeEffect constructor in KeyframeEffectOptions effect.getTiming is not a function
+PASS Invalid easing values are correctly rejected when passed to the KeyframeEffect constructor in KeyframeEffectOptions
+FAIL composite values are parsed correctly when passed to the KeyframeEffect constructor in property-indexed keyframes assert_equals: resulting composite for 'accumulate' expected "accumulate" but got "replace"
+FAIL composite values are parsed correctly when passed to the KeyframeEffect constructor in regular keyframes assert_equals: resulting composite for 'accumulate' expected "accumulate" but got "replace"
 PASS composite value is null if the composite operation specified on the keyframe effect is being used
-PASS A KeyframeEffectReadOnly can be constructed with a one property two value property-indexed keyframes specification
-PASS A KeyframeEffectReadOnly constructed with a one property two value property-indexed keyframes specification roundtrips
-FAIL A KeyframeEffectReadOnly can be constructed with a one shorthand property two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
-PASS A KeyframeEffectReadOnly constructed with a one shorthand property two value property-indexed keyframes specification roundtrips
-FAIL A KeyframeEffectReadOnly can be constructed with a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
-PASS A KeyframeEffectReadOnly constructed with a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a two property two value property-indexed keyframes specification
-PASS A KeyframeEffectReadOnly constructed with a two property two value property-indexed keyframes specification roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a two property property-indexed keyframes specification with different numbers of values
-PASS A KeyframeEffectReadOnly constructed with a two property property-indexed keyframes specification with different numbers of values roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframes specification with an invalid value
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframes specification with an invalid value roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a one property two value property-indexed keyframes specification that needs to stringify its values
-PASS A KeyframeEffectReadOnly constructed with a one property two value property-indexed keyframes specification that needs to stringify its values roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframes specification with a CSS variable reference
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframes specification with a CSS variable reference roundtrips
-FAIL A KeyframeEffectReadOnly can be constructed with a property-indexed keyframes specification with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
-FAIL A KeyframeEffectReadOnly constructed with a property-indexed keyframes specification with a CSS variable reference in a shorthand property roundtrips assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" but got "composite,computedOffset,easing,offset"
-PASS A KeyframeEffectReadOnly can be constructed with a one property one value property-indexed keyframes specification
-PASS A KeyframeEffectReadOnly constructed with a one property one value property-indexed keyframes specification roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a one property one non-array value property-indexed keyframes specification
-PASS A KeyframeEffectReadOnly constructed with a one property one non-array value property-indexed keyframes specification roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a one property two value property-indexed keyframes specification where the first value is invalid
-PASS A KeyframeEffectReadOnly constructed with a one property two value property-indexed keyframes specification where the first value is invalid roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a one property two value property-indexed keyframes specification where the second value is invalid
-PASS A KeyframeEffectReadOnly constructed with a one property two value property-indexed keyframes specification where the second value is invalid roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with a single offset
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with a single offset roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of offsets
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of offsets roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of offsets that is too short
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of offsets that is too short roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of offsets that is too long
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of offsets that is too long roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an empty array of offsets
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an empty array of offsets roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of offsets with an embedded null value
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of offsets with an embedded null value roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of offsets with a trailing null value
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of offsets with a trailing null value roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of offsets with leading and trailing null values
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of offsets with leading and trailing null values roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of offsets with adjacent null values
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of offsets with adjacent null values roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of offsets with all null values (and too many at that)
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of offsets with all null values (and too many at that) roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with a single null offset
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with a single null offset roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of offsets that is not strictly ascending in the unused part of the array
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of offsets that is not strictly ascending in the unused part of the array roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe without any specified easing
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe without any specified easing roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with a single easing
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with a single easing roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of easings
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of easings roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of easings that is too short
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of easings that is too short roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with a single-element array of easings
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with a single-element array of easings roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an empty array of easings
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an empty array of easings roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with an array of easings that is too long
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with an array of easings that is too long roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with a single composite operation
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with a single composite operation roundtrips
-FAIL A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with a composite array assert_equals: value for 'composite' on ComputedKeyframe #2 expected "accumulate" but got "replace"
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with a composite array roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with a composite array that is too short
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with a composite array that is too short roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with a composite array that is too long
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with a composite array that is too long roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframe with a single-element composite array
-PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframe with a single-element composite array roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a one property one keyframe sequence
-PASS A KeyframeEffectReadOnly constructed with a one property one keyframe sequence roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a one property two keyframe sequence
-PASS A KeyframeEffectReadOnly constructed with a one property two keyframe sequence roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a two property two keyframe sequence
-PASS A KeyframeEffectReadOnly constructed with a two property two keyframe sequence roundtrips
-FAIL A KeyframeEffectReadOnly can be constructed with a one shorthand property two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
-PASS A KeyframeEffectReadOnly constructed with a one shorthand property two keyframe sequence roundtrips
-FAIL A KeyframeEffectReadOnly can be constructed with a two property (a shorthand and one of its component longhands) two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
-PASS A KeyframeEffectReadOnly constructed with a two property (a shorthand and one of its component longhands) two keyframe sequence roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a two property keyframe sequence where one property is missing from the first keyframe
-PASS A KeyframeEffectReadOnly constructed with a two property keyframe sequence where one property is missing from the first keyframe roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a two property keyframe sequence where one property is missing from the last keyframe
-PASS A KeyframeEffectReadOnly constructed with a two property keyframe sequence where one property is missing from the last keyframe roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a one property two keyframe sequence that needs to stringify its values
-PASS A KeyframeEffectReadOnly constructed with a one property two keyframe sequence that needs to stringify its values roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a keyframe sequence with a CSS variable reference
-PASS A KeyframeEffectReadOnly constructed with a keyframe sequence with a CSS variable reference roundtrips
-FAIL A KeyframeEffectReadOnly can be constructed with a keyframe sequence with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
-FAIL A KeyframeEffectReadOnly constructed with a keyframe sequence with a CSS variable reference in a shorthand property roundtrips assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" but got "composite,computedOffset,easing,offset"
-PASS A KeyframeEffectReadOnly can be constructed with a keyframe sequence with duplicate values for a given interior offset
-PASS A KeyframeEffectReadOnly constructed with a keyframe sequence with duplicate values for a given interior offset roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a keyframe sequence with duplicate values for offsets 0 and 1
-PASS A KeyframeEffectReadOnly constructed with a keyframe sequence with duplicate values for offsets 0 and 1 roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a two property four keyframe sequence
-PASS A KeyframeEffectReadOnly constructed with a two property four keyframe sequence roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a single keyframe sequence with omitted offset
-PASS A KeyframeEffectReadOnly constructed with a single keyframe sequence with omitted offset roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a single keyframe sequence with null offset
-PASS A KeyframeEffectReadOnly constructed with a single keyframe sequence with null offset roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a single keyframe sequence with string offset
-PASS A KeyframeEffectReadOnly constructed with a single keyframe sequence with string offset roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a one property keyframe sequence with some omitted offsets
-PASS A KeyframeEffectReadOnly constructed with a one property keyframe sequence with some omitted offsets roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a one property keyframe sequence with some null offsets
-PASS A KeyframeEffectReadOnly constructed with a one property keyframe sequence with some null offsets roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a two property keyframe sequence with some omitted offsets
-PASS A KeyframeEffectReadOnly constructed with a two property keyframe sequence with some omitted offsets roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a one property keyframe sequence with all omitted offsets
-PASS A KeyframeEffectReadOnly constructed with a one property keyframe sequence with all omitted offsets roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a keyframe sequence with different easing values, but the same easing value for a given offset
-PASS A KeyframeEffectReadOnly constructed with a keyframe sequence with different easing values, but the same easing value for a given offset roundtrips
-PASS A KeyframeEffectReadOnly can be constructed with a keyframe sequence with different composite values, but the same composite value for a given offset
-PASS A KeyframeEffectReadOnly constructed with a keyframe sequence with different composite values, but the same composite value for a given offset roundtrips
-PASS KeyframeEffectReadOnly constructor throws with keyframes with an out-of-bounded positive offset
-PASS KeyframeEffectReadOnly constructor throws with keyframes with an out-of-bounded negative offset
-PASS KeyframeEffectReadOnly constructor throws with property-indexed keyframes not loosely sorted by offset
-PASS KeyframeEffectReadOnly constructor throws with property-indexed keyframes not loosely sorted by offset even though not all offsets are specified
-PASS KeyframeEffectReadOnly constructor throws with property-indexed keyframes with offsets out of range
-PASS KeyframeEffectReadOnly constructor throws with keyframes not loosely sorted by offset
-PASS KeyframeEffectReadOnly constructor throws with property-indexed keyframes with an invalid easing value
-PASS KeyframeEffectReadOnly constructor throws with property-indexed keyframes with an invalid easing value as one of the array values
-PASS KeyframeEffectReadOnly constructor throws with property-indexed keyframe with an invalid easing in the unused part of the array of easings
-PASS KeyframeEffectReadOnly constructor throws with empty property-indexed keyframe with an invalid easing
-PASS KeyframeEffectReadOnly constructor throws with empty property-indexed keyframe with an invalid easings array
-PASS KeyframeEffectReadOnly constructor throws with a keyframe sequence with an invalid easing value
-PASS KeyframeEffectReadOnly constructor throws with property-indexed keyframes with an invalid composite value
-PASS KeyframeEffectReadOnly constructor throws with property-indexed keyframes with an invalid composite value as one of the array values
-PASS KeyframeEffectReadOnly constructor throws with keyframes with an invalid composite value
-FAIL A KeyframeEffectReadOnly constructed without any KeyframeEffectOptions object assert_equals: default iterationComposite expected (string) "replace" but got (undefined) undefined
-PASS A KeyframeEffectReadOnly constructed by an empty KeyframeEffectOptions object
-PASS A KeyframeEffectReadOnly constructed by a normal KeyframeEffectOptions object
-PASS A KeyframeEffectReadOnly constructed by a double value
-PASS A KeyframeEffectReadOnly constructed by +Infinity
-PASS A KeyframeEffectReadOnly constructed by an Infinity duration
-PASS A KeyframeEffectReadOnly constructed by an auto duration
-PASS A KeyframeEffectReadOnly constructed by an Infinity iterations
-PASS A KeyframeEffectReadOnly constructed by an auto fill
-PASS A KeyframeEffectReadOnly constructed by a forwards fill
-PASS Invalid KeyframeEffectReadOnly option by -Infinity
-PASS Invalid KeyframeEffectReadOnly option by NaN
-PASS Invalid KeyframeEffectReadOnly option by a negative value
-PASS Invalid KeyframeEffectReadOnly option by a negative Infinity duration
-PASS Invalid KeyframeEffectReadOnly option by a NaN duration
-PASS Invalid KeyframeEffectReadOnly option by a negative duration
-PASS Invalid KeyframeEffectReadOnly option by a string duration
-PASS Invalid KeyframeEffectReadOnly option by a negative Infinity iterations
-PASS Invalid KeyframeEffectReadOnly option by a NaN iterations
-PASS Invalid KeyframeEffectReadOnly option by a negative iterations
-PASS Invalid KeyframeEffectReadOnly option by a blank easing
-PASS Invalid KeyframeEffectReadOnly option by an unrecognized easing
-PASS Invalid KeyframeEffectReadOnly option by an 'initial' easing
-PASS Invalid KeyframeEffectReadOnly option by an 'inherit' easing
-PASS Invalid KeyframeEffectReadOnly option by a variable easing
-PASS Invalid KeyframeEffectReadOnly option by a multi-value easing
-PASS A KeyframeEffectReadOnly constructed with null target
+PASS A KeyframeEffect can be constructed with a one property two value property-indexed keyframes specification
+PASS A KeyframeEffect constructed with a one property two value property-indexed keyframes specification roundtrips
+FAIL A KeyframeEffect can be constructed with a one shorthand property two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+PASS A KeyframeEffect constructed with a one shorthand property two value property-indexed keyframes specification roundtrips
+FAIL A KeyframeEffect can be constructed with a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+PASS A KeyframeEffect constructed with a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification roundtrips
+PASS A KeyframeEffect can be constructed with a two property two value property-indexed keyframes specification
+PASS A KeyframeEffect constructed with a two property two value property-indexed keyframes specification roundtrips
+PASS A KeyframeEffect can be constructed with a two property property-indexed keyframes specification with different numbers of values
+PASS A KeyframeEffect constructed with a two property property-indexed keyframes specification with different numbers of values roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframes specification with an invalid value
+PASS A KeyframeEffect constructed with a property-indexed keyframes specification with an invalid value roundtrips
+PASS A KeyframeEffect can be constructed with a one property two value property-indexed keyframes specification that needs to stringify its values
+PASS A KeyframeEffect constructed with a one property two value property-indexed keyframes specification that needs to stringify its values roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframes specification with a CSS variable reference
+PASS A KeyframeEffect constructed with a property-indexed keyframes specification with a CSS variable reference roundtrips
+FAIL A KeyframeEffect can be constructed with a property-indexed keyframes specification with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+FAIL A KeyframeEffect constructed with a property-indexed keyframes specification with a CSS variable reference in a shorthand property roundtrips assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" but got "composite,computedOffset,easing,offset"
+PASS A KeyframeEffect can be constructed with a one property one value property-indexed keyframes specification
+PASS A KeyframeEffect constructed with a one property one value property-indexed keyframes specification roundtrips
+PASS A KeyframeEffect can be constructed with a one property one non-array value property-indexed keyframes specification
+PASS A KeyframeEffect constructed with a one property one non-array value property-indexed keyframes specification roundtrips
+PASS A KeyframeEffect can be constructed with a one property two value property-indexed keyframes specification where the first value is invalid
+PASS A KeyframeEffect constructed with a one property two value property-indexed keyframes specification where the first value is invalid roundtrips
+PASS A KeyframeEffect can be constructed with a one property two value property-indexed keyframes specification where the second value is invalid
+PASS A KeyframeEffect constructed with a one property two value property-indexed keyframes specification where the second value is invalid roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with a single offset
+PASS A KeyframeEffect constructed with a property-indexed keyframe with a single offset roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of offsets
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of offsets roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of offsets that is too short
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of offsets that is too short roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of offsets that is too long
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of offsets that is too long roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an empty array of offsets
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an empty array of offsets roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of offsets with an embedded null value
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of offsets with an embedded null value roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of offsets with a trailing null value
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of offsets with a trailing null value roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of offsets with leading and trailing null values
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of offsets with leading and trailing null values roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of offsets with adjacent null values
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of offsets with adjacent null values roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of offsets with all null values (and too many at that)
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of offsets with all null values (and too many at that) roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with a single null offset
+PASS A KeyframeEffect constructed with a property-indexed keyframe with a single null offset roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of offsets that is not strictly ascending in the unused part of the array
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of offsets that is not strictly ascending in the unused part of the array roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe without any specified easing
+PASS A KeyframeEffect constructed with a property-indexed keyframe without any specified easing roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with a single easing
+PASS A KeyframeEffect constructed with a property-indexed keyframe with a single easing roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of easings
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of easings roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of easings that is too short
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of easings that is too short roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with a single-element array of easings
+PASS A KeyframeEffect constructed with a property-indexed keyframe with a single-element array of easings roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an empty array of easings
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an empty array of easings roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with an array of easings that is too long
+PASS A KeyframeEffect constructed with a property-indexed keyframe with an array of easings that is too long roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with a single composite operation
+PASS A KeyframeEffect constructed with a property-indexed keyframe with a single composite operation roundtrips
+FAIL A KeyframeEffect can be constructed with a property-indexed keyframe with a composite array assert_equals: value for 'composite' on ComputedKeyframe #2 expected "accumulate" but got "replace"
+PASS A KeyframeEffect constructed with a property-indexed keyframe with a composite array roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with a composite array that is too short
+PASS A KeyframeEffect constructed with a property-indexed keyframe with a composite array that is too short roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with a composite array that is too long
+PASS A KeyframeEffect constructed with a property-indexed keyframe with a composite array that is too long roundtrips
+PASS A KeyframeEffect can be constructed with a property-indexed keyframe with a single-element composite array
+PASS A KeyframeEffect constructed with a property-indexed keyframe with a single-element composite array roundtrips
+PASS A KeyframeEffect can be constructed with a one property one keyframe sequence
+PASS A KeyframeEffect constructed with a one property one keyframe sequence roundtrips
+PASS A KeyframeEffect can be constructed with a one property two keyframe sequence
+PASS A KeyframeEffect constructed with a one property two keyframe sequence roundtrips
+PASS A KeyframeEffect can be constructed with a two property two keyframe sequence
+PASS A KeyframeEffect constructed with a two property two keyframe sequence roundtrips
+FAIL A KeyframeEffect can be constructed with a one shorthand property two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+PASS A KeyframeEffect constructed with a one shorthand property two keyframe sequence roundtrips
+FAIL A KeyframeEffect can be constructed with a two property (a shorthand and one of its component longhands) two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+PASS A KeyframeEffect constructed with a two property (a shorthand and one of its component longhands) two keyframe sequence roundtrips
+PASS A KeyframeEffect can be constructed with a two property keyframe sequence where one property is missing from the first keyframe
+PASS A KeyframeEffect constructed with a two property keyframe sequence where one property is missing from the first keyframe roundtrips
+PASS A KeyframeEffect can be constructed with a two property keyframe sequence where one property is missing from the last keyframe
+PASS A KeyframeEffect constructed with a two property keyframe sequence where one property is missing from the last keyframe roundtrips
+PASS A KeyframeEffect can be constructed with a one property two keyframe sequence that needs to stringify its values
+PASS A KeyframeEffect constructed with a one property two keyframe sequence that needs to stringify its values roundtrips
+PASS A KeyframeEffect can be constructed with a keyframe sequence with a CSS variable reference
+PASS A KeyframeEffect constructed with a keyframe sequence with a CSS variable reference roundtrips
+FAIL A KeyframeEffect can be constructed with a keyframe sequence with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+FAIL A KeyframeEffect constructed with a keyframe sequence with a CSS variable reference in a shorthand property roundtrips assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" but got "composite,computedOffset,easing,offset"
+PASS A KeyframeEffect can be constructed with a keyframe sequence with duplicate values for a given interior offset
+PASS A KeyframeEffect constructed with a keyframe sequence with duplicate values for a given interior offset roundtrips
+PASS A KeyframeEffect can be constructed with a keyframe sequence with duplicate values for offsets 0 and 1
+PASS A KeyframeEffect constructed with a keyframe sequence with duplicate values for offsets 0 and 1 roundtrips
+PASS A KeyframeEffect can be constructed with a two property four keyframe sequence
+PASS A KeyframeEffect constructed with a two property four keyframe sequence roundtrips
+PASS A KeyframeEffect can be constructed with a single keyframe sequence with omitted offset
+PASS A KeyframeEffect constructed with a single keyframe sequence with omitted offset roundtrips
+PASS A KeyframeEffect can be constructed with a single keyframe sequence with null offset
+PASS A KeyframeEffect constructed with a single keyframe sequence with null offset roundtrips
+PASS A KeyframeEffect can be constructed with a single keyframe sequence with string offset
+PASS A KeyframeEffect constructed with a single keyframe sequence with string offset roundtrips
+PASS A KeyframeEffect can be constructed with a one property keyframe sequence with some omitted offsets
+PASS A KeyframeEffect constructed with a one property keyframe sequence with some omitted offsets roundtrips
+PASS A KeyframeEffect can be constructed with a one property keyframe sequence with some null offsets
+PASS A KeyframeEffect constructed with a one property keyframe sequence with some null offsets roundtrips
+PASS A KeyframeEffect can be constructed with a two property keyframe sequence with some omitted offsets
+PASS A KeyframeEffect constructed with a two property keyframe sequence with some omitted offsets roundtrips
+PASS A KeyframeEffect can be constructed with a one property keyframe sequence with all omitted offsets
+PASS A KeyframeEffect constructed with a one property keyframe sequence with all omitted offsets roundtrips
+PASS A KeyframeEffect can be constructed with a keyframe sequence with different easing values, but the same easing value for a given offset
+PASS A KeyframeEffect constructed with a keyframe sequence with different easing values, but the same easing value for a given offset roundtrips
+PASS A KeyframeEffect can be constructed with a keyframe sequence with different composite values, but the same composite value for a given offset
+PASS A KeyframeEffect constructed with a keyframe sequence with different composite values, but the same composite value for a given offset roundtrips
+PASS KeyframeEffect constructor throws with keyframes with an out-of-bounded positive offset
+PASS KeyframeEffect constructor throws with keyframes with an out-of-bounded negative offset
+PASS KeyframeEffect constructor throws with property-indexed keyframes not loosely sorted by offset
+PASS KeyframeEffect constructor throws with property-indexed keyframes not loosely sorted by offset even though not all offsets are specified
+PASS KeyframeEffect constructor throws with property-indexed keyframes with offsets out of range
+PASS KeyframeEffect constructor throws with keyframes not loosely sorted by offset
+PASS KeyframeEffect constructor throws with property-indexed keyframes with an invalid easing value
+PASS KeyframeEffect constructor throws with property-indexed keyframes with an invalid easing value as one of the array values
+PASS KeyframeEffect constructor throws with property-indexed keyframe with an invalid easing in the unused part of the array of easings
+PASS KeyframeEffect constructor throws with empty property-indexed keyframe with an invalid easing
+PASS KeyframeEffect constructor throws with empty property-indexed keyframe with an invalid easings array
+PASS KeyframeEffect constructor throws with a keyframe sequence with an invalid easing value
+PASS KeyframeEffect constructor throws with property-indexed keyframes with an invalid composite value
+PASS KeyframeEffect constructor throws with property-indexed keyframes with an invalid composite value as one of the array values
+PASS KeyframeEffect constructor throws with keyframes with an invalid composite value
+FAIL A KeyframeEffect constructed without any KeyframeEffectOptions object effect.getTiming is not a function
+FAIL A KeyframeEffect constructed by an empty KeyframeEffectOptions object effect.getTiming is not a function
+FAIL A KeyframeEffect constructed by a normal KeyframeEffectOptions object effect.getTiming is not a function
+FAIL A KeyframeEffect constructed by a double value effect.getTiming is not a function
+FAIL A KeyframeEffect constructed by +Infinity effect.getTiming is not a function
+FAIL A KeyframeEffect constructed by an Infinity duration effect.getTiming is not a function
+FAIL A KeyframeEffect constructed by an auto duration effect.getTiming is not a function
+FAIL A KeyframeEffect constructed by an Infinity iterations effect.getTiming is not a function
+FAIL A KeyframeEffect constructed by an auto fill effect.getTiming is not a function
+FAIL A KeyframeEffect constructed by a forwards fill effect.getTiming is not a function
+PASS Invalid KeyframeEffect option by -Infinity
+PASS Invalid KeyframeEffect option by NaN
+PASS Invalid KeyframeEffect option by a negative value
+PASS Invalid KeyframeEffect option by a negative Infinity duration
+PASS Invalid KeyframeEffect option by a NaN duration
+PASS Invalid KeyframeEffect option by a negative duration
+PASS Invalid KeyframeEffect option by a string duration
+PASS Invalid KeyframeEffect option by a negative Infinity iterations
+PASS Invalid KeyframeEffect option by a NaN iterations
+PASS Invalid KeyframeEffect option by a negative iterations
+PASS Invalid KeyframeEffect option by a blank easing
+PASS Invalid KeyframeEffect option by an unrecognized easing
+PASS Invalid KeyframeEffect option by an 'initial' easing
+PASS Invalid KeyframeEffect option by an 'inherit' easing
+PASS Invalid KeyframeEffect option by a variable easing
+PASS Invalid KeyframeEffect option by a multi-value easing
+PASS A KeyframeEffect constructed with null target
 FAIL KeyframeEffect constructor propagates exceptions generated by accessing the options object assert_throws: function "() => {
     new KeyframeEffect(target, { get left() { throw test_error }})
   }" did not throw
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor.html
index dfdebde2..250a8c7a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/constructor.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <meta charset=utf-8>
-<title>KeyframeEffect and KeyframeEffectReadOnly constructor</title>
+<title>KeyframeEffect constructor</title>
 <link rel="help"
       href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-keyframeeffect">
 <link rel="help"
@@ -21,49 +21,48 @@
 
 test(t => {
   for (const frames of gEmptyKeyframeListTests) {
-    assert_equals(new KeyframeEffectReadOnly(target, frames)
-                        .getKeyframes().length,
+    assert_equals(new KeyframeEffect(target, frames).getKeyframes().length,
                   0, `number of frames for ${JSON.stringify(frames)}`);
   }
-}, 'A KeyframeEffectReadOnly can be constructed with no frames');
+}, 'A KeyframeEffect can be constructed with no frames');
 
 test(t => {
   for (const subtest of gEasingParsingTests) {
     const easing = subtest[0];
     const expected = subtest[1];
-    const effect = new KeyframeEffectReadOnly(target, {
+    const effect = new KeyframeEffect(target, {
       left: ['10px', '20px']
     }, { easing: easing });
-    assert_equals(effect.timing.easing, expected,
+    assert_equals(effect.getTiming().easing, expected,
                   `resulting easing for '${easing}'`);
   }
 }, 'easing values are parsed correctly when passed to the ' +
-   'KeyframeEffectReadOnly constructor in KeyframeEffectOptions');
+   'KeyframeEffect constructor in KeyframeEffectOptions');
 
 test(t => {
   for (const invalidEasing of gInvalidEasings) {
     assert_throws(new TypeError, () => {
-      new KeyframeEffectReadOnly(target, null, { easing: invalidEasing });
+      new KeyframeEffect(target, null, { easing: invalidEasing });
     }, `TypeError is thrown for easing '${invalidEasing}'`);
   }
 }, 'Invalid easing values are correctly rejected when passed to the ' +
-   'KeyframeEffectReadOnly constructor in KeyframeEffectOptions');
+   'KeyframeEffect constructor in KeyframeEffectOptions');
 
 test(t => {
   const getKeyframe =
     composite => ({ left: [ '10px', '20px' ], composite: composite });
   for (const composite of gGoodKeyframeCompositeValueTests) {
-    const effect = new KeyframeEffectReadOnly(target, getKeyframe(composite));
+    const effect = new KeyframeEffect(target, getKeyframe(composite));
     assert_equals(effect.getKeyframes()[0].composite, composite,
                   `resulting composite for '${composite}'`);
   }
   for (const composite of gBadKeyframeCompositeValueTests) {
     assert_throws(new TypeError, () => {
-      new KeyframeEffectReadOnly(target, getKeyframe(composite));
+      new KeyframeEffect(target, getKeyframe(composite));
     });
   }
 }, 'composite values are parsed correctly when passed to the ' +
-   'KeyframeEffectReadOnly constructor in property-indexed keyframes');
+   'KeyframeEffect constructor in property-indexed keyframes');
 
 test(t => {
   const getKeyframes = composite =>
@@ -72,29 +71,29 @@
       { offset: 1, left: '20px' }
     ];
   for (const composite of gGoodKeyframeCompositeValueTests) {
-    const effect = new KeyframeEffectReadOnly(target, getKeyframes(composite));
+    const effect = new KeyframeEffect(target, getKeyframes(composite));
     assert_equals(effect.getKeyframes()[0].composite, composite,
                   `resulting composite for '${composite}'`);
   }
   for (const composite of gBadKeyframeCompositeValueTests) {
     assert_throws(new TypeError, () => {
-      new KeyframeEffectReadOnly(target, getKeyframes(composite));
+      new KeyframeEffect(target, getKeyframes(composite));
     });
   }
 }, 'composite values are parsed correctly when passed to the ' +
-   'KeyframeEffectReadOnly constructor in regular keyframes');
+   'KeyframeEffect constructor in regular keyframes');
 
 test(t => {
   for (const composite of gGoodOptionsCompositeValueTests) {
-    const effect = new KeyframeEffectReadOnly(target, {
+    const effect = new KeyframeEffect(target, {
       left: ['10px', '20px']
-    }, { composite: composite });
+    }, { composite });
     assert_equals(effect.getKeyframes()[0].composite, null,
                   `resulting composite for '${composite}'`);
   }
   for (const composite of gBadOptionsCompositeValueTests) {
     assert_throws(new TypeError, () => {
-      new KeyframeEffectReadOnly(target, {
+      new KeyframeEffect(target, {
         left: ['10px', '20px']
       }, { composite: composite });
     });
@@ -104,32 +103,30 @@
 
 for (const subtest of gKeyframesTests) {
   test(t => {
-    const effect = new KeyframeEffectReadOnly(target, subtest.input);
+    const effect = new KeyframeEffect(target, subtest.input);
     assert_frame_lists_equal(effect.getKeyframes(), subtest.output);
-  }, `A KeyframeEffectReadOnly can be constructed with ${subtest.desc}`);
+  }, `A KeyframeEffect can be constructed with ${subtest.desc}`);
 
   test(t => {
-    const effect = new KeyframeEffectReadOnly(target, subtest.input);
-    const secondEffect =
-      new KeyframeEffectReadOnly(target, effect.getKeyframes());
+    const effect = new KeyframeEffect(target, subtest.input);
+    const secondEffect = new KeyframeEffect(target, effect.getKeyframes());
     assert_frame_lists_equal(secondEffect.getKeyframes(),
                              effect.getKeyframes());
-  }, `A KeyframeEffectReadOnly constructed with ${subtest.desc} roundtrips`);
+  }, `A KeyframeEffect constructed with ${subtest.desc} roundtrips`);
 }
 
 for (const subtest of gInvalidKeyframesTests) {
   test(t => {
     assert_throws(new TypeError, () => {
-      new KeyframeEffectReadOnly(target, subtest.input);
+      new KeyframeEffect(target, subtest.input);
     });
-  }, `KeyframeEffectReadOnly constructor throws with ${subtest.desc}`);
+  }, `KeyframeEffect constructor throws with ${subtest.desc}`);
 }
 
 test(t => {
-  const effect = new KeyframeEffectReadOnly(target,
-                                            { left: ['10px', '20px'] });
+  const effect = new KeyframeEffect(target, { left: ['10px', '20px'] });
 
-  const timing = effect.timing;
+  const timing = effect.getTiming();
   assert_equals(timing.delay, 0, 'default delay');
   assert_equals(timing.endDelay, 0, 'default endDelay');
   assert_equals(timing.fill, 'auto', 'default fill');
@@ -142,14 +139,12 @@
   assert_equals(effect.composite, 'replace', 'default composite');
   assert_equals(effect.iterationComposite, 'replace',
                 'default iterationComposite');
-}, 'A KeyframeEffectReadOnly constructed without any ' +
-   'KeyframeEffectOptions object');
+}, 'A KeyframeEffect constructed without any KeyframeEffectOptions object');
 
 for (const subtest of gKeyframeEffectOptionTests) {
   test(t => {
-    const effect = new KeyframeEffectReadOnly(target,
-                                              { left: ['10px', '20px'] },
-                                              subtest.input);
+    const effect = new KeyframeEffect(target, { left: ['10px', '20px'] },
+                                      subtest.input);
 
     // Helper function to provide default expected values when the test does
     // not supply them.
@@ -157,7 +152,7 @@
       return field in subtest.expected ? subtest.expected[field] : defaultValue;
     };
 
-    const timing = effect.timing;
+    const timing = effect.getTiming();
     assert_equals(timing.delay, expected('delay', 0),
                   'timing delay');
     assert_equals(timing.fill, expected('fill', 'auto'),
@@ -169,27 +164,24 @@
     assert_equals(timing.direction, expected('direction', 'normal'),
                   'timing direction');
 
-  }, `A KeyframeEffectReadOnly constructed by ${subtest.desc}`);
+  }, `A KeyframeEffect constructed by ${subtest.desc}`);
 }
 
 for (const subtest of gInvalidKeyframeEffectOptionTests) {
   test(t => {
     assert_throws(new TypeError, () => {
-      new KeyframeEffectReadOnly(target,
-                                 { left: ['10px', '20px'] },
-                                 subtest.input);
+      new KeyframeEffect(target, { left: ['10px', '20px'] }, subtest.input);
     });
-  }, `Invalid KeyframeEffectReadOnly option by ${subtest.desc}`);
+  }, `Invalid KeyframeEffect option by ${subtest.desc}`);
 }
 
 test(t => {
-  const effect = new KeyframeEffectReadOnly(null,
-                                            { left: ['10px', '20px'] },
-                                            { duration: 100 * MS_PER_SEC,
-                                              fill: 'forwards' });
+  const effect = new KeyframeEffect(null, { left: ['10px', '20px'] },
+                                    { duration: 100 * MS_PER_SEC,
+                                      fill: 'forwards' });
   assert_equals(effect.target, null,
                 'Effect created with null target has correct target');
-}, 'A KeyframeEffectReadOnly constructed with null target');
+}, 'A KeyframeEffect constructed with null target');
 
 test(t => {
   const test_error = { name: 'test' };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor-expected.txt
new file mode 100644
index 0000000..7e53e256
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+PASS Copied KeyframeEffect has the same target
+PASS Copied KeyframeEffect has the same keyframes
+PASS Copied KeyframeEffect has the same KeyframeEffectOptions
+FAIL Copied KeyframeEffect has the same timing content effect.getTiming is not a function
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor.html
index c4e8a8e..e3bc0db0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/copy-constructor.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <meta charset=utf-8>
-<title>KeyframeEffect and KeyframeEffectReadOnly copy constructor</title>
+<title>KeyframeEffect copy constructor</title>
 <link rel="help"
       href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-keyframeeffect-source">
 <link rel="help"
@@ -14,21 +14,21 @@
 'use strict';
 
 test(t => {
-  const effect = new KeyframeEffectReadOnly(createDiv(t), null);
-  const copiedEffect = new KeyframeEffectReadOnly(effect);
+  const effect = new KeyframeEffect(createDiv(t), null);
+  const copiedEffect = new KeyframeEffect(effect);
   assert_equals(copiedEffect.target, effect.target, 'same target');
-}, 'Copied KeyframeEffectReadOnly has the same target');
+}, 'Copied KeyframeEffect has the same target');
 
 test(t => {
   const effect =
-    new KeyframeEffectReadOnly(null,
-                               [ { marginLeft: '0px' },
-                                 { marginLeft: '-20px', easing: 'ease-in',
-                                   offset: 0.1 },
-                                 { marginLeft: '100px', easing: 'ease-out' },
-                                 { marginLeft: '50px' } ]);
+    new KeyframeEffect(null,
+                       [ { marginLeft: '0px' },
+                         { marginLeft: '-20px', easing: 'ease-in',
+                           offset: 0.1 },
+                         { marginLeft: '100px', easing: 'ease-out' },
+                         { marginLeft: '50px' } ]);
 
-  const copiedEffect = new KeyframeEffectReadOnly(effect);
+  const copiedEffect = new KeyframeEffect(effect);
   const keyframesA = effect.getKeyframes();
   const keyframesB = copiedEffect.getKeyframes();
   assert_equals(keyframesA.length, keyframesB.length, 'same keyframes length');
@@ -50,34 +50,33 @@
     assert_equals(keyframesA[i].marginLeft, keyframesB[i].marginLeft,
                   `Keyframe ${i} has the same property value pair`);
   }
-}, 'Copied KeyframeEffectReadOnly has the same keyframes');
+}, 'Copied KeyframeEffect has the same keyframes');
 
 test(t => {
   const effect =
-    new KeyframeEffectReadOnly(null, null,
-                               { iterationComposite: 'accumulate' });
+    new KeyframeEffect(null, null, { iterationComposite: 'accumulate' });
 
-  const copiedEffect = new KeyframeEffectReadOnly(effect);
+  const copiedEffect = new KeyframeEffect(effect);
   assert_equals(copiedEffect.iterationComposite, effect.iterationComposite,
                 'same iterationCompositeOperation');
   assert_equals(copiedEffect.composite, effect.composite,
                 'same compositeOperation');
-}, 'Copied KeyframeEffectReadOnly has the same KeyframeEffectOptions');
+}, 'Copied KeyframeEffect has the same KeyframeEffectOptions');
 
 test(t => {
-  const effect = new KeyframeEffectReadOnly(null, null,
-                                            { duration: 100 * MS_PER_SEC,
-                                              delay: -1 * MS_PER_SEC,
-                                              endDelay: 2 * MS_PER_SEC,
-                                              fill: 'forwards',
-                                              iterationStart: 2,
-                                              iterations: 20,
-                                              easing: 'ease-out',
-                                              direction: 'alternate' } );
+  const effect = new KeyframeEffect(null, null,
+                                    { duration: 100 * MS_PER_SEC,
+                                      delay: -1 * MS_PER_SEC,
+                                      endDelay: 2 * MS_PER_SEC,
+                                      fill: 'forwards',
+                                      iterationStart: 2,
+                                      iterations: 20,
+                                      easing: 'ease-out',
+                                      direction: 'alternate' } );
 
-  const copiedEffect = new KeyframeEffectReadOnly(effect);
-  const timingA = effect.timing;
-  const timingB = copiedEffect.timing;
+  const copiedEffect = new KeyframeEffect(effect);
+  const timingA = effect.getTiming();
+  const timingB = copiedEffect.getTiming();
   assert_not_equals(timingA, timingB, 'different timing objects');
   assert_equals(timingA.delay, timingB.delay, 'same delay');
   assert_equals(timingA.endDelay, timingB.endDelay, 'same endDelay');
@@ -88,19 +87,7 @@
   assert_equals(timingA.duration, timingB.duration, 'same duration');
   assert_equals(timingA.direction, timingB.direction, 'same direction');
   assert_equals(timingA.easing, timingB.easing, 'same easing');
-}, 'Copied KeyframeEffectReadOnly has the same timing content');
-
-test(t => {
-  const effect = new KeyframeEffectReadOnly(createDiv(t), null);
-  assert_equals(effect.constructor.name, 'KeyframeEffectReadOnly');
-  assert_equals(effect.timing.constructor.name,
-                'AnimationEffectTimingReadOnly');
-
-  // Make a mutable copy
-  const copiedEffect = new KeyframeEffect(effect);
-  assert_equals(copiedEffect.constructor.name, 'KeyframeEffect');
-  assert_equals(copiedEffect.timing.constructor.name, 'AnimationEffectTiming');
-}, 'KeyframeEffect constructed from a KeyframeEffectReadOnly is mutable');
+}, 'Copied KeyframeEffect has the same timing content');
 
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness-expected.txt
index 5c87a92..9a9a09c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness-expected.txt
@@ -1,41 +1,8 @@
 This is a testharness.js-based test.
-Found 59 tests; 53 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS AnimationEffectReadOnly interface: existence and properties of interface object
-PASS AnimationEffectReadOnly interface object length
-PASS AnimationEffectReadOnly interface object name
-PASS AnimationEffectReadOnly interface: existence and properties of interface prototype object
-PASS AnimationEffectReadOnly interface: existence and properties of interface prototype object's "constructor" property
-PASS AnimationEffectReadOnly interface: existence and properties of interface prototype object's @@unscopables property
-PASS AnimationEffectReadOnly interface: attribute timing
-PASS Unscopable handled correctly for timing property on AnimationEffectReadOnly
-PASS AnimationEffectReadOnly interface: operation getComputedTiming()
-PASS Unscopable handled correctly for getComputedTiming() on AnimationEffectReadOnly
-PASS KeyframeEffectReadOnly interface: existence and properties of interface object
-PASS KeyframeEffectReadOnly interface object length
-PASS KeyframeEffectReadOnly interface object name
-PASS KeyframeEffectReadOnly interface: existence and properties of interface prototype object
-PASS KeyframeEffectReadOnly interface: existence and properties of interface prototype object's "constructor" property
-PASS KeyframeEffectReadOnly interface: existence and properties of interface prototype object's @@unscopables property
-PASS KeyframeEffectReadOnly interface: attribute target
-PASS Unscopable handled correctly for target property on KeyframeEffectReadOnly
-FAIL KeyframeEffectReadOnly interface: attribute iterationComposite assert_true: The prototype object must have a property "iterationComposite" expected true got false
-PASS Unscopable handled correctly for iterationComposite property on KeyframeEffectReadOnly
-PASS KeyframeEffectReadOnly interface: attribute composite
-PASS Unscopable handled correctly for composite property on KeyframeEffectReadOnly
-PASS KeyframeEffectReadOnly interface: operation getKeyframes()
-PASS Unscopable handled correctly for getKeyframes() on KeyframeEffectReadOnly
-PASS KeyframeEffectReadOnly must be primary interface of new KeyframeEffectReadOnly(null, null)
-PASS Stringification of new KeyframeEffectReadOnly(null, null)
-PASS KeyframeEffectReadOnly interface: new KeyframeEffectReadOnly(null, null) must inherit property "target" with the proper type
-FAIL KeyframeEffectReadOnly interface: new KeyframeEffectReadOnly(null, null) must inherit property "iterationComposite" with the proper type assert_inherits: property "iterationComposite" not found in prototype chain
-PASS KeyframeEffectReadOnly interface: new KeyframeEffectReadOnly(null, null) must inherit property "composite" with the proper type
-PASS KeyframeEffectReadOnly interface: new KeyframeEffectReadOnly(null, null) must inherit property "getKeyframes()" with the proper type
-PASS AnimationEffectReadOnly interface: new KeyframeEffectReadOnly(null, null) must inherit property "timing" with the proper type
-PASS AnimationEffectReadOnly interface: new KeyframeEffectReadOnly(null, null) must inherit property "getComputedTiming()" with the proper type
-PASS KeyframeEffect interface: existence and properties of interface object
+FAIL KeyframeEffect interface: existence and properties of interface object assert_own_property: should inherit from AnimationEffect, but self has no such property expected property "AnimationEffect" missing
 PASS KeyframeEffect interface object length
 PASS KeyframeEffect interface object name
-PASS KeyframeEffect interface: existence and properties of interface prototype object
+FAIL KeyframeEffect interface: existence and properties of interface prototype object assert_own_property: should inherit from AnimationEffect, but self has no such property expected property "AnimationEffect" missing
 PASS KeyframeEffect interface: existence and properties of interface prototype object's "constructor" property
 PASS KeyframeEffect interface: existence and properties of interface prototype object's @@unscopables property
 FAIL KeyframeEffect interface: attribute target assert_own_property: expected property "target" missing
@@ -44,6 +11,8 @@
 PASS Unscopable handled correctly for iterationComposite property on KeyframeEffect
 PASS KeyframeEffect interface: attribute composite
 PASS Unscopable handled correctly for composite property on KeyframeEffect
+FAIL KeyframeEffect interface: operation getKeyframes() assert_own_property: interface prototype object missing non-static operation expected property "getKeyframes" missing
+PASS Unscopable handled correctly for getKeyframes() on KeyframeEffect
 PASS KeyframeEffect interface: operation setKeyframes(object)
 PASS Unscopable handled correctly for setKeyframes(object) on KeyframeEffect
 PASS KeyframeEffect must be primary interface of new KeyframeEffect(null, null)
@@ -51,13 +20,8 @@
 PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "target" with the proper type
 FAIL KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "iterationComposite" with the proper type assert_inherits: property "iterationComposite" not found in prototype chain
 PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "composite" with the proper type
+PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "getKeyframes()" with the proper type
 PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "setKeyframes(object)" with the proper type
 PASS KeyframeEffect interface: calling setKeyframes(object) on new KeyframeEffect(null, null) with too few arguments must throw TypeError
-PASS KeyframeEffectReadOnly interface: new KeyframeEffect(null, null) must inherit property "target" with the proper type
-FAIL KeyframeEffectReadOnly interface: new KeyframeEffect(null, null) must inherit property "iterationComposite" with the proper type assert_inherits: property "iterationComposite" not found in prototype chain
-PASS KeyframeEffectReadOnly interface: new KeyframeEffect(null, null) must inherit property "composite" with the proper type
-PASS KeyframeEffectReadOnly interface: new KeyframeEffect(null, null) must inherit property "getKeyframes()" with the proper type
-PASS AnimationEffectReadOnly interface: new KeyframeEffect(null, null) must inherit property "timing" with the proper type
-PASS AnimationEffectReadOnly interface: new KeyframeEffect(null, null) must inherit property "getComputedTiming()" with the proper type
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness.html
index 5056a875..0340a19 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness.html
@@ -9,7 +9,7 @@
 <script src="/resources/WebIDLParser.js"></script>
 <script src="/resources/idlharness.js"></script>
 <div id="log"></div>
-<script type="text/plain" id="AnimationEffectTimingReadOnly-IDL">
+<script type="text/plain" id="AnimationEffect-IDL">
 enum FillMode { "none", "forwards", "backwards", "both", "auto" };
 enum PlaybackDirection {
   "normal",
@@ -18,7 +18,7 @@
   "alternate-reverse"
 };
 
-dictionary AnimationEffectTimingProperties {
+dictionary EffectTiming {
   double                             delay = 0.0;
   double                             endDelay = 0.0;
   FillMode                           fill = "auto";
@@ -29,38 +29,37 @@
   DOMString                          easing = "linear";
 };
 
-[Exposed=Window]
-interface AnimationEffectTimingReadOnly {
-  readonly attribute double                             delay;
-  readonly attribute double                             endDelay;
-  readonly attribute FillMode                           fill;
-  readonly attribute double                             iterationStart;
-  readonly attribute unrestricted double                iterations;
-  readonly attribute (unrestricted double or DOMString) duration;
-  readonly attribute PlaybackDirection                  direction;
-  readonly attribute DOMString                          easing;
+dictionary OptionalEffectTiming {
+  double                              delay;
+  double                              endDelay;
+  FillMode                            fill;
+  double                              iterationStart;
+  unrestricted double                 iterations;
+  (unrestricted double or DOMString)  duration;
+  PlaybackDirection                   direction;
+  DOMString                           easing;
 };
-</script>
-<script type="text/plain" id="AnimationEffectReadOnly-IDL">
-dictionary ComputedTimingProperties : AnimationEffectTimingProperties {
-  unrestricted double  endTime;
-  unrestricted double  activeDuration;
-  double?              localTime;
-  double?              progress;
-  unrestricted double? currentIteration;
+
+dictionary ComputedEffectTiming : EffectTiming {
+  unrestricted double   endTime = 0.0;
+  unrestricted double   activeDuration = 0.0;
+  double?               localTime = null;
+  double?               progress = null;
+  unrestricted double?  currentIteration = null;
 };
 
 [Exposed=Window]
-interface AnimationEffectReadOnly {
-  readonly attribute AnimationEffectTimingReadOnly timing;
-  ComputedTimingProperties getComputedTiming();
+interface AnimationEffect {
+  EffectTiming getTiming();
+  ComputedEffectTiming getComputedTiming();
+  void updateTiming(optional OptionalEffectTiming timing);
 };
 </script>
-<script type="text/plain" id="KeyframeEffectReadOnly-IDL">
+<script type="text/plain" id="KeyframeEffect-IDL">
 enum IterationCompositeOperation { "replace", "accumulate" };
 enum CompositeOperation { "replace", "add", "accumulate" };
 
-dictionary KeyframeEffectOptions : AnimationEffectTimingProperties {
+dictionary KeyframeEffectOptions : EffectTiming {
   IterationCompositeOperation iterationComposite = "replace";
   CompositeOperation          composite = "replace";
 };
@@ -69,24 +68,13 @@
  Constructor ((Element or CSSPseudoElement)? target,
               object? keyframes,
               optional (unrestricted double or KeyframeEffectOptions) options),
- Constructor (KeyframeEffectReadOnly source)]
-interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
-  readonly attribute (Element or CSSPseudoElement)? target;
-  readonly attribute IterationCompositeOperation    iterationComposite;
-  readonly attribute CompositeOperation             composite;
+ Constructor (KeyframeEffect source)]
+interface KeyframeEffect : AnimationEffect {
+  attribute (Element or CSSPseudoElement)? target;
+  attribute IterationCompositeOperation    iterationComposite;
+  attribute CompositeOperation             composite;
+
   sequence<object> getKeyframes ();
-};
-</script>
-<script type="text/plain" id="KeyframeEffect-IDL">
-[Exposed=Window,
- Constructor ((Element or CSSPseudoElement)? target,
-              object? keyframes,
-              optional (unrestricted double or KeyframeEffectOptions) options),
- Constructor (KeyframeEffectReadOnly source)]
-interface KeyframeEffect : KeyframeEffectReadOnly {
-  inherit attribute (Element or CSSPseudoElement)? target;
-  inherit attribute IterationCompositeOperation    iterationComposite;
-  inherit attribute CompositeOperation             composite;
   void setKeyframes (object? keyframes);
 };
 </script>
@@ -98,20 +86,13 @@
 idlArray.add_untested_idls('interface CSSPseudoElement {};');
 idlArray.add_untested_idls('interface Element {};');
 idlArray.add_untested_idls(
-  document.getElementById('AnimationEffectTimingReadOnly-IDL').textContent
-);
-idlArray.add_idls(
-  document.getElementById('AnimationEffectReadOnly-IDL').textContent
-);
-idlArray.add_idls(
-  document.getElementById('KeyframeEffectReadOnly-IDL').textContent
+  document.getElementById('AnimationEffect-IDL').textContent
 );
 idlArray.add_idls(
   document.getElementById('KeyframeEffect-IDL').textContent
 );
 idlArray.add_objects({
   KeyframeEffect: ['new KeyframeEffect(null, null)'],
-  KeyframeEffectReadOnly: ['new KeyframeEffectReadOnly(null, null)'],
 });
 
 idlArray.test();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite.html
index de2afa7..bbb8ee2a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/iterationComposite.html
@@ -19,7 +19,8 @@
   anim.pause();
 
   anim.currentTime =
-    anim.effect.timing.duration * 2 + anim.effect.timing.duration / 2;
+    anim.effect.getComputedTiming().duration * 2 +
+    anim.effect.getComputedTiming().duration / 2;
   assert_equals(getComputedStyle(div).marginLeft, '25px',
     'Animated style at 50s of the third iteration');
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html
index 523019d2..133fd57 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html
@@ -13,7 +13,7 @@
 'use strict';
 
 // This file only tests the KeyframeEffect constructor since it is
-// assumed that the implementation of the KeyframeEffectReadOnly constructor,
+// assumed that the implementation of the KeyframeEffect constructor,
 // Animatable.animate() method, and KeyframeEffect.setKeyframes() method will
 // all share common machinery and it is not necessary to test each method.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/timing-tests.js b/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/timing-tests.js
new file mode 100644
index 0000000..4b0f021
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/timing-tests.js
@@ -0,0 +1,46 @@
+'use strict';
+
+// =================================
+//
+// Common timing parameter test data
+//
+// =================================
+
+
+// ------------------------------
+//  Delay values
+// ------------------------------
+
+const gBadDelayValues = [
+  NaN, Infinity, -Infinity
+];
+
+// ------------------------------
+//  Duration values
+// ------------------------------
+
+const gGoodDurationValues = [
+  { specified: 123.45, computed: 123.45 },
+  { specified: 'auto', computed: 0 },
+  { specified: Infinity, computed: Infinity },
+];
+
+const gBadDurationValues = [
+  -1, NaN, -Infinity, 'abc', '100'
+];
+
+// ------------------------------
+//  iterationStart values
+// ------------------------------
+
+const gBadIterationStartValues = [
+  -1, NaN, Infinity, -Infinity
+];
+
+// ------------------------------
+//  iterations values
+// ------------------------------
+
+const gBadIterationsValues = [
+  -1, -Infinity, NaN
+];
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/timing-utils.js b/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/timing-utils.js
new file mode 100644
index 0000000..d7267f9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/resources/timing-utils.js
@@ -0,0 +1,39 @@
+'use strict';
+
+// =======================================
+//
+// Utility functions for testing timing
+//
+// =======================================
+
+
+// ------------------------------
+//  Helper functions
+// ------------------------------
+
+// Utility function to check that a subset of timing properties have their
+// default values.
+function assert_default_timing_except(effect, propertiesToSkip) {
+  const defaults = {
+    delay: 0,
+    endDelay: 0,
+    fill: 'auto',
+    iterationStart: 0,
+    iterations: 1,
+    duration: 'auto',
+    direction: 'normal',
+    easing: 'linear',
+  };
+
+  for (const prop of Object.keys(defaults)) {
+    if (propertiesToSkip.includes(prop)) {
+      continue;
+    }
+
+    assert_equals(
+      effect.getTiming()[prop],
+      defaults[prop],
+      `${prop} parameter has default value:`
+    );
+  }
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/testcommon.js b/third_party/WebKit/LayoutTests/external/wpt/web-animations/testcommon.js
index bb5acc2..46f2356 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/testcommon.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/testcommon.js
@@ -29,7 +29,11 @@
 // a time value based on its precision requirements with a fixed value.
 if (!window.assert_time_equals_literal) {
   window.assert_time_equals_literal = (actual, expected, description) => {
-    assert_approx_equals(actual, expected, TIME_PRECISION, description);
+    if (Math.abs(expected) === Infinity) {
+      assert_equals(actual, expected, description);
+    } else {
+      assert_approx_equals(actual, expected, TIME_PRECISION, description);
+    }
   }
 }
 
@@ -283,4 +287,4 @@
     assert_approx_equals(actualRotationVector[i], expectedRotationVector[i], 0.0001,
       `expected ${expected} but got ${actual}: ${description}`);
   }
-}
\ No newline at end of file
+}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states-expected.txt
index 09b8384f..a1b12c0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states-expected.txt
@@ -1,14 +1,14 @@
 This is a testharness.js-based test.
-PASS Phase calculation for a simple animation effect
-PASS Phase calculation for an animation effect with a positive start delay
-FAIL Phase calculation for an animation effect with a negative start delay assert_equals: Animation effect is in before phase when current time is -1ms (progress is null with 'none' fill mode) expected (object) null but got (number) 0
-PASS Phase calculation for an animation effect with a positive end delay
-PASS Phase calculation for an animation effect with a negative end delay lesser in magnitude than the active duration
-PASS Phase calculation for an animation effect with a negative end delay equal in magnitude to the active duration
-FAIL Phase calculation for an animation effect with a negative end delay greater in magnitude than the active duration assert_not_equals: Animation effect is in before phase when current time is -1ms (progress is non-null with appropriate fill mode) got disallowed value null
-PASS Phase calculation for an animation effect with a positive start delay and a negative end delay lesser in magnitude than the active duration
-FAIL Phase calculation for an animation effect with a negative start delay and a negative end delay equal in magnitude to the active duration assert_not_equals: Animation effect is in before phase when current time is -1ms (progress is non-null with appropriate fill mode) got disallowed value null
-FAIL Phase calculation for an animation effect with a negative start delay and a negative end delay equal greater in magnitude than the active duration assert_not_equals: Animation effect is in before phase when current time is -2ms (progress is non-null with appropriate fill mode) got disallowed value null
-FAIL Phase calculation for a simple animation effect with negative playback rate assert_not_equals: Animation effect is in active phase when current time is 1ms got disallowed value null
+FAIL Phase calculation for a simple animation effect animation.effect.updateTiming is not a function
+FAIL Phase calculation for an animation effect with a positive start delay animation.effect.updateTiming is not a function
+FAIL Phase calculation for an animation effect with a negative start delay animation.effect.updateTiming is not a function
+FAIL Phase calculation for an animation effect with a positive end delay animation.effect.updateTiming is not a function
+FAIL Phase calculation for an animation effect with a negative end delay lesser in magnitude than the active duration animation.effect.updateTiming is not a function
+FAIL Phase calculation for an animation effect with a negative end delay equal in magnitude to the active duration animation.effect.updateTiming is not a function
+FAIL Phase calculation for an animation effect with a negative end delay greater in magnitude than the active duration animation.effect.updateTiming is not a function
+FAIL Phase calculation for an animation effect with a positive start delay and a negative end delay lesser in magnitude than the active duration animation.effect.updateTiming is not a function
+FAIL Phase calculation for an animation effect with a negative start delay and a negative end delay equal in magnitude to the active duration animation.effect.updateTiming is not a function
+FAIL Phase calculation for an animation effect with a negative start delay and a negative end delay equal greater in magnitude than the active duration animation.effect.updateTiming is not a function
+FAIL Phase calculation for a simple animation effect with negative playback rate animation.effect.updateTiming is not a function
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html
index ac3732fe6..b62726c7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animation-effects/phases-and-states.html
@@ -22,7 +22,7 @@
   if (phase === 'active') {
     // If the fill mode is 'none', then progress will only be non-null if we
     // are in the active phase.
-    animation.effect.timing.fill = 'none';
+    animation.effect.updateTiming({ fill: 'none' });
     assert_not_equals(animation.effect.getComputedTiming().progress, null,
                       'Animation effect is in active phase when current time'
                       + ` is ${currentTime}ms`);
@@ -31,15 +31,15 @@
     // phase is to toggle the fill mode. For example, if the progress is null
     // will the fill node is 'none' but non-null when the fill mode is
     // 'backwards' then we are in the before phase.
-    animation.effect.timing.fill = 'none';
+    animation.effect.updateTiming({ fill: 'none' });
     assert_equals(animation.effect.getComputedTiming().progress, null,
                   `Animation effect is in ${phase} phase when current time`
                   + ` is ${currentTime}ms`
                   + ' (progress is null with \'none\' fill mode)');
 
-    animation.effect.timing.fill = phase === 'before'
-                                   ? 'backwards'
-                                   : 'forwards';
+    animation.effect.updateTiming({
+      fill: phase === 'before' ? 'backwards' : 'forwards',
+    });
     assert_not_equals(animation.effect.getComputedTiming().progress, null,
                       `Animation effect is in ${phase} phase when current time`
                       + ` is ${currentTime}ms`
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/finishing-an-animation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/finishing-an-animation.html
index b479db9b9..833f074d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/finishing-an-animation.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/finishing-an-animation.html
@@ -196,7 +196,7 @@
 }, 'Finishing an animation resolves the finished promise synchronously');
 
 promise_test(async t => {
-  const effect = new KeyframeEffectReadOnly(null, null, 100 * MS_PER_SEC);
+  const effect = new KeyframeEffect(null, null, 100 * MS_PER_SEC);
   const animation = new Animation(effect, document.timeline);
   let resolvedFinished = false;
   animation.finished.then(() => {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html
index 184804d6..daa73f5 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/setting-the-target-effect-of-an-animation.html
@@ -36,9 +36,9 @@
   anim.pause();
   assert_true(anim.pending);
 
-  anim.effect = new KeyframeEffectReadOnly(createDiv(t),
-                                           { marginLeft: [ '0px', '100px' ] },
-                                           100 * MS_PER_SEC);
+  anim.effect = new KeyframeEffect(createDiv(t),
+                                   { marginLeft: [ '0px', '100px' ] },
+                                   100 * MS_PER_SEC);
   assert_true(anim.pending);
   await anim.ready;
 
@@ -52,9 +52,9 @@
   anim.play();
   assert_true(anim.pending);
 
-  anim.effect = new KeyframeEffectReadOnly(createDiv(t),
-                                           { marginLeft: [ '0px', '100px' ] },
-                                           100 * MS_PER_SEC);
+  anim.effect = new KeyframeEffect(createDiv(t),
+                                   { marginLeft: [ '0px', '100px' ] },
+                                   100 * MS_PER_SEC);
   assert_true(anim.pending);
   await anim.ready;
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html
index 7059423..8e02fed1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html
@@ -141,7 +141,9 @@
                 'Hold time is initially set');
   // Then extend the duration so that the hold time is cleared and on
   // the next tick the current time will increase.
-  anim.effect.timing.duration *= 2;
+  anim.effect.updateTiming({
+    duration: anim.effect.getComputedTiming().duration * 2,
+  });
   await waitForNextFrame();
 
   assert_greater_than(anim.currentTime, 100 * MS_PER_SEC,
@@ -247,7 +249,7 @@
   anim.cancel();
   // Trigger a change that will cause the "update the finished state"
   // procedure to run.
-  anim.effect.timing.duration = 200 * MS_PER_SEC;
+  anim.effect.updateTiming({ duration: 200 * MS_PER_SEC });
   assert_equals(anim.currentTime, null,
                 'The animation hold time / start time should not be updated');
   // The "update the finished state" procedure is supposed to run after any
@@ -273,7 +275,7 @@
   // is greater than the target end. At this point the "update the finished
   // state" procedure should run and if we fail to check for a pending task
   // we will set the hold time to the target end, i.e. 50ms.
-  anim.effect.timing.duration = 50 * MS_PER_SEC;
+  anim.effect.updateTiming({ duration: 50 * MS_PER_SEC });
   assert_equals(anim.currentTime, 75 * MS_PER_SEC,
                 'Hold time should not be updated');
 }, 'Updating the finished state when there is a pending task');
@@ -289,7 +291,7 @@
   anim.currentTime = 150 * MS_PER_SEC;
   // Trigger a change that will cause the "update the finished state"
   // procedure to run (did seek = false).
-  anim.effect.timing.duration = 200 * MS_PER_SEC;
+  anim.effect.updateTiming({ duration: 200 * MS_PER_SEC });
   await waitForAnimationFrames(1);
 
   assert_equals(anim.currentTime, 150 * MS_PER_SEC,
@@ -348,7 +350,7 @@
 }, 'Finish notification steps run when the animation completes normally');
 
 promise_test(async t => {
-  const effect = new KeyframeEffectReadOnly(null, null, 1);
+  const effect = new KeyframeEffect(null, null, 1);
   const animation = new Animation(effect, document.timeline);
   animation.play();
   await animation.ready;
@@ -417,5 +419,38 @@
   };
 }, 'Animation finish event is fired again after replaying from start');
 
+async_test(t => {
+  const anim = createDiv(t).animate(null,
+                                    { duration: 100000, endDelay: 50000 });
+  anim.onfinish = t.step_func(event => {
+    assert_unreached('finish event should not be fired');
+  });
+
+  anim.ready.then(() => {
+    anim.currentTime = 100000;
+    return waitForAnimationFrames(2);
+  }).then(t.step_func(() => {
+    t.done();
+  }));
+}, 'finish event is not fired at the end of the active interval when the'
+   + ' endDelay has not expired');
+
+async_test(t => {
+  const anim = createDiv(t).animate(null,
+                                    { duration: 100000, endDelay: 30000 });
+  anim.ready.then(() => {
+    anim.currentTime = 110000; // during endDelay
+    anim.onfinish = t.step_func(event => {
+      assert_unreached('onfinish event should not be fired during endDelay');
+    });
+    return waitForAnimationFrames(2);
+  }).then(t.step_func(() => {
+    anim.onfinish = t.step_func(event => {
+      t.done();
+    });
+    anim.currentTime = 130000; // after endTime
+  }));
+}, 'finish event is fired after the endDelay has expired');
+
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLIFrameElement/sandbox-feature-detection.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLIFrameElement/sandbox-feature-detection.html
index 963bf480..2348cbb 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLIFrameElement/sandbox-feature-detection.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLIFrameElement/sandbox-feature-detection.html
@@ -24,5 +24,6 @@
         assert_true(iframe.sandbox.supports("allow-same-origin"));
         assert_true(iframe.sandbox.supports("allow-scripts"));
         assert_true(iframe.sandbox.supports("allow-top-navigation"));
+        assert_true(iframe.sandbox.supports("allow-top-navigation-by-user-activation"));
     }, "Make sure that sandbox based feature detection is working");
 </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame-expected.html b/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame-expected.html
new file mode 100644
index 0000000..31364c9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame-expected.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner)
+  testRunner.setPrinting();
+</script>
+<iframe srcdoc="<!DOCTYPE html>Subframe"></iframe>
diff --git a/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame-scrolled-expected.html b/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame-scrolled-expected.html
new file mode 100644
index 0000000..fab3ee27
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame-scrolled-expected.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<style>
+::-webkit-scrollbar { display: none }
+</style>
+<script>
+if (window.testRunner)
+  testRunner.setPrinting();
+</script>
+<iframe style="position: absolute; top: 200px; left: 200px"
+    srcdoc="<!DOCTYPE html>Subframe"></iframe>
+<div style="height: 3000px"></div>
diff --git a/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame-scrolled.html b/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame-scrolled.html
new file mode 100644
index 0000000..5719c4a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame-scrolled.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<style>
+::-webkit-scrollbar { display: none }
+</style>
+<script>
+if (window.testRunner)
+  testRunner.setPrinting();
+onload = function() {
+  window.scrollBy(0, 150);
+};
+</script>
+<iframe style="position: absolute; top: 200px; left: 200px"
+    src="http://localhost:8080/printing/resources/subframe.html"></iframe>
+<div style="height: 3000px"></div>
diff --git a/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame.html b/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame.html
new file mode 100644
index 0000000..f06ce59
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/printing/cross-site-frame.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner)
+  testRunner.setPrinting();
+</script>
+<iframe src="http://localhost:8080/printing/resources/subframe.html"></iframe>
diff --git a/third_party/WebKit/LayoutTests/http/tests/printing/resources/subframe.html b/third_party/WebKit/LayoutTests/http/tests/printing/resources/subframe.html
new file mode 100644
index 0000000..70303798
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/printing/resources/subframe.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+Subframe
diff --git a/third_party/WebKit/LayoutTests/media/controls/modern/add-poster-after-page-load.html b/third_party/WebKit/LayoutTests/media/controls/modern/add-poster-after-page-load.html
new file mode 100644
index 0000000..4e77795
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/modern/add-poster-after-page-load.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<title>Test that adding a poster after page load shows the poster.</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../media-controls.js"></script>
+<video controls width=400 preload=none src="../../content/60_sec_video.webm"></video>
+<script>
+async_test(t => {
+  const video = document.querySelector('video');
+
+  window.onload = t.step_func(() => {
+    assert_true(showsDefaultPoster());
+    video.setAttribute('poster', '../../content/greenbox.png');
+    setTimeout(t.step_func_done(() => {
+      assert_false(showsDefaultPoster());
+    }));
+  });
+
+  function showsDefaultPoster() {
+    return mediaControls(video).classList.contains('use-default-poster');
+  }
+});
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/media/controls/modern/scrubbing-touch.html b/third_party/WebKit/LayoutTests/media/controls/modern/scrubbing-touch.html
index 561c7cd69..1a896cca 100644
--- a/third_party/WebKit/LayoutTests/media/controls/modern/scrubbing-touch.html
+++ b/third_party/WebKit/LayoutTests/media/controls/modern/scrubbing-touch.html
@@ -9,7 +9,6 @@
 async_test(t => {
   const video = document.querySelector('video');
   const timeline = timelineElement(video);
-  const timeElement = timelineThumbCurrentTime(video);
   const thumb = timelineThumb(video);
 
   video.addEventListener('playing', t.step_func(() => {
@@ -30,9 +29,6 @@
 
     // Check the scrubbing UI is shown with the correct time.
     checkControlsClassName(video, 'phase-ready state-scrubbing');
-    assert_equals('', timeElement.style.display);
-    assert_equals('0:' + Math.round(video.currentTime),
-        timeElement.textContent);
 
     // Ensure that the timeline now has a value in the middle.
     assert_equals(30, Math.round(timeline.value));
@@ -40,9 +36,6 @@
     // Add an event listener for when we start playing again after seeking.
     video.addEventListener('playing', t.step_func_done(() => {
       checkControlsClassName(video, 'phase-ready state-playing');
-
-      // Check the scrubbing UI is no longer shown.
-      assert_equals('none', timeElement.style.display);
     }), { once: true });
 
     // Release the touch.
diff --git a/third_party/WebKit/LayoutTests/media/controls/modern/scrubbing.html b/third_party/WebKit/LayoutTests/media/controls/modern/scrubbing.html
index 045024c..4d5224ba 100644
--- a/third_party/WebKit/LayoutTests/media/controls/modern/scrubbing.html
+++ b/third_party/WebKit/LayoutTests/media/controls/modern/scrubbing.html
@@ -19,7 +19,6 @@
   document.body.appendChild(video);
 
   const timeline = timelineElement(video);
-  const timeElement = timelineThumbCurrentTime(video);
   const thumb = timelineThumb(video);
   const scrubbingMessage = scrubbingMessageElement(video);
 
@@ -35,9 +34,6 @@
       assert_true(seeked);
       checkControlsClassName(video, 'phase-ready state-playing');
 
-      // Check the scrubbing UI is no longer shown.
-      assert_equals('none', timeElement.style.display);
-
       // Check the scrubbing message is no longer shown.
       assert_false(isControlVisible(scrubbingMessage));
     }), { once: true });
@@ -60,11 +56,6 @@
   video.addEventListener('seeking', t.step_func(() => {
     checkControlsClassName(video, 'phase-ready state-scrubbing');
 
-    // Check the scrubbing UI is shown with the correct time.
-    assert_equals('', timeElement.style.display);
-    assert_equals('0:' + Math.round(video.currentTime),
-        timeElement.textContent);
-
     // Check the scrubbing message is shown.
     assert_true(isControlVisible(scrubbingMessage));
   }), { once: true });
diff --git a/third_party/WebKit/LayoutTests/media/media-controls.js b/third_party/WebKit/LayoutTests/media/media-controls.js
index d1c1c9e..2f6e3d19 100644
--- a/third_party/WebKit/LayoutTests/media/media-controls.js
+++ b/third_party/WebKit/LayoutTests/media/media-controls.js
@@ -222,15 +222,6 @@
     return thumb;
 }
 
-function timelineThumbCurrentTime(videoElement) {
-    const controlID = '-internal-media-controls-thumb-current-time';
-    const timeline = timelineElement(videoElement);
-    const thumb = mediaControlsElement(window.internals.shadowRoot(timeline).firstChild, controlID);
-    if (!thumb)
-        throw 'Failed to find timeline current time';
-    return thumb;
-}
-
 function scrubbingMessageElement(videoElement) {
     var controlID = '-internal-media-controls-scrubbing-message';
     var button = mediaControlsElement(window.internals.shadowRoot(videoElement).firstChild, controlID);
diff --git a/third_party/WebKit/LayoutTests/platform/fuchsia/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt b/third_party/WebKit/LayoutTests/platform/fuchsia/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt
new file mode 100644
index 0000000..537e299
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/fuchsia/external/wpt/web-animations/interfaces/Animatable/animate-expected.txt
@@ -0,0 +1,125 @@
+This is a testharness.js-based test.
+Found 121 tests; 111 PASS, 10 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Element.animate() creates an Animation object
+PASS Element.animate() creates an Animation object in the relevant realm of the target element
+PASS Element.animate() creates an Animation object with a KeyframeEffect
+PASS Element.animate() creates an Animation object with a KeyframeEffect that is created in the relevant realm of the target element
+PASS Element.animate() creates an Animation object with a KeyframeEffect whose AnimationEffectTiming object is created in the relevant realm of the target element
+PASS Element.animate() accepts empty keyframe lists (input: [])
+PASS Element.animate() accepts empty keyframe lists (input: null)
+PASS Element.animate() accepts empty keyframe lists (input: undefined)
+PASS Element.animate() accepts a one property two value property-indexed keyframes specification
+FAIL Element.animate() accepts a one shorthand property two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+FAIL Element.animate() accepts a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+PASS Element.animate() accepts a two property two value property-indexed keyframes specification
+PASS Element.animate() accepts a two property property-indexed keyframes specification with different numbers of values
+PASS Element.animate() accepts a property-indexed keyframes specification with an invalid value
+PASS Element.animate() accepts a one property two value property-indexed keyframes specification that needs to stringify its values
+PASS Element.animate() accepts a property-indexed keyframes specification with a CSS variable reference
+FAIL Element.animate() accepts a property-indexed keyframes specification with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+PASS Element.animate() accepts a one property one value property-indexed keyframes specification
+PASS Element.animate() accepts a one property one non-array value property-indexed keyframes specification
+PASS Element.animate() accepts a one property two value property-indexed keyframes specification where the first value is invalid
+PASS Element.animate() accepts a one property two value property-indexed keyframes specification where the second value is invalid
+PASS Element.animate() accepts a property-indexed keyframe with a single offset
+PASS Element.animate() accepts a property-indexed keyframe with an array of offsets
+PASS Element.animate() accepts a property-indexed keyframe with an array of offsets that is too short
+PASS Element.animate() accepts a property-indexed keyframe with an array of offsets that is too long
+PASS Element.animate() accepts a property-indexed keyframe with an empty array of offsets
+PASS Element.animate() accepts a property-indexed keyframe with an array of offsets with an embedded null value
+PASS Element.animate() accepts a property-indexed keyframe with an array of offsets with a trailing null value
+PASS Element.animate() accepts a property-indexed keyframe with an array of offsets with leading and trailing null values
+PASS Element.animate() accepts a property-indexed keyframe with an array of offsets with adjacent null values
+PASS Element.animate() accepts a property-indexed keyframe with an array of offsets with all null values (and too many at that)
+PASS Element.animate() accepts a property-indexed keyframe with a single null offset
+PASS Element.animate() accepts a property-indexed keyframe with an array of offsets that is not strictly ascending in the unused part of the array
+PASS Element.animate() accepts a property-indexed keyframe without any specified easing
+PASS Element.animate() accepts a property-indexed keyframe with a single easing
+PASS Element.animate() accepts a property-indexed keyframe with an array of easings
+PASS Element.animate() accepts a property-indexed keyframe with an array of easings that is too short
+PASS Element.animate() accepts a property-indexed keyframe with a single-element array of easings
+PASS Element.animate() accepts a property-indexed keyframe with an empty array of easings
+PASS Element.animate() accepts a property-indexed keyframe with an array of easings that is too long
+PASS Element.animate() accepts a property-indexed keyframe with a single composite operation
+FAIL Element.animate() accepts a property-indexed keyframe with a composite array assert_equals: value for 'composite' on ComputedKeyframe #2 expected "accumulate" but got "replace"
+PASS Element.animate() accepts a property-indexed keyframe with a composite array that is too short
+PASS Element.animate() accepts a property-indexed keyframe with a composite array that is too long
+PASS Element.animate() accepts a property-indexed keyframe with a single-element composite array
+PASS Element.animate() accepts a one property one keyframe sequence
+PASS Element.animate() accepts a one property two keyframe sequence
+PASS Element.animate() accepts a two property two keyframe sequence
+FAIL Element.animate() accepts a one shorthand property two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+FAIL Element.animate() accepts a two property (a shorthand and one of its component longhands) two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+PASS Element.animate() accepts a two property keyframe sequence where one property is missing from the first keyframe
+PASS Element.animate() accepts a two property keyframe sequence where one property is missing from the last keyframe
+PASS Element.animate() accepts a one property two keyframe sequence that needs to stringify its values
+PASS Element.animate() accepts a keyframe sequence with a CSS variable reference
+FAIL Element.animate() accepts a keyframe sequence with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset"
+PASS Element.animate() accepts a keyframe sequence with duplicate values for a given interior offset
+PASS Element.animate() accepts a keyframe sequence with duplicate values for offsets 0 and 1
+PASS Element.animate() accepts a two property four keyframe sequence
+PASS Element.animate() accepts a single keyframe sequence with omitted offset
+PASS Element.animate() accepts a single keyframe sequence with null offset
+PASS Element.animate() accepts a single keyframe sequence with string offset
+PASS Element.animate() accepts a one property keyframe sequence with some omitted offsets
+PASS Element.animate() accepts a one property keyframe sequence with some null offsets
+PASS Element.animate() accepts a two property keyframe sequence with some omitted offsets
+PASS Element.animate() accepts a one property keyframe sequence with all omitted offsets
+PASS Element.animate() accepts a keyframe sequence with different easing values, but the same easing value for a given offset
+PASS Element.animate() accepts a keyframe sequence with different composite values, but the same composite value for a given offset
+PASS Element.animate() does not accept keyframes with an out-of-bounded positive offset
+PASS Element.animate() does not accept keyframes with an out-of-bounded negative offset
+PASS Element.animate() does not accept property-indexed keyframes not loosely sorted by offset
+PASS Element.animate() does not accept property-indexed keyframes not loosely sorted by offset even though not all offsets are specified
+PASS Element.animate() does not accept property-indexed keyframes with offsets out of range
+PASS Element.animate() does not accept keyframes not loosely sorted by offset
+PASS Element.animate() does not accept property-indexed keyframes with an invalid easing value
+PASS Element.animate() does not accept property-indexed keyframes with an invalid easing value as one of the array values
+PASS Element.animate() does not accept property-indexed keyframe with an invalid easing in the unused part of the array of easings
+PASS Element.animate() does not accept empty property-indexed keyframe with an invalid easing
+PASS Element.animate() does not accept empty property-indexed keyframe with an invalid easings array
+PASS Element.animate() does not accept a keyframe sequence with an invalid easing value
+PASS Element.animate() does not accept property-indexed keyframes with an invalid composite value
+PASS Element.animate() does not accept property-indexed keyframes with an invalid composite value as one of the array values
+PASS Element.animate() does not accept keyframes with an invalid composite value
+PASS Element.animate() does not accept invalid easing: ''
+PASS Element.animate() does not accept invalid easing: '7'
+PASS Element.animate() does not accept invalid easing: 'test'
+PASS Element.animate() does not accept invalid easing: 'initial'
+PASS Element.animate() does not accept invalid easing: 'inherit'
+PASS Element.animate() does not accept invalid easing: 'unset'
+PASS Element.animate() does not accept invalid easing: 'unrecognized'
+PASS Element.animate() does not accept invalid easing: 'var(--x)'
+PASS Element.animate() does not accept invalid easing: 'ease-in-out, ease-out'
+PASS Element.animate() does not accept invalid easing: 'cubic-bezier(1.1, 0, 1, 1)'
+PASS Element.animate() does not accept invalid easing: 'cubic-bezier(0, 0, 1.1, 1)'
+PASS Element.animate() does not accept invalid easing: 'cubic-bezier(-0.1, 0, 1, 1)'
+PASS Element.animate() does not accept invalid easing: 'cubic-bezier(0, 0, -0.1, 1)'
+PASS Element.animate() does not accept invalid easing: 'cubic-bezier(0.1, 0, 4, 0.4)'
+PASS Element.animate() does not accept invalid easing: 'steps(-1, start)'
+PASS Element.animate() does not accept invalid easing: 'steps(0.1, start)'
+PASS Element.animate() does not accept invalid easing: 'steps(3, nowhere)'
+PASS Element.animate() does not accept invalid easing: 'steps(-3, end)'
+PASS Element.animate() does not accept invalid easing: 'function (a){return a}'
+PASS Element.animate() does not accept invalid easing: 'function (x){return x}'
+PASS Element.animate() does not accept invalid easing: 'function(x, y){return 0.3}'
+PASS Element.animate() does not accept invalid easing: 'frames(1)'
+PASS Element.animate() does not accept invalid easing: 'frames'
+PASS Element.animate() does not accept invalid easing: 'frames()'
+PASS Element.animate() does not accept invalid easing: 'frames(,)'
+PASS Element.animate() does not accept invalid easing: 'frames(a)'
+PASS Element.animate() does not accept invalid easing: 'frames(2.0)'
+PASS Element.animate() does not accept invalid easing: 'frames(2.5)'
+PASS Element.animate() does not accept invalid easing: 'frames(2 3)'
+PASS Element.animate() accepts a double as an options argument
+PASS Element.animate() accepts a KeyframeAnimationOptions argument
+PASS Element.animate() accepts an absent options argument
+PASS Element.animate() correctly sets the id attribute when no id is specified
+PASS Element.animate() correctly sets the id attribute
+PASS Element.animate() correctly sets the Animation's timeline
+PASS Element.animate() correctly sets the Animation's timeline when triggered on an element in a different document
+FAIL Element.animate() calls play on the Animation assert_equals: expected "running" but got "pending"
+FAIL CSSPseudoElement.animate() creates an Animation object assert_equals: expected (string) "::before" but got (undefined) undefined
+FAIL CSSPseudoElement.animate() creates an Animation object targeting to the correct CSSPseudoElement object assert_equals: expected (string) "::before" but got (undefined) undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture.html b/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture.html
index 5924bd2f..c3519d2 100644
--- a/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture.html
+++ b/third_party/WebKit/LayoutTests/plugins/overlay-scrollbar-mouse-capture.html
@@ -60,6 +60,8 @@
         internals.runtimeFlags.overlayScrollbarsEnabled = true;
 
         var d = document.getElementById('container');
+        internals.setScrollbarVisibilityInScrollableArea(d, true);
+
         var plugin = document.createElement('object');
         plugin.type = 'application/x-blink-test-plugin';
         plugin.width = window.innerWidth * 2;
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableMarkingVisitorTest.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableMarkingVisitorTest.cpp
index 1bd9a08..2f2d2a4 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableMarkingVisitorTest.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptWrappableMarkingVisitorTest.cpp
@@ -250,6 +250,7 @@
   void TraceWrappers(const ScriptWrappableVisitor* visitor) const {
     visitor->TraceWrappers(handle_.Cast<v8::Value>());
   }
+  const char* NameInHeapSnapshot() const override { return "HandleContainer"; }
 
   void SetValue(v8::Isolate* isolate, v8::Local<v8::String> string) {
     handle_.Set(isolate, string);
@@ -472,11 +473,13 @@
     return new Base(wrapper_in_base, wrapper_in_mixin);
   }
 
-  virtual void TraceWrappers(const ScriptWrappableVisitor* visitor) const {
+  void TraceWrappers(const ScriptWrappableVisitor* visitor) const override {
     visitor->TraceWrappers(wrapper_in_base_);
     Mixin::TraceWrappers(visitor);
   }
 
+  const char* NameInHeapSnapshot() const override { return "HandleContainer"; }
+
  protected:
   Base(DeathAwareScriptWrappable* wrapper_in_base,
        DeathAwareScriptWrappable* wrapper_in_mixin)
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.h b/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.h
index 44e2e10..2fb872b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.h
@@ -59,7 +59,10 @@
 
   ~V8NodeFilterCondition();
   virtual void Trace(blink::Visitor* visitor) {}
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "V8NodeFilterCondition";
+  }
 
   unsigned acceptNode(Node*, ExceptionState&);
   v8::Local<v8::Value> Callback(v8::Isolate* isolate) const {
diff --git a/third_party/WebKit/Source/core/animation/EffectInput.cpp b/third_party/WebKit/Source/core/animation/EffectInput.cpp
index 979e9f67..3f2d2236 100644
--- a/third_party/WebKit/Source/core/animation/EffectInput.cpp
+++ b/third_party/WebKit/Source/core/animation/EffectInput.cpp
@@ -53,7 +53,6 @@
 #include "core/inspector/ConsoleMessage.h"
 #include "platform/wtf/ASCIICType.h"
 #include "platform/wtf/HashSet.h"
-#include "platform/wtf/NonCopyingSort.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/core/animation/EffectStack.cpp b/third_party/WebKit/Source/core/animation/EffectStack.cpp
index ce1a1c6..25036bc 100644
--- a/third_party/WebKit/Source/core/animation/EffectStack.cpp
+++ b/third_party/WebKit/Source/core/animation/EffectStack.cpp
@@ -35,7 +35,6 @@
 #include "core/animation/InvalidatableInterpolation.h"
 #include "core/animation/css/CSSAnimations.h"
 #include "platform/runtime_enabled_features.h"
-#include "platform/wtf/NonCopyingSort.h"
 
 namespace blink {
 
@@ -119,9 +118,8 @@
   if (effect_stack) {
     HeapVector<Member<SampledEffect>>& sampled_effects =
         effect_stack->sampled_effects_;
-    // std::sort doesn't work with OwnPtrs
-    NonCopyingSort(sampled_effects.begin(), sampled_effects.end(),
-                   CompareSampledEffects);
+    std::sort(sampled_effects.begin(), sampled_effects.end(),
+              CompareSampledEffects);
     effect_stack->RemoveRedundantSampledEffects();
     for (const auto& sampled_effect : sampled_effects) {
       if (sampled_effect->GetPriority() != priority ||
diff --git a/third_party/WebKit/Source/core/css/MediaQuery.cpp b/third_party/WebKit/Source/core/css/MediaQuery.cpp
index cddad2e..c6dca30 100644
--- a/third_party/WebKit/Source/core/css/MediaQuery.cpp
+++ b/third_party/WebKit/Source/core/css/MediaQuery.cpp
@@ -28,11 +28,11 @@
 
 #include "core/css/MediaQuery.h"
 
+#include <algorithm>
 #include <memory>
 #include "core/css/MediaQueryExp.h"
 #include "core/html/parser/HTMLParserIdioms.h"
 #include "core/media_type_names.h"
-#include "platform/wtf/NonCopyingSort.h"
 #include "platform/wtf/text/StringBuilder.h"
 
 namespace blink {
@@ -92,7 +92,7 @@
     : restrictor_(restrictor),
       media_type_(AttemptStaticStringCreation(media_type.LowerASCII())),
       expressions_(std::move(expressions)) {
-  NonCopyingSort(expressions_.begin(), expressions_.end(), ExpressionCompare);
+  std::sort(expressions_.begin(), expressions_.end(), ExpressionCompare);
 
   // Remove all duplicated expressions.
   MediaQueryExp key = MediaQueryExp::Invalid();
diff --git a/third_party/WebKit/Source/core/css/StyleEngine.h b/third_party/WebKit/Source/core/css/StyleEngine.h
index 0f77ce5..ec764a7 100644
--- a/third_party/WebKit/Source/core/css/StyleEngine.h
+++ b/third_party/WebKit/Source/core/css/StyleEngine.h
@@ -310,7 +310,8 @@
       const AtomicString& animation_name);
 
   virtual void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "StyleEngine"; }
 
  private:
   // FontSelectorClient implementation.
diff --git a/third_party/WebKit/Source/core/css/StyleSheetCollection.h b/third_party/WebKit/Source/core/css/StyleSheetCollection.h
index eb48dd5..0b042f1 100644
--- a/third_party/WebKit/Source/core/css/StyleSheetCollection.h
+++ b/third_party/WebKit/Source/core/css/StyleSheetCollection.h
@@ -67,7 +67,10 @@
   void MarkSheetListDirty() { sheet_list_dirty_ = true; }
 
   virtual void Trace(blink::Visitor*);
-  virtual void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "StyleSheetCollection";
+  }
 
   void Dispose();
 
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index ba77372..e599c01 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -2881,6 +2881,21 @@
   return Parser() ? Parser()->AsScriptableDocumentParser() : nullptr;
 }
 
+void Document::SetPrinting(PrintingState state) {
+  bool was_printing = Printing();
+  printing_ = state;
+  bool is_printing = Printing();
+
+  // Changing the state of Printing() can change whether layout objects are
+  // created for iframes. As such, we need to do a full reattach. See
+  // LayoutView::CanHaveChildren.
+  // https://crbug.com/819327.
+  if ((was_printing != is_printing) && documentElement() && GetFrame() &&
+      !GetFrame()->IsMainFrame()) {
+    documentElement()->LazyReattachIfAttached();
+  }
+}
+
 void Document::open(Document* entered_document,
                     ExceptionState& exception_state) {
   if (ImportLoader()) {
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h
index 26c27bc8..dbcff5a 100644
--- a/third_party/WebKit/Source/core/dom/Document.h
+++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -709,7 +709,7 @@
   bool FinishingOrIsPrinting() {
     return printing_ == kPrinting || printing_ == kFinishingPrinting;
   }
-  void SetPrinting(PrintingState state) { printing_ = state; }
+  void SetPrinting(PrintingState);
 
   bool PaginatedForScreen() const { return paginated_for_screen_; }
   void SetPaginatedForScreen(bool p) { paginated_for_screen_ = p; }
diff --git a/third_party/WebKit/Source/core/dom/DocumentParser.h b/third_party/WebKit/Source/core/dom/DocumentParser.h
index 1473bbf..6e6c9ae 100644
--- a/third_party/WebKit/Source/core/dom/DocumentParser.h
+++ b/third_party/WebKit/Source/core/dom/DocumentParser.h
@@ -44,6 +44,7 @@
   virtual ~DocumentParser();
   virtual void Trace(blink::Visitor*);
   void TraceWrappers(const ScriptWrappableVisitor*) const override {}
+  const char* NameInHeapSnapshot() const override { return "DocumentParser"; }
 
   virtual ScriptableDocumentParser* AsScriptableDocumentParser() {
     return nullptr;
diff --git a/third_party/WebKit/Source/core/dom/ElementShadow.h b/third_party/WebKit/Source/core/dom/ElementShadow.h
index c13a5b0..6ba8cdb 100644
--- a/third_party/WebKit/Source/core/dom/ElementShadow.h
+++ b/third_party/WebKit/Source/core/dom/ElementShadow.h
@@ -74,7 +74,8 @@
   }
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "ElementShadow"; }
 
  private:
   ElementShadow();
diff --git a/third_party/WebKit/Source/core/dom/ElementShadowV0.h b/third_party/WebKit/Source/core/dom/ElementShadowV0.h
index daf1db5..1b5b5cfc 100644
--- a/third_party/WebKit/Source/core/dom/ElementShadowV0.h
+++ b/third_party/WebKit/Source/core/dom/ElementShadowV0.h
@@ -55,7 +55,8 @@
   void ClearDistribution();
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "ElementShadowV0"; }
 
  private:
   explicit ElementShadowV0(ElementShadow&);
diff --git a/third_party/WebKit/Source/core/dom/FrameRequestCallbackCollection.h b/third_party/WebKit/Source/core/dom/FrameRequestCallbackCollection.h
index 01ea923..aae8265 100644
--- a/third_party/WebKit/Source/core/dom/FrameRequestCallbackCollection.h
+++ b/third_party/WebKit/Source/core/dom/FrameRequestCallbackCollection.h
@@ -31,7 +31,8 @@
         public TraceWrapperBase {
    public:
     virtual void Trace(blink::Visitor* visitor) {}
-    virtual void TraceWrappers(const ScriptWrappableVisitor* visitor) const {}
+    void TraceWrappers(const ScriptWrappableVisitor* visitor) const override {}
+    const char* NameInHeapSnapshot() const override { return "FrameCallback"; }
     virtual ~FrameCallback() = default;
     virtual void Invoke(double) = 0;
 
@@ -61,7 +62,10 @@
       return new V8FrameCallback(callback);
     }
     void Trace(blink::Visitor*);
-    void TraceWrappers(const ScriptWrappableVisitor*) const;
+    void TraceWrappers(const ScriptWrappableVisitor*) const override;
+    const char* NameInHeapSnapshot() const override {
+      return "V8FrameCallback";
+    }
     ~V8FrameCallback() override = default;
     void Invoke(double) override;
 
@@ -77,7 +81,10 @@
   bool IsEmpty() const { return !callbacks_.size(); }
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "FrameRequestCallbackCollection";
+  }
 
  private:
   using CallbackList = HeapVector<TraceWrapperMember<FrameCallback>>;
diff --git a/third_party/WebKit/Source/core/dom/MutationObserver.h b/third_party/WebKit/Source/core/dom/MutationObserver.h
index 0f6eb425..5b197db 100644
--- a/third_party/WebKit/Source/core/dom/MutationObserver.h
+++ b/third_party/WebKit/Source/core/dom/MutationObserver.h
@@ -95,7 +95,10 @@
     virtual void Deliver(const MutationRecordVector& records,
                          MutationObserver&) = 0;
     virtual void Trace(blink::Visitor* visitor) {}
-    virtual void TraceWrappers(const ScriptWrappableVisitor* visitor) const {}
+    void TraceWrappers(const ScriptWrappableVisitor* visitor) const override {}
+    const char* NameInHeapSnapshot() const override {
+      return "MutationObserver::Delegate";
+    }
   };
 
   class CORE_EXPORT V8DelegateImpl;
diff --git a/third_party/WebKit/Source/core/dom/MutationObserverRegistration.h b/third_party/WebKit/Source/core/dom/MutationObserverRegistration.h
index 2129114e..6c6942ca 100644
--- a/third_party/WebKit/Source/core/dom/MutationObserverRegistration.h
+++ b/third_party/WebKit/Source/core/dom/MutationObserverRegistration.h
@@ -84,7 +84,10 @@
   void Dispose();
 
   void Trace(blink::Visitor*);
-  virtual void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "MutationObserverRegistration";
+  }
 
  private:
   MutationObserverRegistration(MutationObserver&,
diff --git a/third_party/WebKit/Source/core/dom/ScriptedAnimationController.h b/third_party/WebKit/Source/core/dom/ScriptedAnimationController.h
index 6cada56..a6773a2 100644
--- a/third_party/WebKit/Source/core/dom/ScriptedAnimationController.h
+++ b/third_party/WebKit/Source/core/dom/ScriptedAnimationController.h
@@ -51,7 +51,10 @@
   virtual ~ScriptedAnimationController() = default;
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "ScriptedAnimationController";
+  }
   void ClearDocumentPointer() { document_ = nullptr; }
 
   // Animation frame callbacks are used for requestAnimationFrame().
diff --git a/third_party/WebKit/Source/core/dom/ScriptedIdleTaskController.h b/third_party/WebKit/Source/core/dom/ScriptedIdleTaskController.h
index dd9b86b0..6febd4c 100644
--- a/third_party/WebKit/Source/core/dom/ScriptedIdleTaskController.h
+++ b/third_party/WebKit/Source/core/dom/ScriptedIdleTaskController.h
@@ -34,7 +34,10 @@
   ~ScriptedIdleTaskController();
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "ScriptedIdleTaskController";
+  }
 
   using CallbackId = int;
 
@@ -45,6 +48,7 @@
    public:
     virtual void Trace(blink::Visitor* visitor) {}
     virtual void TraceWrappers(const ScriptWrappableVisitor* visitor) const {}
+    const char* NameInHeapSnapshot() const override { return "IdleTask"; }
     virtual ~IdleTask() = default;
     virtual void invoke(IdleDeadline*) = 0;
   };
diff --git a/third_party/WebKit/Source/core/editing/RenderedPosition.cpp b/third_party/WebKit/Source/core/editing/RenderedPosition.cpp
index 98cf6da..35a8a66 100644
--- a/third_party/WebKit/Source/core/editing/RenderedPosition.cpp
+++ b/third_party/WebKit/Source/core/editing/RenderedPosition.cpp
@@ -248,8 +248,21 @@
       PrevLeafChild()->CaretRightmostOffset());
 }
 
+// Note: If the layout object has a scrolling contents layer, the selection
+// will be relative to that.
+static GraphicsLayer* GetGraphicsLayerBacking(
+    const LayoutObject& layout_object) {
+  const LayoutBoxModelObject& paint_invalidation_container =
+      layout_object.ContainerForPaintInvalidation();
+  DCHECK(paint_invalidation_container.Layer());
+  if (paint_invalidation_container.Layer()->GetCompositingState() ==
+      kNotComposited)
+    return nullptr;
+  return paint_invalidation_container.Layer()->GraphicsLayerBacking(
+      &layout_object);
+}
+
 // Convert a local point into the coordinate system of backing coordinates.
-// Also returns the backing layer if needed.
 static FloatPoint LocalToInvalidationBackingPoint(
     const LayoutPoint& local_point,
     const LayoutObject& layout_object) {
@@ -270,26 +283,18 @@
   PaintLayer::MapPointInPaintInvalidationContainerToBacking(
       paint_invalidation_container, container_point);
 
-  // Must not use the scrolling contents layer, so pass
-  // |paintInvalidationContainer|.
-  if (GraphicsLayer* graphics_layer =
-          paint_invalidation_container.Layer()->GraphicsLayerBacking(
-              &paint_invalidation_container))
+  if (GraphicsLayer* graphics_layer = GetGraphicsLayerBacking(layout_object))
     container_point.Move(-graphics_layer->OffsetFromLayoutObject());
 
-  return container_point;
-}
+  // Ensure the coordinates are in the scrolling contents space, if the object
+  // is a scroller.
+  if (paint_invalidation_container.UsesCompositedScrolling()) {
+    container_point.Move(paint_invalidation_container.Layer()
+                             ->GetScrollableArea()
+                             ->GetScrollOffset());
+  }
 
-static GraphicsLayer* GetGraphicsLayerBacking(
-    const LayoutObject& layout_object) {
-  const LayoutBoxModelObject& paint_invalidation_container =
-      layout_object.ContainerForPaintInvalidation();
-  DCHECK(paint_invalidation_container.Layer());
-  if (paint_invalidation_container.Layer()->GetCompositingState() ==
-      kNotComposited)
-    return nullptr;
-  return paint_invalidation_container.Layer()->GraphicsLayerBacking(
-      &paint_invalidation_container);
+  return container_point;
 }
 
 std::pair<LayoutPoint, LayoutPoint> static GetLocalSelectionStartpoints(
diff --git a/third_party/WebKit/Source/core/editing/RenderedPositionTest.cpp b/third_party/WebKit/Source/core/editing/RenderedPositionTest.cpp
index af07c01..e1ba05e 100644
--- a/third_party/WebKit/Source/core/editing/RenderedPositionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/RenderedPositionTest.cpp
@@ -10,37 +10,59 @@
 #include "core/editing/testing/EditingTestBase.h"
 #include "core/frame/Settings.h"
 #include "core/html/forms/HTMLInputElement.h"
+#include "core/layout/LayoutBox.h"
+#include "core/paint/PaintLayerScrollableArea.h"
 #include "core/paint/compositing/CompositedSelection.h"
+#include "platform/testing/UseMockScrollbarSettings.h"
+#include "platform/testing/runtime_enabled_features_test_helpers.h"
 
 namespace blink {
 
-class RenderedPositionTest : public EditingTestBase {};
+class RenderedPositionTest : public ::testing::WithParamInterface<bool>,
+                             private ScopedRootLayerScrollingForTest,
+                             public EditingTestBase {
+ public:
+  RenderedPositionTest() : ScopedRootLayerScrollingForTest(GetParam()) {}
+  void SetUp() override {
+    EditingTestBase::SetUp();
+    GetPage().GetSettings().SetAcceleratedCompositingEnabled(true);
+    GetDocument().View()->SetParentVisible(true);
+    GetDocument().View()->SetSelfVisible(true);
+    LoadAhem();
+  }
 
-#if defined(OS_ANDROID)
-#define MAYBE_ComputeCompositedSelection DISABLED_ComputeCompositedSelection
-#else
-#define MAYBE_ComputeCompositedSelection ComputeCompositedSelection
-#endif
-TEST_F(RenderedPositionTest, MAYBE_ComputeCompositedSelection) {
-  // Enable compositing.
-  GetPage().GetSettings().SetAcceleratedCompositingEnabled(true);
-  GetDocument().View()->SetParentVisible(true);
-  GetDocument().View()->SetSelfVisible(true);
-  GetDocument().View()->UpdateAllLifecyclePhases();
+  void FocusAndSelectAll() {
+    HTMLInputElement* target =
+        ToHTMLInputElement(GetDocument().getElementById("target"));
+    DCHECK(target);
+    target->focus();
+    Selection().SetSelection(
+        SelectionInDOMTree::Builder()
+            .SelectAllChildren(*target->InnerEditorElement())
+            .Build(),
+        SetSelectionOptions::Builder().SetShouldShowHandle(true).Build());
+    UpdateAllLifecyclePhases();
+  }
 
-  SetBodyContent(
-      "<input id=target width=20 value='test test test test test tes tes test'"
-      "style='width: 100px; height: 20px;'>");
-  HTMLInputElement* target =
-      ToHTMLInputElement(GetDocument().getElementById("target"));
-  DCHECK(target);
-  target->focus();
-  Selection().SetSelection(
-      SelectionInDOMTree::Builder()
-          .SelectAllChildren(*target->InnerEditorElement())
-          .Build(),
-      SetSelectionOptions::Builder().SetShouldShowHandle(true).Build());
-  UpdateAllLifecyclePhases();
+ private:
+  UseMockScrollbarSettings mock_scrollbars_;
+};
+
+INSTANTIATE_TEST_CASE_P(All, RenderedPositionTest, ::testing::Bool());
+
+TEST_P(RenderedPositionTest, ComputeCompositedSelection) {
+  SetBodyContent(R"HTML(
+      <!DOCTYPE html>
+      input {
+        font: 10px/1 Ahem;
+        padding: 0;
+        border: 0;
+      }
+      <input id=target width=20 value='test test test test test tes tes test'
+      style='width: 100px; height: 20px;'>
+  )HTML");
+
+  FocusAndSelectAll();
 
   const CompositedSelection& composited_selection =
       RenderedPosition::ComputeCompositedSelection(Selection());
@@ -48,4 +70,115 @@
   EXPECT_TRUE(composited_selection.end.hidden);
 }
 
+TEST_P(RenderedPositionTest, PositionInScrollableRoot) {
+  SetBodyContent(R"HTML(
+      <!DOCTYPE html>
+      <style>
+        body {
+           margin: 0;
+           height: 2000px;
+           width: 2000px;
+        }
+        input {
+          font: 10px/1 Ahem;
+          padding: 0;
+          border: 0;
+          width: 100px;
+          height: 20px;
+          position: absolute;
+          top: 900px;
+          left: 1000px;
+        }
+      </style>
+      <input id=target width=20 value='test test test test test tes tes test'>
+  )HTML");
+
+  FocusAndSelectAll();
+
+  ScrollableArea* root_scroller = GetDocument().View()->GetScrollableArea();
+  root_scroller->SetScrollOffset(ScrollOffset(800, 500), kProgrammaticScroll);
+  ASSERT_EQ(ScrollOffset(800, 500), root_scroller->GetScrollOffset());
+
+  UpdateAllLifecyclePhases();
+
+  const CompositedSelection& composited_selection =
+      RenderedPosition::ComputeCompositedSelection(Selection());
+
+  // Top-left corner should be around (1000, 905) - 10px centered in 20px
+  // height.
+  EXPECT_EQ(FloatPoint(1000, 905),
+            composited_selection.start.edge_top_in_layer);
+  EXPECT_EQ(FloatPoint(1000, 915),
+            composited_selection.start.edge_bottom_in_layer);
+  EXPECT_EQ(FloatPoint(1369, 905), composited_selection.end.edge_top_in_layer);
+  EXPECT_EQ(FloatPoint(1369, 915),
+            composited_selection.end.edge_bottom_in_layer);
+}
+
+TEST_P(RenderedPositionTest, PositionInScroller) {
+  SetBodyContent(R"HTML(
+      <!DOCTYPE html>
+      <style>
+        body {
+           margin: 0;
+           height: 2000px;
+           width: 2000px;
+        }
+        input {
+          font: 10px/1 Ahem;
+          padding: 0;
+          border: 0;
+          width: 100px;
+          height: 20px;
+          position: absolute;
+          top: 900px;
+          left: 1000px;
+        }
+
+        #scroller {
+          width: 300px;
+          height: 300px;
+          position: absolute;
+          left: 300px;
+          top: 400px;
+          overflow: scroll;
+          border: 200px;
+          will-change: transform;
+        }
+
+        #space {
+          width: 2000px;
+          height: 2000px;
+        }
+      </style>
+      <div id="scroller">
+        <div id="space"></div>
+        <input id=target width=20 value='test test test test test tes tes test'>
+      </div>
+  )HTML");
+
+  FocusAndSelectAll();
+
+  Element* e = GetDocument().getElementById("scroller");
+  PaintLayerScrollableArea* scroller =
+      ToLayoutBox(e->GetLayoutObject())->GetScrollableArea();
+  scroller->SetScrollOffset(ScrollOffset(900, 800), kProgrammaticScroll);
+  ASSERT_EQ(ScrollOffset(900, 800), scroller->GetScrollOffset());
+
+  UpdateAllLifecyclePhases();
+
+  const CompositedSelection& composited_selection =
+      RenderedPosition::ComputeCompositedSelection(Selection());
+
+  // Top-left corner should be around (1000, 905) - 10px centered in 20px
+  // height.
+  EXPECT_EQ(FloatPoint(1000, 905),
+            composited_selection.start.edge_top_in_layer);
+  EXPECT_EQ(FloatPoint(1000, 915),
+            composited_selection.start.edge_bottom_in_layer);
+  EXPECT_EQ(FloatPoint(1369, 905), composited_selection.end.edge_top_in_layer);
+  EXPECT_EQ(FloatPoint(1369, 915),
+            composited_selection.end.edge_bottom_in_layer);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
index 0aa806a..eb3edc7 100644
--- a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
@@ -6332,11 +6332,7 @@
     blink::Node* layer_owner_node_for_start = V8Node::ToImplWithTypeCheck(
         v8::Isolate::GetCurrent(), expected_result.Get(0));
     ASSERT_TRUE(layer_owner_node_for_start);
-    EXPECT_EQ(layer_owner_node_for_start->GetLayoutObject()
-                  ->EnclosingLayer()
-                  ->EnclosingLayerForPaintInvalidation()
-                  ->GetCompositedLayerMapping()
-                  ->MainGraphicsLayer()
+    EXPECT_EQ(GetExpectedLayerForSelection(layer_owner_node_for_start)
                   ->PlatformLayer()
                   ->Id(),
               select_start->layer_id);
@@ -6351,11 +6347,7 @@
         expected_result.Get(context, 5).ToLocalChecked());
 
     ASSERT_TRUE(layer_owner_node_for_end);
-    EXPECT_EQ(layer_owner_node_for_end->GetLayoutObject()
-                  ->EnclosingLayer()
-                  ->EnclosingLayerForPaintInvalidation()
-                  ->GetCompositedLayerMapping()
-                  ->MainGraphicsLayer()
+    EXPECT_EQ(GetExpectedLayerForSelection(layer_owner_node_for_end)
                   ->PlatformLayer()
                   ->Id(),
               select_end->layer_id);
@@ -6407,6 +6399,18 @@
     RunTest(test_file);
   }
 
+  GraphicsLayer* GetExpectedLayerForSelection(blink::Node* node) const {
+    CompositedLayerMapping* clm = node->GetLayoutObject()
+                                      ->EnclosingLayer()
+                                      ->EnclosingLayerForPaintInvalidation()
+                                      ->GetCompositedLayerMapping();
+
+    // If the Node is a scroller, the selection will be relative to its
+    // scrolling contents layer.
+    return clm->ScrollingContentsLayer() ? clm->ScrollingContentsLayer()
+                                         : clm->MainGraphicsLayer();
+  }
+
   CompositedSelectionBoundsTestWebViewClient fake_selection_web_view_client_;
   CompositedSelectionBoundsTestLayerTreeView& fake_selection_layer_tree_view_;
   FrameTestHelpers::WebViewHelper web_view_helper_;
@@ -11895,6 +11899,35 @@
   EXPECT_FALSE(iframe_doc->documentElement()->GetLayoutObject());
 }
 
+// Although it is not spec compliant, many websites intentionally call
+// Window.print() on display:none iframes. https://crbug.com/819327.
+TEST_P(WebFrameSimTest, DisplayNoneIFramePrints) {
+  SimRequest main_resource("https://example.com/test.html", "text/html");
+  SimRequest frame_resource("https://example.com/frame.html", "text/html");
+
+  LoadURL("https://example.com/test.html");
+  main_resource.Complete(
+      "<!DOCTYPE html>"
+      "<iframe src=frame.html style='display: none'></iframe>");
+  frame_resource.Complete(
+      "<!DOCTYPE html>"
+      "<html><body>This is a visible iframe.</body></html>");
+
+  Element* element = GetDocument().QuerySelector("iframe");
+  HTMLFrameOwnerElement* frame_owner_element = ToHTMLFrameOwnerElement(element);
+  Document* iframe_doc = frame_owner_element->contentDocument();
+  EXPECT_FALSE(iframe_doc->documentElement()->GetLayoutObject());
+
+  FloatSize page_size(400, 400);
+  float maximum_shrink_ratio = 1.0;
+  iframe_doc->GetFrame()->StartPrinting(page_size, page_size,
+                                        maximum_shrink_ratio);
+  EXPECT_TRUE(iframe_doc->documentElement()->GetLayoutObject());
+
+  iframe_doc->GetFrame()->EndPrinting();
+  EXPECT_FALSE(iframe_doc->documentElement()->GetLayoutObject());
+}
+
 TEST_P(WebFrameSimTest, NormalIFrameHasLayoutObjects) {
   SimRequest main_resource("https://example.com/test.html", "text/html");
   SimRequest frame_resource("https://example.com/frame.html", "text/html");
diff --git a/third_party/WebKit/Source/core/exported/WebViewTest.cpp b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
index 8512ed9..2472bc1 100644
--- a/third_party/WebKit/Source/core/exported/WebViewTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
@@ -4382,19 +4382,27 @@
       mojom::blink::UnhandledTapInfoPtr unhandled_tap_info) override {
     was_unhandled_tap_ = true;
     tapped_position_ = unhandled_tap_info->tapped_position_in_viewport;
+    element_text_run_length_ = unhandled_tap_info->element_text_run_length;
+    font_size_ = unhandled_tap_info->font_size_in_pixels;
   }
   bool WasUnhandledTap() const { return was_unhandled_tap_; }
   int GetTappedXPos() const { return tapped_position_.X(); }
   int GetTappedYPos() const { return tapped_position_.Y(); }
+  int GetFontSize() const { return font_size_; }
+  int GetElementTextRunLength() const { return element_text_run_length_; }
   void Reset() {
     was_unhandled_tap_ = false;
     tapped_position_ = IntPoint();
+    element_text_run_length_ = 0;
+    font_size_ = 0;
     binding_.Close();
   }
 
  private:
   bool was_unhandled_tap_ = false;
   IntPoint tapped_position_;
+  int element_text_run_length_ = 0;
+  int font_size_ = 0;
 
   mojo::Binding<mojom::blink::UnhandledTapNotifier> binding_;
 };
@@ -4468,6 +4476,8 @@
   EXPECT_TRUE(mock_notifier_.WasUnhandledTap());
   EXPECT_EQ(64, mock_notifier_.GetTappedXPos());
   EXPECT_EQ(278, mock_notifier_.GetTappedYPos());
+  EXPECT_EQ(16, mock_notifier_.GetFontSize());
+  EXPECT_EQ(7, mock_notifier_.GetElementTextRunLength());
 
   // Test basic tap handling and notification.
   Tap("target");
@@ -4483,6 +4493,8 @@
   EXPECT_TRUE(mock_notifier_.WasUnhandledTap());
   EXPECT_EQ(188, mock_notifier_.GetTappedXPos());
   EXPECT_EQ(124, mock_notifier_.GetTappedYPos());
+  EXPECT_EQ(16, mock_notifier_.GetFontSize());
+  EXPECT_EQ(28, mock_notifier_.GetElementTextRunLength());
 }
 
 TEST_P(ShowUnhandledTapTest, ShowUnhandledTapUIIfNeededWithMutateDom) {
@@ -4514,7 +4526,7 @@
 }
 
 TEST_P(ShowUnhandledTapTest, ShowUnhandledTapUIIfNeededWithNonTriggeringNodes) {
-  Tap("checkbox");
+  Tap("image");
   EXPECT_FALSE(mock_notifier_.WasUnhandledTap());
 
   Tap("editable");
@@ -4524,6 +4536,16 @@
   EXPECT_FALSE(mock_notifier_.WasUnhandledTap());
 }
 
+TEST_P(ShowUnhandledTapTest, ShowUnhandledTapUIIfNeededWithTextSizes) {
+  Tap("large");
+  EXPECT_TRUE(mock_notifier_.WasUnhandledTap());
+  EXPECT_EQ(20, mock_notifier_.GetFontSize());
+
+  Tap("small");
+  EXPECT_TRUE(mock_notifier_.WasUnhandledTap());
+  EXPECT_EQ(10, mock_notifier_.GetFontSize());
+}
+
 #endif  // BUILDFLAG(ENABLE_UNHANDLED_TAP)
 
 TEST_P(WebViewTest, StopLoadingIfJavaScriptURLReturnsNoStringResult) {
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index 53077edc..712c5a2 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -4506,7 +4506,7 @@
 void LocalFrameView::UpdateScrollbarEnabledState() {
   bool force_disabled =
       GetPageScrollbarTheme().ShouldDisableInvisibleScrollbars() &&
-      ScrollbarsHidden();
+      ScrollbarsHiddenIfOverlay();
 
   if (HorizontalScrollbar()) {
     HorizontalScrollbar()->SetEnabled(ContentsWidth() > VisibleWidth() &&
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp b/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp
index 3d5a9d8a..99651d6 100644
--- a/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/RemoteFrameView.cpp
@@ -163,8 +163,6 @@
                             const GlobalPaintFlags flags,
                             const CullRect& rect,
                             const IntSize& paint_offset) const {
-  // TODO(wangxianzhu): Should we consider |paint_offset| for SPv175?
-
   // Painting remote frames is only for printing.
   if (!context.Printing())
     return;
@@ -174,12 +172,16 @@
 
   DrawingRecorder recorder(context, *GetFrame().OwnerLayoutObject(),
                            DisplayItem::kDocumentBackground);
+  context.Save();
+  context.Translate(paint_offset.Width(), paint_offset.Height());
+
   DCHECK(context.Canvas());
   // Inform the remote frame to print.
   uint32_t content_id = Print(FrameRect(), context.Canvas());
 
   // Record the place holder id on canvas.
   context.Canvas()->recordCustomData(content_id);
+  context.Restore();
 }
 
 void RemoteFrameView::UpdateGeometry() {
diff --git a/third_party/WebKit/Source/core/html/HTMLIFrameElementSandbox.cpp b/third_party/WebKit/Source/core/html/HTMLIFrameElementSandbox.cpp
index e5050698..37d62d9a 100644
--- a/third_party/WebKit/Source/core/html/HTMLIFrameElementSandbox.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLIFrameElementSandbox.cpp
@@ -11,9 +11,11 @@
 namespace {
 
 const char* const kSupportedSandboxTokens[] = {
-    "allow-downloads",    "allow-forms",   "allow-modals",
-    "allow-pointer-lock", "allow-popups",  "allow-popups-to-escape-sandbox",
-    "allow-same-origin",  "allow-scripts", "allow-top-navigation"};
+    "allow-downloads",      "allow-forms",
+    "allow-modals",         "allow-pointer-lock",
+    "allow-popups",         "allow-popups-to-escape-sandbox",
+    "allow-same-origin",    "allow-scripts",
+    "allow-top-navigation", "allow-top-navigation-by-user-activation"};
 
 bool IsTokenSupported(const AtomicString& token) {
   for (const char* supported_token : kSupportedSandboxTokens) {
diff --git a/third_party/WebKit/Source/core/html/custom/CustomElementDefinition.h b/third_party/WebKit/Source/core/html/custom/CustomElementDefinition.h
index a57ab14b..fd289962 100644
--- a/third_party/WebKit/Source/core/html/custom/CustomElementDefinition.h
+++ b/third_party/WebKit/Source/core/html/custom/CustomElementDefinition.h
@@ -38,7 +38,10 @@
   virtual ~CustomElementDefinition();
 
   virtual void Trace(blink::Visitor*);
-  virtual void TraceWrappers(const ScriptWrappableVisitor* visitor) const {}
+  void TraceWrappers(const ScriptWrappableVisitor* visitor) const override {}
+  const char* NameInHeapSnapshot() const override {
+    return "CustomElementDefinition";
+  }
 
   const CustomElementDescriptor& Descriptor() { return descriptor_; }
 
diff --git a/third_party/WebKit/Source/core/html/custom/CustomElementReactionStack.h b/third_party/WebKit/Source/core/html/custom/CustomElementReactionStack.h
index 274d83f..f968a3f 100644
--- a/third_party/WebKit/Source/core/html/custom/CustomElementReactionStack.h
+++ b/third_party/WebKit/Source/core/html/custom/CustomElementReactionStack.h
@@ -24,7 +24,10 @@
   CustomElementReactionStack();
 
   void Trace(blink::Visitor*);
-  virtual void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "CustomElementReactionStack";
+  }
 
   void Push();
   void PopInvokingReactions();
diff --git a/third_party/WebKit/Source/core/html/forms/RangeInputType.cpp b/third_party/WebKit/Source/core/html/forms/RangeInputType.cpp
index 38d66b31..d713db4 100644
--- a/third_party/WebKit/Source/core/html/forms/RangeInputType.cpp
+++ b/third_party/WebKit/Source/core/html/forms/RangeInputType.cpp
@@ -31,6 +31,7 @@
 
 #include "core/html/forms/RangeInputType.h"
 
+#include <algorithm>
 #include <limits>
 #include "bindings/core/v8/ExceptionState.h"
 #include "core/dom/AXObjectCache.h"
@@ -53,7 +54,6 @@
 #include "core/input_type_names.h"
 #include "core/layout/LayoutSlider.h"
 #include "platform/wtf/MathExtras.h"
-#include "platform/wtf/NonCopyingSort.h"
 
 namespace blink {
 
@@ -375,8 +375,7 @@
     tick_mark_values_.push_back(ParseToNumber(option_value, Decimal::Nan()));
   }
   tick_mark_values_.ShrinkToFit();
-  NonCopyingSort(tick_mark_values_.begin(), tick_mark_values_.end(),
-                 DecimalCompare);
+  std::sort(tick_mark_values_.begin(), tick_mark_values_.end(), DecimalCompare);
 }
 
 Decimal RangeInputType::FindClosestTickMarkValue(const Decimal& value) {
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.h b/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.h
index 7dc3f22..d88159b 100644
--- a/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.h
+++ b/third_party/WebKit/Source/core/html/imports/HTMLImportTreeRoot.h
@@ -35,7 +35,10 @@
   HTMLImportChild* Find(const KURL&) const;
 
   virtual void Trace(blink::Visitor*);
-  virtual void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "HTMLImportTreeRoot";
+  }
 
  private:
   explicit HTMLImportTreeRoot(Document*);
diff --git a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h
index 1e092f0b6..0e6281b 100644
--- a/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h
+++ b/third_party/WebKit/Source/core/html/imports/HTMLImportsController.h
@@ -73,6 +73,9 @@
   void Dispose();
 
   void TraceWrappers(const ScriptWrappableVisitor*) const;
+  const char* NameInHeapSnapshot() const override {
+    return "HTMLImportsController";
+  }
 
  private:
   explicit HTMLImportsController(Document&);
diff --git a/third_party/WebKit/Source/core/html/track/CueTimeline.cpp b/third_party/WebKit/Source/core/html/track/CueTimeline.cpp
index 9682ed2..40a45f32 100644
--- a/third_party/WebKit/Source/core/html/track/CueTimeline.cpp
+++ b/third_party/WebKit/Source/core/html/track/CueTimeline.cpp
@@ -4,6 +4,7 @@
 
 #include "core/html/track/CueTimeline.h"
 
+#include <algorithm>
 #include "core/dom/events/Event.h"
 #include "core/html/media/HTMLMediaElement.h"
 #include "core/html/track/HTMLTrackElement.h"
@@ -11,7 +12,6 @@
 #include "core/html/track/TextTrack.h"
 #include "core/html/track/TextTrackCue.h"
 #include "core/html/track/TextTrackCueList.h"
-#include "platform/wtf/NonCopyingSort.h"
 
 namespace blink {
 
@@ -283,7 +283,7 @@
 
   // 12 - Sort the tasks in events in ascending time order (tasks with earlier
   // times first).
-  NonCopyingSort(event_tasks.begin(), event_tasks.end(), EventTimeCueCompare);
+  std::sort(event_tasks.begin(), event_tasks.end(), EventTimeCueCompare);
 
   for (const auto& task : event_tasks) {
     if (!affected_tracks.Contains(task.second->track()))
@@ -311,8 +311,7 @@
 
   // 14 - Sort affected tracks in the same order as the text tracks appear in
   // the media element's list of text tracks, and remove duplicates.
-  NonCopyingSort(affected_tracks.begin(), affected_tracks.end(),
-                 TrackIndexCompare);
+  std::sort(affected_tracks.begin(), affected_tracks.end(), TrackIndexCompare);
 
   // 15 - For each text track in affected tracks, in the list order, queue a
   // task to fire a simple event named cuechange at the TextTrack object, and,
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
index bddaf78..2fb9cb6 100644
--- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
+++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
@@ -95,6 +95,9 @@
 
   void Trace(blink::Visitor*);
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "ImageBitmapLoader";
+  }
 
  private:
   class ImageBitmapLoader final
diff --git a/third_party/WebKit/Source/core/input/GestureManager.cpp b/third_party/WebKit/Source/core/input/GestureManager.cpp
index 7d88b7b6..87728986 100644
--- a/third_party/WebKit/Source/core/input/GestureManager.cpp
+++ b/third_party/WebKit/Source/core/input/GestureManager.cpp
@@ -21,7 +21,11 @@
 #include "public/public_features.h"
 
 #if BUILDFLAG(ENABLE_UNHANDLED_TAP)
+#include "core/editing/FrameSelection.h"
+#include "core/editing/SelectionTemplate.h"
+#include "core/editing/VisibleSelection.h"
 #include "core/frame/LocalFrameClient.h"
+#include "core/style/ComputedStyle.h"
 #include "public/platform/unhandled_tap_notifier.mojom-blink.h"
 #include "public/web/WebNode.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
@@ -310,7 +314,7 @@
         frame_->GetPage()->GetVisualViewport().RootFrameToViewport(
             tapped_position);
     ShowUnhandledTapUIIfNeeded(dom_tree_changed, style_changed, tapped_node,
-                               tapped_position_in_viewport);
+                               tapped_element, tapped_position_in_viewport);
   }
   return event_result;
 }
@@ -447,9 +451,11 @@
     bool dom_tree_changed,
     bool style_changed,
     Node* tapped_node,
+    Element* tapped_element,
     const IntPoint& tapped_position_in_viewport) {
 #if BUILDFLAG(ENABLE_UNHANDLED_TAP)
   WebNode web_node(tapped_node);
+  // TODO(donnd): roll in ML-identified signals for suppression once identified.
   bool should_trigger = !dom_tree_changed && !style_changed &&
                         tapped_node->IsTextNode() &&
                         !web_node.IsContentEditable() &&
@@ -457,12 +463,29 @@
   // Renderer-side trigger-filtering to minimize messaging.
   // The Browser may do additional trigger-filtering.
   if (should_trigger) {
-    WebPoint point(tapped_position_in_viewport.X(),
-                   tapped_position_in_viewport.Y());
-    auto tapped_info = mojom::blink::UnhandledTapInfo::New(point);
+    // Start setting up the Mojo interface connection.
     mojom::blink::UnhandledTapNotifierPtr provider;
     frame_->Client()->GetInterfaceProvider()->GetInterface(
         mojo::MakeRequest(&provider));
+
+    // Extract text run-length.
+    int text_run_length = 0;
+    if (tapped_element)
+      text_run_length = tapped_element->textContent().length();
+
+    // Compute the style of the tapped node to extract text characteristics.
+    const ComputedStyle* style = tapped_node->EnsureComputedStyle();
+    int font_size = 0;
+    if (style)
+      font_size = style->FontSize();
+    // TODO(donnd): get the text color and style and return,
+    // e.g. style->GetFontWeight() to return bold.  Need italic, color, etc.
+
+    // Notify the Browser.
+    WebPoint point(tapped_position_in_viewport.X(),
+                   tapped_position_in_viewport.Y());
+    auto tapped_info =
+        mojom::blink::UnhandledTapInfo::New(point, font_size, text_run_length);
     provider->ShowUnhandledTapUIIfNeeded(std::move(tapped_info));
   }
 #endif  // BUILDFLAG(ENABLE_UNHANDLED_TAP)
diff --git a/third_party/WebKit/Source/core/input/GestureManager.h b/third_party/WebKit/Source/core/input/GestureManager.h
index e14889d7..3709fa83 100644
--- a/third_party/WebKit/Source/core/input/GestureManager.h
+++ b/third_party/WebKit/Source/core/input/GestureManager.h
@@ -64,6 +64,7 @@
   void ShowUnhandledTapUIIfNeeded(bool dom_tree_changed,
                                   bool style_changed,
                                   Node* tapped_node,
+                                  Element* tapped_element,
                                   const IntPoint& tapped_position_in_viewport);
 
   // NOTE: If adding a new field to this class please ensure that it is
diff --git a/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.h b/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.h
index 90e46a6..680627ba 100644
--- a/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.h
+++ b/third_party/WebKit/Source/core/intersection_observer/ElementIntersectionObserverData.h
@@ -30,7 +30,10 @@
   void DeactivateAllIntersectionObservers(Node&);
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "ElementIntersectionObserverData";
+  }
 
  private:
   // IntersectionObservers for which the Node owning this data is root.
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverController.h b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverController.h
index b3236bd0..0b68f6ed 100644
--- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverController.h
+++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverController.h
@@ -38,6 +38,9 @@
 
   void Trace(blink::Visitor*);
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "IntersectionObserverController";
+  }
 
  private:
   explicit IntersectionObserverController(Document*);
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverDelegate.h b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverDelegate.h
index 27a52a0..466c7bd 100644
--- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverDelegate.h
+++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverDelegate.h
@@ -23,7 +23,10 @@
                        IntersectionObserver&) = 0;
   virtual ExecutionContext* GetExecutionContext() const = 0;
   virtual void Trace(blink::Visitor* visitor) {}
-  virtual void TraceWrappers(const ScriptWrappableVisitor* visitor) const {}
+  void TraceWrappers(const ScriptWrappableVisitor* visitor) const override {}
+  const char* NameInHeapSnapshot() const override {
+    return "IntersectionObserverDelegate";
+  }
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/FloatingObjects.h b/third_party/WebKit/Source/core/layout/FloatingObjects.h
index 353b8c8..321b5ff 100644
--- a/third_party/WebKit/Source/core/layout/FloatingObjects.h
+++ b/third_party/WebKit/Source/core/layout/FloatingObjects.h
@@ -229,10 +229,6 @@
       LayoutUnit logical_top,
       LayoutUnit* height_remaining);
 
-  // NOTE(ikilpatrick): These methods exist for determining how shape-outside
-  // affects positioning and sizing of block children avoiding floats.
-  // If usage is low enough these may be used instead of LogicalLeftOffset,
-  // LogicalLeftOffset for children avoiding floats.
   LayoutUnit LogicalLeftOffsetForAvoidingFloats(LayoutUnit fixed_offset,
                                                 LayoutUnit logical_top,
                                                 LayoutUnit logical_height);
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index 6d3900a..1018967 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -664,21 +664,8 @@
   LayoutUnit new_position = start_position + child_margin_start;
 
   if (child.AvoidsFloats() && ContainsFloats()) {
-    LayoutUnit position_to_avoid_floats =
-        StartOffsetForLine(LogicalTopForChild(child), kDoNotIndentText,
-                           LogicalHeightForChild(child));
-
-    // This section of code is just for a use counter. It counts if something
-    // that avoids floats may have been affected by a float with shape-outside.
-    if (!ShapeOutsideInfo::IsEmpty()) {
-      LayoutUnit alternate_position_to_avoid_floats =
-          StartOffsetForAvoidingFloats(LogicalTopForChild(child),
-                                       LogicalHeightForChild(child));
-      if (alternate_position_to_avoid_floats != position_to_avoid_floats) {
-        UseCounter::Count(GetDocument(),
-                          WebFeature::kShapeOutsideMaybeAffectedInlinePosition);
-      }
-    }
+    LayoutUnit position_to_avoid_floats = StartOffsetForAvoidingFloats(
+        LogicalTopForChild(child), LogicalHeightForChild(child));
 
     // If the child has an offset from the content edge to avoid floats then use
     // that, otherwise let any negative margin pull it back over the content
@@ -2841,8 +2828,8 @@
         IsHorizontalWritingMode() ? border_box.Width() : border_box.Height();
     while (true) {
       LayoutUnit available_logical_width_at_new_logical_top_offset =
-          AvailableLogicalWidthForLine(new_logical_top, kDoNotIndentText,
-                                       LogicalHeightForChild(*child));
+          AvailableLogicalWidthForAvoidingFloats(new_logical_top,
+                                                 LogicalHeightForChild(*child));
       if (available_logical_width_at_new_logical_top_offset ==
           AvailableLogicalWidthForContent())
         return new_logical_top - logical_top;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
index c9ccd0a..b270e92 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.h
@@ -147,14 +147,6 @@
                : LogicalWidth() - LogicalRightOffsetForLine(
                                       position, indent_text, logical_height);
   }
-  LayoutUnit EndOffsetForLine(LayoutUnit position,
-                              IndentTextOrNot indent_text,
-                              LayoutUnit logical_height = LayoutUnit()) const {
-    return !Style()->IsLeftToRightDirection()
-               ? LogicalLeftOffsetForLine(position, indent_text, logical_height)
-               : LogicalWidth() - LogicalRightOffsetForLine(
-                                      position, indent_text, logical_height);
-  }
 
   LayoutUnit AvailableLogicalWidthForAvoidingFloats(
       LayoutUnit position,
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 68b9657..d956953d 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -1218,11 +1218,10 @@
   DCHECK(HasLayer());
   // FIXME: Return DoubleSize here. crbug.com/414283.
   PaintLayerScrollableArea* scrollable_area = GetScrollableArea();
-  IntSize result =
-      scrollable_area->ScrollOffsetInt() + OriginAdjustmentForScrollbars();
-  if (IsHorizontalWritingMode() &&
-      ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
-    result.Expand(-VerticalScrollbarWidth(), 0);
+  if (!UNLIKELY(HasFlippedBlocksWritingMode()))
+    return scrollable_area->ScrollOffsetInt();
+  IntSize result = scrollable_area->ScrollOffsetInt();
+  result.Expand(VerticalScrollbarWidth(), 0);
   return result;
 }
 
@@ -2045,38 +2044,25 @@
   LayoutUnit logical_top_position = LogicalTop();
   LayoutUnit start_offset_for_content = cb->StartOffsetForContent();
   LayoutUnit end_offset_for_content = cb->EndOffsetForContent();
+
+  // NOTE: This call to LogicalHeightForChild is bad, as it may contain data
+  // from a previous layout.
   LayoutUnit logical_height = cb->LogicalHeightForChild(*this);
-  LayoutUnit start_offset_for_line = cb->StartOffsetForLine(
-      logical_top_position, kDoNotIndentText, logical_height);
-  LayoutUnit end_offset_for_line = cb->EndOffsetForLine(
-      logical_top_position, kDoNotIndentText, logical_height);
+  LayoutUnit start_offset_for_avoiding_floats =
+      cb->StartOffsetForAvoidingFloats(logical_top_position, logical_height);
+  LayoutUnit end_offset_for_avoiding_floats =
+      cb->EndOffsetForAvoidingFloats(logical_top_position, logical_height);
 
   // If there aren't any floats constraining us then allow the margins to
   // shrink/expand the width as much as they want.
-  if (start_offset_for_content == start_offset_for_line &&
-      end_offset_for_content == end_offset_for_line)
-    return cb->AvailableLogicalWidthForLine(logical_top_position,
-                                            kDoNotIndentText, logical_height) -
+  if (start_offset_for_content == start_offset_for_avoiding_floats &&
+      end_offset_for_content == end_offset_for_avoiding_floats)
+    return cb->AvailableLogicalWidthForAvoidingFloats(logical_top_position,
+                                                      logical_height) -
            child_margin_start - child_margin_end;
 
-  LayoutUnit width = cb->AvailableLogicalWidthForLine(
-      logical_top_position, kDoNotIndentText, logical_height);
-
-  // This section of code is just for a use counter. It counts if something
-  // that avoids floats may have been affected by a float with shape-outside.
-  // NOTE(ikilpatrick): This isn't the only code-path which uses
-  // AvailableLogicalWidthForLine, if we switch this over we need to inspect
-  // other usages.
-  if (!ShapeOutsideInfo::IsEmpty()) {
-    LayoutUnit alternate_width = cb->AvailableLogicalWidthForAvoidingFloats(
-        logical_top_position, logical_height);
-
-    if (alternate_width != width) {
-      UseCounter::Count(GetDocument(),
-                        WebFeature::kShapeOutsideMaybeAffectedInlineSize);
-    }
-  }
-
+  LayoutUnit width = cb->AvailableLogicalWidthForAvoidingFloats(
+      logical_top_position, logical_height);
   width -= std::max(LayoutUnit(), child_margin_start);
   width -= std::max(LayoutUnit(), child_margin_end);
 
@@ -2088,10 +2074,11 @@
   // can use the line offset, but we need to grow it by the margin to reflect
   // the fact that the margin was "consumed" by the float. Negative margins
   // aren't consumed by the float, and so we ignore them.
+  width += PortionOfMarginNotConsumedByFloat(child_margin_start,
+                                             start_offset_for_content,
+                                             start_offset_for_avoiding_floats);
   width += PortionOfMarginNotConsumedByFloat(
-      child_margin_start, start_offset_for_content, start_offset_for_line);
-  width += PortionOfMarginNotConsumedByFloat(
-      child_margin_end, end_offset_for_content, end_offset_for_line);
+      child_margin_end, end_offset_for_content, end_offset_for_avoiding_floats);
   return width;
 }
 
@@ -2130,10 +2117,10 @@
 
 LayoutUnit LayoutBox::ContainingBlockAvailableLineWidth() const {
   LayoutBlock* cb = ContainingBlock();
-  if (cb->IsLayoutBlockFlow())
-    return ToLayoutBlockFlow(cb)->AvailableLogicalWidthForLine(
-        LogicalTop(), kDoNotIndentText,
-        AvailableLogicalHeight(kIncludeMarginBorderPadding));
+  if (cb->IsLayoutBlockFlow()) {
+    return ToLayoutBlockFlow(cb)->AvailableLogicalWidthForAvoidingFloats(
+        LogicalTop(), AvailableLogicalHeight(kIncludeMarginBorderPadding));
+  }
   return LayoutUnit();
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h
index 4c33848..14e40e1 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -1242,7 +1242,7 @@
 
   // See README.md for an explanation of scroll origin.
   virtual IntSize OriginAdjustmentForScrollbars() const;
-  IntSize ScrolledContentOffset() const;
+  virtual IntSize ScrolledContentOffset() const;
 
   // Maps from scrolling contents space to box space and apply overflow
   // clip if needed. Returns true if no clipping applied or the flattened quad
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
index 1a8bed1..43f7549e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -279,6 +279,19 @@
   return size;
 }
 
+IntSize LayoutFlexibleBox::ScrolledContentOffset() const {
+  DCHECK(HasOverflowClip());
+  DCHECK(HasLayer());
+  // FIXME: Return DoubleSize here. crbug.com/414283.
+  PaintLayerScrollableArea* scrollable_area = GetScrollableArea();
+  IntSize result =
+      scrollable_area->ScrollOffsetInt() + OriginAdjustmentForScrollbars();
+  if (IsHorizontalWritingMode() &&
+      ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+    result.Expand(-VerticalScrollbarWidth(), 0);
+  return result;
+}
+
 bool LayoutFlexibleBox::HasTopOverflow() const {
   EFlexDirection flex_direction = Style()->FlexDirection();
   if (IsHorizontalWritingMode())
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
index b0975d72..68740cf 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
+++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
@@ -64,7 +64,8 @@
 
   LayoutUnit FirstLineBoxBaseline() const override;
   LayoutUnit InlineBlockBaseline(LineDirectionMode) const override;
-  IntSize OriginAdjustmentForScrollbars() const override;
+  IntSize OriginAdjustmentForScrollbars() const final;
+  IntSize ScrolledContentOffset() const final;
   bool HasTopOverflow() const override;
   bool HasLeftOverflow() const override;
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index 13852e6d..c4f0333e2 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -697,9 +697,10 @@
 }
 
 bool LayoutObject::IsFixedPositionObjectInPagedMedia() const {
+  if (StyleRef().GetPosition() != EPosition::kFixed)
+    return false;
   LayoutView* view = View();
-  return StyleRef().GetPosition() == EPosition::kFixed && Container() == view &&
-         view->PageLogicalHeight() &&
+  return Container() == view && view->PageLogicalHeight() &&
          // TODO(crbug.com/619094): Figure out the correct behaviour for fixed
          // position objects in paged media with vertical writing modes.
          view->IsHorizontalWritingMode();
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.cpp b/third_party/WebKit/Source/core/layout/LayoutView.cpp
index 436ab77b8..d4c5da6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutView.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutView.cpp
@@ -216,6 +216,10 @@
     return true;
   if (!RuntimeEnabledFeatures::DisplayNoneIFrameCreatesNoLayoutObjectEnabled())
     return true;
+  // Although it is not spec compliant, many websites intentionally call
+  // Window.print() on display:none iframes. https://crbug.com/819327.
+  if (GetDocument().Printing())
+    return true;
   // A PluginDocument needs a layout tree during loading, even if it is inside a
   // display: none iframe.  This is because WebLocalFrameImpl::DidFinish expects
   // the PluginDocument's <embed> element to have an EmbeddedContentView, which
@@ -914,6 +918,12 @@
   return rect;
 }
 
+IntSize LayoutView::ScrolledContentOffset() const {
+  DCHECK(HasOverflowClip());
+  // FIXME: Return DoubleSize here. crbug.com/414283.
+  return GetScrollableArea()->ScrollOffsetInt();
+}
+
 bool LayoutView::UpdateLogicalWidthAndColumnWidth() {
   bool relayout_children = LayoutBlockFlow::UpdateLogicalWidthAndColumnWidth();
   // When we're printing, the size of LayoutView is changed outside of layout,
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.h b/third_party/WebKit/Source/core/layout/LayoutView.h
index 2600b60..01b55ac 100644
--- a/third_party/WebKit/Source/core/layout/LayoutView.h
+++ b/third_party/WebKit/Source/core/layout/LayoutView.h
@@ -249,6 +249,8 @@
 
   LayoutRect DebugRect() const override;
 
+  virtual IntSize ScrolledContentOffset() const;
+
  private:
   void MapLocalToAncestor(
       const LayoutBoxModelObject* ancestor,
diff --git a/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp b/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp
index 7ce3cb2..7e30287 100644
--- a/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp
+++ b/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp
@@ -482,44 +482,47 @@
   ScrollableArea* frame_scroller_area =
       frame_view->LayoutViewportScrollableArea();
 
+  // Scrollbars are hidden at start.
+  scroller_area->SetScrollbarsHiddenIfOverlay(true);
+  frame_scroller_area->SetScrollbarsHiddenIfOverlay(true);
   ASSERT_TRUE(scroller_area->HorizontalScrollbar());
   ASSERT_TRUE(scroller_area->VerticalScrollbar());
   ASSERT_TRUE(frame_scroller_area->HorizontalScrollbar());
   ASSERT_TRUE(frame_scroller_area->VerticalScrollbar());
 
-  EXPECT_FALSE(frame_scroller_area->ScrollbarsHidden());
-  EXPECT_TRUE(frame_scroller_area->HorizontalScrollbar()
-                  ->ShouldParticipateInHitTesting());
-  EXPECT_TRUE(frame_scroller_area->VerticalScrollbar()
-                  ->ShouldParticipateInHitTesting());
-
-  EXPECT_FALSE(scroller_area->ScrollbarsHidden());
-  EXPECT_TRUE(
-      scroller_area->HorizontalScrollbar()->ShouldParticipateInHitTesting());
-  EXPECT_TRUE(
-      scroller_area->VerticalScrollbar()->ShouldParticipateInHitTesting());
-
-  frame_scroller_area->SetScrollbarsHidden(true);
+  EXPECT_TRUE(frame_scroller_area->ScrollbarsHiddenIfOverlay());
   EXPECT_FALSE(frame_scroller_area->HorizontalScrollbar()
                    ->ShouldParticipateInHitTesting());
   EXPECT_FALSE(frame_scroller_area->VerticalScrollbar()
                    ->ShouldParticipateInHitTesting());
-  frame_scroller_area->SetScrollbarsHidden(false);
-  EXPECT_TRUE(frame_scroller_area->HorizontalScrollbar()
-                  ->ShouldParticipateInHitTesting());
-  EXPECT_TRUE(frame_scroller_area->VerticalScrollbar()
-                  ->ShouldParticipateInHitTesting());
 
-  scroller_area->SetScrollbarsHidden(true);
+  EXPECT_TRUE(scroller_area->ScrollbarsHiddenIfOverlay());
   EXPECT_FALSE(
       scroller_area->HorizontalScrollbar()->ShouldParticipateInHitTesting());
   EXPECT_FALSE(
       scroller_area->VerticalScrollbar()->ShouldParticipateInHitTesting());
-  scroller_area->SetScrollbarsHidden(false);
+
+  frame_scroller_area->SetScrollbarsHiddenIfOverlay(false);
+  EXPECT_TRUE(frame_scroller_area->HorizontalScrollbar()
+                  ->ShouldParticipateInHitTesting());
+  EXPECT_TRUE(frame_scroller_area->VerticalScrollbar()
+                  ->ShouldParticipateInHitTesting());
+  frame_scroller_area->SetScrollbarsHiddenIfOverlay(true);
+  EXPECT_FALSE(frame_scroller_area->HorizontalScrollbar()
+                   ->ShouldParticipateInHitTesting());
+  EXPECT_FALSE(frame_scroller_area->VerticalScrollbar()
+                   ->ShouldParticipateInHitTesting());
+
+  scroller_area->SetScrollbarsHiddenIfOverlay(false);
   EXPECT_TRUE(
       scroller_area->HorizontalScrollbar()->ShouldParticipateInHitTesting());
   EXPECT_TRUE(
       scroller_area->VerticalScrollbar()->ShouldParticipateInHitTesting());
+  scroller_area->SetScrollbarsHiddenIfOverlay(true);
+  EXPECT_FALSE(
+      scroller_area->HorizontalScrollbar()->ShouldParticipateInHitTesting());
+  EXPECT_FALSE(
+      scroller_area->VerticalScrollbar()->ShouldParticipateInHitTesting());
 }
 
 // Ensure mouse cursor should be pointer when hovering over the scrollbar.
@@ -587,6 +590,13 @@
 
   Compositor().BeginFrame();
 
+  // Enable the Scrollbar.
+  WebView()
+      .MainFrameImpl()
+      ->GetFrameView()
+      ->LayoutViewportScrollableArea()
+      ->SetScrollbarsHiddenIfOverlay(false);
+
   Document& document = GetDocument();
   Element* a_tag = document.getElementById("a");
 
@@ -622,7 +632,7 @@
       .MainFrameImpl()
       ->GetFrameView()
       ->LayoutViewportScrollableArea()
-      ->SetScrollbarsHidden(true);
+      ->SetScrollbarsHiddenIfOverlay(true);
 
   // Ensure hittest only has link
   hit_test_result = HitTest(18, a_tag->OffsetTop());
@@ -733,6 +743,13 @@
   )HTML");
   Compositor().BeginFrame();
 
+  // Enable the Scrollbar.
+  WebView()
+      .MainFrameImpl()
+      ->GetFrameView()
+      ->LayoutViewportScrollableArea()
+      ->SetScrollbarsHiddenIfOverlay(false);
+
   frame_resource.Complete("<!DOCTYPE html>");
   Compositor().BeginFrame();
 
@@ -769,7 +786,7 @@
       .MainFrameImpl()
       ->GetFrameView()
       ->LayoutViewportScrollableArea()
-      ->SetScrollbarsHidden(true);
+      ->SetScrollbarsHiddenIfOverlay(true);
 
   // Ensure hittest has IFRAME and no scrollbar.
   hit_test_result = HitTest(196, 5);
@@ -1198,42 +1215,42 @@
 
   DCHECK(!scrollable_area->UsesCompositedScrolling());
 
-  EXPECT_FALSE(scrollable_area->ScrollbarsHidden());
+  EXPECT_FALSE(scrollable_area->ScrollbarsHiddenIfOverlay());
   RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
-  EXPECT_TRUE(scrollable_area->ScrollbarsHidden());
+  EXPECT_TRUE(scrollable_area->ScrollbarsHiddenIfOverlay());
 
   scrollable_area->SetScrollOffset(ScrollOffset(10, 10), kProgrammaticScroll,
                                    kScrollBehaviorInstant);
 
-  EXPECT_FALSE(scrollable_area->ScrollbarsHidden());
+  EXPECT_FALSE(scrollable_area->ScrollbarsHiddenIfOverlay());
   RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
-  EXPECT_TRUE(scrollable_area->ScrollbarsHidden());
+  EXPECT_TRUE(scrollable_area->ScrollbarsHiddenIfOverlay());
 
   MainFrame().ExecuteScript(WebScriptSource(
       "document.getElementById('space').style.height = '500px';"));
   Compositor().BeginFrame();
 
-  EXPECT_TRUE(scrollable_area->ScrollbarsHidden());
+  EXPECT_TRUE(scrollable_area->ScrollbarsHiddenIfOverlay());
 
   MainFrame().ExecuteScript(WebScriptSource(
       "document.getElementById('container').style.height = '300px';"));
   Compositor().BeginFrame();
 
-  EXPECT_FALSE(scrollable_area->ScrollbarsHidden());
+  EXPECT_FALSE(scrollable_area->ScrollbarsHiddenIfOverlay());
   RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
-  EXPECT_TRUE(scrollable_area->ScrollbarsHidden());
+  EXPECT_TRUE(scrollable_area->ScrollbarsHiddenIfOverlay());
 
   // Non-composited scrollbars don't fade out while mouse is over.
   EXPECT_TRUE(scrollable_area->VerticalScrollbar());
   scrollable_area->SetScrollOffset(ScrollOffset(20, 20), kProgrammaticScroll,
                                    kScrollBehaviorInstant);
-  EXPECT_FALSE(scrollable_area->ScrollbarsHidden());
+  EXPECT_FALSE(scrollable_area->ScrollbarsHiddenIfOverlay());
   scrollable_area->MouseEnteredScrollbar(*scrollable_area->VerticalScrollbar());
   RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
-  EXPECT_FALSE(scrollable_area->ScrollbarsHidden());
+  EXPECT_FALSE(scrollable_area->ScrollbarsHiddenIfOverlay());
   scrollable_area->MouseExitedScrollbar(*scrollable_area->VerticalScrollbar());
   RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
-  EXPECT_TRUE(scrollable_area->ScrollbarsHidden());
+  EXPECT_TRUE(scrollable_area->ScrollbarsHiddenIfOverlay());
 
   mock_overlay_theme.SetOverlayScrollbarFadeOutDelay(0.0);
 }
@@ -1685,6 +1702,7 @@
 }
 
 TEST_P(ScrollbarsTest, MouseOverIFrameScrollbar) {
+  ScopedOverlayScrollbarsForTest overlay_scrollbars(false);
   WebView().Resize(WebSize(800, 600));
 
   SimRequest main_resource("https://example.com/test.html", "text/html");
diff --git a/third_party/WebKit/Source/core/layout/custom/CSSLayoutDefinition.h b/third_party/WebKit/Source/core/layout/custom/CSSLayoutDefinition.h
index a089fb9..e969f7c 100644
--- a/third_party/WebKit/Source/core/layout/custom/CSSLayoutDefinition.h
+++ b/third_party/WebKit/Source/core/layout/custom/CSSLayoutDefinition.h
@@ -50,6 +50,9 @@
 
     void Trace(blink::Visitor*);
     void TraceWrappers(const ScriptWrappableVisitor*) const override;
+    const char* NameInHeapSnapshot() const override {
+      return "CSSLayoutDefinition::Instance";
+    }
 
    private:
     Member<CSSLayoutDefinition> definition_;
@@ -81,6 +84,9 @@
 
   void Trace(blink::Visitor* visitor) {}
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "CSSLayoutDefinition";
+  }
 
  private:
   scoped_refptr<ScriptState> script_state_;
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp
index 87bd542..452560a 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp
@@ -136,18 +136,13 @@
     const FloatRect& object_bounding_box) {
   ClearInvalidationMask();
 
-  SVGPatternElement* pattern_element = ToSVGPatternElement(GetElement());
-  if (!pattern_element)
-    return SVGPaintServer::Invalid();
-
   // Validate pattern DOM state before building the actual
   // pattern. This should avoid tearing down the pattern we're
   // currently working on. Preferably the state validation should have
   // no side-effects though.
   if (should_collect_pattern_attributes_) {
-    pattern_element->SynchronizeAnimatedSVGAttribute(AnyQName());
-
     attributes_wrapper_->Set(PatternAttributes());
+    SVGPatternElement* pattern_element = ToSVGPatternElement(GetElement());
     pattern_element->CollectPatternAttributes(MutableAttributes());
     should_collect_pattern_attributes_ = false;
   }
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.h b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.h
index a4f09587..2879874 100644
--- a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.h
+++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerRegistry.h
@@ -28,6 +28,9 @@
   }
   void Trace(blink::Visitor*);
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "ModuleTreeLinkerRegistry";
+  }
 
   ModuleTreeLinker* Fetch(const ModuleScriptFetchRequest&,
                           Modulator*,
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index 4249662..932d1ac 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -892,7 +892,7 @@
 void PaintLayerScrollableArea::UpdateScrollbarEnabledState() {
   bool force_disable =
       GetPageScrollbarTheme().ShouldDisableInvisibleScrollbars() &&
-      ScrollbarsHidden();
+      ScrollbarsHiddenIfOverlay();
 
   if (HorizontalScrollbar())
     HorizontalScrollbar()->SetEnabled(HasHorizontalOverflow() &&
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
index bcd4e63..615e4346 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
@@ -881,7 +881,7 @@
   auto* scroller = GetLayoutObjectByElementId("scroller");
   auto* scrollable_area = ToLayoutBoxModelObject(scroller)->GetScrollableArea();
 
-  scrollable_area->SetScrollbarsHidden(true);
+  scrollable_area->SetScrollbarsHiddenIfOverlay(true);
 
   HitTestRequest hit_request(HitTestRequest::kMove | HitTestRequest::kReadOnly);
   HitTestResult hit_result(hit_request, LayoutPoint(95, 5));
@@ -891,7 +891,7 @@
   GetDocument().GetLayoutView()->HitTest(hit_result);
   EXPECT_EQ(hit_result.GetScrollbar(), nullptr);
 
-  scrollable_area->SetScrollbarsHidden(false);
+  scrollable_area->SetScrollbarsHiddenIfOverlay(false);
 
   hit_result = HitTestResult(hit_request, LayoutPoint(95, 5));
   GetDocument().GetLayoutView()->HitTest(hit_result);
diff --git a/third_party/WebKit/Source/core/script/HTMLParserScriptRunner.h b/third_party/WebKit/Source/core/script/HTMLParserScriptRunner.h
index 40fc83a..a47f4ed 100644
--- a/third_party/WebKit/Source/core/script/HTMLParserScriptRunner.h
+++ b/third_party/WebKit/Source/core/script/HTMLParserScriptRunner.h
@@ -99,6 +99,9 @@
 
   void Trace(blink::Visitor*) override;
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "HTMLParserScriptRunner";
+  }
 
  private:
   HTMLParserScriptRunner(HTMLParserReentryPermit*,
diff --git a/third_party/WebKit/Source/core/script/Modulator.h b/third_party/WebKit/Source/core/script/Modulator.h
index 610dda1..b17ac2a 100644
--- a/third_party/WebKit/Source/core/script/Modulator.h
+++ b/third_party/WebKit/Source/core/script/Modulator.h
@@ -43,6 +43,9 @@
   virtual ~SingleModuleClient() = default;
   virtual void Trace(blink::Visitor* visitor) {}
   void TraceWrappers(const ScriptWrappableVisitor*) const override {}
+  const char* NameInHeapSnapshot() const override {
+    return "SingleModuleClient";
+  }
 
   virtual void NotifyModuleLoadFinished(ModuleScript*) = 0;
 };
@@ -56,6 +59,7 @@
   virtual ~ModuleTreeClient() = default;
   virtual void Trace(blink::Visitor* visitor) {}
   void TraceWrappers(const ScriptWrappableVisitor*) const override {}
+  const char* NameInHeapSnapshot() const override { return "ModuleTreeClient"; }
 
   virtual void NotifyModuleTreeLoadFinished(ModuleScript*) = 0;
 };
@@ -83,6 +87,7 @@
 
   virtual void Trace(blink::Visitor* visitor) {}
   void TraceWrappers(const ScriptWrappableVisitor*) const override {}
+  const char* NameInHeapSnapshot() const override { return "Modulator"; }
 
   virtual ScriptModuleResolver* GetScriptModuleResolver() = 0;
   virtual base::SingleThreadTaskRunner* TaskRunner() = 0;
diff --git a/third_party/WebKit/Source/core/script/ModuleMap.cpp b/third_party/WebKit/Source/core/script/ModuleMap.cpp
index 538f6b9..973e77c 100644
--- a/third_party/WebKit/Source/core/script/ModuleMap.cpp
+++ b/third_party/WebKit/Source/core/script/ModuleMap.cpp
@@ -23,7 +23,8 @@
   ~Entry() override {}
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "ModuleMap::Entry"; }
 
   // Notify fetched |m_moduleScript| to the client asynchronously.
   void AddClient(SingleModuleClient*);
diff --git a/third_party/WebKit/Source/core/script/ModuleMap.h b/third_party/WebKit/Source/core/script/ModuleMap.h
index 3ce3a5c..00b2c17 100644
--- a/third_party/WebKit/Source/core/script/ModuleMap.h
+++ b/third_party/WebKit/Source/core/script/ModuleMap.h
@@ -33,7 +33,8 @@
     return new ModuleMap(modulator);
   }
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "ModuleMap"; }
 
   // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
   void FetchSingleModuleScript(const ModuleScriptFetchRequest&,
diff --git a/third_party/WebKit/Source/core/script/ModuleScript.h b/third_party/WebKit/Source/core/script/ModuleScript.h
index 0b419a9..5da11008 100644
--- a/third_party/WebKit/Source/core/script/ModuleScript.h
+++ b/third_party/WebKit/Source/core/script/ModuleScript.h
@@ -62,7 +62,8 @@
                               String* failure_reason = nullptr);
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "ModuleScript"; }
 
  private:
   ModuleScript(Modulator* settings_object,
diff --git a/third_party/WebKit/Source/core/script/PendingScript.h b/third_party/WebKit/Source/core/script/PendingScript.h
index 910aaf0..a36a5e4 100644
--- a/third_party/WebKit/Source/core/script/PendingScript.h
+++ b/third_party/WebKit/Source/core/script/PendingScript.h
@@ -83,6 +83,7 @@
 
   virtual void Trace(blink::Visitor*);
   void TraceWrappers(const ScriptWrappableVisitor*) const override {}
+  const char* NameInHeapSnapshot() const override { return "PendingScript"; }
 
   // Returns false if the script should not be run due to MIME type check.
   // Should be called just before GetSource().
diff --git a/third_party/WebKit/Source/core/script/ScriptLoader.h b/third_party/WebKit/Source/core/script/ScriptLoader.h
index 826d00f..448dc04 100644
--- a/third_party/WebKit/Source/core/script/ScriptLoader.h
+++ b/third_party/WebKit/Source/core/script/ScriptLoader.h
@@ -62,7 +62,8 @@
 
   ~ScriptLoader() override;
   virtual void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "ScriptLoader"; }
 
   enum LegacyTypeSupport {
     kDisallowLegacyTypeInTypeAttribute,
diff --git a/third_party/WebKit/Source/core/script/ScriptRunner.h b/third_party/WebKit/Source/core/script/ScriptRunner.h
index d1b9c3f..97895a5b 100644
--- a/third_party/WebKit/Source/core/script/ScriptRunner.h
+++ b/third_party/WebKit/Source/core/script/ScriptRunner.h
@@ -67,7 +67,8 @@
   static void MovePendingScript(Document&, Document&, ScriptLoader*);
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "ScriptRunner"; }
 
  private:
   class Task;
diff --git a/third_party/WebKit/Source/core/svg/SVGGradientElement.cpp b/third_party/WebKit/Source/core/svg/SVGGradientElement.cpp
index 9a6b762..1e85fab 100644
--- a/third_party/WebKit/Source/core/svg/SVGGradientElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGGradientElement.cpp
@@ -188,11 +188,8 @@
 
 const SVGGradientElement* SVGGradientElement::ReferencedElement() const {
   // Respect xlink:href, take attributes from referenced element.
-  Element* referenced_element =
-      TargetElementFromIRIString(HrefString(), GetTreeScope());
-  if (!referenced_element || !IsSVGGradientElement(*referenced_element))
-    return nullptr;
-  return ToSVGGradientElement(referenced_element);
+  return ToSVGGradientElementOrNull(
+      TargetElementFromIRIString(HrefString(), GetTreeScope()));
 }
 
 Vector<Gradient::ColorStop> SVGGradientElement::BuildStops() const {
diff --git a/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp b/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp
index 6d2fee4..a2df711 100644
--- a/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPatternElement.cpp
@@ -148,46 +148,56 @@
   return new LayoutSVGResourcePattern(this);
 }
 
-static void SetPatternAttributes(const SVGPatternElement* element,
+static void SetPatternAttributes(const SVGPatternElement& element,
                                  PatternAttributes& attributes) {
-  if (!attributes.HasX() && element->x()->IsSpecified())
-    attributes.SetX(element->x()->CurrentValue());
+  element.SynchronizeAnimatedSVGAttribute(AnyQName());
 
-  if (!attributes.HasY() && element->y()->IsSpecified())
-    attributes.SetY(element->y()->CurrentValue());
+  if (!attributes.HasX() && element.x()->IsSpecified())
+    attributes.SetX(element.x()->CurrentValue());
 
-  if (!attributes.HasWidth() && element->width()->IsSpecified())
-    attributes.SetWidth(element->width()->CurrentValue());
+  if (!attributes.HasY() && element.y()->IsSpecified())
+    attributes.SetY(element.y()->CurrentValue());
 
-  if (!attributes.HasHeight() && element->height()->IsSpecified())
-    attributes.SetHeight(element->height()->CurrentValue());
+  if (!attributes.HasWidth() && element.width()->IsSpecified())
+    attributes.SetWidth(element.width()->CurrentValue());
 
-  if (!attributes.HasViewBox() && element->HasValidViewBox())
-    attributes.SetViewBox(element->viewBox()->CurrentValue()->Value());
+  if (!attributes.HasHeight() && element.height()->IsSpecified())
+    attributes.SetHeight(element.height()->CurrentValue());
+
+  if (!attributes.HasViewBox() && element.HasValidViewBox())
+    attributes.SetViewBox(element.viewBox()->CurrentValue()->Value());
 
   if (!attributes.HasPreserveAspectRatio() &&
-      element->preserveAspectRatio()->IsSpecified())
+      element.preserveAspectRatio()->IsSpecified()) {
     attributes.SetPreserveAspectRatio(
-        element->preserveAspectRatio()->CurrentValue());
+        element.preserveAspectRatio()->CurrentValue());
+  }
 
-  if (!attributes.HasPatternUnits() && element->patternUnits()->IsSpecified())
+  if (!attributes.HasPatternUnits() && element.patternUnits()->IsSpecified()) {
     attributes.SetPatternUnits(
-        element->patternUnits()->CurrentValue()->EnumValue());
+        element.patternUnits()->CurrentValue()->EnumValue());
+  }
 
   if (!attributes.HasPatternContentUnits() &&
-      element->patternContentUnits()->IsSpecified())
+      element.patternContentUnits()->IsSpecified()) {
     attributes.SetPatternContentUnits(
-        element->patternContentUnits()->CurrentValue()->EnumValue());
+        element.patternContentUnits()->CurrentValue()->EnumValue());
+  }
 
   if (!attributes.HasPatternTransform() &&
-      element->HasTransform(SVGElement::kExcludeMotionTransform)) {
+      element.HasTransform(SVGElement::kExcludeMotionTransform)) {
     attributes.SetPatternTransform(
-        element->CalculateTransform(SVGElement::kExcludeMotionTransform));
+        element.CalculateTransform(SVGElement::kExcludeMotionTransform));
   }
 
   if (!attributes.HasPatternContentElement() &&
-      ElementTraversal::FirstWithin(*element))
-    attributes.SetPatternContentElement(element);
+      ElementTraversal::FirstWithin(element))
+    attributes.SetPatternContentElement(&element);
+}
+
+const SVGPatternElement* SVGPatternElement::ReferencedElement() const {
+  return ToSVGPatternElementOrNull(
+      TargetElementFromIRIString(HrefString(), GetTreeScope()));
 }
 
 void SVGPatternElement::CollectPatternAttributes(
@@ -196,19 +206,16 @@
   const SVGPatternElement* current = this;
 
   while (true) {
-    SetPatternAttributes(current, attributes);
+    SetPatternAttributes(*current, attributes);
     processed_patterns.insert(current);
 
-    // Respect xlink:href, take attributes from referenced element
-    Node* ref_node = SVGURIReference::TargetElementFromIRIString(
-        current->HrefString(), GetTreeScope());
+    // If (xlink:)href links to another SVGPatternElement, allow attributes
+    // from that element to override values this pattern didn't set.
+    current = current->ReferencedElement();
 
     // Only consider attached SVG pattern elements.
-    if (!IsSVGPatternElement(ref_node) || !ref_node->GetLayoutObject())
+    if (!current || !current->GetLayoutObject())
       break;
-
-    current = ToSVGPatternElement(ref_node);
-
     // Cycle detection
     if (processed_patterns.Contains(current))
       break;
diff --git a/third_party/WebKit/Source/core/svg/SVGPatternElement.h b/third_party/WebKit/Source/core/svg/SVGPatternElement.h
index 1cd2a8e..6d580ad 100644
--- a/third_party/WebKit/Source/core/svg/SVGPatternElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGPatternElement.h
@@ -89,6 +89,8 @@
   void SvgAttributeChanged(const QualifiedName&) override;
   void ChildrenChanged(const ChildrenChange&) override;
 
+  const SVGPatternElement* ReferencedElement() const;
+
   LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
 
   bool SelfHasRelativeLengths() const override;
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index e064a9ad..3b50610 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -3435,7 +3435,7 @@
 bool Internals::setScrollbarVisibilityInScrollableArea(Node* node,
                                                        bool visible) {
   if (ScrollableArea* scrollable_area = ScrollableAreaForNode(node)) {
-    scrollable_area->SetScrollbarsHidden(!visible);
+    scrollable_area->SetScrollbarsHiddenIfOverlay(!visible);
     scrollable_area->GetScrollAnimator().SetScrollbarsVisibleForTesting(
         visible);
     return scrollable_area->GetPageScrollbarTheme().UsesOverlayScrollbars();
diff --git a/third_party/WebKit/Source/core/testing/data/show_unhandled_tap.html b/third_party/WebKit/Source/core/testing/data/show_unhandled_tap.html
index fca4d227432..6955c2a 100644
--- a/third_party/WebKit/Source/core/testing/data/show_unhandled_tap.html
+++ b/third_party/WebKit/Source/core/testing/data/show_unhandled_tap.html
@@ -16,16 +16,25 @@
 :indeterminate + span {
   background-color: blue;
 }
+#large {
+  font-size: 20px;
+}
+#small {
+  font-size: 10px;
+}
 </style>
 </head>
 <body>
-<div style="position: absolute; left: 8px; top: 66px; width: 400px; height: 30px;">
+<div style="position: absolute; left: 8px; top: 66px; width: 400px; height: 350px;">
 <span id="target">This has multiple listeners.</span>
 <div id="mutate">This block gets mutated to change the DOM.</div>
 <div id="style_active">This block gets red if active</div>
-<input id="checkbox" type="checkbox"><span>indeterminate checkbox</span>
-<input id="editable" type="text" value="editable">
-<div id="focusable" tabindex="1">focusable</div>
+<input id="checkbox" type="checkbox"><span>indeterminate checkbox</span><br>
+<img id="image" width="10" height="10" src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="><br>
+<span id="editable" contenteditable="true">editable</span><br>
+<span id="focusable" tabindex="1">focusable</span><br>
+<span id="large">large</span><br>
+<span id="small">small</span><br>
 </div>
 
 <p style="position: absolute; left: 8px; top: 400px; width: 400px; height: 30px;"><span id="bottom">Bottom.</span></p>
@@ -33,14 +42,17 @@
 <script>
 var test;
 var mutations = 0;
+// Remembers which test to run.
 function setTest(whichTest) {
   test = whichTest;
 }
+// Determines if we currently have a test for the given event/handler pair.
 function hasTest(operation, handler) {
   var candidate = operation + '-' + handler;
   var result = test === candidate;
   return result;
 }
+// Our universal event handler.  Changes the page based on the stored operation.
 function handle(event) {
   var operation = event.type;
   if (hasTest(operation, 'mutateDom')) {
@@ -54,6 +66,7 @@
     event.preventDefault();
   }
 }
+// Set up $target to have the handle() handler for all tap-related events.
 var t = document.getElementById('target');
 t.addEventListener('mousedown', handle);
 t.addEventListener('mouseup', handle);
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
index 61a47485..166976e1 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
@@ -167,7 +167,8 @@
   DEFINE_ATTRIBUTE_EVENT_LISTENER(readystatechange);
 
   virtual void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "XMLHttpRequest"; }
 
  private:
   class BlobLoader;
diff --git a/third_party/WebKit/Source/modules/animationworklet/Animator.h b/third_party/WebKit/Source/modules/animationworklet/Animator.h
index 7fd1c62..0430309 100644
--- a/third_party/WebKit/Source/modules/animationworklet/Animator.h
+++ b/third_party/WebKit/Source/modules/animationworklet/Animator.h
@@ -29,6 +29,7 @@
   ~Animator();
   void Trace(blink::Visitor*);
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "Animator"; }
 
   // Returns true if it successfully invoked animate callback in JS. It receives
   // latest state coming from |AnimationHost| as input and fills
diff --git a/third_party/WebKit/Source/modules/animationworklet/AnimatorDefinition.h b/third_party/WebKit/Source/modules/animationworklet/AnimatorDefinition.h
index 2da1fd4..c8380e5 100644
--- a/third_party/WebKit/Source/modules/animationworklet/AnimatorDefinition.h
+++ b/third_party/WebKit/Source/modules/animationworklet/AnimatorDefinition.h
@@ -28,6 +28,9 @@
   ~AnimatorDefinition();
   void Trace(blink::Visitor* visitor) {}
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "AnimatorDefinition";
+  }
 
   v8::Local<v8::Function> ConstructorLocal(v8::Isolate*);
   v8::Local<v8::Function> AnimateLocal(v8::Isolate*);
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp
index d74d237..ceaf326 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp
@@ -1564,10 +1564,18 @@
     return nullptr;
 
   if (sw < 0) {
+    if (!WTF::CheckAdd(sx, sw).IsValid<int>()) {
+      exception_state.ThrowRangeError("Out of memory at ImageData creation");
+      return nullptr;
+    }
     sx += sw;
     sw = -sw;
   }
   if (sh < 0) {
+    if (!WTF::CheckAdd(sy, sh).IsValid<int>()) {
+      exception_state.ThrowRangeError("Out of memory at ImageData creation");
+      return nullptr;
+    }
     sy += sh;
     sh = -sh;
   }
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DAPITest.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DAPITest.cpp
index ec1fc28..eab8f3a 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DAPITest.cpp
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DAPITest.cpp
@@ -287,6 +287,24 @@
   EXPECT_EQ(kV8RangeError, exception_state.Code());
 }
 
+TEST_F(CanvasRenderingContext2DAPITest,
+       GetImageDataIntegerOverflowNegativeParams) {
+  CreateContext(kNonOpaque);
+  DummyExceptionStateForTesting exception_state;
+  ImageData* image_data = Context2d()->getImageData(
+      1, -2147483647, 1, -2147483647, exception_state);
+  EXPECT_EQ(nullptr, image_data);
+  EXPECT_TRUE(exception_state.HadException());
+  EXPECT_EQ(kV8RangeError, exception_state.Code());
+
+  exception_state.ClearException();
+  image_data = Context2d()->getImageData(-2147483647, 1, -2147483647, 1,
+                                         exception_state);
+  EXPECT_EQ(nullptr, image_data);
+  EXPECT_TRUE(exception_state.HadException());
+  EXPECT_EQ(kV8RangeError, exception_state.Code());
+}
+
 void ResetCanvasForAccessibilityRectTest(Document& document) {
   document.documentElement()->SetInnerHTMLFromString(R"HTML(
     <canvas id='canvas' style='position:absolute; top:0px; left:0px;
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h
index 8baf957..a65e7e7 100644
--- a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h
+++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h
@@ -73,6 +73,9 @@
 
   void Trace(blink::Visitor* visitor){};
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "CSSPaintDefinition";
+  }
 
  private:
   CSSPaintDefinition(
diff --git a/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h b/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h
index ff464ae1..2ff9211 100644
--- a/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h
+++ b/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h
@@ -77,6 +77,7 @@
 
   void Trace(blink::Visitor*) override;
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "LocalFileSystem"; }
 
  private:
   WebFileSystem* GetFileSystem() const;
diff --git a/third_party/WebKit/Source/modules/geolocation/GeoNotifier.h b/third_party/WebKit/Source/modules/geolocation/GeoNotifier.h
index 955e38f..4d295256 100644
--- a/third_party/WebKit/Source/modules/geolocation/GeoNotifier.h
+++ b/third_party/WebKit/Source/modules/geolocation/GeoNotifier.h
@@ -30,7 +30,8 @@
   }
   ~GeoNotifier() = default;
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "GeoNotifier"; }
 
   const PositionOptions& Options() const { return options_; }
 
diff --git a/third_party/WebKit/Source/modules/geolocation/GeolocationWatchers.h b/third_party/WebKit/Source/modules/geolocation/GeolocationWatchers.h
index e05fabc..5daac433 100644
--- a/third_party/WebKit/Source/modules/geolocation/GeolocationWatchers.h
+++ b/third_party/WebKit/Source/modules/geolocation/GeolocationWatchers.h
@@ -19,6 +19,9 @@
   GeolocationWatchers() = default;
   void Trace(blink::Visitor*);
   void TraceWrappers(const ScriptWrappableVisitor*) const;
+  const char* NameInHeapSnapshot() const override {
+    return "GeolocationWatchers";
+  }
 
   bool Add(int id, GeoNotifier*);
   GeoNotifier* Find(int id) const;
diff --git a/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.h b/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.h
index 06c9bb27..54c18aac 100644
--- a/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.h
+++ b/third_party/WebKit/Source/modules/geolocation/NavigatorGeolocation.h
@@ -44,7 +44,10 @@
   Geolocation* geolocation();
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "NavigatorGeolocation";
+  }
 
  private:
   explicit NavigatorGeolocation(Navigator&);
diff --git a/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h b/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h
index b52b2db..7951af4 100644
--- a/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h
+++ b/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h
@@ -56,6 +56,7 @@
 
   void Trace(blink::Visitor*) override;
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "IndexedDBClient"; }
 
   bool AllowIndexedDB(ExecutionContext*, const String& name);
 
diff --git a/third_party/WebKit/Source/modules/locks/LockManager.cpp b/third_party/WebKit/Source/modules/locks/LockManager.cpp
index 2bfcb3c..dee31e2 100644
--- a/third_party/WebKit/Source/modules/locks/LockManager.cpp
+++ b/third_party/WebKit/Source/modules/locks/LockManager.cpp
@@ -83,6 +83,9 @@
   void TraceWrappers(const ScriptWrappableVisitor* visitor) const override {
     visitor->TraceWrappers(callback_);
   }
+  const char* NameInHeapSnapshot() const override {
+    return "LockManager::LockRequestImpl";
+  }
 
   // Called to immediately close the pipe which signals the back-end,
   // unblocking further requests, without waiting for GC finalize the object.
diff --git a/third_party/WebKit/Source/modules/locks/NavigatorLocks.cpp b/third_party/WebKit/Source/modules/locks/NavigatorLocks.cpp
index de37487..25654ff 100644
--- a/third_party/WebKit/Source/modules/locks/NavigatorLocks.cpp
+++ b/third_party/WebKit/Source/modules/locks/NavigatorLocks.cpp
@@ -49,10 +49,14 @@
   // Wrapper tracing is needed for callbacks. The reference chain is
   // NavigatorLocksImpl -> LockManager -> LockRequestImpl ->
   // V8LockGrantedCallback.
-  void TraceWrappers(const ScriptWrappableVisitor* visitor) const {
+  void TraceWrappers(const ScriptWrappableVisitor* visitor) const override {
     visitor->TraceWrappers(lock_manager_);
   }
 
+  const char* NameInHeapSnapshot() const override {
+    return "NavigatorLocksImpl";
+  }
+
  private:
   explicit NavigatorLocksImpl(T& navigator) : Supplement<T>(navigator) {}
 
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
index 81cc7e9dc..03bfc34 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
@@ -243,8 +243,6 @@
 };
 
 // Observes changes to the HTMLMediaElement attributes that affect controls.
-// Currently only observes the disableRemotePlayback and disablePictureInPicture
-// attributes.
 class MediaControlsImpl::MediaElementMutationCallback
     : public MutationObserver::Delegate {
  public:
@@ -253,9 +251,9 @@
     MutationObserverInit init;
     init.setAttributeOldValue(true);
     init.setAttributes(true);
-    init.setAttributeFilter(
-        {HTMLNames::disableremoteplaybackAttr.ToString(),
-         HTMLNames::disablepictureinpictureAttr.ToString()});
+    init.setAttributeFilter({HTMLNames::disableremoteplaybackAttr.ToString(),
+                             HTMLNames::disablepictureinpictureAttr.ToString(),
+                             HTMLNames::posterAttr.ToString()});
     observer_->observe(&controls_->MediaElement(), init, ASSERT_NO_EXCEPTION);
   }
 
@@ -274,8 +272,9 @@
         continue;
 
       if (record->attributeName() ==
-          HTMLNames::disableremoteplaybackAttr.ToString())
+          HTMLNames::disableremoteplaybackAttr.ToString()) {
         controls_->RefreshCastButtonVisibilityWithoutUpdate();
+      }
 
       if (record->attributeName() ==
               HTMLNames::disablepictureinpictureAttr.ToString() &&
@@ -284,6 +283,9 @@
             ShouldShowPictureInPictureButton(controls_->MediaElement()));
       }
 
+      if (record->attributeName() == HTMLNames::posterAttr.ToString())
+        controls_->UpdateCSSClassFromState();
+
       BatchedControlUpdate batch(controls_);
     }
   }
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.cpp
index 045a1c0..02bf2de 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.cpp
@@ -24,7 +24,6 @@
 #include "core/style/ComputedStyle.h"
 #include "modules/media_controls/MediaControlsImpl.h"
 #include "modules/media_controls/MediaControlsResourceLoader.h"
-#include "modules/media_controls/elements/MediaControlCurrentTimeDisplayElement.h"
 #include "modules/media_controls/elements/MediaControlElementsHelper.h"
 #include "platform/runtime_enabled_features.h"
 #include "public/platform/Platform.h"
@@ -52,8 +51,6 @@
 // MediaControlTimelineElement
 //   (-webkit-media-controls-timeline)
 // +-div#thumb (created by the HTMLSliderElement)
-//  +-MediaControlCurrentTimeDisplayElement#thumb-current-time
-//    {if IsModern() and IsHTMLVideoElement()}
 //
 //   The child elements are only present if MediaControlsImpl::IsModern() is
 //   enabled. These three <div>'s are used to show the buffering animation.
@@ -63,8 +60,7 @@
 // +-HTMLStyleElement
 MediaControlTimelineElement::MediaControlTimelineElement(
     MediaControlsImpl& media_controls)
-    : MediaControlSliderElement(media_controls, kMediaSlider),
-      current_time_display_(nullptr) {
+    : MediaControlSliderElement(media_controls, kMediaSlider) {
   SetShadowPseudoId(AtomicString("-webkit-media-controls-timeline"));
 
   if (MediaControlsImpl::IsModern()) {
@@ -76,21 +72,6 @@
     MediaControlElementsHelper::CreateDiv("-internal-track-segment-buffering",
                                           &track);
 
-    // Create the current time scrubbing element.
-    if (MediaElement().IsHTMLVideoElement()) {
-      Element* thumb = track.getElementById("thumb");
-      DCHECK(thumb);
-
-      // The time display should have a have a timeline-specific pseudo ID. This
-      // is to ensure it does not pick up styles from the current time display.
-      current_time_display_ =
-          new MediaControlCurrentTimeDisplayElement(GetMediaControls());
-      current_time_display_->setAttribute(
-          "pseudo", "-internal-media-controls-thumb-current-time");
-      current_time_display_->SetIsWanted(false);
-      thumb->AppendChild(current_time_display_);
-    }
-
     // This stylesheet element contains rules that cannot be present in the UA
     // stylesheet (e.g. animations).
     auto* style = HTMLStyleElement::Create(GetDocument(), CreateElementFlags());
@@ -142,17 +123,11 @@
         ShadowElementNames::SliderThumb());
     bool started_from_thumb = thumb && thumb == event->target()->ToNode();
     metrics_.StartGesture(started_from_thumb);
-
-    if (current_time_display_)
-      current_time_display_->SetIsWanted(true);
   } else if (EndScrubbingEvent(*event)) {
     Platform::Current()->RecordAction(
         UserMetricsAction("Media.Controls.ScrubbingEnd"));
     GetMediaControls().EndScrubbing();
     metrics_.RecordEndGesture(TrackWidth(), MediaElement().duration());
-
-    if (current_time_display_)
-      current_time_display_->SetIsWanted(false);
   }
 
   if (event->type() == EventTypeNames::keydown) {
@@ -183,22 +158,6 @@
   }
 
   double time = value().ToDouble();
-
-  // Update the scrubbing UI with the current time.
-  if (current_time_display_) {
-    current_time_display_->SetCurrentValue(time);
-
-    // Set the margin left based on the new width of the text so we are
-    // correctly centered.
-    if (LayoutBox* box = current_time_display_->GetLayoutBox()) {
-      String margin_left =
-          WTF::String::Number(ceil(box->LogicalWidth().Round() / 2) * -1) +
-          "px";
-      current_time_display_->style()->setProperty(
-          &GetDocument(), "margin-left", margin_left, "", ASSERT_NO_EXCEPTION);
-    }
-  }
-
   double duration = MediaElement().duration();
   // Workaround for floating point error - it's possible for this element's max
   // attribute to be rounded to a value slightly higher than the duration. If
@@ -294,7 +253,6 @@
 
 void MediaControlTimelineElement::Trace(blink::Visitor* visitor) {
   MediaControlSliderElement::Trace(visitor);
-  visitor->Trace(current_time_display_);
 }
 
 bool MediaControlTimelineElement::BeginScrubbingEvent(Event& event) {
@@ -313,8 +271,6 @@
 
   // End scrubbing state.
   is_touching_ = false;
-  if (current_time_display_)
-    current_time_display_->SetIsWanted(false);
 }
 
 void MediaControlTimelineElement::OnControlsShown() {
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.h
index 371db2fe..ccbded5d2 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.h
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlTimelineElement.h
@@ -13,7 +13,6 @@
 
 class Event;
 class HTMLDivElement;
-class MediaControlCurrentTimeDisplayElement;
 class MediaControlsImpl;
 
 class MediaControlTimelineElement : public MediaControlSliderElement {
@@ -56,8 +55,6 @@
 
   MediaControlTimelineMetrics metrics_;
 
-  Member<MediaControlCurrentTimeDisplayElement> current_time_display_;
-
   bool is_touching_ = false;
 
   bool controls_hidden_ = false;
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css b/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
index 4e4ca9e..fa5c0f0 100644
--- a/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
+++ b/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
@@ -333,28 +333,6 @@
   box-shadow: 0 2px 10px 0 rgba(0,0,0,0.5);
 }
 
-/* thumb-current-time CSS here instead of in the scoped CSS so we can hide on
- * audio-only. */
-input[pseudo="-webkit-media-controls-timeline" i]::-internal-media-controls-thumb-current-time {
-  position: absolute;
-  height: 16px;
-  left: 5px;
-  bottom: 16px;
-  padding: 4px 12px;
-  opacity: 0.9;
-  background: #FFFFFF;
-  border-radius: 100px;
-  font-family: Roboto-Regular, Roboto, sans-serif;
-  font-size: 14px;
-  color: #000000;
-  letter-spacing: 0;
-  text-shadow: 0 0 10px #FFFFFF;
-}
-
-video::-webkit-media-controls.audio-only input[pseudo="-webkit-media-controls-timeline"]::-internal-media-controls-thumb-current-time {
-  display: none;
-}
-
 input[pseudo="-webkit-media-controls-timeline" i]::-webkit-slider-thumb {
   -webkit-appearance: -internal-media-control;
   background: rgba(0, 0, 0, .87);
@@ -694,7 +672,6 @@
   color: #FFFFFF;
 }
 
-.state-scrubbing div[pseudo="-internal-media-controls-button-panel" i],
 .state-scrubbing input[pseudo="-webkit-media-controls-overlay-play-button" i] {
   display: none;
 }
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp b/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp
index ec6fe9e..509434e0 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/MediaDevices.cpp
@@ -21,6 +21,7 @@
 #include "modules/mediastream/UserMediaRequest.h"
 #include "platform/bindings/ScriptState.h"
 #include "platform/wtf/Functional.h"
+#include "public/platform/Platform.h"
 #include "public/platform/TaskType.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 
@@ -81,6 +82,7 @@
 MediaDevices::~MediaDevices() = default;
 
 ScriptPromise MediaDevices::enumerateDevices(ScriptState* script_state) {
+  Platform::Current()->UpdateWebRTCAPICount(WebRTCAPIName::kEnumerateDevices);
   LocalFrame* frame =
       ToDocument(ExecutionContext::From(script_state))->GetFrame();
   if (!frame) {
diff --git a/third_party/WebKit/Source/modules/remoteplayback/AvailabilityCallbackWrapper.h b/third_party/WebKit/Source/modules/remoteplayback/AvailabilityCallbackWrapper.h
index 850d34f..61d6b8d 100644
--- a/third_party/WebKit/Source/modules/remoteplayback/AvailabilityCallbackWrapper.h
+++ b/third_party/WebKit/Source/modules/remoteplayback/AvailabilityCallbackWrapper.h
@@ -33,7 +33,10 @@
   void Run(RemotePlayback*, bool new_availability);
 
   virtual void Trace(blink::Visitor*);
-  virtual void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "AvailabilityCallbackWrapper";
+  }
 
  private:
   // Only one of these callbacks must be set.
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.h
index 1be7d3b..b54c54f 100644
--- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.h
+++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerContainerClient.h
@@ -49,6 +49,10 @@
     Supplement<WorkerClients>::TraceWrappers(visitor);
   }
 
+  const char* NameInHeapSnapshot() const override {
+    return "ServiceWorkerContainerClient";
+  }
+
  private:
   std::unique_ptr<WebServiceWorkerProvider> provider_;
 };
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorDefinition.h b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorDefinition.h
index 3bd7eb4..46f833a 100644
--- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorDefinition.h
+++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletProcessorDefinition.h
@@ -49,7 +49,10 @@
   void Trace(blink::Visitor* visitor) {
     visitor->Trace(audio_param_descriptors_);
   };
-  void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "AudioWorkletProcessorDefinition";
+  }
 
  private:
   AudioWorkletProcessorDefinition(
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLContextGroup.h b/third_party/WebKit/Source/modules/webgl/WebGLContextGroup.h
index 872034a..e350d1a 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLContextGroup.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLContextGroup.h
@@ -63,7 +63,10 @@
 
   void Trace(blink::Visitor* visitor) { visitor->Trace(contexts_); }
 
-  virtual void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "WebGLContextGroup";
+  }
 
  private:
   friend class WebGLObject;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp
index 64dabf0..5ce9001 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp
@@ -40,9 +40,10 @@
   static WebGLFramebuffer::WebGLAttachment* Create(WebGLRenderbuffer*);
 
   virtual void Trace(blink::Visitor*);
-  virtual void TraceWrappers(const ScriptWrappableVisitor* visitor) const {
+  void TraceWrappers(const ScriptWrappableVisitor* visitor) const override {
     visitor->TraceWrappers(renderbuffer_);
   }
+  const char* NameInHeapSnapshot() const override { return "WebGLAttachment"; }
 
  private:
   explicit WebGLRenderbufferAttachment(WebGLRenderbuffer*);
@@ -113,9 +114,12 @@
                                                    GLint layer);
 
   virtual void Trace(blink::Visitor*);
-  virtual void TraceWrappers(const ScriptWrappableVisitor* visitor) const {
+  void TraceWrappers(const ScriptWrappableVisitor* visitor) const override {
     visitor->TraceWrappers(texture_);
   }
+  const char* NameInHeapSnapshot() const override {
+    return "WebGLTextureAttachment";
+  }
 
  private:
   WebGLTextureAttachment(WebGLTexture*,
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h
index d7fc1a1..78078958 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.h
@@ -117,7 +117,8 @@
   GLenum GetReadBuffer() const { return read_buffer_; }
 
   virtual void Trace(blink::Visitor*);
-  virtual void TraceWrappers(const ScriptWrappableVisitor*) const;
+  void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override { return "WebGLFramebuffer"; }
 
  protected:
   explicit WebGLFramebuffer(WebGLRenderingContextBase*, bool opaque);
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
index ff5878f..f5d404b 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
+++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
@@ -842,6 +842,9 @@
 
     virtual void Trace(blink::Visitor* visitor) {}
     void TraceWrappers(const ScriptWrappableVisitor*) const override {}
+    const char* NameInHeapSnapshot() const override {
+      return "ExtensionTracker";
+    }
 
    private:
     bool draft_;
diff --git a/third_party/WebKit/Source/modules/websockets/DEPS b/third_party/WebKit/Source/modules/websockets/DEPS
index 5b2f1f8..c37370d 100644
--- a/third_party/WebKit/Source/modules/websockets/DEPS
+++ b/third_party/WebKit/Source/modules/websockets/DEPS
@@ -5,5 +5,4 @@
     "+modules/ModulesExport.h",
     "+modules/websockets",
     "+mojo/public/cpp/bindings",
-    "+services/network/public/mojom/websocket.mojom-blink.h",
 ]
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
index 1da16c5..af64deb 100644
--- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
@@ -200,10 +200,9 @@
   DCHECK(!blob_loader_);
 }
 
-bool DocumentWebSocketChannel::Connect(
-    const KURL& url,
-    const String& protocol,
-    network::mojom::blink::WebSocketPtr socket_ptr) {
+bool DocumentWebSocketChannel::Connect(const KURL& url,
+                                       const String& protocol,
+                                       mojom::blink::WebSocketPtr socket_ptr) {
   NETWORK_DVLOG(1) << this << " Connect()";
   if (!handle_)
     return false;
@@ -287,7 +286,7 @@
 
 bool DocumentWebSocketChannel::Connect(const KURL& url,
                                        const String& protocol) {
-  network::mojom::blink::WebSocketPtr socket_ptr;
+  mojom::blink::WebSocketPtr socket_ptr;
   auto socket_request = mojo::MakeRequest(&socket_ptr);
   if (GetDocument() && GetDocument()->GetFrame()) {
     GetDocument()->GetFrame()->GetInterfaceProvider().GetInterface(
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h
index 411a6c29..6d83b098 100644
--- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h
+++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h
@@ -51,7 +51,7 @@
 #include "platform/wtf/text/CString.h"
 #include "platform/wtf/text/WTFString.h"
 #include "public/platform/WebCallbacks.h"
-#include "services/network/public/mojom/websocket.mojom-blink.h"
+#include "public/platform/modules/websockets/websocket.mojom-blink.h"
 
 namespace blink {
 
@@ -91,9 +91,7 @@
 
   // Allows the caller to provide the Mojo pipe through which the socket is
   // connected, overriding the interface provider of the Document.
-  bool Connect(const KURL&,
-               const String& protocol,
-               network::mojom::blink::WebSocketPtr);
+  bool Connect(const KURL&, const String& protocol, mojom::blink::WebSocketPtr);
 
   // WebSocketChannel functions.
   bool Connect(const KURL&, const String& protocol) override;
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
index f293594..bc43a54 100644
--- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
@@ -82,8 +82,8 @@
 
   ~MockWebSocketHandle() override = default;
 
-  MOCK_METHOD1(DoInitialize, void(network::mojom::blink::WebSocketPtr*));
-  void Initialize(network::mojom::blink::WebSocketPtr websocket) override {
+  MOCK_METHOD1(DoInitialize, void(mojom::blink::WebSocketPtr*));
+  void Initialize(mojom::blink::WebSocketPtr websocket) override {
     DoInitialize(&websocket);
   }
 
diff --git a/third_party/WebKit/Source/modules/websockets/WebSocketHandle.h b/third_party/WebKit/Source/modules/websockets/WebSocketHandle.h
index c939970..959149a9 100644
--- a/third_party/WebKit/Source/modules/websockets/WebSocketHandle.h
+++ b/third_party/WebKit/Source/modules/websockets/WebSocketHandle.h
@@ -35,7 +35,7 @@
 #include "base/single_thread_task_runner.h"
 #include "platform/wtf/Forward.h"
 #include "platform/wtf/Vector.h"
-#include "services/network/public/mojom/websocket.mojom-blink.h"
+#include "public/platform/modules/websockets/websocket.mojom-blink.h"
 
 namespace blink {
 
@@ -60,7 +60,7 @@
 
   virtual ~WebSocketHandle() = default;
 
-  virtual void Initialize(network::mojom::blink::WebSocketPtr) = 0;
+  virtual void Initialize(mojom::blink::WebSocketPtr) = 0;
   virtual void Connect(const KURL&,
                        const Vector<String>& protocols,
                        const KURL& site_for_cookies,
diff --git a/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp b/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp
index f0b1154..3df5e8b1 100644
--- a/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp
+++ b/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp
@@ -34,8 +34,7 @@
     websocket_->StartClosingHandshake(kAbnormalShutdownOpCode, g_empty_string);
 }
 
-void WebSocketHandleImpl::Initialize(
-    network::mojom::blink::WebSocketPtr websocket) {
+void WebSocketHandleImpl::Initialize(mojom::blink::WebSocketPtr websocket) {
   NETWORK_DVLOG(1) << this << " initialize(...)";
 
   DCHECK(!websocket_);
@@ -58,7 +57,7 @@
   DCHECK(client);
   client_ = client;
 
-  network::mojom::blink::WebSocketClientPtr client_proxy;
+  mojom::blink::WebSocketClientPtr client_proxy;
   client_binding_.Bind(mojo::MakeRequest(&client_proxy, task_runner));
   websocket_->AddChannelRequest(
       url, protocols, site_for_cookies,
@@ -72,16 +71,16 @@
                                size_t size) {
   DCHECK(websocket_);
 
-  network::mojom::blink::WebSocketMessageType type_to_pass;
+  mojom::blink::WebSocketMessageType type_to_pass;
   switch (type) {
     case WebSocketHandle::kMessageTypeContinuation:
-      type_to_pass = network::mojom::blink::WebSocketMessageType::CONTINUATION;
+      type_to_pass = mojom::blink::WebSocketMessageType::CONTINUATION;
       break;
     case WebSocketHandle::kMessageTypeText:
-      type_to_pass = network::mojom::blink::WebSocketMessageType::TEXT;
+      type_to_pass = mojom::blink::WebSocketMessageType::TEXT;
       break;
     case WebSocketHandle::kMessageTypeBinary:
-      type_to_pass = network::mojom::blink::WebSocketMessageType::BINARY;
+      type_to_pass = mojom::blink::WebSocketMessageType::BINARY;
       break;
     default:
       NOTREACHED();
@@ -125,8 +124,7 @@
   // Our connection to the WebSocket was dropped. This could be due to
   // exceeding the maximum number of concurrent websockets from this process.
   String failure_message;
-  if (custom_reason ==
-      network::mojom::blink::WebSocket::kInsufficientResources) {
+  if (custom_reason == mojom::blink::WebSocket::kInsufficientResources) {
     failure_message =
         description.empty()
             ? "Insufficient resources"
@@ -151,14 +149,14 @@
 }
 
 void WebSocketHandleImpl::OnStartOpeningHandshake(
-    network::mojom::blink::WebSocketHandshakeRequestPtr request) {
+    mojom::blink::WebSocketHandshakeRequestPtr request) {
   NETWORK_DVLOG(1) << this << " OnStartOpeningHandshake("
                    << request->url.GetString() << ")";
 
   scoped_refptr<WebSocketHandshakeRequest> request_to_pass =
       WebSocketHandshakeRequest::Create(request->url);
   for (size_t i = 0; i < request->headers.size(); ++i) {
-    const network::mojom::blink::HttpHeaderPtr& header = request->headers[i];
+    const mojom::blink::HttpHeaderPtr& header = request->headers[i];
     request_to_pass->AddHeaderField(AtomicString(header->name),
                                     AtomicString(header->value));
   }
@@ -167,7 +165,7 @@
 }
 
 void WebSocketHandleImpl::OnFinishOpeningHandshake(
-    network::mojom::blink::WebSocketHandshakeResponsePtr response) {
+    mojom::blink::WebSocketHandshakeResponsePtr response) {
   NETWORK_DVLOG(1) << this << " OnFinishOpeningHandshake("
                    << response->url.GetString() << ")";
 
@@ -175,7 +173,7 @@
   response_to_pass.SetStatusCode(response->status_code);
   response_to_pass.SetStatusText(response->status_text);
   for (size_t i = 0; i < response->headers.size(); ++i) {
-    const network::mojom::blink::HttpHeaderPtr& header = response->headers[i];
+    const mojom::blink::HttpHeaderPtr& header = response->headers[i];
     response_to_pass.AddHeaderField(AtomicString(header->name),
                                     AtomicString(header->value));
   }
@@ -195,10 +193,9 @@
   // |this| can be deleted here.
 }
 
-void WebSocketHandleImpl::OnDataFrame(
-    bool fin,
-    network::mojom::blink::WebSocketMessageType type,
-    const Vector<uint8_t>& data) {
+void WebSocketHandleImpl::OnDataFrame(bool fin,
+                                      mojom::blink::WebSocketMessageType type,
+                                      const Vector<uint8_t>& data) {
   NETWORK_DVLOG(1) << this << " OnDataFrame(" << fin << ", " << type << ", "
                    << "(data size = " << data.size() << "))";
   if (!client_)
@@ -207,13 +204,13 @@
   WebSocketHandle::MessageType type_to_pass =
       WebSocketHandle::kMessageTypeContinuation;
   switch (type) {
-    case network::mojom::blink::WebSocketMessageType::CONTINUATION:
+    case mojom::blink::WebSocketMessageType::CONTINUATION:
       type_to_pass = WebSocketHandle::kMessageTypeContinuation;
       break;
-    case network::mojom::blink::WebSocketMessageType::TEXT:
+    case mojom::blink::WebSocketMessageType::TEXT:
       type_to_pass = WebSocketHandle::kMessageTypeText;
       break;
-    case network::mojom::blink::WebSocketMessageType::BINARY:
+    case mojom::blink::WebSocketMessageType::BINARY:
       type_to_pass = WebSocketHandle::kMessageTypeBinary;
       break;
   }
diff --git a/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.h b/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.h
index 1c5ebac2..db8fe9fb 100644
--- a/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.h
+++ b/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.h
@@ -33,17 +33,17 @@
 
 #include "modules/websockets/WebSocketHandle.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "services/network/public/mojom/websocket.mojom-blink.h"
+#include "public/platform/modules/websockets/websocket.mojom-blink.h"
 
 namespace blink {
 
 class WebSocketHandleImpl : public WebSocketHandle,
-                            public network::mojom::blink::WebSocketClient {
+                            public mojom::blink::WebSocketClient {
  public:
   WebSocketHandleImpl();
   ~WebSocketHandleImpl() override;
 
-  void Initialize(network::mojom::blink::WebSocketPtr) override;
+  void Initialize(mojom::blink::WebSocketPtr) override;
   void Connect(const KURL&,
                const Vector<String>& protocols,
                const KURL& site_for_cookies,
@@ -59,16 +59,16 @@
   void OnConnectionError(uint32_t custom_reason,
                          const std::string& description);
 
-  // network::mojom::blink::WebSocketClient methods:
+  // mojom::blink::WebSocketClient methods:
   void OnFailChannel(const String& reason) override;
   void OnStartOpeningHandshake(
-      network::mojom::blink::WebSocketHandshakeRequestPtr) override;
+      mojom::blink::WebSocketHandshakeRequestPtr) override;
   void OnFinishOpeningHandshake(
-      network::mojom::blink::WebSocketHandshakeResponsePtr) override;
+      mojom::blink::WebSocketHandshakeResponsePtr) override;
   void OnAddChannelResponse(const String& selected_protocol,
                             const String& extensions) override;
   void OnDataFrame(bool fin,
-                   network::mojom::blink::WebSocketMessageType,
+                   mojom::blink::WebSocketMessageType,
                    const Vector<uint8_t>& data) override;
   void OnFlowControl(int64_t quota) override;
   void OnDropChannel(bool was_clean,
@@ -78,8 +78,8 @@
 
   WebSocketHandleClient* client_;
 
-  network::mojom::blink::WebSocketPtr websocket_;
-  mojo::Binding<network::mojom::blink::WebSocketClient> client_binding_;
+  mojom::blink::WebSocketPtr websocket_;
+  mojo::Binding<mojom::blink::WebSocketClient> client_binding_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
index f1c8994..ad09763 100644
--- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
+++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
@@ -184,10 +184,9 @@
   return true;
 }
 
-bool MainChannelClient::Connect(
-    const KURL& url,
-    const String& protocol,
-    network::mojom::blink::WebSocketPtr socket_ptr) {
+bool MainChannelClient::Connect(const KURL& url,
+                                const String& protocol,
+                                mojom::blink::WebSocketPtr socket_ptr) {
   DCHECK(IsMainThread());
   if (!main_channel_)
     return false;
@@ -383,7 +382,7 @@
     WorkerThreadLifecycleContext* worker_thread_lifecycle_context,
     const KURL& url,
     const String& protocol,
-    network::mojom::blink::WebSocketPtrInfo socket_ptr_info,
+    mojom::blink::WebSocketPtrInfo socket_ptr_info,
     WebSocketChannelSyncHelper* sync_helper) {
   DCHECK(IsMainThread());
   DCHECK(!main_channel_client_);
@@ -413,7 +412,7 @@
   // document and so can make requests using that context. In the case of
   // https://crbug.com/760708 for example this is necessary to apply the user's
   // SSL interstitial decision to WebSocket connections from the worker.
-  network::mojom::blink::WebSocketPtrInfo socket_ptr_info;
+  mojom::blink::WebSocketPtrInfo socket_ptr_info;
   if (!worker_global_scope_->IsDedicatedWorkerGlobalScope()) {
     worker_global_scope_->GetInterfaceProvider()->GetInterface(
         mojo::MakeRequest(&socket_ptr_info));
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
index 2e9f09b8..c38f99b 100644
--- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
+++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
@@ -46,7 +46,7 @@
 #include "platform/wtf/Forward.h"
 #include "platform/wtf/Vector.h"
 #include "platform/wtf/text/WTFString.h"
-#include "services/network/public/mojom/websocket.mojom-blink.h"
+#include "public/platform/modules/websockets/websocket.mojom-blink.h"
 
 namespace blink {
 
@@ -115,7 +115,7 @@
 
     bool Connect(const KURL&,
                  const String& protocol,
-                 network::mojom::blink::WebSocketPtr);
+                 mojom::blink::WebSocketPtr);
     void SendTextAsCharVector(std::unique_ptr<Vector<char>>);
     void SendBinaryAsCharVector(std::unique_ptr<Vector<char>>);
     void SendBlob(scoped_refptr<BlobDataHandle>);
@@ -182,7 +182,7 @@
                              WorkerThreadLifecycleContext*,
                              const KURL&,
                              const String& protocol,
-                             network::mojom::blink::WebSocketPtrInfo,
+                             mojom::blink::WebSocketPtrInfo,
                              WebSocketChannelSyncHelper*);
 
     // Returns null when |disconnect| has already been called.
diff --git a/third_party/WebKit/Source/modules/xr/XRFrameRequestCallbackCollection.h b/third_party/WebKit/Source/modules/xr/XRFrameRequestCallbackCollection.h
index 94970aa9..1e41d0c 100644
--- a/third_party/WebKit/Source/modules/xr/XRFrameRequestCallbackCollection.h
+++ b/third_party/WebKit/Source/modules/xr/XRFrameRequestCallbackCollection.h
@@ -29,7 +29,10 @@
   bool IsEmpty() const { return !callbacks_.size(); }
 
   void Trace(blink::Visitor*);
-  void TraceWrappers(const blink::ScriptWrappableVisitor*) const;
+  void TraceWrappers(const blink::ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "XRFrameRequestCallbackCollection";
+  }
 
  private:
   bool IsValidCallbackId(int id) {
diff --git a/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h b/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h
index d5b59a2..c532d2b 100644
--- a/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h
+++ b/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h
@@ -42,10 +42,8 @@
                                 float* dest_p,
                                 int dest_stride,
                                 size_t frames_to_process) {
-  vDSP_vclip(const_cast<float*>(source_p), source_stride,
-             const_cast<float*>(low_threshold_p),
-             const_cast<float*>(high_threshold_p), dest_p, dest_stride,
-             frames_to_process);
+  vDSP_vclip(source_p, source_stride, low_threshold_p, high_threshold_p, dest_p,
+             dest_stride, frames_to_process);
 }
 
 static ALWAYS_INLINE void Vmaxmgv(const float* source_p,
@@ -100,8 +98,7 @@
                                  int source_stride,
                                  float* sum_p,
                                  size_t frames_to_process) {
-  vDSP_svesq(const_cast<float*>(source_p), source_stride, sum_p,
-             frames_to_process);
+  vDSP_svesq(source_p, source_stride, sum_p, frames_to_process);
 }
 
 static ALWAYS_INLINE void Zvmul(const float* real1p,
diff --git a/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h b/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h
index e589933..76e919b 100644
--- a/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h
+++ b/third_party/WebKit/Source/platform/bindings/CallbackFunctionBase.h
@@ -31,6 +31,9 @@
 
   virtual void Trace(blink::Visitor* visitor) {}
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "CallbackFunctionBase";
+  }
 
   v8::Isolate* GetIsolate() const {
     return callback_relevant_script_state_->GetIsolate();
diff --git a/third_party/WebKit/Source/platform/bindings/CallbackInterfaceBase.h b/third_party/WebKit/Source/platform/bindings/CallbackInterfaceBase.h
index 12cfcf2..84a51784 100644
--- a/third_party/WebKit/Source/platform/bindings/CallbackInterfaceBase.h
+++ b/third_party/WebKit/Source/platform/bindings/CallbackInterfaceBase.h
@@ -38,6 +38,9 @@
 
   virtual void Trace(blink::Visitor*) {}
   void TraceWrappers(const ScriptWrappableVisitor*) const override;
+  const char* NameInHeapSnapshot() const override {
+    return "CallbackInterfaceBase";
+  }
 
   v8::Isolate* GetIsolate() {
     return callback_relevant_script_state_->GetIsolate();
diff --git a/third_party/WebKit/Source/platform/bindings/TraceWrapperBase.h b/third_party/WebKit/Source/platform/bindings/TraceWrapperBase.h
index e0ef9083..9d4153b6 100644
--- a/third_party/WebKit/Source/platform/bindings/TraceWrapperBase.h
+++ b/third_party/WebKit/Source/platform/bindings/TraceWrapperBase.h
@@ -24,7 +24,7 @@
 
   // Human-readable name of this object. The DevTools heap snapshot uses
   // this method to show the object.
-  virtual const char* NameInHeapSnapshot() const { return "UnknownNode"; }
+  virtual const char* NameInHeapSnapshot() const = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/bindings/TraceWrapperV8String.h b/third_party/WebKit/Source/platform/bindings/TraceWrapperV8String.h
index 6232119..eb401d2 100644
--- a/third_party/WebKit/Source/platform/bindings/TraceWrapperV8String.h
+++ b/third_party/WebKit/Source/platform/bindings/TraceWrapperV8String.h
@@ -35,6 +35,9 @@
   void TraceWrappers(const ScriptWrappableVisitor* visitor) const override {
     visitor->TraceWrappers(string_);
   }
+  const char* NameInHeapSnapshot() const override {
+    return "TraceWrapperV8String";
+  }
 
  private:
   TraceWrapperV8Reference<v8::String> string_;
diff --git a/third_party/WebKit/Source/platform/blob/BlobBytesProvider.cpp b/third_party/WebKit/Source/platform/blob/BlobBytesProvider.cpp
index 16b9349..f6904bba 100644
--- a/third_party/WebKit/Source/platform/blob/BlobBytesProvider.cpp
+++ b/third_party/WebKit/Source/platform/blob/BlobBytesProvider.cpp
@@ -124,13 +124,17 @@
 }
 
 void BlobBytesProvider::AppendData(scoped_refptr<RawData> data) {
+  if (!data_.IsEmpty()) {
+    uint64_t last_offset = offsets_.IsEmpty() ? 0 : offsets_.back();
+    offsets_.push_back(last_offset + data_.back()->length());
+  }
   data_.push_back(std::move(data));
 }
 
 void BlobBytesProvider::AppendData(base::span<const char> data) {
   if (data_.IsEmpty() || data_.back()->length() + data.length() >
                              kMaxConsolidatedItemSizeInBytes) {
-    data_.push_back(RawData::Create());
+    AppendData(RawData::Create());
   }
   data_.back()->MutableData()->Append(data.data(), data.length());
 }
@@ -176,17 +180,17 @@
     return;
   }
 
-  // TODO(mek): Could have a more efficient way to find beginning.
+  // Find first data item that should be read from (by finding the first offset
+  // that starts after the offset we want to start reading from).
+  size_t data_index =
+      std::upper_bound(offsets_.begin(), offsets_.end(), source_offset) -
+      offsets_.begin();
 
   // Offset of the current data chunk in the overall stream provided by this
   // provider.
-  uint64_t offset = 0;
-  for (const scoped_refptr<RawData>& data : data_) {
-    // Skip any chunks that are entirely before the data we need to write.
-    if (offset + data->length() <= source_offset) {
-      offset += data->length();
-      continue;
-    }
+  uint64_t offset = data_index == 0 ? 0 : offsets_[data_index - 1];
+  for (; data_index < data_.size(); ++data_index) {
+    const auto& data = data_[data_index];
 
     // We're done if the beginning of the current chunk is past the end of the
     // data to write.
diff --git a/third_party/WebKit/Source/platform/blob/BlobBytesProvider.h b/third_party/WebKit/Source/platform/blob/BlobBytesProvider.h
index 78b4edd..6f0b0222 100644
--- a/third_party/WebKit/Source/platform/blob/BlobBytesProvider.h
+++ b/third_party/WebKit/Source/platform/blob/BlobBytesProvider.h
@@ -43,6 +43,10 @@
   FRIEND_TEST_ALL_PREFIXES(BlobBytesProviderTest, Consolidation);
 
   Vector<scoped_refptr<RawData>> data_;
+  // |offsets_| always contains exactly one fewer item than |data_| (except when
+  // |data_| itself is empty).
+  // offsets_[x] is equal to the sum of data_[i].length for all i <= x.
+  Vector<uint64_t> offsets_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/blob/testing/FakeBlob.cpp b/third_party/WebKit/Source/platform/blob/testing/FakeBlob.cpp
index 8746304..abd1aa5 100644
--- a/third_party/WebKit/Source/platform/blob/testing/FakeBlob.cpp
+++ b/third_party/WebKit/Source/platform/blob/testing/FakeBlob.cpp
@@ -15,6 +15,11 @@
                           std::move(request));
 }
 
+void FakeBlob::AsDataPipeGetter(
+    network::mojom::blink::DataPipeGetterRequest request) {
+  NOTREACHED();
+}
+
 void FakeBlob::ReadRange(uint64_t offset,
                          uint64_t length,
                          mojo::ScopedDataPipeProducerHandle,
diff --git a/third_party/WebKit/Source/platform/blob/testing/FakeBlob.h b/third_party/WebKit/Source/platform/blob/testing/FakeBlob.h
index daa7e17a..ed4e8ef 100644
--- a/third_party/WebKit/Source/platform/blob/testing/FakeBlob.h
+++ b/third_party/WebKit/Source/platform/blob/testing/FakeBlob.h
@@ -16,6 +16,7 @@
   explicit FakeBlob(const String& uuid);
 
   void Clone(mojom::blink::BlobRequest) override;
+  void AsDataPipeGetter(network::mojom::blink::DataPipeGetterRequest) override;
   void ReadRange(uint64_t offset,
                  uint64_t length,
                  mojo::ScopedDataPipeProducerHandle,
diff --git a/third_party/WebKit/Source/platform/exported/WebHTTPBody.cpp b/third_party/WebKit/Source/platform/exported/WebHTTPBody.cpp
index 745b4636..d630993 100644
--- a/third_party/WebKit/Source/platform/exported/WebHTTPBody.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebHTTPBody.cpp
@@ -86,6 +86,12 @@
     case FormDataElement::kEncodedBlob:
       result.type = Element::kTypeBlob;
       result.blob_uuid = element.blob_uuid_;
+      if (element.optional_blob_data_handle_) {
+        result.optional_blob_handle =
+            element.optional_blob_data_handle_->CloneBlobPtr()
+                .PassInterface()
+                .PassHandle();
+      }
       break;
     case FormDataElement::kDataPipe:
       result.type = Element::kTypeDataPipe;
diff --git a/third_party/WebKit/Source/platform/exported/WebScrollbarThemeClientImpl.cpp b/third_party/WebKit/Source/platform/exported/WebScrollbarThemeClientImpl.cpp
index 70a6bff9..efc598a 100644
--- a/third_party/WebKit/Source/platform/exported/WebScrollbarThemeClientImpl.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebScrollbarThemeClientImpl.cpp
@@ -156,7 +156,7 @@
   NOTREACHED();
 }
 
-void WebScrollbarThemeClientImpl::SetScrollbarsHidden(bool hidden) {
+void WebScrollbarThemeClientImpl::SetScrollbarsHiddenIfOverlay(bool hidden) {
   NOTREACHED();
 }
 
diff --git a/third_party/WebKit/Source/platform/exported/WebScrollbarThemeClientImpl.h b/third_party/WebKit/Source/platform/exported/WebScrollbarThemeClientImpl.h
index 0ce97be..5bbfa8a 100644
--- a/third_party/WebKit/Source/platform/exported/WebScrollbarThemeClientImpl.h
+++ b/third_party/WebKit/Source/platform/exported/WebScrollbarThemeClientImpl.h
@@ -73,7 +73,7 @@
   ScrollbarPart PressedPart() const override;
   ScrollbarPart HoveredPart() const override;
   void StyleChanged() override;
-  void SetScrollbarsHidden(bool) override;
+  void SetScrollbarsHiddenIfOverlay(bool) override;
   bool Enabled() const override;
   void SetEnabled(bool) override;
   bool IsOverlayScrollbar() const override;
diff --git a/third_party/WebKit/Source/platform/geometry/FloatRoundedRect.cpp b/third_party/WebKit/Source/platform/geometry/FloatRoundedRect.cpp
index b82654e..7739064 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatRoundedRect.cpp
+++ b/third_party/WebKit/Source/platform/geometry/FloatRoundedRect.cpp
@@ -49,11 +49,6 @@
                                    const FloatSize& bottom_right)
     : rect_(rect), radii_(top_left, top_right, bottom_left, bottom_right) {}
 
-bool FloatRoundedRect::Radii::IsZero() const {
-  return top_left_.IsZero() && top_right_.IsZero() && bottom_left_.IsZero() &&
-         bottom_right_.IsZero();
-}
-
 void FloatRoundedRect::Radii::Scale(float factor) {
   if (factor == 1)
     return;
diff --git a/third_party/WebKit/Source/platform/geometry/FloatRoundedRect.h b/third_party/WebKit/Source/platform/geometry/FloatRoundedRect.h
index ce71c65f..4aaba3ba 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatRoundedRect.h
+++ b/third_party/WebKit/Source/platform/geometry/FloatRoundedRect.h
@@ -73,7 +73,10 @@
     const FloatSize& BottomLeft() const { return bottom_left_; }
     const FloatSize& BottomRight() const { return bottom_right_; }
 
-    bool IsZero() const;
+    bool IsZero() const {
+      return top_left_.IsZero() && top_right_.IsZero() &&
+             bottom_left_.IsZero() && bottom_right_.IsZero();
+    }
 
     void Scale(float factor);
     // Multiply all radii by |factor| and floor the result to the nearest
diff --git a/third_party/WebKit/Source/platform/geometry/FloatSize.cpp b/third_party/WebKit/Source/platform/geometry/FloatSize.cpp
index 9688cec..11f0d95a 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatSize.cpp
+++ b/third_party/WebKit/Source/platform/geometry/FloatSize.cpp
@@ -46,11 +46,6 @@
   return hypotf(width_, height_);
 }
 
-bool FloatSize::IsZero() const {
-  return fabs(width_) < std::numeric_limits<float>::epsilon() &&
-         fabs(height_) < std::numeric_limits<float>::epsilon();
-}
-
 bool FloatSize::IsExpressibleAsIntSize() const {
   return isWithinIntRange(width_) && isWithinIntRange(height_);
 }
diff --git a/third_party/WebKit/Source/platform/geometry/FloatSize.h b/third_party/WebKit/Source/platform/geometry/FloatSize.h
index 40cbc40..0e2a0bd 100644
--- a/third_party/WebKit/Source/platform/geometry/FloatSize.h
+++ b/third_party/WebKit/Source/platform/geometry/FloatSize.h
@@ -70,7 +70,10 @@
   void SetHeight(float height) { height_ = height; }
 
   bool IsEmpty() const { return width_ <= 0 || height_ <= 0; }
-  bool IsZero() const;
+  bool IsZero() const {
+    return fabs(width_) < std::numeric_limits<float>::epsilon() &&
+           fabs(height_) < std::numeric_limits<float>::epsilon();
+  }
   bool IsExpressibleAsIntSize() const;
 
   float AspectRatio() const { return width_ / height_; }
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
index 3178fdb9..8a25d09 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -1321,9 +1321,9 @@
       PlatformLayer()->MainThreadScrollingReasons());
 }
 
-void GraphicsLayer::didChangeScrollbarsHidden(bool hidden) {
+void GraphicsLayer::didChangeScrollbarsHiddenIfOverlay(bool hidden) {
   if (scrollable_area_)
-    scrollable_area_->SetScrollbarsHidden(hidden);
+    scrollable_area_->SetScrollbarsHiddenIfOverlay(hidden);
 }
 
 PaintController& GraphicsLayer::GetPaintController() const {
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
index e301946..048d9c2 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -262,7 +262,7 @@
   std::unique_ptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo(
       cc::Layer*) override;
   void didUpdateMainThreadScrollingReasons() override;
-  void didChangeScrollbarsHidden(bool) override;
+  void didChangeScrollbarsHiddenIfOverlay(bool) override;
 
   PaintController& GetPaintController() const;
 
diff --git a/third_party/WebKit/Source/platform/heap/IncrementalMarkingTest.cpp b/third_party/WebKit/Source/platform/heap/IncrementalMarkingTest.cpp
index 705f047..eef1a74 100644
--- a/third_party/WebKit/Source/platform/heap/IncrementalMarkingTest.cpp
+++ b/third_party/WebKit/Source/platform/heap/IncrementalMarkingTest.cpp
@@ -79,6 +79,7 @@
     // All headers of objects watched should be marked.
     for (HeapObjectHeader* header : headers_) {
       EXPECT_TRUE(header->IsMarked());
+      header->Unmark();
     }
     // All objects watched should be on the marking stack.
     while (!marking_stack_->IsEmpty()) {
@@ -86,8 +87,10 @@
       T* obj = reinterpret_cast<T*>(item->Object());
       // Ignore the backing object.
       if (!ThreadHeap::IsNormalArenaIndex(
-              PageFromObject(obj)->Arena()->ArenaIndex()))
+              PageFromObject(obj)->Arena()->ArenaIndex())) {
+        HeapObjectHeader::FromPayload(obj)->Unmark();
         continue;
+      }
       auto pos = std::find(objects_.begin(), objects_.end(), obj);
       // The following check makes sure that there are no unexpected objects on
       // the marking stack. If it fails then the write barrier fired for an
@@ -126,6 +129,7 @@
     EXPECT_TRUE(marking_stack_->IsEmpty());
     for (size_t i = 0; i < headers_.size(); i++) {
       EXPECT_EQ(was_marked_[i], headers_[i]->IsMarked());
+      headers_[i]->Unmark();
     }
   }
 
diff --git a/third_party/WebKit/Source/platform/network/EncodedFormData.cpp b/third_party/WebKit/Source/platform/network/EncodedFormData.cpp
index 9d900ee..77623de 100644
--- a/third_party/WebKit/Source/platform/network/EncodedFormData.cpp
+++ b/third_party/WebKit/Source/platform/network/EncodedFormData.cpp
@@ -178,12 +178,13 @@
           size += e.optional_blob_data_handle_->size();
         break;
       case FormDataElement::kDataPipe:
-        // We can get the size but it'd be async. Data pipe elements only exist
-        // for requests intercepted by service workers (and possibly
-        // subsequently redirected). But this function is only called for
-        // requests initiated by PingLoader, assume this function isn't needed
-        // in that case.
-        NOTREACHED();
+        // We can get the size but it'd be async. Data pipe elements exist only
+        // in EncodedFormData instances that were filled from the content side
+        // using the WebHTTPBody interface, and generally represent blobs.
+        // Since for actual kEncodedBlob elements we ignore their size as well
+        // if the element was created through WebHTTPBody (which never sets
+        // optional_blob_data_handle), we'll ignore the size of these elements
+        // as well.
         break;
     }
   }
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
index 181bb3c..47991081 100644
--- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5
+++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -188,7 +188,7 @@
     },
     {
       name: "ClientHintsPersistent",
-      status: "experimental",
+      status: "stable",
     },
     {
       name: "ClientPlaceholdersForServerLoFi",
diff --git a/third_party/WebKit/Source/platform/scheduler/BUILD.gn b/third_party/WebKit/Source/platform/scheduler/BUILD.gn
index 07d1b7e..10d08416 100644
--- a/third_party/WebKit/Source/platform/scheduler/BUILD.gn
+++ b/third_party/WebKit/Source/platform/scheduler/BUILD.gn
@@ -158,8 +158,6 @@
 
   sources = [
     "base/test_task_time_observer.h",
-    "test/create_task_queue_manager_for_test.cc",
-    "test/create_task_queue_manager_for_test.h",
     "test/fake_page_scheduler.h",
     "test/fake_renderer_scheduler.cc",
     "test/fake_task_runner.cc",
@@ -168,6 +166,8 @@
     "test/lazy_thread_controller_for_test.cc",
     "test/lazy_thread_controller_for_test.h",
     "test/renderer_scheduler_test_support.cc",
+    "test/task_queue_manager_for_test.cc",
+    "test/task_queue_manager_for_test.h",
     "test/test_task_queue.cc",
     "test/test_task_queue.h",
   ]
diff --git a/third_party/WebKit/Source/platform/scheduler/base/lazy_now.cc b/third_party/WebKit/Source/platform/scheduler/base/lazy_now.cc
index 7e8bc7b..17ccda0e 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/lazy_now.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/lazy_now.cc
@@ -9,9 +9,9 @@
 namespace blink {
 namespace scheduler {
 base::TimeTicks LazyNow::Now() {
-  if (now_.is_null())
+  if (!now_)
     now_ = tick_clock_->NowTicks();
-  return now_;
+  return now_.value();
 }
 
 }  // namespace scheduler
diff --git a/third_party/WebKit/Source/platform/scheduler/base/lazy_now.h b/third_party/WebKit/Source/platform/scheduler/base/lazy_now.h
index ca3f5b4..ab9eb2b 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/lazy_now.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/lazy_now.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_LAZY_NOW_H_
 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_LAZY_NOW_H_
 
+#include "base/optional.h"
 #include "base/time/time.h"
 #include "platform/PlatformExport.h"
 
@@ -20,7 +21,6 @@
 class PLATFORM_EXPORT LazyNow {
  public:
   explicit LazyNow(base::TimeTicks now) : tick_clock_(nullptr), now_(now) {
-    DCHECK(!now.is_null());
   }
 
   explicit LazyNow(base::TickClock* tick_clock) : tick_clock_(tick_clock) {}
@@ -30,7 +30,7 @@
 
  private:
   base::TickClock* tick_clock_;  // NOT OWNED
-  base::TimeTicks now_;
+  base::Optional<base::TimeTicks> now_;
 };
 
 }  // namespace scheduler
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
index bbc3b55c..54813d6e 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc
@@ -58,7 +58,7 @@
   // contains a strong reference to this TaskQueueImpl and the
   // TaskQueueManagerImpl destructor calls UnregisterTaskQueue on all task
   // queues.
-  DCHECK(any_thread().task_queue_manager == nullptr)
+  DCHECK(!any_thread().task_queue_manager)
       << "UnregisterTaskQueue must be called first!";
   DCHECK(main_thread_only().on_task_started_handler.is_null());
   DCHECK(main_thread_only().on_task_completed_handler.is_null());
@@ -254,20 +254,11 @@
 
 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(
     Task pending_task, base::TimeTicks now) {
-  DelayedWakeUp wake_up = pending_task.delayed_wake_up();
   main_thread_only().task_queue_manager->DidQueueTask(pending_task);
   main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
 
-  // If |pending_task| is at the head of the queue, then make sure a wake-up
-  // is requested if the queue is enabled.  Note we still want to schedule a
-  // wake-up even if blocked by a fence, because we'd break throttling logic
-  // otherwise.
-  DelayedWakeUp new_wake_up =
-      main_thread_only().delayed_incoming_queue.top().delayed_wake_up();
-  if (wake_up.time == new_wake_up.time &&
-      wake_up.sequence_num == new_wake_up.sequence_num) {
-    ScheduleDelayedWorkInTimeDomain(now);
-  }
+  LazyNow lazy_now = main_thread_only().time_domain->CreateLazyNow();
+  UpdateDelayedWakeUp(&lazy_now);
 
   TraceQueueSize();
 }
@@ -420,16 +411,23 @@
   return !immediate_incoming_queue().empty();
 }
 
-base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() {
+base::Optional<TaskQueueImpl::DelayedWakeUp>
+TaskQueueImpl::GetNextScheduledWakeUpImpl() {
   // Note we don't scheduled a wake-up for disabled queues.
   if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled())
     return base::nullopt;
 
-  return main_thread_only().delayed_incoming_queue.top().delayed_run_time;
+  return main_thread_only().delayed_incoming_queue.top().delayed_wake_up();
 }
 
-base::Optional<TaskQueueImpl::DelayedWakeUp>
-TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) {
+base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() {
+  base::Optional<DelayedWakeUp> wake_up = GetNextScheduledWakeUpImpl();
+  if (!wake_up)
+    return base::nullopt;
+  return wake_up->time;
+}
+
+void TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) {
   // Enqueue all delayed tasks that should be running now, skipping any that
   // have been canceled.
   while (!main_thread_only().delayed_incoming_queue.empty()) {
@@ -446,14 +444,18 @@
         main_thread_only().task_queue_manager->GetNextSequenceNumber());
     main_thread_only().delayed_work_queue->Push(std::move(task));
     main_thread_only().delayed_incoming_queue.pop();
+
+    // Normally WakeUpForDelayedWork is called inside DoWork, but it also
+    // can be called elsewhere (e.g. tests and fast-path for posting
+    // delayed tasks). Ensure that there is a DoWork posting. No-op inside
+    // existing DoWork due to DoWork deduplication.
+    if (IsQueueEnabled() || !main_thread_only().current_fence) {
+      main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
+          FROM_HERE);
+    }
   }
 
-  // Make sure the next wake up is scheduled.
-  if (!main_thread_only().delayed_incoming_queue.empty()) {
-    return main_thread_only().delayed_incoming_queue.top().delayed_wake_up();
-  }
-
-  return base::nullopt;
+  UpdateDelayedWakeUp(lazy_now);
 }
 
 void TaskQueueImpl::TraceQueueSize() const {
@@ -599,7 +601,13 @@
   main_thread_only().time_domain = time_domain;
   time_domain->RegisterQueue(this);
 
-  ScheduleDelayedWorkInTimeDomain(time_domain->Now());
+  LazyNow lazy_now = time_domain->CreateLazyNow();
+  // Clear scheduled wake up to ensure that new notifications are issued
+  // correctly.
+  // TODO(altimin): Remove this when we won't have to support changing time
+  // domains.
+  main_thread_only().scheduled_wake_up = base::nullopt;
+  UpdateDelayedWakeUp(&lazy_now);
 }
 
 TimeDomain* TaskQueueImpl::GetTimeDomain() const {
@@ -836,6 +844,9 @@
   if (!main_thread_only().task_queue_manager)
     return;
 
+  LazyNow lazy_now = main_thread_only().time_domain->CreateLazyNow();
+  UpdateDelayedWakeUp(&lazy_now);
+
   if (enable) {
     if (HasPendingImmediateWork() &&
         !main_thread_only().on_next_wake_up_changed_callback.is_null()) {
@@ -844,16 +855,12 @@
           base::TimeTicks());
     }
 
-    ScheduleDelayedWorkInTimeDomain(main_thread_only().time_domain->Now());
-
-    // Note the selector calls TaskQueueManagerImpl::OnTaskQueueEnabled which
-    // posts a DoWork if needed.
+    // Note the selector calls TaskQueueManager::OnTaskQueueEnabled which posts
+    // a DoWork if needed.
     main_thread_only()
         .task_queue_manager->main_thread_only()
         .selector.EnableQueue(this);
   } else {
-    if (!main_thread_only().delayed_incoming_queue.empty())
-      main_thread_only().time_domain->CancelDelayedWork(this);
     main_thread_only()
         .task_queue_manager->main_thread_only()
         .selector.DisableQueue(this);
@@ -872,9 +879,6 @@
   if (main_thread_only().delayed_incoming_queue.empty())
     return;
 
-  base::TimeTicks first_task_runtime =
-      main_thread_only().delayed_incoming_queue.top().delayed_run_time;
-
   // Remove canceled tasks.
   std::priority_queue<Task> remaining_tasks;
   while (!main_thread_only().delayed_incoming_queue.empty()) {
@@ -887,13 +891,8 @@
 
   main_thread_only().delayed_incoming_queue = std::move(remaining_tasks);
 
-  // Re-schedule delayed call to WakeUpForDelayedWork if needed.
-  if (main_thread_only().delayed_incoming_queue.empty()) {
-    main_thread_only().time_domain->CancelDelayedWork(this);
-  } else if (first_task_runtime !=
-             main_thread_only().delayed_incoming_queue.top().delayed_run_time) {
-    ScheduleDelayedWorkInTimeDomain(main_thread_only().time_domain->Now());
-  }
+  LazyNow lazy_now(now);
+  UpdateDelayedWakeUp(&lazy_now);
 }
 
 void TaskQueueImpl::PushImmediateIncomingTaskForTest(
@@ -933,31 +932,31 @@
   main_thread_only().on_next_wake_up_changed_callback = callback;
 }
 
-void TaskQueueImpl::ScheduleDelayedWorkInTimeDomain(base::TimeTicks now) {
-  if (!IsQueueEnabled())
-    return;
-  if (main_thread_only().delayed_incoming_queue.empty())
-    return;
-
-  main_thread_only().time_domain->ScheduleDelayedWork(
-      this, main_thread_only().delayed_incoming_queue.top().delayed_wake_up(),
-      now);
+void TaskQueueImpl::UpdateDelayedWakeUp(LazyNow* lazy_now) {
+  return UpdateDelayedWakeUpImpl(lazy_now, GetNextScheduledWakeUpImpl());
 }
 
-void TaskQueueImpl::SetScheduledTimeDomainWakeUp(
-    base::Optional<base::TimeTicks> scheduled_time_domain_wake_up) {
-  main_thread_only().scheduled_time_domain_wake_up =
-      scheduled_time_domain_wake_up;
-
-  // If queue has immediate work an appropriate notification has already
-  // been issued.
-  if (!scheduled_time_domain_wake_up ||
-      main_thread_only().on_next_wake_up_changed_callback.is_null() ||
-      HasPendingImmediateWork())
+void TaskQueueImpl::UpdateDelayedWakeUpImpl(
+    LazyNow* lazy_now,
+    base::Optional<TaskQueueImpl::DelayedWakeUp> wake_up) {
+  if (main_thread_only().scheduled_wake_up == wake_up)
     return;
+  main_thread_only().scheduled_wake_up = wake_up;
 
-  main_thread_only().on_next_wake_up_changed_callback.Run(
-      scheduled_time_domain_wake_up.value());
+  if (wake_up &&
+      !main_thread_only().on_next_wake_up_changed_callback.is_null() &&
+      !HasPendingImmediateWork()) {
+    main_thread_only().on_next_wake_up_changed_callback.Run(wake_up->time);
+  }
+
+  main_thread_only().time_domain->ScheduleWakeUpForQueue(this, wake_up,
+                                                         lazy_now);
+}
+
+void TaskQueueImpl::SetDelayedWakeUpForTesting(
+    base::Optional<TaskQueueImpl::DelayedWakeUp> wake_up) {
+  LazyNow lazy_now = main_thread_only().time_domain->CreateLazyNow();
+  UpdateDelayedWakeUpImpl(&lazy_now, wake_up);
 }
 
 bool TaskQueueImpl::HasPendingImmediateWork() {
@@ -993,9 +992,10 @@
     base::TimeTicks start,
     base::TimeTicks end,
     base::Optional<base::TimeDelta> thread_time) {
-  if (!main_thread_only().on_task_completed_handler.is_null())
+  if (!main_thread_only().on_task_completed_handler.is_null()) {
     main_thread_only().on_task_completed_handler.Run(task, start, end,
                                                      thread_time);
+  }
 }
 
 bool TaskQueueImpl::RequiresTaskTiming() const {
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
index 1df5ad6..792c5a17 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
@@ -75,6 +75,14 @@
     base::TimeTicks time;
     int sequence_num;
 
+    bool operator!=(const DelayedWakeUp& other) const {
+      return time != other.time || other.sequence_num != sequence_num;
+    }
+
+    bool operator==(const DelayedWakeUp& other) const {
+      return !(*this != other);
+    }
+
     bool operator<=(const DelayedWakeUp& other) const {
       if (time == other.time) {
         // Debug gcc builds can compare an element against itself.
@@ -166,6 +174,7 @@
   size_t GetNumberOfPendingTasks() const;
   bool HasTaskToRunImmediately() const;
   base::Optional<base::TimeTicks> GetNextScheduledWakeUp();
+  base::Optional<DelayedWakeUp> GetNextScheduledWakeUpImpl();
   void SetQueuePriority(TaskQueue::QueuePriority priority);
   TaskQueue::QueuePriority GetQueuePriority() const;
   void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer);
@@ -200,14 +209,6 @@
   void NotifyWillProcessTask(const base::PendingTask& pending_task);
   void NotifyDidProcessTask(const base::PendingTask& pending_task);
 
-  // Called by TimeDomain when the wake-up for this queue has changed.
-  // There is only one wake-up, new wake-up cancels any previous wake-ups.
-  // If |scheduled_time_domain_wake_up| is base::nullopt then the wake-up
-  // has been cancelled.
-  // Must be called from the main thread.
-  void SetScheduledTimeDomainWakeUp(
-      base::Optional<base::TimeTicks> scheduled_time_domain_wake_up);
-
   // Check for available tasks in immediate work queues.
   // Used to check if we need to generate notifications about delayed work.
   bool HasPendingImmediateWork();
@@ -229,13 +230,9 @@
   }
 
   // Enqueues any delayed tasks which should be run now on the
-  // |delayed_work_queue|. Returns the subsequent wake-up that is required, if
-  // any. Must be called from the main thread.
-  base::Optional<DelayedWakeUp> WakeUpForDelayedWork(LazyNow* lazy_now);
-
-  base::Optional<base::TimeTicks> scheduled_time_domain_wake_up() const {
-    return main_thread_only().scheduled_time_domain_wake_up;
-  }
+  // |delayed_work_queue|.
+  // Must be called from the main thread.
+  void WakeUpForDelayedWork(LazyNow* lazy_now);
 
   HeapHandle heap_handle() const { return main_thread_only().heap_handle; }
 
@@ -296,6 +293,9 @@
   // constructed due to not having TaskQueue.
   void SetQueueEnabledForTest(bool enabled);
 
+ protected:
+  void SetDelayedWakeUpForTesting(base::Optional<DelayedWakeUp> wake_up);
+
  private:
   friend class WorkQueue;
   friend class WorkQueueTest;
@@ -340,9 +340,11 @@
     base::trace_event::BlameContext* blame_context;  // Not owned.
     EnqueueOrder current_fence;
     base::Optional<base::TimeTicks> delayed_fence;
-    base::Optional<base::TimeTicks> scheduled_time_domain_wake_up;
     OnTaskStartedHandler on_task_started_handler;
     OnTaskCompletedHandler on_task_completed_handler;
+    // Last reported wake up, used only in UpdateWakeUp to avoid
+    // excessive calls.
+    base::Optional<DelayedWakeUp> scheduled_wake_up;
     // If false, queue will be disabled. Used only for tests.
     bool is_enabled_for_test;
   };
@@ -392,7 +394,9 @@
   void EnableOrDisableWithSelector(bool enable);
 
   // Schedules delayed work on time domain and calls the observer.
-  void ScheduleDelayedWorkInTimeDomain(base::TimeTicks now);
+  void UpdateDelayedWakeUp(LazyNow* lazy_now);
+  void UpdateDelayedWakeUpImpl(LazyNow* lazy_now,
+                               base::Optional<DelayedWakeUp> wake_up);
 
   // Activate a delayed fence if a time has come.
   void ActivateDelayedFenceIfNeeded(base::TimeTicks now);
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h
index f811d89..4808a2a 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager.h
@@ -81,14 +81,6 @@
   virtual void EnableCrashKeys(const char* file_name_crash_key,
                                const char* function_name_crash_key) = 0;
 
-  // Return number of pending tasks in task queues.
-  // TODO(kraynov): Remove test-only method.
-  virtual size_t GetNumberOfPendingTasks() const = 0;
-
-  // Returns true if there is a task that could be executed immediately.
-  // TODO(kraynov): Remove test-only method.
-  virtual bool HasImmediateWorkForTesting() const = 0;
-
   // Creates a task queue with the given type, |spec| and args. Must be called
   // on the thread this class was created on.
   // TODO(altimin): TaskQueueManager should not create TaskQueues.
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl.cc
index f313fe91..053ffeff 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl.cc
@@ -465,11 +465,12 @@
   {
     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
                  "TaskQueueManager.QueueOnTaskCompleted");
-    if (task_start_time_sec && task_end_time_sec)
+    if (task_start_time_sec && task_end_time_sec) {
       executing_task.task_queue->OnTaskCompleted(
           executing_task.pending_task, executing_task.task_start_time,
           time_after_task->Now(),
           task_end_thread_time - executing_task.task_start_thread_time);
+    }
   }
 
   if (task_start_time_sec && task_end_time_sec &&
@@ -524,13 +525,6 @@
   return LazyNow(controller_->GetClock());
 }
 
-size_t TaskQueueManagerImpl::GetNumberOfPendingTasks() const {
-  size_t task_count = 0;
-  for (auto& queue : main_thread_only().active_queues)
-    task_count += queue->GetNumberOfPendingTasks();
-  return task_count;
-}
-
 std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
 TaskQueueManagerImpl::AsValueWithSelectorResult(
     bool should_run,
@@ -584,10 +578,6 @@
     MaybeScheduleImmediateWork(FROM_HERE);
 }
 
-bool TaskQueueManagerImpl::HasImmediateWorkForTesting() const {
-  return !main_thread_only().selector.AllEnabledWorkQueuesAreEmpty();
-}
-
 void TaskQueueManagerImpl::SweepCanceledDelayedTasks() {
   std::map<TimeDomain*, base::TimeTicks> time_domain_now;
   for (const auto& queue : main_thread_only().active_queues)
@@ -650,10 +640,6 @@
              kSamplingRateForRecordingCPUTime;
 }
 
-void TaskQueueManagerImpl::SetRandomSeed(uint64_t value) {
-  main_thread_only().random_generator.seed(value);
-}
-
 MSVC_DISABLE_OPTIMIZE()
 bool TaskQueueManagerImpl::Validate() {
   return memory_corruption_sentinel_ == kMemoryCorruptionSentinelValue;
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl.h
index 18b6903..4b3a9a0 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl.h
@@ -45,10 +45,6 @@
 class ThreadController;
 }  // namespace internal
 
-namespace task_queue_manager_unittest {
-class TaskQueueManagerTest;
-}  // namespace task_queue_manager_unittest
-
 class LazyNow;
 class RealTimeDomain;
 class TaskQueue;
@@ -106,8 +102,6 @@
   void SetWorkBatchSize(int work_batch_size) override;
   void EnableCrashKeys(const char* file_name_crash_key,
                        const char* function_name_crash_key) override;
-  size_t GetNumberOfPendingTasks() const override;
-  bool HasImmediateWorkForTesting() const override;
 
   // Implementation of SequencedTaskSource:
   base::Optional<base::PendingTask> TakeTask() override;
@@ -156,22 +150,7 @@
       std::unique_ptr<internal::ThreadController> controller);
 
   friend class internal::TaskQueueImpl;
-  friend class task_queue_manager_unittest::TaskQueueManagerTest;
-
- protected:
-  // Protected functions for testing.
-  size_t ActiveQueuesCount() { return main_thread_only().active_queues.size(); }
-
-  size_t QueuesToShutdownCount() {
-    TakeQueuesToGracefullyShutdownFromHelper();
-    return main_thread_only().queues_to_gracefully_shutdown.size();
-  }
-
-  size_t QueuesToDeleteCount() {
-    return main_thread_only().queues_to_delete.size();
-  }
-
-  void SetRandomSeed(uint64_t seed);
+  friend class TaskQueueManagerForTest;
 
  private:
   enum class ProcessTaskResult {
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl_unittest.cc
index f7f3f8b7..a454d76b 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_impl_unittest.cc
@@ -29,6 +29,7 @@
 #include "platform/scheduler/base/virtual_time_domain.h"
 #include "platform/scheduler/base/work_queue.h"
 #include "platform/scheduler/base/work_queue_sets.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/scheduler/test/test_task_queue.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/WebKit/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -43,46 +44,7 @@
 using blink::scheduler::internal::EnqueueOrder;
 
 namespace blink {
-
 namespace scheduler {
-// To avoid symbol collisions in jumbo builds.
-namespace task_queue_manager_unittest {
-
-class TaskQueueManagerForTest : public TaskQueueManagerImpl {
- public:
-  explicit TaskQueueManagerForTest(
-      std::unique_ptr<internal::ThreadController> thread_controller)
-      : TaskQueueManagerImpl(std::move(thread_controller)) {}
-
-  using TaskQueueManagerImpl::ActiveQueuesCount;
-  using TaskQueueManagerImpl::QueuesToShutdownCount;
-  using TaskQueueManagerImpl::QueuesToDeleteCount;
-};
-
-class ThreadControllerForTest : public internal::ThreadControllerImpl {
- public:
-  ThreadControllerForTest(
-      base::MessageLoop* message_loop,
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      base::TickClock* time_source)
-      : ThreadControllerImpl(message_loop,
-                             std::move(task_runner),
-                             time_source) {}
-
-  ~ThreadControllerForTest() override = default;
-
-  void AddNestingObserver(base::RunLoop::NestingObserver* observer) override {
-    if (!message_loop_)
-      return;
-    ThreadControllerImpl::AddNestingObserver(observer);
-  }
-  void RemoveNestingObserver(
-      base::RunLoop::NestingObserver* observer) override {
-    if (!message_loop_)
-      return;
-    ThreadControllerImpl::RemoveNestingObserver(observer);
-  }
-};
 
 class TaskQueueManagerTest : public ::testing::Test {
  public:
@@ -111,9 +73,8 @@
     test_task_runner_ =
         base::WrapRefCounted(new cc::OrderedSimpleTaskRunner(&now_src_, false));
 
-    manager_ = std::make_unique<TaskQueueManagerForTest>(
-        std::make_unique<ThreadControllerForTest>(
-            nullptr, test_task_runner_.get(), &now_src_));
+    manager_ = TaskQueueManagerForTest::Create(nullptr, test_task_runner_.get(),
+                                               &now_src_);
 
     for (size_t i = 0; i < num_queues; i++)
       runners_.push_back(CreateTaskQueue());
@@ -124,10 +85,8 @@
     original_message_loop_task_runner_ = message_loop_->task_runner();
     // A null clock triggers some assertions.
     now_src_.Advance(base::TimeDelta::FromMicroseconds(1000));
-    manager_ = std::make_unique<TaskQueueManagerForTest>(
-        std::make_unique<ThreadControllerForTest>(
-            message_loop_.get(), GetSingleThreadTaskRunnerForTesting(),
-            &now_src_));
+    manager_ = TaskQueueManagerForTest::Create(
+        message_loop_.get(), GetSingleThreadTaskRunnerForTesting(), &now_src_);
 
     for (size_t i = 0; i < num_queues; i++)
       runners_.push_back(CreateTaskQueue());
@@ -151,8 +110,7 @@
   void RunUntilIdle(base::RepeatingClosure per_run_time_callback) {
     for (;;) {
       // Advance time if we've run out of immediate work to do.
-      if (manager_->main_thread_only()
-              .selector.AllEnabledWorkQueuesAreEmpty()) {
+      if (!manager_->HasImmediateWork()) {
         base::TimeTicks run_time;
         if (manager_->GetRealTimeDomain()->NextScheduledRunTime(&run_time)) {
           now_src_.SetNowTicks(run_time);
@@ -202,10 +160,9 @@
   // pointer to this object to read out how many times Now was called.
   TestCountUsesTimeSource test_count_uses_time_source;
 
-  manager_ = std::make_unique<TaskQueueManagerForTest>(
-      std::make_unique<ThreadControllerForTest>(
-          nullptr, GetSingleThreadTaskRunnerForTesting(),
-          &test_count_uses_time_source));
+  manager_ = TaskQueueManagerForTest::Create(
+      nullptr, GetSingleThreadTaskRunnerForTesting(),
+      &test_count_uses_time_source);
   manager_->SetWorkBatchSize(6);
   manager_->AddTaskTimeObserver(&test_task_time_observer_);
 
@@ -231,10 +188,9 @@
   // pointer to this object to read out how many times Now was called.
   TestCountUsesTimeSource test_count_uses_time_source;
 
-  manager_ = std::make_unique<TaskQueueManagerForTest>(
-      std::make_unique<ThreadControllerForTest>(message_loop_.get(),
-                                                message_loop_->task_runner(),
-                                                &test_count_uses_time_source));
+  manager_ = TaskQueueManagerForTest::Create(message_loop_.get(),
+                                             message_loop_->task_runner(),
+                                             &test_count_uses_time_source);
   manager_->AddTaskTimeObserver(&test_task_time_observer_);
 
   runners_.push_back(CreateTaskQueue());
@@ -3200,9 +3156,9 @@
   scoped_refptr<base::SingleThreadTaskRunner> custom_task_runner =
       base::MakeRefCounted<base::TestSimpleTaskRunner>();
   {
-    std::unique_ptr<TaskQueueManagerForTest> manager(
-        new TaskQueueManagerForTest(std::make_unique<ThreadControllerForTest>(
-            &message_loop, message_loop.task_runner(), nullptr)));
+    std::unique_ptr<TaskQueueManagerForTest> manager =
+        TaskQueueManagerForTest::Create(&message_loop,
+                                        message_loop.task_runner(), nullptr);
     manager->SetDefaultTaskRunner(custom_task_runner);
     DCHECK_EQ(custom_task_runner, message_loop.task_runner());
   }
@@ -3352,6 +3308,5 @@
   test_executed.Wait();
 }
 
-}  // namespace task_queue_manager_unittest
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc
index 0b6e09d..4986813 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_manager_perftest.cc
@@ -20,7 +20,7 @@
 #include "platform/scheduler/base/test_task_time_observer.h"
 #include "platform/scheduler/base/virtual_time_domain.h"
 #include "platform/scheduler/base/work_queue_sets.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/scheduler/test/test_task_queue.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
@@ -84,7 +84,7 @@
   void Initialize(size_t num_queues) {
     num_queues_ = num_queues;
     message_loop_.reset(new base::MessageLoop());
-    manager_ = CreateTaskQueueManagerForTest(
+    manager_ = TaskQueueManagerForTest::Create(
         message_loop_.get(), message_loop_->task_runner(),
         base::DefaultTickClock::GetInstance());
     manager_->AddTaskTimeObserver(&test_task_time_observer_);
diff --git a/third_party/WebKit/Source/platform/scheduler/base/thread_controller.h b/third_party/WebKit/Source/platform/scheduler/base/thread_controller.h
index 36a832fa..20279c4 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/thread_controller.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/thread_controller.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_WORKER_CONTROLLER_H_
-#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_WORKER_CONTROLLER_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_THREAD_CONTROLLER_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_THREAD_CONTROLLER_H_
 
 #include "base/location.h"
 #include "base/run_loop.h"
@@ -91,4 +91,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_WORKER_CONTROLLER_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_THREAD_CONTROLLER_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/base/thread_controller_impl.h b/third_party/WebKit/Source/platform/scheduler/base/thread_controller_impl.h
index 1227ef3..095d20c 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/thread_controller_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/thread_controller_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_WORKER_CONTROLLER_IMPL_H_
-#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_WORKER_CONTROLLER_IMPL_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_THREAD_CONTROLLER_IMPL_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_THREAD_CONTROLLER_IMPL_H_
 
 #include "platform/scheduler/base/thread_controller.h"
 
@@ -129,4 +129,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_WORKER_CONTROLLER_IMPL_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_THREAD_CONTROLLER_IMPL_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
index d621846..bb486ce8 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.cc
@@ -27,57 +27,49 @@
   DCHECK(main_thread_checker_.CalledOnValidThread());
   DCHECK_EQ(queue->GetTimeDomain(), this);
 
-  CancelDelayedWork(queue);
+  LazyNow lazy_now = CreateLazyNow();
+  ScheduleWakeUpForQueue(queue, base::nullopt, &lazy_now);
 }
 
-void TimeDomain::ScheduleDelayedWork(
+void TimeDomain::ScheduleWakeUpForQueue(
     internal::TaskQueueImpl* queue,
-    internal::TaskQueueImpl::DelayedWakeUp wake_up,
-    base::TimeTicks now) {
+    base::Optional<internal::TaskQueueImpl::DelayedWakeUp> wake_up,
+    LazyNow* lazy_now) {
   DCHECK(main_thread_checker_.CalledOnValidThread());
   DCHECK_EQ(queue->GetTimeDomain(), this);
-  DCHECK(queue->IsQueueEnabled());
-  // We only want to store a single wake-up per queue, so we need to remove any
-  // previously registered wake up for |queue|.
-  if (queue->heap_handle().IsValid()) {
-    DCHECK(queue->scheduled_time_domain_wake_up());
+  DCHECK(queue->IsQueueEnabled() || !wake_up);
 
-    // O(log n)
-    delayed_wake_up_queue_.ChangeKey(queue->heap_handle(), {wake_up, queue});
+  base::Optional<base::TimeTicks> previous_wake_up;
+  if (!delayed_wake_up_queue_.empty())
+    previous_wake_up = delayed_wake_up_queue_.Min().wake_up.time;
+
+  if (wake_up) {
+    // Insert a new wake-up into the heap.
+    if (queue->heap_handle().IsValid()) {
+      // O(log n)
+      delayed_wake_up_queue_.ChangeKey(queue->heap_handle(),
+                                       {wake_up.value(), queue});
+    } else {
+      // O(log n)
+      delayed_wake_up_queue_.insert({wake_up.value(), queue});
+    }
   } else {
-    // O(log n)
-    delayed_wake_up_queue_.insert({wake_up, queue});
+    // Remove a wake-up from heap if present.
+    if (queue->heap_handle().IsValid())
+      delayed_wake_up_queue_.erase(queue->heap_handle());
   }
 
-  queue->SetScheduledTimeDomainWakeUp(wake_up.time);
+  base::Optional<base::TimeTicks> new_wake_up;
+  if (!delayed_wake_up_queue_.empty())
+    new_wake_up = delayed_wake_up_queue_.Min().wake_up.time;
 
-  // If |queue| is the first wake-up then request the wake-up.
-  if (delayed_wake_up_queue_.Min().queue == queue)
-    RequestWakeUpAt(now, wake_up.time);
-}
-
-void TimeDomain::CancelDelayedWork(internal::TaskQueueImpl* queue) {
-  DCHECK(main_thread_checker_.CalledOnValidThread());
-  DCHECK_EQ(queue->GetTimeDomain(), this);
-
-  // If no wake-up has been requested then bail out.
-  if (!queue->heap_handle().IsValid())
+  if (previous_wake_up == new_wake_up)
     return;
 
-  DCHECK(queue->scheduled_time_domain_wake_up());
-  DCHECK(!delayed_wake_up_queue_.empty());
-  base::TimeTicks prev_first_wake_up =
-      delayed_wake_up_queue_.Min().wake_up.time;
-
-  // O(log n)
-  delayed_wake_up_queue_.erase(queue->heap_handle());
-
-  if (delayed_wake_up_queue_.empty()) {
-    CancelWakeUpAt(prev_first_wake_up);
-  } else if (prev_first_wake_up != delayed_wake_up_queue_.Min().wake_up.time) {
-    CancelWakeUpAt(prev_first_wake_up);
-    RequestWakeUpAt(Now(), delayed_wake_up_queue_.Min().wake_up.time);
-  }
+  if (previous_wake_up)
+    CancelWakeUpAt(previous_wake_up.value());
+  if (new_wake_up)
+    RequestWakeUpAt(lazy_now->Now(), new_wake_up.value());
 }
 
 void TimeDomain::WakeUpReadyDelayedQueues(LazyNow* lazy_now) {
@@ -88,18 +80,7 @@
   while (!delayed_wake_up_queue_.empty() &&
          delayed_wake_up_queue_.Min().wake_up.time <= lazy_now->Now()) {
     internal::TaskQueueImpl* queue = delayed_wake_up_queue_.Min().queue;
-    base::Optional<internal::TaskQueueImpl::DelayedWakeUp> next_wake_up =
-        queue->WakeUpForDelayedWork(lazy_now);
-
-    if (next_wake_up) {
-      // O(log n)
-      delayed_wake_up_queue_.ReplaceMin({*next_wake_up, queue});
-      queue->SetScheduledTimeDomainWakeUp(next_wake_up->time);
-    } else {
-      // O(log n)
-      delayed_wake_up_queue_.Pop();
-      DCHECK(!queue->scheduled_time_domain_wake_up());
-    }
+    queue->WakeUpForDelayedWork(lazy_now);
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain.h b/third_party/WebKit/Source/platform/scheduler/base/time_domain.h
index fc350dc..22218e3 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/time_domain.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain.h
@@ -69,16 +69,10 @@
   // the next task was posted to and it returns true.  Returns false otherwise.
   bool NextScheduledTaskQueue(internal::TaskQueueImpl** out_task_queue) const;
 
-  // Schedules a call to TaskQueueImpl::WakeUpForDelayedWork when this
-  // TimeDomain reaches |delayed_run_time|.  This supersedes any previously
-  // registered wake-up for |queue|.
-  void ScheduleDelayedWork(internal::TaskQueueImpl* queue,
-                           internal::TaskQueueImpl::DelayedWakeUp wake_up,
-                           base::TimeTicks now);
-
-  // Cancels any scheduled calls to TaskQueueImpl::WakeUpForDelayedWork for
-  // |queue|.
-  void CancelDelayedWork(internal::TaskQueueImpl* queue);
+  void ScheduleWakeUpForQueue(
+      internal::TaskQueueImpl* queue,
+      base::Optional<internal::TaskQueueImpl::DelayedWakeUp> wake_up,
+      LazyNow* lazy_now);
 
   // Registers the |queue|.
   void RegisterQueue(internal::TaskQueueImpl* queue);
@@ -132,9 +126,6 @@
     void ClearHeapHandle() {
       DCHECK(queue->heap_handle().IsValid());
       queue->set_heap_handle(HeapHandle());
-
-      DCHECK(queue->scheduled_time_domain_wake_up());
-      queue->SetScheduledTimeDomainWakeUp(base::nullopt);
     }
   };
 
diff --git a/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc b/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc
index 8a97a23..a193baf 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/base/time_domain_unittest.cc
@@ -21,6 +21,17 @@
 namespace blink {
 namespace scheduler {
 
+class TaskQueueImplForTest : public internal::TaskQueueImpl {
+ public:
+  TaskQueueImplForTest(TaskQueueManagerImpl* task_queue_manager,
+                       TimeDomain* time_domain,
+                       const TaskQueue::Spec& spec)
+      : TaskQueueImpl(task_queue_manager, time_domain, spec) {}
+  ~TaskQueueImplForTest() {}
+
+  using TaskQueueImpl::SetDelayedWakeUpForTesting;
+};
+
 class MockTimeDomain : public TimeDomain {
  public:
   MockTimeDomain()
@@ -28,10 +39,8 @@
 
   ~MockTimeDomain() override = default;
 
-  using TimeDomain::CancelDelayedWork;
   using TimeDomain::NextScheduledRunTime;
   using TimeDomain::NextScheduledTaskQueue;
-  using TimeDomain::ScheduleDelayedWork;
   using TimeDomain::UnregisterQueue;
   using TimeDomain::WakeUpReadyDelayedQueues;
 
@@ -67,7 +76,7 @@
  public:
   void SetUp() final {
     time_domain_ = base::WrapUnique(CreateMockTimeDomain());
-    task_queue_ = std::make_unique<internal::TaskQueueImpl>(
+    task_queue_ = std::make_unique<TaskQueueImplForTest>(
         nullptr, time_domain_.get(), TaskQueue::Spec("test"));
   }
 
@@ -81,15 +90,17 @@
   }
 
   std::unique_ptr<MockTimeDomain> time_domain_;
-  std::unique_ptr<internal::TaskQueueImpl> task_queue_;
+  std::unique_ptr<TaskQueueImplForTest> task_queue_;
 };
 
-TEST_F(TimeDomainTest, ScheduleDelayedWork) {
+TEST_F(TimeDomainTest, ScheduleWakeUpForQueue) {
   base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10);
   base::TimeTicks delayed_runtime = time_domain_->Now() + delay;
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, delayed_runtime));
   base::TimeTicks now = time_domain_->Now();
-  time_domain_->ScheduleDelayedWork(task_queue_.get(), {now + delay, 0}, now);
+  LazyNow lazy_now(now);
+  task_queue_->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{now + delay, 0});
 
   base::TimeTicks next_scheduled_runtime;
   EXPECT_TRUE(time_domain_->NextScheduledRunTime(&next_scheduled_runtime));
@@ -103,15 +114,16 @@
   EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(_)).Times(AnyNumber());
 }
 
-TEST_F(TimeDomainTest, ScheduleDelayedWorkSupersedesPreviousWakeUp) {
+TEST_F(TimeDomainTest, ScheduleWakeUpForQueueSupersedesPreviousWakeUp) {
   base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(10);
   base::TimeDelta delay2 = base::TimeDelta::FromMilliseconds(100);
   base::TimeTicks delayed_runtime1 = time_domain_->Now() + delay1;
   base::TimeTicks delayed_runtime2 = time_domain_->Now() + delay2;
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, delayed_runtime1));
   base::TimeTicks now = time_domain_->Now();
-  time_domain_->ScheduleDelayedWork(task_queue_.get(), {delayed_runtime1, 0},
-                                    now);
+  LazyNow lazy_now(now);
+  task_queue_->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{delayed_runtime1, 0});
 
   base::TimeTicks next_scheduled_runtime;
   EXPECT_TRUE(time_domain_->NextScheduledRunTime(&next_scheduled_runtime));
@@ -122,8 +134,8 @@
   // Now schedule a later wake_up, which should replace the previously
   // requested one.
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, delayed_runtime2));
-  time_domain_->ScheduleDelayedWork(task_queue_.get(), {delayed_runtime2, 0},
-                                    now);
+  task_queue_->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{delayed_runtime2, 0});
 
   EXPECT_TRUE(time_domain_->NextScheduledRunTime(&next_scheduled_runtime));
   EXPECT_EQ(delayed_runtime2, next_scheduled_runtime);
@@ -133,17 +145,17 @@
 }
 
 TEST_F(TimeDomainTest, RequestWakeUpAt_OnlyCalledForEarlierTasks) {
-  std::unique_ptr<internal::TaskQueueImpl> task_queue2 =
-      std::make_unique<internal::TaskQueueImpl>(nullptr, time_domain_.get(),
-                                                TaskQueue::Spec("test"));
+  std::unique_ptr<TaskQueueImplForTest> task_queue2 =
+      std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
+                                             TaskQueue::Spec("test"));
 
-  std::unique_ptr<internal::TaskQueueImpl> task_queue3 =
-      std::make_unique<internal::TaskQueueImpl>(nullptr, time_domain_.get(),
-                                                TaskQueue::Spec("test"));
+  std::unique_ptr<TaskQueueImplForTest> task_queue3 =
+      std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
+                                             TaskQueue::Spec("test"));
 
-  std::unique_ptr<internal::TaskQueueImpl> task_queue4 =
-      std::make_unique<internal::TaskQueueImpl>(nullptr, time_domain_.get(),
-                                                TaskQueue::Spec("test"));
+  std::unique_ptr<TaskQueueImplForTest> task_queue4 =
+      std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
+                                             TaskQueue::Spec("test"));
 
   base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(10);
   base::TimeDelta delay2 = base::TimeDelta::FromMilliseconds(20);
@@ -152,20 +164,25 @@
 
   // RequestWakeUpAt should always be called if there are no other wake-ups.
   base::TimeTicks now = time_domain_->Now();
+  LazyNow lazy_now(now);
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, now + delay1));
-  time_domain_->ScheduleDelayedWork(task_queue_.get(), {now + delay1, 0}, now);
+  task_queue_->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{now + delay1, 0});
 
   Mock::VerifyAndClearExpectations(time_domain_.get());
 
   // RequestWakeUpAt should not be called when scheduling later tasks.
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, _)).Times(0);
-  time_domain_->ScheduleDelayedWork(task_queue2.get(), {now + delay2, 0}, now);
-  time_domain_->ScheduleDelayedWork(task_queue3.get(), {now + delay3, 0}, now);
+  task_queue2->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{now + delay2, 0});
+  task_queue3->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{now + delay3, 0});
 
   // RequestWakeUpAt should be called when scheduling earlier tasks.
   Mock::VerifyAndClearExpectations(time_domain_.get());
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, now + delay4));
-  time_domain_->ScheduleDelayedWork(task_queue4.get(), {now + delay4, 0}, now);
+  task_queue4->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{now + delay4, 0});
 
   Mock::VerifyAndClearExpectations(time_domain_.get());
 
@@ -177,16 +194,19 @@
 }
 
 TEST_F(TimeDomainTest, UnregisterQueue) {
-  std::unique_ptr<internal::TaskQueueImpl> task_queue2_ =
-      std::make_unique<internal::TaskQueueImpl>(nullptr, time_domain_.get(),
-                                                TaskQueue::Spec("test"));
+  std::unique_ptr<TaskQueueImplForTest> task_queue2_ =
+      std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
+                                             TaskQueue::Spec("test"));
 
   base::TimeTicks now = time_domain_->Now();
+  LazyNow lazy_now(now);
   base::TimeTicks wake_up1 = now + base::TimeDelta::FromMilliseconds(10);
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, wake_up1)).Times(1);
-  time_domain_->ScheduleDelayedWork(task_queue_.get(), {wake_up1, 0}, now);
+  task_queue_->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{wake_up1, 0});
   base::TimeTicks wake_up2 = now + base::TimeDelta::FromMilliseconds(100);
-  time_domain_->ScheduleDelayedWork(task_queue2_.get(), {wake_up2, 0}, now);
+  task_queue2_->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{wake_up2, 0});
 
   internal::TaskQueueImpl* next_task_queue;
   EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
@@ -198,7 +218,7 @@
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, wake_up2)).Times(1);
 
   time_domain_->UnregisterQueue(task_queue_.get());
-  task_queue_ = std::unique_ptr<internal::TaskQueueImpl>();
+  task_queue_ = std::unique_ptr<TaskQueueImplForTest>();
   EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
   EXPECT_EQ(task_queue2_.get(), next_task_queue);
 
@@ -213,16 +233,16 @@
 TEST_F(TimeDomainTest, WakeUpReadyDelayedQueues) {
   base::TimeDelta delay = base::TimeDelta::FromMilliseconds(50);
   base::TimeTicks now = time_domain_->Now();
+  LazyNow lazy_now(now);
   base::TimeTicks delayed_runtime = now + delay;
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, delayed_runtime));
-  time_domain_->ScheduleDelayedWork(task_queue_.get(), {delayed_runtime, 0},
-                                    now);
+  task_queue_->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{delayed_runtime, 0});
 
   base::TimeTicks next_run_time;
   ASSERT_TRUE(time_domain_->NextScheduledRunTime(&next_run_time));
   EXPECT_EQ(delayed_runtime, next_run_time);
 
-  LazyNow lazy_now = time_domain_->CreateLazyNow();
   time_domain_->WakeUpReadyDelayedQueues(&lazy_now);
   ASSERT_TRUE(time_domain_->NextScheduledRunTime(&next_run_time));
   EXPECT_EQ(delayed_runtime, next_run_time);
@@ -237,20 +257,20 @@
   int sequence_num = 0;
   base::TimeDelta delay = base::TimeDelta::FromMilliseconds(50);
   base::TimeTicks now = time_domain_->Now();
+  LazyNow lazy_now(now);
   base::TimeTicks delayed_runtime = now + delay;
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, delayed_runtime));
   EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(delayed_runtime));
 
-  std::unique_ptr<internal::TaskQueueImpl> task_queue2 =
-      std::make_unique<internal::TaskQueueImpl>(nullptr, time_domain_.get(),
-                                                TaskQueue::Spec("test"));
+  std::unique_ptr<TaskQueueImplForTest> task_queue2 =
+      std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
+                                             TaskQueue::Spec("test"));
 
-  time_domain_->ScheduleDelayedWork(task_queue2.get(),
-                                    {delayed_runtime, ++sequence_num}, now);
-  time_domain_->ScheduleDelayedWork(task_queue_.get(),
-                                    {delayed_runtime, ++sequence_num}, now);
+  task_queue2->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{delayed_runtime, ++sequence_num});
+  task_queue_->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{delayed_runtime, ++sequence_num});
 
-  LazyNow lazy_now = time_domain_->CreateLazyNow();
   time_domain_->WakeUpReadyDelayedQueues(&lazy_now);
 
   // The second task queue should wake up first since it has a lower sequence
@@ -264,34 +284,39 @@
 
 TEST_F(TimeDomainTest, CancelDelayedWork) {
   base::TimeTicks now = time_domain_->Now();
+  LazyNow lazy_now(now);
   base::TimeTicks run_time = now + base::TimeDelta::FromMilliseconds(20);
 
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, run_time));
-  time_domain_->ScheduleDelayedWork(task_queue_.get(), {run_time, 0}, now);
+  task_queue_->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{run_time, 0});
 
   internal::TaskQueueImpl* next_task_queue;
   EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
   EXPECT_EQ(task_queue_.get(), next_task_queue);
 
   EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(run_time));
-  time_domain_->CancelDelayedWork(task_queue_.get());
+  task_queue_->SetDelayedWakeUpForTesting(base::nullopt);
   EXPECT_FALSE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
 }
 
 TEST_F(TimeDomainTest, CancelDelayedWork_TwoQueues) {
-  std::unique_ptr<internal::TaskQueueImpl> task_queue2 =
-      std::make_unique<internal::TaskQueueImpl>(nullptr, time_domain_.get(),
-                                                TaskQueue::Spec("test"));
+  std::unique_ptr<TaskQueueImplForTest> task_queue2 =
+      std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
+                                             TaskQueue::Spec("test"));
 
   base::TimeTicks now = time_domain_->Now();
+  LazyNow lazy_now(now);
   base::TimeTicks run_time1 = now + base::TimeDelta::FromMilliseconds(20);
   base::TimeTicks run_time2 = now + base::TimeDelta::FromMilliseconds(40);
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, run_time1));
-  time_domain_->ScheduleDelayedWork(task_queue_.get(), {run_time1, 0}, now);
+  task_queue_->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{run_time1, 0});
   Mock::VerifyAndClearExpectations(time_domain_.get());
 
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, _)).Times(0);
-  time_domain_->ScheduleDelayedWork(task_queue2.get(), {run_time2, 0}, now);
+  task_queue2->SetDelayedWakeUpForTesting(
+      internal::TaskQueueImpl::DelayedWakeUp{run_time2, 0});
   Mock::VerifyAndClearExpectations(time_domain_.get());
 
   internal::TaskQueueImpl* next_task_queue;
@@ -304,7 +329,7 @@
 
   EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(run_time1));
   EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, run_time2));
-  time_domain_->CancelDelayedWork(task_queue_.get());
+  task_queue_->SetDelayedWakeUpForTesting(base::nullopt);
   EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
   EXPECT_EQ(task_queue2.get(), next_task_queue);
 
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
index 50852a48..52c46af 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
@@ -12,7 +12,7 @@
 #include "platform/scheduler/child/idle_helper.h"
 #include "platform/scheduler/child/scheduler_helper.h"
 #include "platform/scheduler/renderer/main_thread_scheduler_helper.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
@@ -33,7 +33,9 @@
   IdleCanceledDelayedTaskSweeperTest()
       : mock_task_runner_(new cc::OrderedSimpleTaskRunner(&clock_, true)),
         scheduler_helper_(new MainThreadSchedulerHelper(
-            CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_),
+            TaskQueueManagerForTest::Create(nullptr,
+                                            mock_task_runner_,
+                                            &clock_),
             nullptr)),
         idle_helper_(
             new IdleHelper(scheduler_helper_.get(),
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc
index 3c5a19b..9913ce17 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_helper.cc
@@ -93,13 +93,11 @@
   if (long_idle_period_duration >=
       base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) {
     *next_long_idle_period_delay_out = long_idle_period_duration;
-    if (!idle_queue_->HasTaskToRunImmediately()) {
+    if (!idle_queue_->HasTaskToRunImmediately())
       return IdlePeriodState::kInLongIdlePeriodPaused;
-    } else if (long_idle_period_duration == max_long_idle_period_duration) {
+    if (long_idle_period_duration == max_long_idle_period_duration)
       return IdlePeriodState::kInLongIdlePeriodWithMaxDeadline;
-    } else {
-      return IdlePeriodState::kInLongIdlePeriod;
-    }
+    return IdlePeriodState::kInLongIdlePeriod;
   } else {
     // If we can't start the idle period yet then try again after wake-up.
     *next_long_idle_period_delay_out = base::TimeDelta::FromMilliseconds(
diff --git a/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
index 1d4535f..894982f7 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/idle_helper_unittest.cc
@@ -19,7 +19,7 @@
 #include "platform/scheduler/base/task_queue_manager.h"
 #include "platform/scheduler/child/scheduler_helper.h"
 #include "platform/scheduler/child/worker_scheduler_helper.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -196,19 +196,21 @@
       : mock_task_runner_(
             message_loop ? nullptr
                          : new cc::OrderedSimpleTaskRunner(&clock_, false)),
-        message_loop_(message_loop),
-        scheduler_helper_(new WorkerSchedulerHelper(
-            CreateTaskQueueManagerForTest(
-                message_loop,
-                message_loop ? message_loop->task_runner() : mock_task_runner_,
-                &clock_),
-            nullptr)),
-        idle_helper_(new IdleHelperForTest(
-            scheduler_helper_.get(),
-            required_quiescence_duration_before_long_idle_period,
-            scheduler_helper_->NewTaskQueue(TaskQueue::Spec("idle_test")))),
-        default_task_runner_(scheduler_helper_->DefaultWorkerTaskQueue()),
-        idle_task_runner_(idle_helper_->IdleTaskRunner()) {
+        message_loop_(message_loop) {
+    std::unique_ptr<TaskQueueManager> task_queue_manager =
+        TaskQueueManagerForTest::Create(
+            message_loop,
+            message_loop ? message_loop->task_runner() : mock_task_runner_,
+            &clock_);
+    task_queue_manager_ = task_queue_manager.get();
+    scheduler_helper_ = std::make_unique<WorkerSchedulerHelper>(
+        std::move(task_queue_manager), nullptr);
+    idle_helper_ = std::make_unique<IdleHelperForTest>(
+        scheduler_helper_.get(),
+        required_quiescence_duration_before_long_idle_period,
+        scheduler_helper_->NewTaskQueue(TaskQueue::Spec("idle_test")));
+    default_task_runner_ = scheduler_helper_->DefaultWorkerTaskQueue();
+    idle_task_runner_ = idle_helper_->IdleTaskRunner();
     clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
   }
 
@@ -237,6 +239,8 @@
     }
   }
 
+  TaskQueueManager* task_queue_manager() const { return task_queue_manager_; }
+
   void RunUntilIdle() {
     // Only one of mock_task_runner_ or message_loop_ should be set.
     DCHECK(!mock_task_runner_.get() || !message_loop_.get());
@@ -304,6 +308,7 @@
   std::unique_ptr<base::MessageLoop> message_loop_;
 
   std::unique_ptr<WorkerSchedulerHelper> scheduler_helper_;
+  TaskQueueManager* task_queue_manager_;  // Owned by scheduler_helper_.
   std::unique_ptr<IdleHelperForTest> idle_helper_;
   scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
   scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
@@ -317,10 +322,6 @@
 
   ~IdleHelperTest() override = default;
 
-  TaskQueueManager* task_queue_manager() const {
-    return scheduler_helper_->GetTaskQueueManagerForTesting();
-  }
-
  private:
   DISALLOW_COPY_AND_ASSIGN(IdleHelperTest);
 };
@@ -428,10 +429,6 @@
     // Don't set expectations on IdleHelper::Delegate.
   }
 
-  TaskQueueManager* task_queue_manager() const {
-    return scheduler_helper_->GetTaskQueueManagerForTesting();
-  }
-
   void ExpectIdlePeriodStartsButNeverEnds() {
     EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(1);
     EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(0);
diff --git a/third_party/WebKit/Source/platform/scheduler/child/page_visibility_state.h b/third_party/WebKit/Source/platform/scheduler/child/page_visibility_state.h
index a36d701..ce3f9a7 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/page_visibility_state.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/page_visibility_state.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_PAGE_VISIBILITY_STATE_H_
-#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_PAGE_VISIBILITY_STATE_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_PAGE_VISIBILITY_STATE_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_PAGE_VISIBILITY_STATE_H_
 
 namespace blink {
 namespace scheduler {
@@ -16,4 +16,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_PAGE_VISIBILITY_STATE_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_PAGE_VISIBILITY_STATE_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/child/pollable_thread_safe_flag.cc b/third_party/WebKit/Source/platform/scheduler/child/pollable_thread_safe_flag.cc
index 318015c..afc442f 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/pollable_thread_safe_flag.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/pollable_thread_safe_flag.cc
@@ -15,5 +15,5 @@
 }
 
 bool PollableThreadSafeFlag::IsSet() const {
-  return base::subtle::Acquire_Load(&flag_) != false;
+  return base::subtle::Acquire_Load(&flag_);
 }
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc
index 211f437..6eedcf6 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.cc
@@ -39,21 +39,12 @@
   task_queue_manager_.reset();
 }
 
-size_t SchedulerHelper::GetNumberOfPendingTasks() const {
-  return task_queue_manager_->GetNumberOfPendingTasks();
-}
-
 void SchedulerHelper::SetWorkBatchSizeForTesting(size_t work_batch_size) {
   CheckOnValidThread();
   DCHECK(task_queue_manager_.get());
   task_queue_manager_->SetWorkBatchSize(work_batch_size);
 }
 
-TaskQueueManager* SchedulerHelper::GetTaskQueueManagerForTesting() {
-  CheckOnValidThread();
-  return task_queue_manager_.get();
-}
-
 bool SchedulerHelper::GetAndClearSystemIsQuiescentBit() {
   CheckOnValidThread();
   DCHECK(task_queue_manager_.get());
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
index 8d04836f..03ccc0e 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper.h
@@ -84,11 +84,8 @@
   void UnregisterTimeDomain(TimeDomain* time_domain);
   bool GetAndClearSystemIsQuiescentBit();
 
-  size_t GetNumberOfPendingTasks() const;
-
   // Test helpers.
   void SetWorkBatchSizeForTesting(size_t work_batch_size);
-  TaskQueueManager* GetTaskQueueManagerForTesting();
 
  protected:
   void InitDefaultQueues(scoped_refptr<TaskQueue> default_task_queue,
diff --git a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
index e7916837..17270eb5 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/scheduler_helper_unittest.cc
@@ -14,7 +14,7 @@
 #include "platform/scheduler/base/lazy_now.h"
 #include "platform/scheduler/base/task_queue.h"
 #include "platform/scheduler/child/worker_scheduler_helper.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -51,11 +51,13 @@
 class SchedulerHelperTest : public ::testing::Test {
  public:
   SchedulerHelperTest()
-      : mock_task_runner_(new cc::OrderedSimpleTaskRunner(&clock_, false)),
-        scheduler_helper_(new WorkerSchedulerHelper(
-            CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_),
-            nullptr)),
-        default_task_runner_(scheduler_helper_->DefaultWorkerTaskQueue()) {
+      : mock_task_runner_(new cc::OrderedSimpleTaskRunner(&clock_, false)) {
+    std::unique_ptr<TaskQueueManagerForTest> task_queue_manager =
+        TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_);
+    task_queue_manager_ = task_queue_manager.get();
+    scheduler_helper_ = std::make_unique<WorkerSchedulerHelper>(
+        std::move(task_queue_manager), nullptr);
+    default_task_runner_ = scheduler_helper_->DefaultWorkerTaskQueue();
     clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
   }
 
@@ -85,6 +87,7 @@
   scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
 
   std::unique_ptr<WorkerSchedulerHelper> scheduler_helper_;
+  TaskQueueManagerForTest* task_queue_manager_;  // Owned by scheduler_helper.
   scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
 
   DISALLOW_COPY_AND_ASSIGN(SchedulerHelperTest);
@@ -134,9 +137,9 @@
       FROM_HERE, base::BindOnce(&AppendToVectorTestTask, &run_order, "D2"));
   scheduler_helper_->ControlWorkerTaskQueue()->PostTask(
       FROM_HERE, base::BindOnce(&AppendToVectorTestTask, &run_order, "C1"));
-  EXPECT_EQ(3U, scheduler_helper_->GetNumberOfPendingTasks());
+  EXPECT_EQ(3U, task_queue_manager_->PendingTasksCount());
   RunUntilIdle();
-  EXPECT_EQ(0U, scheduler_helper_->GetNumberOfPendingTasks());
+  EXPECT_EQ(0U, task_queue_manager_->PendingTasksCount());
 }
 
 namespace {
diff --git a/third_party/WebKit/Source/platform/scheduler/child/web_scheduler.h b/third_party/WebKit/Source/platform/scheduler/child/web_scheduler.h
index 4e9e12f..aba5121 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/web_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/web_scheduler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_WEB_SCHEDULER_H_
-#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_WEB_SCHEDULER_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WEB_SCHEDULER_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WEB_SCHEDULER_H_
 
 #include <memory>
 #include "base/location.h"
@@ -100,4 +100,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_WEB_SCHEDULER_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_CHILD_WEB_SCHEDULER_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc
index 2b67ed1..8e5d6d9 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/test/simple_test_tick_clock.h"
 #include "base/test/test_simple_task_runner.h"
 #include "platform/scheduler/child/worker_scheduler_impl.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/wtf/Functional.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -32,7 +32,9 @@
   WorkerGlobalScopeSchedulerTest()
       : mock_task_runner_(new base::TestSimpleTaskRunner()),
         scheduler_(new WorkerSchedulerImpl(
-            CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_),
+            TaskQueueManagerForTest::Create(nullptr,
+                                            mock_task_runner_,
+                                            &clock_),
             nullptr /* proxy */)) {
     clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
   }
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc
index 064b7adc..ab90389 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "components/viz/test/ordered_simple_task_runner.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -92,7 +92,9 @@
   WorkerSchedulerImplTest()
       : mock_task_runner_(new cc::OrderedSimpleTaskRunner(&clock_, true)),
         scheduler_(new WorkerSchedulerImplForTest(
-            CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_),
+            TaskQueueManagerForTest::Create(nullptr,
+                                            mock_task_runner_,
+                                            &clock_),
             &clock_)),
         timeline_(nullptr) {
     clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy_unittest.cc
index 7c4b546..a8a003b 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy_unittest.cc
@@ -11,7 +11,7 @@
 #include "platform/scheduler/renderer/page_scheduler_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -84,9 +84,9 @@
       : mock_main_thread_task_runner_(
             new cc::OrderedSimpleTaskRunner(&clock_, true)),
         renderer_scheduler_(std::make_unique<RendererSchedulerImpl>(
-            CreateTaskQueueManagerForTest(nullptr,
-                                          mock_main_thread_task_runner_,
-                                          &clock_),
+            TaskQueueManagerForTest::Create(nullptr,
+                                            mock_main_thread_task_runner_,
+                                            &clock_),
             base::nullopt)),
         page_scheduler_(
             std::make_unique<PageSchedulerImpl>(nullptr,
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
index 7f0f1f4d..eec640c 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/auto_advancing_virtual_time_domain_unittest.cc
@@ -10,7 +10,7 @@
 #include "platform/scheduler/base/task_queue_manager.h"
 #include "platform/scheduler/base/test_task_time_observer.h"
 #include "platform/scheduler/child/worker_scheduler_helper.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/scheduler/test/test_task_queue.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -32,7 +32,7 @@
         base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
 
     scheduler_helper_.reset(new WorkerSchedulerHelper(
-        CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_),
+        TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_),
         nullptr));
 
     scheduler_helper_->AddTaskTimeObserver(&test_task_time_observer_);
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc
index 1f16994a..f38e0d3 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/budget_pool_unittest.cc
@@ -17,7 +17,7 @@
 #include "platform/scheduler/renderer/cpu_time_budget_pool.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
 #include "platform/scheduler/renderer/wake_up_budget_pool.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -34,7 +34,7 @@
     mock_task_runner_ =
         base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
     scheduler_.reset(new RendererSchedulerImpl(
-        CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_),
+        TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_),
         base::nullopt));
     task_queue_throttler_ = scheduler_->task_queue_throttler();
     start_time_ = clock_.NowTicks();
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/cpu_time_budget_pool.cc b/third_party/WebKit/Source/platform/scheduler/renderer/cpu_time_budget_pool.cc
index b607860..0d50180d 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/cpu_time_budget_pool.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/cpu_time_budget_pool.cc
@@ -91,14 +91,11 @@
 
 base::TimeTicks CPUTimeBudgetPool::GetNextAllowedRunTime(
     base::TimeTicks desired_run_time) const {
-  if (!is_enabled_ || current_budget_level_->InMicroseconds() >= 0) {
+  if (!is_enabled_ || current_budget_level_->InMicroseconds() >= 0)
     return last_checkpoint_;
-  } else {
-    // Subtract because current_budget is negative.
-    return last_checkpoint_ +
-           (-current_budget_level_ + min_budget_level_to_run_) /
-               cpu_percentage_;
-  }
+  // Subtract because current_budget is negative.
+  return last_checkpoint_ +
+         (-current_budget_level_ + min_budget_level_to_run_) / cpu_percentage_;
 }
 
 void CPUTimeBudgetPool::RecordTaskRunTime(TaskQueue* queue,
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.h b/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.h
index db6b3bf3..16b18b8 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_METRICS_H_
-#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_METRICS_H_
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_FRAME_STATUS_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_FRAME_STATUS_H_
 
 #include "platform/PlatformExport.h"
 
@@ -82,4 +82,4 @@
 }  // namespace scheduler
 }  // namespace blink
 
-#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_METRICS_H_
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_FRAME_STATUS_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc
index 1ae852b..1b8e07f 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/idle_time_estimator_unittest.cc
@@ -11,7 +11,7 @@
 #include "platform/scheduler/base/task_queue.h"
 #include "platform/scheduler/base/task_queue_manager.h"
 #include "platform/scheduler/base/test_task_time_observer.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/scheduler/test/test_task_queue.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -44,7 +44,7 @@
     mock_task_runner_ =
         base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
     manager_ =
-        CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_);
+        TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_);
     compositor_task_queue_ =
         manager_->CreateTaskQueue<TestTaskQueue>(TaskQueue::Spec("test_tq"));
     estimator_.reset(
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl_unittest.cc
index 7ddd39c..6e1d5529 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl_unittest.cc
@@ -17,7 +17,7 @@
 #include "platform/scheduler/child/task_runner_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -40,7 +40,7 @@
     mock_task_runner_ =
         base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
     scheduler_.reset(new RendererSchedulerImpl(
-        CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_),
+        TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_),
         base::nullopt));
     page_scheduler_.reset(new PageSchedulerImpl(
         nullptr, scheduler_.get(), DisableBackgroundTimerThrottling()));
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc
index 8b31542..8a069e5 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc
@@ -27,6 +27,8 @@
 #define DURATION_PER_TASK_TYPE_METRIC_NAME \
   "RendererScheduler.TaskDurationPerTaskType"
 #define COUNT_PER_FRAME_METRIC_NAME "RendererScheduler.TaskCountPerFrameType"
+#define DURATION_PER_TASK_USE_CASE_NAME \
+  "RendererScheduler.TaskDurationPerUseCase"
 
 enum class MainThreadTaskLoadState { kLow, kHigh, kUnknown };
 
@@ -100,6 +102,7 @@
           DURATION_PER_TASK_TYPE_METRIC_NAME ".Foreground"),
       background_per_task_type_duration_reporter_(
           DURATION_PER_TASK_TYPE_METRIC_NAME ".Background"),
+      per_task_use_case_duration_reporter_(DURATION_PER_TASK_USE_CASE_NAME),
       main_thread_task_load_state_(MainThreadTaskLoadState::kUnknown) {
   main_thread_load_tracker_.Resume(now);
   if (renderer_backgrounded) {
@@ -365,6 +368,9 @@
     UMA_HISTOGRAM_ENUMERATION(COUNT_PER_FRAME_METRIC_NAME ".LongerThan1s",
                               frame_status, FrameStatus::kCount);
   }
+
+  per_task_use_case_duration_reporter_.RecordTask(
+      renderer_scheduler_->main_thread_only().current_use_case, duration);
 }
 
 void RendererMetricsHelper::RecordMainThreadTaskLoad(base::TimeTicks time,
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h
index ce5631766..3a286100 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h
@@ -12,6 +12,7 @@
 #include "platform/scheduler/child/metrics_helper.h"
 #include "platform/scheduler/renderer/frame_status.h"
 #include "platform/scheduler/renderer/main_thread_task_queue.h"
+#include "platform/scheduler/renderer/use_case.h"
 #include "platform/scheduler/util/task_duration_metric_reporter.h"
 #include "platform/scheduler/util/thread_load_tracker.h"
 #include "public/platform/TaskType.h"
@@ -125,6 +126,8 @@
   TaskDurationPerTaskTypeMetricReporter
       background_per_task_type_duration_reporter_;
 
+  TaskDurationMetricReporter<UseCase> per_task_use_case_duration_reporter_;
+
   MainThreadTaskLoadState main_thread_task_load_state_;
 
   DISALLOW_COPY_AND_ASSIGN(RendererMetricsHelper);
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc
index 757989f5..61dfa084 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc
@@ -11,9 +11,9 @@
 #include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/WebFrameScheduler.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
 #include "platform/scheduler/test/fake_page_scheduler.h"
 #include "platform/scheduler/test/fake_web_frame_scheduler.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/common/page/launching_process_state.h"
@@ -21,10 +21,23 @@
 namespace blink {
 namespace scheduler {
 
+namespace {
+class RendererSchedulerImplForTest : public RendererSchedulerImpl {
+ public:
+  RendererSchedulerImplForTest(
+      std::unique_ptr<TaskQueueManager> task_queue_manager,
+      base::Optional<base::Time> initial_virtual_time)
+      : RendererSchedulerImpl(std::move(task_queue_manager),
+                              initial_virtual_time){};
+
+  using RendererSchedulerImpl::SetCurrentUseCaseForTest;
+};
+}  // namespace
+
 using QueueType = MainThreadTaskQueue::QueueType;
+using base::Bucket;
 using testing::ElementsAre;
 using testing::UnorderedElementsAre;
-using base::Bucket;
 
 class RendererMetricsHelperTest : public ::testing::Test {
  public:
@@ -35,8 +48,8 @@
     histogram_tester_.reset(new base::HistogramTester());
     mock_task_runner_ =
         base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
-    scheduler_ = std::make_unique<RendererSchedulerImpl>(
-        CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_),
+    scheduler_ = std::make_unique<RendererSchedulerImplForTest>(
+        TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_),
         base::nullopt);
     metrics_helper_ = &scheduler_->main_thread_only().metrics_helper;
   }
@@ -55,7 +68,7 @@
         new MainThreadTaskQueueForTest(queue_type));
 
     // Pass an empty task for recording.
-    TaskQueue::PostedTask posted_task(base::Closure(), FROM_HERE);
+    TaskQueue::PostedTask posted_task(base::OnceClosure(), FROM_HERE);
     TaskQueue::Task task(std::move(posted_task), base::TimeTicks());
     metrics_helper_->RecordTaskMetrics(queue.get(), task, start,
                                        start + duration, base::nullopt);
@@ -70,7 +83,22 @@
         new MainThreadTaskQueueForTest(QueueType::kDefault));
     queue->SetFrameScheduler(scheduler);
     // Pass an empty task for recording.
-    TaskQueue::PostedTask posted_task(base::Closure(), FROM_HERE);
+    TaskQueue::PostedTask posted_task(base::OnceClosure(), FROM_HERE);
+    TaskQueue::Task task(std::move(posted_task), base::TimeTicks());
+    metrics_helper_->RecordTaskMetrics(queue.get(), task, start,
+                                       start + duration, base::nullopt);
+  }
+
+  void RunTask(UseCase use_case,
+               base::TimeTicks start,
+               base::TimeDelta duration) {
+    DCHECK_LE(clock_.NowTicks(), start);
+    clock_.SetNowTicks(start + duration);
+    scoped_refptr<MainThreadTaskQueueForTest> queue(
+        new MainThreadTaskQueueForTest(QueueType::kDefault));
+    scheduler_->SetCurrentUseCaseForTest(use_case);
+    // Pass an empty task for recording.
+    TaskQueue::PostedTask posted_task(base::OnceClosure(), FROM_HERE);
     TaskQueue::Task task(std::move(posted_task), base::TimeTicks());
     metrics_helper_->RecordTaskMetrics(queue.get(), task, start,
                                        start + duration, base::nullopt);
@@ -192,7 +220,7 @@
 
   base::SimpleTestTickClock clock_;
   scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
-  std::unique_ptr<RendererSchedulerImpl> scheduler_;
+  std::unique_ptr<RendererSchedulerImplForTest> scheduler_;
   RendererMetricsHelper* metrics_helper_;  // NOT OWNED
   std::unique_ptr<base::HistogramTester> histogram_tester_;
   std::unique_ptr<FakePageScheduler> playing_view_ =
@@ -294,6 +322,41 @@
           Bucket(static_cast<int>(QueueType::kCompositor), 20),
           Bucket(static_cast<int>(QueueType::kIdle), 1650),
           Bucket(static_cast<int>(QueueType::kFrameLoadingControl), 5)));
+
+  RunTask(UseCase::kTouchstart, Milliseconds(7000),
+          base::TimeDelta::FromMilliseconds(25));
+  RunTask(UseCase::kTouchstart, Milliseconds(7050),
+          base::TimeDelta::FromMilliseconds(25));
+  RunTask(UseCase::kTouchstart, Milliseconds(7100),
+          base::TimeDelta::FromMilliseconds(25));
+
+  RunTask(UseCase::kCompositorGesture, Milliseconds(7150),
+          base::TimeDelta::FromMilliseconds(5));
+  RunTask(UseCase::kCompositorGesture, Milliseconds(7200),
+          base::TimeDelta::FromMilliseconds(30));
+
+  RunTask(UseCase::kMainThreadCustomInputHandling, Milliseconds(7300),
+          base::TimeDelta::FromMilliseconds(2));
+  RunTask(UseCase::kSynchronizedGesture, Milliseconds(7400),
+          base::TimeDelta::FromMilliseconds(250));
+  RunTask(UseCase::kMainThreadCustomInputHandling, Milliseconds(7700),
+          base::TimeDelta::FromMilliseconds(150));
+  RunTask(UseCase::kLoading, Milliseconds(7900),
+          base::TimeDelta::FromMilliseconds(50));
+  RunTask(UseCase::kMainThreadGesture, Milliseconds(8000),
+          base::TimeDelta::FromMilliseconds(60));
+  EXPECT_THAT(
+      histogram_tester_->GetAllSamples(
+          "RendererScheduler.TaskDurationPerUseCase"),
+      UnorderedElementsAre(
+          Bucket(static_cast<int>(UseCase::kNone), 2482),
+          Bucket(static_cast<int>(UseCase::kCompositorGesture), 35),
+          Bucket(static_cast<int>(UseCase::kMainThreadCustomInputHandling),
+                 152),
+          Bucket(static_cast<int>(UseCase::kSynchronizedGesture), 250),
+          Bucket(static_cast<int>(UseCase::kTouchstart), 75),
+          Bucket(static_cast<int>(UseCase::kLoading), 50),
+          Bucket(static_cast<int>(UseCase::kMainThreadGesture), 60)));
 }
 
 TEST_F(RendererMetricsHelperTest, GetFrameStatusTest) {
@@ -361,8 +424,8 @@
   // Waste 5+ minutes so that the delayed stop is triggered
   RunTask(QueueType::kDefault, Milliseconds(1),
           base::TimeDelta::FromSeconds(5 * 61));
-  // Firing ForceUpdatePolicy multiple times to make sure that the metric is
-  // only recorded upon an actual change.
+  // Firing ForceUpdatePolicy multiple times to make sure that the
+  // metric is only recorded upon an actual change.
   ForceUpdatePolicy();
   ForceUpdatePolicy();
   ForceUpdatePolicy();
@@ -472,7 +535,8 @@
 
   EXPECT_THAT(
       histogram_tester_->GetAllSamples(
-          "RendererScheduler.TaskCountPerFrameType.LongerThan16ms"),
+          "RendererScheduler.TaskCountPerFrameType."
+          "LongerThan16ms"),
       UnorderedElementsAre(
           Bucket(static_cast<int>(FrameStatus::kMainFrameBackground), 10),
           Bucket(static_cast<int>(FrameStatus::kSameOriginHidden), 15),
@@ -481,7 +545,8 @@
 
   EXPECT_THAT(
       histogram_tester_->GetAllSamples(
-          "RendererScheduler.TaskCountPerFrameType.LongerThan50ms"),
+          "RendererScheduler.TaskCountPerFrameType."
+          "LongerThan50ms"),
       UnorderedElementsAre(
           Bucket(static_cast<int>(FrameStatus::kMainFrameBackground), 7),
           Bucket(static_cast<int>(FrameStatus::kSameOriginHidden), 10),
@@ -490,7 +555,8 @@
 
   EXPECT_THAT(
       histogram_tester_->GetAllSamples(
-          "RendererScheduler.TaskCountPerFrameType.LongerThan100ms"),
+          "RendererScheduler.TaskCountPerFrameType."
+          "LongerThan100ms"),
       UnorderedElementsAre(
           Bucket(static_cast<int>(FrameStatus::kMainFrameBackground), 2),
           Bucket(static_cast<int>(FrameStatus::kSameOriginHidden), 7),
@@ -499,7 +565,8 @@
 
   EXPECT_THAT(
       histogram_tester_->GetAllSamples(
-          "RendererScheduler.TaskCountPerFrameType.LongerThan150ms"),
+          "RendererScheduler.TaskCountPerFrameType."
+          "LongerThan150ms"),
       UnorderedElementsAre(
           Bucket(static_cast<int>(FrameStatus::kMainFrameBackground), 1),
           Bucket(static_cast<int>(FrameStatus::kSameOriginHidden), 4),
@@ -514,12 +581,14 @@
           Bucket(static_cast<int>(FrameStatus::kSameOriginHidden), 2)));
 }
 
-// TODO(crbug.com/754656): Add tests for NthMinute and AfterNthMinute
+// TODO(crbug.com/754656): Add tests for NthMinute and
+// AfterNthMinute histograms.
+
+// TODO(crbug.com/754656): Add tests for
+// TaskDuration.Hidden/Visible histograms.
+
+// TODO(crbug.com/754656): Add tests for non-TaskDuration
 // histograms.
 
-// TODO(crbug.com/754656): Add tests for TaskDuration.Hidden/Visible histograms.
-
-// TODO(crbug.com/754656): Add tests for non-TaskDuration histograms.
-
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
index ad272a6..d999250b 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
@@ -539,12 +539,11 @@
           renderer_scheduler_impl,
           &renderer_scheduler_impl->tracing_controller_,
           YesNoStateToString),
-      in_idle_period(
-          false,
-          "RendererScheduler.InIdlePeriod",
-          renderer_scheduler_impl,
-          &renderer_scheduler_impl->tracing_controller_,
-          YesNoStateToString),
+      in_idle_period(false,
+                     "RendererScheduler.InIdlePeriod",
+                     renderer_scheduler_impl,
+                     &renderer_scheduler_impl->tracing_controller_,
+                     YesNoStateToString),
       begin_main_frame_on_critical_path(
           false,
           "RendererScheduler.BeginMainFrameOnCriticalPath",
@@ -557,12 +556,11 @@
           renderer_scheduler_impl,
           &renderer_scheduler_impl->tracing_controller_,
           YesNoStateToString),
-      default_gesture_prevented(
-          true,
-          "RendererScheduler.DefaultGesturePrevented",
-          renderer_scheduler_impl,
-          &renderer_scheduler_impl->tracing_controller_,
-          YesNoStateToString),
+      default_gesture_prevented(true,
+                                "RendererScheduler.DefaultGesturePrevented",
+                                renderer_scheduler_impl,
+                                &renderer_scheduler_impl->tracing_controller_,
+                                YesNoStateToString),
       have_seen_a_potentially_blocking_gesture(
           false,
           "RendererScheduler.HaveSeenPotentiallyBlockingGesture",
@@ -1659,7 +1657,7 @@
   }
 }
 
-RendererSchedulerImpl::UseCase RendererSchedulerImpl::ComputeCurrentUseCase(
+UseCase RendererSchedulerImpl::ComputeCurrentUseCase(
     base::TimeTicks now,
     base::TimeDelta* expected_use_case_duration) const {
   any_thread_lock_.AssertAcquired();
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
index e2b739b..bf209071 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.h
@@ -31,6 +31,7 @@
 #include "platform/scheduler/renderer/render_widget_signals.h"
 #include "platform/scheduler/renderer/renderer_metrics_helper.h"
 #include "platform/scheduler/renderer/task_cost_estimator.h"
+#include "platform/scheduler/renderer/use_case.h"
 #include "platform/scheduler/renderer/user_model.h"
 #include "platform/scheduler/util/tracing_helper.h"
 #include "public/platform/scheduler/renderer/renderer_scheduler.h"
@@ -39,7 +40,7 @@
 namespace trace_event {
 class ConvertableToTraceFormat;
 }
-}
+}  // namespace base
 
 namespace blink {
 namespace scheduler {
@@ -61,36 +62,6 @@
       public base::trace_event::TraceLog::AsyncEnabledStateObserver,
       public AutoAdvancingVirtualTimeDomain::Observer {
  public:
-  // Keep RendererScheduler::UseCaseToString in sync with this enum.
-  enum class UseCase {
-    // No active use case detected.
-    kNone,
-    // A continuous gesture (e.g., scroll, pinch) which is being driven by the
-    // compositor thread.
-    kCompositorGesture,
-    // An unspecified touch gesture which is being handled by the main thread.
-    // Note that since we don't have a full view of the use case, we should be
-    // careful to prioritize all work equally.
-    kMainThreadCustomInputHandling,
-    // A continuous gesture (e.g., scroll, pinch) which is being driven by the
-    // compositor thread but also observed by the main thread. An example is
-    // synchronized scrolling where a scroll listener on the main thread changes
-    // page layout based on the current scroll position.
-    kSynchronizedGesture,
-    // A gesture has recently started and we are about to run main thread touch
-    // listeners to find out the actual gesture type. To minimize touch latency,
-    // only input handling work should run in this state.
-    kTouchstart,
-    // A page is loading.
-    kLoading,
-    // A continuous gesture (e.g., scroll) which is being handled by the main
-    // thread.
-    kMainThreadGesture,
-    // Must be the last entry.
-    kUseCaseCount,
-    kFirstUseCase = kNone,
-  };
-
   // Don't use except for tracing.
   struct TaskDescriptionForTracing {
     TaskType task_type;
@@ -314,6 +285,12 @@
   scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
   scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override;
 
+  // `current_use_case` will be overwritten by the next call to UpdatePolicy.
+  // Thus, this function should be only used for testing purposes.
+  void SetCurrentUseCaseForTest(UseCase use_case) {
+    main_thread_only().current_use_case = use_case;
+  }
+
  private:
   friend class RenderWidgetSchedulingState;
   friend class RendererMetricsHelper;
@@ -681,8 +658,7 @@
         keep_active_fetch_or_worker;
     TraceableState<bool, kTracingCategoryNameInfo>
         stopping_when_backgrounded_enabled;
-    TraceableState<bool, kTracingCategoryNameInfo>
-        stopped_when_backgrounded;
+    TraceableState<bool, kTracingCategoryNameInfo> stopped_when_backgrounded;
     TraceableCounter<base::TimeDelta, kTracingCategoryNameInfo>
         loading_task_estimated_cost;
     TraceableCounter<base::TimeDelta, kTracingCategoryNameInfo>
@@ -750,18 +726,15 @@
     UserModel user_model;
     TraceableState<bool, kTracingCategoryNameInfo>
         awaiting_touch_start_response;
-    TraceableState<bool, kTracingCategoryNameInfo>
-        in_idle_period;
+    TraceableState<bool, kTracingCategoryNameInfo> in_idle_period;
     TraceableState<bool, kTracingCategoryNameInfo>
         begin_main_frame_on_critical_path;
     TraceableState<bool, kTracingCategoryNameInfo>
         last_gesture_was_compositor_driven;
-    TraceableState<bool, kTracingCategoryNameInfo>
-        default_gesture_prevented;
+    TraceableState<bool, kTracingCategoryNameInfo> default_gesture_prevented;
     TraceableState<bool, kTracingCategoryNameInfo>
         have_seen_a_potentially_blocking_gesture;
-    TraceableState<bool, kTracingCategoryNameInfo>
-        waiting_for_meaningful_paint;
+    TraceableState<bool, kTracingCategoryNameInfo> waiting_for_meaningful_paint;
     TraceableState<bool, kTracingCategoryNameInfo>
         have_seen_input_since_navigation;
   };
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
index e57ee7e..5a6adc8 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -23,7 +23,7 @@
 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
 #include "platform/scheduler/renderer/budget_pool.h"
 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -261,15 +261,12 @@
 };
 
 // Lets gtest print human readable Policy values.
-::std::ostream& operator<<(::std::ostream& os,
-                           const RendererSchedulerImpl::UseCase& use_case) {
+::std::ostream& operator<<(::std::ostream& os, const UseCase& use_case) {
   return os << RendererSchedulerImpl::UseCaseToString(use_case);
 }
 
 class RendererSchedulerImplTest : public ::testing::Test {
  public:
-  using UseCase = RendererSchedulerImpl::UseCase;
-
   RendererSchedulerImplTest()
       : fake_task_(TaskQueue::PostedTask(base::BindOnce([] {}), FROM_HERE),
                    base::TimeTicks()) {
@@ -292,7 +289,7 @@
           base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
     }
     Initialize(std::make_unique<RendererSchedulerImplForTest>(
-        CreateTaskQueueManagerForTest(
+        TaskQueueManagerForTest::Create(
             message_loop_.get(),
             message_loop_ ? message_loop_->task_runner() : mock_task_runner_,
             &clock_),
@@ -726,10 +723,8 @@
   }
 
   static void CheckAllUseCaseToString() {
-    CallForEachEnumValue<RendererSchedulerImpl::UseCase>(
-        RendererSchedulerImpl::UseCase::kFirstUseCase,
-        RendererSchedulerImpl::UseCase::kUseCaseCount,
-        &RendererSchedulerImpl::UseCaseToString);
+    CallForEachEnumValue<UseCase>(UseCase::kFirstUseCase, UseCase::kCount,
+                                  &RendererSchedulerImpl::UseCaseToString);
   }
 
   static scoped_refptr<TaskQueue> ThrottableTaskQueue(
@@ -923,7 +918,7 @@
                                      std::string("L1"), std::string("D1"),
                                      std::string("C1"), std::string("D2"),
                                      std::string("C2"), std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kNone, CurrentUseCase());
+  EXPECT_EQ(UseCase::kNone, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest, TestDefaultPolicyWithSlowCompositor) {
@@ -940,7 +935,7 @@
                                      std::string("D1"), std::string("C1"),
                                      std::string("D2"), std::string("C2"),
                                      std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kNone, CurrentUseCase());
+  EXPECT_EQ(UseCase::kNone, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -956,8 +951,7 @@
               ::testing::ElementsAre(std::string("L1"), std::string("D1"),
                                      std::string("D2"), std::string("C1"),
                                      std::string("C2"), std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -973,8 +967,7 @@
               ::testing::ElementsAre(std::string("C1"), std::string("C2"),
                                      std::string("L1"), std::string("D1"),
                                      std::string("D2"), std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -990,8 +983,7 @@
               ::testing::ElementsAre(std::string("L1"), std::string("D1"),
                                      std::string("D2"), std::string("C1"),
                                      std::string("C2"), std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -1004,9 +996,10 @@
       clock_.NowTicks() + base::TimeDelta::FromMilliseconds(
                               UserModel::kMedianGestureDurationMillis * 2);
 
-  // The UseCase::kCompositorGesture usecase initially deprioritizes compositor
-  // tasks (see TestCompositorPolicy_CompositorHandlesInput_WithTouchHandler)
-  // but if the gesture is long enough, compositor tasks get prioritized again.
+  // The UseCase::kCompositorGesture usecase initially deprioritizes
+  // compositor tasks (see
+  // TestCompositorPolicy_CompositorHandlesInput_WithTouchHandler) but if the
+  // gesture is long enough, compositor tasks get prioritized again.
   while (clock_.NowTicks() < loop_end_time) {
     scheduler_->DidHandleInputEventOnCompositorThread(
         FakeInputEvent(blink::WebInputEvent::kTouchMove),
@@ -1023,8 +1016,7 @@
               ::testing::ElementsAre(std::string("C1"), std::string("C2"),
                                      std::string("L1"), std::string("D1"),
                                      std::string("D2")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -1039,8 +1031,7 @@
               ::testing::ElementsAre(std::string("L1"), std::string("D1"),
                                      std::string("D2"), std::string("C1"),
                                      std::string("C2"), std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -1057,8 +1048,7 @@
               ::testing::ElementsAre(std::string("C1"), std::string("C2"),
                                      std::string("L1"), std::string("D1"),
                                      std::string("D2"), std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
   scheduler_->DidHandleInputEventOnMainThread(
       FakeInputEvent(blink::WebInputEvent::kGestureFlingStart),
       WebInputEventResult::kHandledSystem);
@@ -1077,8 +1067,7 @@
               ::testing::ElementsAre(std::string("C1"), std::string("C2"),
                                      std::string("L1"), std::string("D1"),
                                      std::string("D2"), std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
   scheduler_->DidHandleInputEventOnMainThread(
       FakeInputEvent(blink::WebInputEvent::kGestureFlingStart),
       WebInputEventResult::kHandledSystem);
@@ -1104,8 +1093,7 @@
               ::testing::ElementsAre(std::string("C1"), std::string("C2"),
                                      std::string("L1"), std::string("D1"),
                                      std::string("D2"), std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
 }
 
 TEST_F(
@@ -1129,7 +1117,7 @@
               ::testing::ElementsAre(std::string("C1"), std::string("C2"),
                                      std::string("D1"), std::string("D2"),
                                      std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kTouchstart, CurrentUseCase());
+  EXPECT_EQ(UseCase::kTouchstart, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest, TestCompositorPolicy_DidAnimateForInput) {
@@ -1140,7 +1128,7 @@
   scheduler_->DidAnimateForInputOnCompositorThread();
   // Note DidAnimateForInputOnCompositorThread does not by itself trigger a
   // policy update.
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
+  EXPECT_EQ(UseCase::kCompositorGesture,
             ForceUpdatePolicyAndGetCurrentUseCase());
   EnableIdleTasks();
   RunUntilIdle();
@@ -1148,8 +1136,7 @@
               ::testing::ElementsAre(std::string("D1"), std::string("D2"),
                                      std::string("C1"), std::string("C2"),
                                      std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest, Navigation_ResetsTaskCostEstimations) {
@@ -1186,8 +1173,7 @@
 
   RunUntilIdle();
   EXPECT_FALSE(TouchStartExpectedSoon());
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadGesture, CurrentUseCase());
 
   EXPECT_THAT(run_order, ::testing::ElementsAre(std::string("C1")));
 }
@@ -1206,8 +1192,7 @@
 
   RunUntilIdle();
   EXPECT_FALSE(TouchStartExpectedSoon());
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
 
   EXPECT_THAT(run_order,
               ::testing::ElementsAre(std::string("C1"), std::string("T1")));
@@ -1227,8 +1212,7 @@
 
   RunUntilIdle();
   EXPECT_FALSE(TouchStartExpectedSoon());
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
 
   EXPECT_THAT(run_order,
               ::testing::ElementsAre(std::string("C1"), std::string("T1")));
@@ -1326,7 +1310,8 @@
                                      std::string("T2")));
 }
 
-// TODO(alexclarke): Reenable once we've reinstaed the Loading UseCase.
+// TODO(alexclarke): Reenable once we've reinstaed the Loading
+// UseCase.
 TEST_F(RendererSchedulerImplTest, DISABLED_LoadingUseCase) {
   std::vector<std::string> run_order;
   PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2");
@@ -1341,7 +1326,7 @@
       std::string("L2"), std::string("C1"), std::string("T1"),
       std::string("C2"), std::string("T2"), std::string("I1")};
   EXPECT_THAT(run_order, ::testing::ElementsAreArray(loading_policy_expected));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kLoading, CurrentUseCase());
+  EXPECT_EQ(UseCase::kLoading, CurrentUseCase());
 
   // Advance 15s and try again, the loading policy should have ended and the
   // task order should return to the NONE use case where loading tasks are no
@@ -1357,7 +1342,7 @@
       std::string("L1"), std::string("D2"), std::string("C2"),
       std::string("T2"), std::string("L2"), std::string("I1")};
   EXPECT_THAT(run_order, ::testing::ElementsAreArray(default_order_expected));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kNone, CurrentUseCase());
+  EXPECT_EQ(UseCase::kNone, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -1373,7 +1358,7 @@
       RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
   RunUntilIdle();
   // Note compositor tasks are not prioritized.
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kNone, CurrentUseCase());
+  EXPECT_EQ(UseCase::kNone, CurrentUseCase());
   EXPECT_THAT(run_order,
               ::testing::ElementsAre(std::string("D1"), std::string("C1"),
                                      std::string("D2"), std::string("C2"),
@@ -1393,7 +1378,7 @@
       RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
   RunUntilIdle();
   // Note compositor tasks are not prioritized.
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kNone, CurrentUseCase());
+  EXPECT_EQ(UseCase::kNone, CurrentUseCase());
   EXPECT_THAT(run_order,
               ::testing::ElementsAre(std::string("D1"), std::string("C1"),
                                      std::string("D2"), std::string("C2"),
@@ -1414,8 +1399,7 @@
       RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
   RunUntilIdle();
   // Note compositor tasks deprioritized.
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
   EXPECT_THAT(run_order,
               ::testing::ElementsAre(std::string("D1"), std::string("D2"),
                                      std::string("C1"), std::string("C2"),
@@ -1451,8 +1435,7 @@
                                  blink::WebInputEvent::kGestureScrollUpdate);
   RunUntilIdle();
   EXPECT_FALSE(TouchStartExpectedSoon());
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadGesture, CurrentUseCase());
 
   // Now start a main thread mouse touch gesture. It should be detected as main
   // thread custom input handling.
@@ -1470,8 +1453,7 @@
       RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
   RunUntilIdle();
 
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
 
   // Note compositor tasks are prioritized.
   EXPECT_THAT(run_order,
@@ -1480,8 +1462,7 @@
                                      std::string("I1")));
 }
 
-TEST_F(RendererSchedulerImplTest,
-       EventForwardedToMainThread_MouseClick) {
+TEST_F(RendererSchedulerImplTest, EventForwardedToMainThread_MouseClick) {
   // A mouse click should be detected as main thread input handling, which means
   // we won't try to defer expensive tasks because of one. We can, however,
   // prioritize compositing/input handling.
@@ -1499,8 +1480,7 @@
       RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
   RunUntilIdle();
 
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
 
   // Note compositor tasks are prioritized.
   EXPECT_THAT(run_order,
@@ -1523,8 +1503,7 @@
               ::testing::ElementsAre(std::string("D1"), std::string("D2"),
                                      std::string("C1"), std::string("C2"),
                                      std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -1542,8 +1521,7 @@
               ::testing::ElementsAre(std::string("C1"), std::string("C2"),
                                      std::string("D1"), std::string("D2"),
                                      std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest, EventForwardedToMainThread_NoPreventDefault) {
@@ -1569,8 +1547,7 @@
               ::testing::ElementsAre(std::string("C1"), std::string("C2"),
                                      std::string("D1"), std::string("D2"),
                                      std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadGesture, CurrentUseCase());
 }
 
 TEST_F(
@@ -1598,8 +1575,7 @@
               ::testing::ElementsAre(std::string("D1"), std::string("D2"),
                                      std::string("C1"), std::string("C2"),
                                      std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -1619,7 +1595,7 @@
               ::testing::ElementsAre(std::string("D1"), std::string("C1"),
                                      std::string("D2"), std::string("C2"),
                                      std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kNone, CurrentUseCase());
+  EXPECT_EQ(UseCase::kNone, CurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest,
@@ -1639,7 +1615,7 @@
               ::testing::ElementsAre(std::string("D1"), std::string("C1"),
                                      std::string("D2"), std::string("C2"),
                                      std::string("I1")));
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kNone, CurrentUseCase());
+  EXPECT_EQ(UseCase::kNone, CurrentUseCase());
   // Note compositor tasks are not prioritized.
   scheduler_->DidHandleInputEventOnMainThread(
       FakeInputEvent(blink::WebInputEvent::kKeyDown),
@@ -1895,7 +1871,7 @@
     mock_task_runner_ =
         base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
     mock_scheduler_ = new RendererSchedulerImplForTest(
-        CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_),
+        TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_),
         base::nullopt);
     Initialize(base::WrapUnique(mock_scheduler_));
   }
@@ -2306,7 +2282,6 @@
   EXPECT_EQ(4, run_count);
 }
 
-
 TEST_F(RendererSchedulerImplTest, TestLongIdlePeriodInTouchStartPolicy) {
   base::TimeTicks deadline_in_task;
   int run_count = 0;
@@ -2743,7 +2718,7 @@
   PostTestTasks(&run_order, "L1 D1");
   RunUntilIdle();
 
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kNone, CurrentUseCase());
+  EXPECT_EQ(UseCase::kNone, CurrentUseCase());
   EXPECT_TRUE(HaveSeenABeginMainframe());
   EXPECT_TRUE(LoadingTasksSeemExpensive());
   EXPECT_FALSE(TimerTasksSeemExpensive());
@@ -2926,7 +2901,7 @@
   PostTestTasks(&run_order, "L1 D1");
   RunUntilIdle();
 
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kNone, CurrentUseCase());
+  EXPECT_EQ(UseCase::kNone, CurrentUseCase());
   EXPECT_TRUE(HaveSeenABeginMainframe());
   EXPECT_TRUE(LoadingTasksSeemExpensive());
   EXPECT_FALSE(TimerTasksSeemExpensive());
@@ -2986,7 +2961,7 @@
   PostTestTasks(&run_order, "L1 D1");
   RunUntilIdle();
 
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kNone, CurrentUseCase());
+  EXPECT_EQ(UseCase::kNone, CurrentUseCase());
   EXPECT_TRUE(HaveSeenABeginMainframe());
   EXPECT_TRUE(LoadingTasksSeemExpensive());
   EXPECT_FALSE(TimerTasksSeemExpensive());
@@ -3009,8 +2984,7 @@
   SimulateMainThreadGestureStart(TouchEventPolicy::kSendTouchStart,
                                  blink::WebInputEvent::kGestureScrollBegin);
   RunUntilIdle();
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-            CurrentUseCase());
+  EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
 
   EXPECT_TRUE(LoadingTasksSeemExpensive());
   EXPECT_FALSE(TimerTasksSeemExpensive());
@@ -3047,8 +3021,7 @@
 
     RunUntilIdle();
     EXPECT_TRUE(simulate_timer_task_ran_) << " i = " << i;
-    EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-              CurrentUseCase())
+    EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase())
         << " i = " << i;
     EXPECT_FALSE(LoadingTasksSeemExpensive()) << " i = " << i;
     EXPECT_FALSE(TimerTasksSeemExpensive()) << " i = " << i;
@@ -3087,9 +3060,7 @@
 
     RunUntilIdle();
     EXPECT_TRUE(simulate_timer_task_ran_) << " i = " << i;
-    EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
-              CurrentUseCase())
-        << " i = " << i;
+    EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase()) << " i = " << i;
     EXPECT_FALSE(LoadingTasksSeemExpensive()) << " i = " << i;
     EXPECT_FALSE(TimerTasksSeemExpensive()) << " i = " << i;
 
@@ -3128,8 +3099,7 @@
                                   base::TimeDelta::FromMilliseconds(10)));
 
     RunUntilIdle();
-    EXPECT_EQ(RendererSchedulerImpl::UseCase::kMainThreadCustomInputHandling,
-              CurrentUseCase())
+    EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase())
         << " i = " << i;
     EXPECT_FALSE(LoadingTasksSeemExpensive()) << " i = " << i;
     if (i == 0) {
@@ -3162,7 +3132,8 @@
             scheduler_->EstimateLongestJankFreeTaskDuration());
 }
 
-// TODO(alexclarke): Reenable once we've reinstaed the Loading UseCase.
+// TODO(alexclarke): Reenable once we've reinstaed the Loading
+// UseCase.
 TEST_F(RendererSchedulerImplTest,
        DISABLED_EstimateLongestJankFreeTaskDuration_UseCase_) {
   scheduler_->DidStartProvisionalLoad(true);
@@ -3281,7 +3252,7 @@
                                   timer_queue));
   }
 }
-}
+}  // namespace
 
 TEST_F(RendererSchedulerImplTest,
        SYNCHRONIZED_GESTURE_TimerTaskThrottling_task_expensive) {
@@ -3498,15 +3469,14 @@
   scheduler_->DidAnimateForInputOnCompositorThread();
   // Note DidAnimateForInputOnCompositorThread does not by itself trigger a
   // policy update.
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kCompositorGesture,
+  EXPECT_EQ(UseCase::kCompositorGesture,
             ForceUpdatePolicyAndGetCurrentUseCase());
 
   // Make sure TouchStart causes a policy change.
   scheduler_->DidHandleInputEventOnCompositorThread(
       FakeInputEvent(blink::WebInputEvent::kTouchStart),
       RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
-  EXPECT_EQ(RendererSchedulerImpl::UseCase::kTouchstart,
-            ForceUpdatePolicyAndGetCurrentUseCase());
+  EXPECT_EQ(UseCase::kTouchstart, ForceUpdatePolicyAndGetCurrentUseCase());
 }
 
 TEST_F(RendererSchedulerImplTest, SYNCHRONIZED_GESTURE_CompositingExpensive) {
@@ -4229,7 +4199,7 @@
           base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
     }
     Initialize(std::make_unique<RendererSchedulerImplForTest>(
-        CreateTaskQueueManagerForTest(
+        TaskQueueManagerForTest::Create(
             message_loop_.get(),
             message_loop_ ? message_loop_->task_runner() : mock_task_runner_,
             &clock_),
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
index d6c7ac0..43f1b9e2 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/task_queue_throttler_unittest.cc
@@ -20,7 +20,7 @@
 #include "platform/scheduler/renderer/budget_pool.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
 #include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -80,9 +80,10 @@
     clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
     mock_task_runner_ =
         base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(clock_.get(), true);
-    scheduler_.reset(new RendererSchedulerImpl(
-        CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, clock_.get()),
-        base::nullopt));
+    scheduler_.reset(
+        new RendererSchedulerImpl(TaskQueueManagerForTest::Create(
+                                      nullptr, mock_task_runner_, clock_.get()),
+                                  base::nullopt));
     task_queue_throttler_ = scheduler_->task_queue_throttler();
     timer_queue_ = scheduler_->NewTimerTaskQueue(
         MainThreadTaskQueue::QueueType::kFrameThrottleable);
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/use_case.h b/third_party/WebKit/Source/platform/scheduler/renderer/use_case.h
new file mode 100644
index 0000000..9420785
--- /dev/null
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/use_case.h
@@ -0,0 +1,42 @@
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_USE_CASE_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_USE_CASE_H_
+
+namespace blink {
+namespace scheduler {
+
+// Keep RendererScheduler::UseCaseToString in sync with this enum.
+// This enum is used for histograms and should not be renumbered.
+enum class UseCase {
+  // No active use case detected.
+  kNone = 0,
+  // A continuous gesture (e.g., scroll, pinch) which is being driven by the
+  // compositor thread.
+  kCompositorGesture = 1,
+  // An unspecified touch gesture which is being handled by the main thread.
+  // Note that since we don't have a full view of the use case, we should be
+  // careful to prioritize all work equally.
+  kMainThreadCustomInputHandling = 2,
+  // A continuous gesture (e.g., scroll, pinch) which is being driven by the
+  // compositor thread but also observed by the main thread. An example is
+  // synchronized scrolling where a scroll listener on the main thread changes
+  // page layout based on the current scroll position.
+  kSynchronizedGesture = 3,
+  // A gesture has recently started and we are about to run main thread touch
+  // listeners to find out the actual gesture type. To minimize touch latency,
+  // only input handling work should run in this state.
+  kTouchstart = 4,
+  // A page is loading.
+  kLoading = 5,
+  // A continuous gesture (e.g., scroll) which is being handled by the main
+  // thread.
+  kMainThreadGesture = 6,
+  kFirstUseCase = kNone,
+
+  // Must be the last entry.
+  kCount = 7,
+};
+
+}  // namespace scheduler
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/user_model.cc b/third_party/WebKit/Source/platform/scheduler/renderer/user_model.cc
index 7d3a592..2b75a67 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/user_model.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/user_model.cc
@@ -93,15 +93,11 @@
     const base::TimeTicks now,
     base::TimeDelta* prediction_valid_duration) const {
   if (is_gesture_active_) {
-    if (IsGestureExpectedToContinue(now, prediction_valid_duration)) {
+    if (IsGestureExpectedToContinue(now, prediction_valid_duration))
       return false;
-    } else {
-      // If a gesture is not expected to continue then we expect a subsequent
-      // gesture soon.
-      *prediction_valid_duration =
-          base::TimeDelta::FromMilliseconds(kExpectSubsequentGestureMillis);
-      return true;
-    }
+    *prediction_valid_duration =
+        base::TimeDelta::FromMilliseconds(kExpectSubsequentGestureMillis);
+    return true;
   } else {
     // If we've have a finished a gesture then a subsequent gesture is deemed
     // likely.
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
index ca0f5238..6a0fa01 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
@@ -462,9 +462,10 @@
     state->SetString("loading_control_task_queue",
                      PointerToString(loading_control_task_queue_.get()));
   }
-  if (throttleable_task_queue_)
+  if (throttleable_task_queue_) {
     state->SetString("throttleable_task_queue",
                      PointerToString(throttleable_task_queue_.get()));
+  }
   if (deferrable_task_queue_) {
     state->SetString("deferrable_task_queue",
                      PointerToString(deferrable_task_queue_.get()));
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
index 1de8b37c..8e4c63e 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
@@ -14,7 +14,7 @@
 #include "platform/runtime_enabled_features.h"
 #include "platform/scheduler/renderer/page_scheduler_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -33,7 +33,7 @@
     mock_task_runner_ =
         base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
     scheduler_.reset(new RendererSchedulerImpl(
-        CreateTaskQueueManagerForTest(nullptr, mock_task_runner_, &clock_),
+        TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_),
         base::nullopt));
     page_scheduler_.reset(
         new PageSchedulerImpl(nullptr, scheduler_.get(), false));
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
index a5f80a61..2276cd5 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
@@ -14,7 +14,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -43,8 +43,8 @@
   void SetUp() override {
     clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
     scheduler_.reset(new RendererSchedulerImpl(
-        CreateTaskQueueManagerForTest(&message_loop_,
-                                      message_loop_.task_runner(), &clock_),
+        TaskQueueManagerForTest::Create(&message_loop_,
+                                        message_loop_.task_runner(), &clock_),
         base::nullopt));
     default_task_runner_ = scheduler_->DefaultTaskQueue();
     thread_ = scheduler_->CreateMainThread();
diff --git a/third_party/WebKit/Source/platform/scheduler/test/create_task_queue_manager_for_test.cc b/third_party/WebKit/Source/platform/scheduler/test/create_task_queue_manager_for_test.cc
deleted file mode 100644
index c926629..0000000
--- a/third_party/WebKit/Source/platform/scheduler/test/create_task_queue_manager_for_test.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
-
-#include "platform/scheduler/base/task_queue_manager_impl.h"
-#include "platform/scheduler/base/thread_controller_impl.h"
-
-namespace blink {
-namespace scheduler {
-
-namespace {
-
-class TaskQueueManagerForTest : public TaskQueueManagerImpl {
- public:
-  explicit TaskQueueManagerForTest(
-      std::unique_ptr<internal::ThreadController> thread_controller)
-      : TaskQueueManagerImpl(std::move(thread_controller)) {}
-
-  using TaskQueueManagerImpl::SetRandomSeed;
-};
-
-class ThreadControllerForTest : public internal::ThreadControllerImpl {
- public:
-  ThreadControllerForTest(
-      base::MessageLoop* message_loop,
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      base::TickClock* time_source)
-      : ThreadControllerImpl(message_loop,
-                             std::move(task_runner),
-                             time_source) {}
-
-  void AddNestingObserver(base::RunLoop::NestingObserver* observer) override {
-    if (!message_loop_)
-      return;
-    ThreadControllerImpl::AddNestingObserver(observer);
-  }
-
-  void RemoveNestingObserver(
-      base::RunLoop::NestingObserver* observer) override {
-    if (!message_loop_)
-      return;
-    ThreadControllerImpl::RemoveNestingObserver(observer);
-  }
-
-  ~ThreadControllerForTest() override = default;
-};
-
-}  // namespace
-
-std::unique_ptr<TaskQueueManager> CreateTaskQueueManagerForTest(
-    base::MessageLoop* message_loop,
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    base::TickClock* clock,
-    base::Optional<uint64_t> random_seed) {
-  std::unique_ptr<TaskQueueManagerForTest> task_queue_manager =
-      std::make_unique<TaskQueueManagerForTest>(
-          std::make_unique<ThreadControllerForTest>(
-              message_loop, std::move(task_runner), clock));
-  if (random_seed)
-    task_queue_manager->SetRandomSeed(random_seed.value());
-  return task_queue_manager;
-}
-
-}  // namespace scheduler
-}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/test/create_task_queue_manager_for_test.h b/third_party/WebKit/Source/platform/scheduler/test/create_task_queue_manager_for_test.h
deleted file mode 100644
index 315b4422..0000000
--- a/third_party/WebKit/Source/platform/scheduler/test/create_task_queue_manager_for_test.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.  // Use of this
-// source code is governed by a BSD-style license that can be found in the
-// LICENSE file.
-
-#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_CREATE_TASK_QUEUE_MANAGER_FOR_TEST_H_
-#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_CREATE_TASK_QUEUE_MANAGER_FOR_TEST_H_
-
-#include "base/single_thread_task_runner.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "platform/scheduler/base/task_queue_manager.h"
-
-namespace base {
-class MessageLoop;
-}
-
-namespace blink {
-namespace scheduler {
-
-std::unique_ptr<TaskQueueManager> CreateTaskQueueManagerForTest(
-    base::MessageLoop* message_loop,
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    base::TickClock* clock,
-    base::Optional<uint64_t> random_seed = base::nullopt);
-
-}  // namespace scheduler
-}  // namespace blink
-
-#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_CREATE_TASK_QUEUE_MANAGER_FOR_TEST_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc b/third_party/WebKit/Source/platform/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc
index e4688fd..b254351f 100644
--- a/third_party/WebKit/Source/platform/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc
+++ b/third_party/WebKit/Source/platform/scheduler/test/lazy_scheduler_message_loop_delegate_for_tests.cc
@@ -64,7 +64,7 @@
 }
 
 bool LazySchedulerMessageLoopDelegateForTests::HasMessageLoop() const {
-  return message_loop_ != nullptr;
+  return !!message_loop_;
 }
 
 bool LazySchedulerMessageLoopDelegateForTests::PostDelayedTask(
diff --git a/third_party/WebKit/Source/platform/scheduler/test/renderer_scheduler_test_support.cc b/third_party/WebKit/Source/platform/scheduler/test/renderer_scheduler_test_support.cc
index d9f064b..b81f80d 100644
--- a/third_party/WebKit/Source/platform/scheduler/test/renderer_scheduler_test_support.cc
+++ b/third_party/WebKit/Source/platform/scheduler/test/renderer_scheduler_test_support.cc
@@ -12,25 +12,14 @@
 #include "platform/scheduler/base/task_queue_manager_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
 #include "platform/scheduler/test/lazy_thread_controller_for_test.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 
 namespace blink {
 namespace scheduler {
 
-namespace {
-
-// TODO(kraynov): Use CreateTaskQueueManagerForTest instead.
-class TaskQueueManagerForRendererSchedulerTest : public TaskQueueManagerImpl {
- public:
-  explicit TaskQueueManagerForRendererSchedulerTest(
-      std::unique_ptr<internal::ThreadController> thread_controller)
-      : TaskQueueManagerImpl(std::move(thread_controller)) {}
-};
-
-}  // namespace
-
 std::unique_ptr<RendererScheduler> CreateRendererSchedulerForTests() {
   return std::make_unique<scheduler::RendererSchedulerImpl>(
-      std::make_unique<TaskQueueManagerForRendererSchedulerTest>(
+      std::make_unique<TaskQueueManagerForTest>(
           std::make_unique<LazyThreadControllerForTest>()),
       base::nullopt);
 }
diff --git a/third_party/WebKit/Source/platform/scheduler/test/task_queue_manager_for_test.cc b/third_party/WebKit/Source/platform/scheduler/test/task_queue_manager_for_test.cc
new file mode 100644
index 0000000..f835e044
--- /dev/null
+++ b/third_party/WebKit/Source/platform/scheduler/test/task_queue_manager_for_test.cc
@@ -0,0 +1,81 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
+
+#include "platform/scheduler/base/thread_controller_impl.h"
+
+namespace blink {
+namespace scheduler {
+
+namespace {
+
+class ThreadControllerForTest : public internal::ThreadControllerImpl {
+ public:
+  ThreadControllerForTest(
+      base::MessageLoop* message_loop,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      base::TickClock* time_source)
+      : ThreadControllerImpl(message_loop,
+                             std::move(task_runner),
+                             time_source) {}
+
+  void AddNestingObserver(base::RunLoop::NestingObserver* observer) override {
+    if (!message_loop_)
+      return;
+    ThreadControllerImpl::AddNestingObserver(observer);
+  }
+
+  void RemoveNestingObserver(
+      base::RunLoop::NestingObserver* observer) override {
+    if (!message_loop_)
+      return;
+    ThreadControllerImpl::RemoveNestingObserver(observer);
+  }
+
+  ~ThreadControllerForTest() override = default;
+};
+
+}  // namespace
+
+TaskQueueManagerForTest::TaskQueueManagerForTest(
+    std::unique_ptr<internal::ThreadController> thread_controller)
+    : TaskQueueManagerImpl(std::move(thread_controller)) {}
+
+// static
+std::unique_ptr<TaskQueueManagerForTest> TaskQueueManagerForTest::Create(
+    base::MessageLoop* message_loop,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    base::TickClock* clock) {
+  return std::make_unique<TaskQueueManagerForTest>(
+      std::make_unique<ThreadControllerForTest>(message_loop,
+                                                std::move(task_runner), clock));
+}
+
+size_t TaskQueueManagerForTest::ActiveQueuesCount() const {
+  return main_thread_only().active_queues.size();
+}
+
+bool TaskQueueManagerForTest::HasImmediateWork() const {
+  return !main_thread_only().selector.AllEnabledWorkQueuesAreEmpty();
+}
+
+size_t TaskQueueManagerForTest::PendingTasksCount() const {
+  size_t task_count = 0;
+  for (auto& queue : main_thread_only().active_queues)
+    task_count += queue->GetNumberOfPendingTasks();
+  return task_count;
+}
+
+size_t TaskQueueManagerForTest::QueuesToDeleteCount() const {
+  return main_thread_only().queues_to_delete.size();
+}
+
+size_t TaskQueueManagerForTest::QueuesToShutdownCount() {
+  TakeQueuesToGracefullyShutdownFromHelper();
+  return main_thread_only().queues_to_gracefully_shutdown.size();
+}
+
+}  // namespace scheduler
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/test/task_queue_manager_for_test.h b/third_party/WebKit/Source/platform/scheduler/test/task_queue_manager_for_test.h
new file mode 100644
index 0000000..98fa34e
--- /dev/null
+++ b/third_party/WebKit/Source/platform/scheduler/test/task_queue_manager_for_test.h
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.  // Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_TASK_QUEUE_MANAGER_FOR_TEST_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_TASK_QUEUE_MANAGER_FOR_TEST_H_
+
+#include "base/single_thread_task_runner.h"
+#include "base/time/tick_clock.h"
+#include "platform/scheduler/base/task_queue_manager_impl.h"
+
+namespace base {
+class MessageLoop;
+}
+
+namespace blink {
+namespace scheduler {
+
+class TaskQueueManagerForTest : public TaskQueueManagerImpl {
+ public:
+  explicit TaskQueueManagerForTest(
+      std::unique_ptr<internal::ThreadController> thread_controller);
+
+  ~TaskQueueManagerForTest() override = default;
+
+  // Creates TaskQueueManagerImpl using ThreadControllerImpl constructed with
+  // the given arguments. ThreadControllerImpl is slightly overridden to skip
+  // nesting observers registration if message loop is absent.
+  static std::unique_ptr<TaskQueueManagerForTest> Create(
+      base::MessageLoop* message_loop,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      base::TickClock* clock);
+
+  size_t ActiveQueuesCount() const;
+  bool HasImmediateWork() const;
+  size_t PendingTasksCount() const;
+  size_t QueuesToDeleteCount() const;
+  size_t QueuesToShutdownCount();
+
+  using TaskQueueManagerImpl::GetNextSequenceNumber;
+  using TaskQueueManagerImpl::WakeUpReadyDelayedQueues;
+};
+
+}  // namespace scheduler
+}  // namespace blink
+
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_TASK_QUEUE_MANAGER_FOR_TEST_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/util/thread_cpu_throttler.cc b/third_party/WebKit/Source/platform/scheduler/util/thread_cpu_throttler.cc
index dbb54e1..52965df1 100644
--- a/third_party/WebKit/Source/platform/scheduler/util/thread_cpu_throttler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/util/thread_cpu_throttler.cc
@@ -77,13 +77,13 @@
     : throttled_thread_handle_(base::PlatformThread::CurrentHandle()) {
 #endif
   SetThrottlingRate(rate);
-  CHECK(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 1) == 0);
+  CHECK_EQ(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 1), 0);
   Start();
 }
 
 ThreadCPUThrottler::ThrottlingThread::~ThrottlingThread() {
   Stop();
-  CHECK(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 0) == 1);
+  CHECK_EQ(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 0), 1);
 }
 
 void ThreadCPUThrottler::ThrottlingThread::SetThrottlingRate(double rate) {
diff --git a/third_party/WebKit/Source/platform/scheduler/util/tracing_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/util/tracing_helper_unittest.cc
index 728ed3c8..e755a97b 100644
--- a/third_party/WebKit/Source/platform/scheduler/util/tracing_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/util/tracing_helper_unittest.cc
@@ -27,13 +27,11 @@
 }
 
 const char* SignOfInt(int value) {
-  if (value > 0) {
+  if (value > 0)
     return "positive";
-  } else if (value < 0) {
+  if (value < 0)
     return "negative";
-  } else {
-    return "zero";
-  }
+  return "zero";
 }
 
 class TraceableStateForTest
@@ -86,10 +84,10 @@
   x = 1;
   EXPECT_EQ(0, y - x);
   EXPECT_EQ(2, x + y);
-  EXPECT_TRUE(x == y);
+  EXPECT_EQ(x, y);
   EXPECT_FALSE(x != y);
-  EXPECT_TRUE((x + y) != 3);
-  EXPECT_TRUE((2 - y + 1 + x) == 3);
+  EXPECT_NE(x + y, 3);
+  EXPECT_EQ(2 - y + 1 + x, 3);
   x = 3;
   y = 2;
   int z = x = y;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
index 4033006..004cd4d 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
@@ -84,7 +84,7 @@
       horizontal_scrollbar_needs_paint_invalidation_(false),
       vertical_scrollbar_needs_paint_invalidation_(false),
       scroll_corner_needs_paint_invalidation_(false),
-      scrollbars_hidden_(false),
+      scrollbars_hidden_if_overlay_(true),
       scrollbar_captured_(false),
       mouse_over_scrollbar_(false),
       needs_show_scrollbar_layers_(false),
@@ -382,7 +382,7 @@
 void ScrollableArea::MouseExitedScrollbar(Scrollbar& scrollbar) {
   mouse_over_scrollbar_ = false;
   GetScrollAnimator().MouseExitedScrollbar(scrollbar);
-  if (!scrollbars_hidden_) {
+  if (HasOverlayScrollbars() && !scrollbars_hidden_if_overlay_) {
     // This will kick off the fade out timer.
     ShowOverlayScrollbars();
   }
@@ -586,27 +586,30 @@
   return true;
 }
 
-bool ScrollableArea::ScrollbarsHidden() const {
-  return HasOverlayScrollbars() && scrollbars_hidden_;
+bool ScrollableArea::ScrollbarsHiddenIfOverlay() const {
+  return HasOverlayScrollbars() && scrollbars_hidden_if_overlay_;
 }
 
-void ScrollableArea::SetScrollbarsHidden(bool hidden) {
-  if (scrollbars_hidden_ == static_cast<unsigned>(hidden))
+void ScrollableArea::SetScrollbarsHiddenIfOverlay(bool hidden) {
+  if (!GetPageScrollbarTheme().UsesOverlayScrollbars())
     return;
 
-  scrollbars_hidden_ = hidden;
+  if (scrollbars_hidden_if_overlay_ == static_cast<unsigned>(hidden))
+    return;
+
+  scrollbars_hidden_if_overlay_ = hidden;
   ScrollbarVisibilityChanged();
 }
 
 void ScrollableArea::FadeOverlayScrollbarsTimerFired(TimerBase*) {
-  SetScrollbarsHidden(true);
+  SetScrollbarsHiddenIfOverlay(true);
 }
 
 void ScrollableArea::ShowOverlayScrollbars() {
   if (!GetPageScrollbarTheme().UsesOverlayScrollbars())
     return;
 
-  SetScrollbarsHidden(false);
+  SetScrollbarsHiddenIfOverlay(false);
   needs_show_scrollbar_layers_ = true;
 
   const double time_until_disable =
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
index 7a3dcd5..9ba8209 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -277,17 +277,15 @@
   virtual void RegisterForAnimation() {}
   virtual void DeregisterForAnimation() {}
 
-  virtual bool UsesCompositedScrolling() const {
-    return uses_composited_scrolling_;
-  }
+  bool UsesCompositedScrolling() const { return uses_composited_scrolling_; }
   void SetUsesCompositedScrolling(bool uses_composited_scrolling) {
     uses_composited_scrolling_ = uses_composited_scrolling;
   }
   virtual bool ShouldScrollOnMainThread() const;
 
   // Overlay scrollbars can "fade-out" when inactive.
-  virtual bool ScrollbarsHidden() const;
-  virtual void SetScrollbarsHidden(bool);
+  virtual bool ScrollbarsHiddenIfOverlay() const;
+  virtual void SetScrollbarsHiddenIfOverlay(bool);
 
   // Returns true if the GraphicsLayer tree needs to be rebuilt.
   virtual bool UpdateAfterCompositingChange() { return false; }
@@ -490,7 +488,7 @@
   unsigned horizontal_scrollbar_needs_paint_invalidation_ : 1;
   unsigned vertical_scrollbar_needs_paint_invalidation_ : 1;
   unsigned scroll_corner_needs_paint_invalidation_ : 1;
-  unsigned scrollbars_hidden_ : 1;
+  unsigned scrollbars_hidden_if_overlay_ : 1;
   unsigned scrollbar_captured_ : 1;
   unsigned mouse_over_scrollbar_ : 1;
 
diff --git a/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp b/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
index a6b6a623..d9b6b9d 100644
--- a/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
+++ b/third_party/WebKit/Source/platform/scroll/Scrollbar.cpp
@@ -524,9 +524,9 @@
   AutoscrollPressedPart(GetTheme().InitialAutoscrollTimerDelay());
 }
 
-void Scrollbar::SetScrollbarsHidden(bool hidden) {
+void Scrollbar::SetScrollbarsHiddenIfOverlay(bool hidden) {
   if (scrollable_area_)
-    scrollable_area_->SetScrollbarsHidden(hidden);
+    scrollable_area_->SetScrollbarsHiddenIfOverlay(hidden);
 }
 
 void Scrollbar::SetEnabled(bool e) {
@@ -538,7 +538,7 @@
   // We can skip thumb/track repaint when hiding an overlay scrollbar, but not
   // when showing (since the proportions may have changed while hidden).
   bool skipPartsRepaint = IsOverlayScrollbar() && scrollable_area_ &&
-                          scrollable_area_->ScrollbarsHidden();
+                          scrollable_area_->ScrollbarsHiddenIfOverlay();
   SetNeedsPaintInvalidation(skipPartsRepaint ? kNoPart : kAllParts);
 }
 
@@ -557,7 +557,7 @@
   // Non-overlay scrollbars should always participate in hit testing.
   if (!IsOverlayScrollbar())
     return true;
-  return !scrollable_area_->ScrollbarsHidden();
+  return !scrollable_area_->ScrollbarsHiddenIfOverlay();
 }
 
 bool Scrollbar::IsWindowActive() const {
diff --git a/third_party/WebKit/Source/platform/scroll/Scrollbar.h b/third_party/WebKit/Source/platform/scroll/Scrollbar.h
index c27387b..c3cf1c0 100644
--- a/third_party/WebKit/Source/platform/scroll/Scrollbar.h
+++ b/third_party/WebKit/Source/platform/scroll/Scrollbar.h
@@ -98,7 +98,7 @@
   ScrollbarPart HoveredPart() const override { return hovered_part_; }
 
   void StyleChanged() override {}
-  void SetScrollbarsHidden(bool) override;
+  void SetScrollbarsHiddenIfOverlay(bool) override;
   bool Enabled() const override { return enabled_; }
   void SetEnabled(bool) override;
 
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h b/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h
index 1a73e8ef..2972f48 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarTestSuite.h
@@ -68,7 +68,7 @@
   MOCK_CONST_METHOD0(LayerForVerticalScrollbar, GraphicsLayer*());
   MOCK_CONST_METHOD0(HorizontalScrollbar, Scrollbar*());
   MOCK_CONST_METHOD0(VerticalScrollbar, Scrollbar*());
-  MOCK_CONST_METHOD0(ScrollbarsHidden, bool());
+  MOCK_CONST_METHOD0(ScrollbarsHiddenIfOverlay, bool());
 
   bool UserInputScrollable(ScrollbarOrientation) const override { return true; }
   bool ScrollbarsCanBeActive() const override { return true; }
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeClient.h b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeClient.h
index 189c250..eec8a5e 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeClient.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeClient.h
@@ -71,7 +71,7 @@
   virtual ScrollbarPart HoveredPart() const = 0;
 
   virtual void StyleChanged() = 0;
-  virtual void SetScrollbarsHidden(bool) = 0;
+  virtual void SetScrollbarsHiddenIfOverlay(bool) = 0;
 
   virtual bool Enabled() const = 0;
   virtual void SetEnabled(bool) = 0;
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMac.mm b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMac.mm
index bbfab78..89a7c64 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMac.mm
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeMac.mm
@@ -89,7 +89,7 @@
                        context:(void*)context {
   if ([keyPath isEqualToString:@"knobAlpha"]) {
     BOOL visible = [_scrollbarPainter.Get() knobAlpha] > 0;
-    _scrollbar->SetScrollbarsHidden(!visible);
+    _scrollbar->SetScrollbarsHiddenIfOverlay(!visible);
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeOverlayTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeOverlayTest.cpp
index f2e8616b..5a3564b 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollbarThemeOverlayTest.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollbarThemeOverlayTest.cpp
@@ -121,7 +121,8 @@
   // Hiding the scrollbar should invalidate the layer (SetNeedsDisplay) but not
   // trigger repaint of the thumb resouce, since the compositor will give the
   // entire layer opacity 0.
-  EXPECT_CALL(*mock_scrollable_area, ScrollbarsHidden()).WillOnce(Return(true));
+  EXPECT_CALL(*mock_scrollable_area, ScrollbarsHiddenIfOverlay())
+      .WillOnce(Return(true));
   vertical_scrollbar->SetEnabled(false);
   EXPECT_FALSE(vertical_scrollbar->ThumbNeedsRepaint());
   EXPECT_TRUE(mock_scrollable_area->VerticalScrollbarNeedsPaintInvalidation());
@@ -131,7 +132,7 @@
   // Showing the scrollbar needs to repaint the thumb resource, since it may
   // have been repainted in the disabled state while hidden (e.g. from
   // SetProportion on bounds changes).
-  EXPECT_CALL(*mock_scrollable_area, ScrollbarsHidden())
+  EXPECT_CALL(*mock_scrollable_area, ScrollbarsHiddenIfOverlay())
       .WillOnce(Return(false));
   vertical_scrollbar->SetEnabled(true);
   EXPECT_TRUE(vertical_scrollbar->ThumbNeedsRepaint());
diff --git a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
index 6da09e02..cc5a25fa 100644
--- a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
+++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
@@ -51,7 +51,6 @@
 #include "platform/scheduler/base/real_time_domain.h"
 #include "platform/scheduler/base/task_queue_manager.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
 #include "platform/wtf/CryptographicallyRandomNumber.h"
 #include "platform/wtf/WTF.h"
 #include "platform/wtf/allocator/Partitions.h"
diff --git a/third_party/WebKit/Source/platform/testing/TestingPlatformSupportWithMockScheduler.cpp b/third_party/WebKit/Source/platform/testing/TestingPlatformSupportWithMockScheduler.cpp
index e1c2106..c62bc967 100644
--- a/third_party/WebKit/Source/platform/testing/TestingPlatformSupportWithMockScheduler.cpp
+++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupportWithMockScheduler.cpp
@@ -9,7 +9,6 @@
 #include "platform/WaitableEvent.h"
 #include "platform/scheduler/base/real_time_domain.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/test/create_task_queue_manager_for_test.h"
 #include "platform/wtf/ThreadSpecific.h"
 #include "platform/wtf/Time.h"
 #include "public/platform/scheduler/child/webthread_base.h"
@@ -42,14 +41,15 @@
 TestingPlatformSupportWithMockScheduler::
     TestingPlatformSupportWithMockScheduler(const Config& config)
     : TestingPlatformSupport(config),
-      mock_task_runner_(new cc::OrderedSimpleTaskRunner(&clock_, true)),
-      scheduler_(new scheduler::RendererSchedulerImpl(
-          scheduler::CreateTaskQueueManagerForTest(nullptr,
-                                                   mock_task_runner_,
-                                                   &clock_),
-          base::nullopt)),
-      thread_(scheduler_->CreateMainThread()) {
+      mock_task_runner_(new cc::OrderedSimpleTaskRunner(&clock_, true)) {
   DCHECK(IsMainThread());
+  std::unique_ptr<scheduler::TaskQueueManagerForTest> task_queue_manager =
+      scheduler::TaskQueueManagerForTest::Create(nullptr, mock_task_runner_,
+                                                 &clock_);
+  task_queue_manager_ = task_queue_manager.get();
+  scheduler_ = std::make_unique<scheduler::RendererSchedulerImpl>(
+      std::move(task_queue_manager), base::nullopt);
+  thread_ = scheduler_->CreateMainThread();
   // Set the work batch size to one so RunPendingTasks behaves as expected.
   scheduler_->GetSchedulerHelperForTesting()->SetWorkBatchSizeForTesting(1);
 
@@ -102,16 +102,12 @@
   const base::TimeTicks deadline =
       clock_.NowTicks() + base::TimeDelta::FromSecondsD(seconds);
 
-  scheduler::TaskQueueManager* task_queue_manager =
-      scheduler_->GetSchedulerHelperForTesting()
-          ->GetTaskQueueManagerForTesting();
-
   for (;;) {
     // If we've run out of immediate work then fast forward to the next delayed
     // task, but don't pass |deadline|.
-    if (!task_queue_manager->HasImmediateWorkForTesting()) {
+    if (!task_queue_manager_->HasImmediateWork()) {
       base::TimeTicks next_delayed_task;
-      if (!task_queue_manager->GetRealTimeDomain()->NextScheduledRunTime(
+      if (!task_queue_manager_->GetRealTimeDomain()->NextScheduledRunTime(
               &next_delayed_task) ||
           next_delayed_task > deadline) {
         break;
diff --git a/third_party/WebKit/Source/platform/testing/TestingPlatformSupportWithMockScheduler.h b/third_party/WebKit/Source/platform/testing/TestingPlatformSupportWithMockScheduler.h
index 740bcf4..08adef9 100644
--- a/third_party/WebKit/Source/platform/testing/TestingPlatformSupportWithMockScheduler.h
+++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupportWithMockScheduler.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include "base/test/simple_test_tick_clock.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/testing/TestingPlatformSupport.h"
 #include "platform/wtf/Noncopyable.h"
 #include "public/platform/WebThread.h"
@@ -68,6 +69,8 @@
   base::SimpleTestTickClock clock_;
   scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
   std::unique_ptr<scheduler::RendererSchedulerImpl> scheduler_;
+  scheduler::TaskQueueManagerForTest*
+      task_queue_manager_;  // Owned by scheduler_.
   std::unique_ptr<WebThread> thread_;
 };
 
diff --git a/third_party/WebKit/Source/platform/wtf/BUILD.gn b/third_party/WebKit/Source/platform/wtf/BUILD.gn
index 1506121..5bbda9c 100644
--- a/third_party/WebKit/Source/platform/wtf/BUILD.gn
+++ b/third_party/WebKit/Source/platform/wtf/BUILD.gn
@@ -73,8 +73,6 @@
     "DoublyLinkedList.h",
     "DynamicAnnotations.cpp",
     "DynamicAnnotations.h",
-    "FilePrintStream.cpp",
-    "FilePrintStream.h",
     "Forward.h",
     "Functional.h",
     "GetPtr.h",
@@ -93,12 +91,9 @@
     "ListHashSet.h",
     "Locker.h",
     "MathExtras.h",
-    "NonCopyingSort.h",
     "Noncopyable.h",
     "NotFound.h",
     "Optional.h",
-    "PrintStream.cpp",
-    "PrintStream.h",
     "ProcessMetrics.h",
     "RefCounted.h",
     "RefVector.h",
diff --git a/third_party/WebKit/Source/platform/wtf/BitVector.cpp b/third_party/WebKit/Source/platform/wtf/BitVector.cpp
index f79e626..adb572b 100644
--- a/third_party/WebKit/Source/platform/wtf/BitVector.cpp
+++ b/third_party/WebKit/Source/platform/wtf/BitVector.cpp
@@ -26,7 +26,6 @@
 #include "platform/wtf/BitVector.h"
 
 #include "platform/wtf/LeakAnnotations.h"
-#include "platform/wtf/PrintStream.h"
 #include "platform/wtf/allocator/Partitions.h"
 #include <algorithm>
 #include <string.h>
@@ -112,13 +111,4 @@
   bits_or_pointer_ = BitwiseCast<uintptr_t>(new_out_of_line_bits) >> 1;
 }
 
-void BitVector::Dump(PrintStream& out) {
-  for (size_t i = 0; i < size(); ++i) {
-    if (Get(i))
-      out.Printf("1");
-    else
-      out.Printf("-");
-  }
-}
-
 }  // namespace WTF
diff --git a/third_party/WebKit/Source/platform/wtf/BitVector.h b/third_party/WebKit/Source/platform/wtf/BitVector.h
index d7b273bb..1ce011c 100644
--- a/third_party/WebKit/Source/platform/wtf/BitVector.h
+++ b/third_party/WebKit/Source/platform/wtf/BitVector.h
@@ -33,8 +33,6 @@
 
 namespace WTF {
 
-class PrintStream;
-
 // This is a space-efficient, resizeable bitvector class. In the common case it
 // occupies one word, but if necessary, it will inflate this one word to point
 // to a single chunk of out-of-line allocated storage to store an arbitrary
@@ -156,8 +154,6 @@
       Clear(bit);
   }
 
-  void Dump(PrintStream& out);
-
  private:
   static unsigned BitsInPointer() { return sizeof(void*) << 3; }
 
diff --git a/third_party/WebKit/Source/platform/wtf/DataLog.cpp b/third_party/WebKit/Source/platform/wtf/DataLog.cpp
index 2df8036..af53ebb 100644
--- a/third_party/WebKit/Source/platform/wtf/DataLog.cpp
+++ b/third_party/WebKit/Source/platform/wtf/DataLog.cpp
@@ -25,13 +25,11 @@
 
 #include "platform/wtf/DataLog.h"
 
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
 #include "build/build_config.h"
 
-#if defined(OS_POSIX)
-#include <pthread.h>
-#include <unistd.h>
-#endif
-
 #define DATA_LOG_TO_FILE 0
 
 // Uncomment to force logging to the given file regardless of what the
@@ -44,61 +42,42 @@
 
 namespace WTF {
 
-#if defined(OS_POSIX)
-static pthread_once_t g_initialize_log_file_once_key = PTHREAD_ONCE_INIT;
-#endif
-
-static FilePrintStream* g_file;
-
-static void InitializeLogFileOnce() {
+static FILE* OpenLogFile() {
+  FILE* file = nullptr;
 #if DATA_LOG_TO_FILE
 #ifdef DATA_LOG_FILENAME
   const char* filename = DATA_LOG_FILENAME;
 #else
   const char* filename = getenv("WTF_DATA_LOG_FILENAME");
 #endif
-  char actualFilename[1024];
+  char actual_filename[1024];
 
-  snprintf(actualFilename, sizeof(actualFilename), "%s.%d.txt", filename,
+  snprintf(actual_filename, sizeof(actual_filename), "%s.%d.txt", filename,
            getpid());
 
   if (filename) {
-    file = FilePrintStream::open(actualFilename, "w").release();
-    if (!file)
+    file = fopen(actual_filename, "w");
+    if (!file) {
       fprintf(stderr, "Warning: Could not open log file %s for writing.\n",
-              actualFilename);
+              actual_filename);
+    }
   }
 #endif  // DATA_LOG_TO_FILE
-  if (!g_file)
-    g_file = new FilePrintStream(stderr, FilePrintStream::kBorrow);
+  if (!file)
+    file = stderr;
 
   // Prefer unbuffered output, so that we get a full log upon crash or
   // deadlock.
-  setvbuf(g_file->File(), nullptr, _IONBF, 0);
-}
+  setvbuf(file, nullptr, _IONBF, 0);
 
-static void InitializeLogFile() {
-#if defined(OS_POSIX)
-  pthread_once(&g_initialize_log_file_once_key, InitializeLogFileOnce);
-#else
-  if (!g_file)
-    InitializeLogFileOnce();
-#endif
-}
-
-FilePrintStream& DataFile() {
-  InitializeLogFile();
-  return *g_file;
-}
-
-void DataLogFV(const char* format, va_list arg_list) {
-  DataFile().Vprintf(format, arg_list);
+  return file;
 }
 
 void DataLogF(const char* format, ...) {
+  static FILE* file = OpenLogFile();
   va_list arg_list;
   va_start(arg_list, format);
-  DataLogFV(format, arg_list);
+  vfprintf(file, format, arg_list);
   va_end(arg_list);
 }
 
diff --git a/third_party/WebKit/Source/platform/wtf/DataLog.h b/third_party/WebKit/Source/platform/wtf/DataLog.h
index 55abd9c..3c25846 100644
--- a/third_party/WebKit/Source/platform/wtf/DataLog.h
+++ b/third_party/WebKit/Source/platform/wtf/DataLog.h
@@ -26,29 +26,15 @@
 #ifndef DataLog_h
 #define DataLog_h
 
-#include "platform/wtf/Assertions.h"
-#include "platform/wtf/Compiler.h"
-#include "platform/wtf/FilePrintStream.h"
+#include "base/compiler_specific.h"
 #include "platform/wtf/WTFExport.h"
 
-#include <stdarg.h>
-#include <stdio.h>
-
 namespace WTF {
 
-FilePrintStream& DataFile();
-
-WTF_EXPORT PRINTF_FORMAT(1, 0) void DataLogFV(const char* format, va_list);
 WTF_EXPORT PRINTF_FORMAT(1, 2) void DataLogF(const char* format, ...);
 
-template <typename... T>
-void DataLog(const T&... values) {
-  DataFile().Print(values...);
-}
-
 }  // namespace WTF
 
-using WTF::DataLog;
 using WTF::DataLogF;
 
 #endif  // DataLog_h
diff --git a/third_party/WebKit/Source/platform/wtf/FilePrintStream.cpp b/third_party/WebKit/Source/platform/wtf/FilePrintStream.cpp
deleted file mode 100644
index e2c96b76..0000000
--- a/third_party/WebKit/Source/platform/wtf/FilePrintStream.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "platform/wtf/FilePrintStream.h"
-
-#include <memory>
-
-namespace WTF {
-
-FilePrintStream::FilePrintStream(FILE* file, AdoptionMode adoption_mode)
-    : file_(file), adoption_mode_(adoption_mode) {}
-
-FilePrintStream::~FilePrintStream() {
-  if (adoption_mode_ == kBorrow)
-    return;
-  fclose(file_);
-}
-
-std::unique_ptr<FilePrintStream> FilePrintStream::Open(const char* filename,
-                                                       const char* mode) {
-  FILE* file = fopen(filename, mode);
-  if (!file)
-    return std::unique_ptr<FilePrintStream>();
-
-  return std::make_unique<FilePrintStream>(file);
-}
-
-void FilePrintStream::Vprintf(const char* format, va_list arg_list) {
-  vfprintf(file_, format, arg_list);
-}
-
-void FilePrintStream::Flush() {
-  fflush(file_);
-}
-
-}  // namespace WTF
diff --git a/third_party/WebKit/Source/platform/wtf/FilePrintStream.h b/third_party/WebKit/Source/platform/wtf/FilePrintStream.h
deleted file mode 100644
index f8fdb9ea..0000000
--- a/third_party/WebKit/Source/platform/wtf/FilePrintStream.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FilePrintStream_h
-#define FilePrintStream_h
-
-#include "platform/wtf/Compiler.h"
-#include "platform/wtf/PrintStream.h"
-#include <memory>
-#include <stdio.h>
-
-namespace WTF {
-
-class WTF_EXPORT FilePrintStream final : public PrintStream {
- public:
-  enum AdoptionMode { kAdopt, kBorrow };
-
-  FilePrintStream(FILE*, AdoptionMode = kAdopt);
-  ~FilePrintStream() override;
-
-  static std::unique_ptr<FilePrintStream> Open(const char* filename,
-                                               const char* mode);
-
-  FILE* File() { return file_; }
-
-  PRINTF_FORMAT(2, 0) void Vprintf(const char* format, va_list) override;
-  void Flush() override;
-
- private:
-  FILE* file_;
-  AdoptionMode adoption_mode_;
-};
-
-}  // namespace WTF
-
-using WTF::FilePrintStream;
-
-#endif  // FilePrintStream_h
diff --git a/third_party/WebKit/Source/platform/wtf/NonCopyingSort.h b/third_party/WebKit/Source/platform/wtf/NonCopyingSort.h
deleted file mode 100644
index ae61682..0000000
--- a/third_party/WebKit/Source/platform/wtf/NonCopyingSort.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef WTF_NonCopyingSort_h
-#define WTF_NonCopyingSort_h
-
-namespace WTF {
-
-using std::swap;
-
-template <typename RandomAccessIterator, typename Predicate>
-inline void SiftDown(RandomAccessIterator array,
-                     ptrdiff_t start,
-                     ptrdiff_t end,
-                     Predicate compare_less) {
-  ptrdiff_t root = start;
-
-  while (root * 2 + 1 <= end) {
-    ptrdiff_t child = root * 2 + 1;
-    if (child < end && compare_less(array[child], array[child + 1]))
-      child++;
-
-    if (compare_less(array[root], array[child])) {
-      swap(array[root], array[child]);
-      root = child;
-    } else {
-      return;
-    }
-  }
-}
-
-template <typename RandomAccessIterator, typename Predicate>
-inline void Heapify(RandomAccessIterator array,
-                    ptrdiff_t count,
-                    Predicate compare_less) {
-  ptrdiff_t start = (count - 2) / 2;
-
-  while (start >= 0) {
-    SiftDown(array, start, count - 1, compare_less);
-    start--;
-  }
-}
-
-template <typename RandomAccessIterator, typename Predicate>
-void HeapSort(RandomAccessIterator start,
-              RandomAccessIterator end,
-              Predicate compare_less) {
-  ptrdiff_t count = end - start;
-  Heapify(start, count, compare_less);
-
-  ptrdiff_t end_index = count - 1;
-  while (end_index > 0) {
-    swap(start[end_index], start[0]);
-    SiftDown(start, 0, end_index - 1, compare_less);
-    end_index--;
-  }
-}
-
-template <typename RandomAccessIterator, typename Predicate>
-inline void NonCopyingSort(RandomAccessIterator start,
-                           RandomAccessIterator end,
-                           Predicate compare_less) {
-  // heapsort happens to use only swaps, not copies, but the essential thing
-  // about this function is the fact that it does not copy, not the specific
-  // algorithm
-  HeapSort(start, end, compare_less);
-}
-
-}  // namespace WTF
-
-using WTF::NonCopyingSort;
-
-#endif  // WTF_NonCopyingSort_h
diff --git a/third_party/WebKit/Source/platform/wtf/PrintStream.cpp b/third_party/WebKit/Source/platform/wtf/PrintStream.cpp
deleted file mode 100644
index 86ca3b28..0000000
--- a/third_party/WebKit/Source/platform/wtf/PrintStream.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "platform/wtf/PrintStream.h"
-
-#include "platform/wtf/text/CString.h"
-#include "platform/wtf/text/WTFString.h"
-#include <stdio.h>
-
-namespace WTF {
-
-PrintStream::PrintStream() = default;
-PrintStream::~PrintStream() = default;  // Force the vtable to be in this module
-
-void PrintStream::Printf(const char* format, ...) {
-  va_list arg_list;
-  va_start(arg_list, format);
-  Vprintf(format, arg_list);
-  va_end(arg_list);
-}
-
-void PrintStream::Flush() {}
-
-void PrintInternal(PrintStream& out, const char* string) {
-  out.Printf("%s", string);
-}
-
-void PrintInternal(PrintStream& out, const CString& string) {
-  out.Print(string.data());
-}
-
-void PrintInternal(PrintStream& out, const String& string) {
-  out.Print(string.Utf8());
-}
-
-void PrintInternal(PrintStream& out, bool value) {
-  if (value)
-    out.Print("true");
-  else
-    out.Print("false");
-}
-
-void PrintInternal(PrintStream& out, int value) {
-  out.Printf("%d", value);
-}
-
-void PrintInternal(PrintStream& out, unsigned value) {
-  out.Printf("%u", value);
-}
-
-void PrintInternal(PrintStream& out, long value) {
-  out.Printf("%ld", value);
-}
-
-void PrintInternal(PrintStream& out, unsigned long value) {
-  out.Printf("%lu", value);
-}
-
-void PrintInternal(PrintStream& out, long long value) {
-  out.Printf("%lld", value);
-}
-
-void PrintInternal(PrintStream& out, unsigned long long value) {
-  out.Printf("%llu", value);
-}
-
-void PrintInternal(PrintStream& out, float value) {
-  out.Print(static_cast<double>(value));
-}
-
-void PrintInternal(PrintStream& out, double value) {
-  out.Printf("%lf", value);
-}
-
-void DumpCharacter(PrintStream& out, char value) {
-  out.Printf("%c", value);
-}
-
-}  // namespace WTF
diff --git a/third_party/WebKit/Source/platform/wtf/PrintStream.h b/third_party/WebKit/Source/platform/wtf/PrintStream.h
deleted file mode 100644
index dfc8acc..0000000
--- a/third_party/WebKit/Source/platform/wtf/PrintStream.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef PrintStream_h
-#define PrintStream_h
-
-#include <stdarg.h>
-#include "base/macros.h"
-#include "platform/wtf/Allocator.h"
-#include "platform/wtf/Compiler.h"
-#include "platform/wtf/StdLibExtras.h"
-#include "platform/wtf/WTFExport.h"
-
-namespace WTF {
-
-class CString;
-class String;
-
-class WTF_EXPORT PrintStream {
-  USING_FAST_MALLOC(PrintStream);
-
- public:
-  PrintStream();
-  virtual ~PrintStream();
-
-  PRINTF_FORMAT(2, 3) void Printf(const char* format, ...);
-  PRINTF_FORMAT(2, 0) virtual void Vprintf(const char* format, va_list) = 0;
-
-  // Typically a no-op for many subclasses of PrintStream, this is a hint that
-  // the implementation should flush its buffers if it had not done so already.
-  virtual void Flush();
-
-  template <typename T>
-  void Print(const T& value) {
-    PrintInternal(*this, value);
-  }
-
-  template <typename T1, typename... RemainingTypes>
-  void Print(const T1& value1, const RemainingTypes&... values) {
-    Print(value1);
-    Print(values...);
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(PrintStream);
-};
-
-WTF_EXPORT void PrintInternal(PrintStream&, const char*);
-WTF_EXPORT void PrintInternal(PrintStream&, const CString&);
-WTF_EXPORT void PrintInternal(PrintStream&, const String&);
-inline void PrintInternal(PrintStream& out, char* value) {
-  PrintInternal(out, static_cast<const char*>(value));
-}
-inline void PrintInternal(PrintStream& out, CString& value) {
-  PrintInternal(out, static_cast<const CString&>(value));
-}
-inline void PrintInternal(PrintStream& out, String& value) {
-  PrintInternal(out, static_cast<const String&>(value));
-}
-WTF_EXPORT void PrintInternal(PrintStream&, bool);
-WTF_EXPORT void PrintInternal(PrintStream&, int);
-WTF_EXPORT void PrintInternal(PrintStream&, unsigned);
-WTF_EXPORT void PrintInternal(PrintStream&, long);
-WTF_EXPORT void PrintInternal(PrintStream&, unsigned long);
-WTF_EXPORT void PrintInternal(PrintStream&, long long);
-WTF_EXPORT void PrintInternal(PrintStream&, unsigned long long);
-WTF_EXPORT void PrintInternal(PrintStream&, float);
-WTF_EXPORT void PrintInternal(PrintStream&, double);
-
-template <typename T>
-void PrintInternal(PrintStream& out, const T& value) {
-  value.Dump(out);
-}
-
-}  // namespace WTF
-
-using WTF::PrintStream;
-
-#endif  // PrintStream_h
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/checker.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/checker.py
index f7a45fe..93e8495 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/checker.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/checker.py
@@ -142,7 +142,8 @@
         # Blink style.
         'Source/platform/scheduler',
         'public/platform/scheduler'],
-     ['-readability/parameter_name'])
+     ['-readability/parameter_name',
+      '-readability/control_flow'])
 ]
 
 
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index daeaa0b80..8e35b7d 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -281,6 +281,7 @@
     "platform/WebPrescientNetworking.h",
     "platform/WebPrivatePtr.h",
     "platform/WebPublicSuffixList.h",
+    "platform/WebRTCAPIName.h",
     "platform/WebRTCAnswerOptions.h",
     "platform/WebRTCCertificate.h",
     "platform/WebRTCCertificateGenerator.h",
@@ -769,6 +770,7 @@
     "platform/modules/presentation/presentation.mojom",
     "platform/modules/webauth/authenticator.mojom",
     "platform/modules/webdatabase/web_database.mojom",
+    "platform/modules/websockets/websocket.mojom",
     "platform/oom_intervention.mojom",
     "platform/referrer.mojom",
     "platform/reporting.mojom",
diff --git a/third_party/WebKit/public/mojom/BUILD.gn b/third_party/WebKit/public/mojom/BUILD.gn
index 20117fdd..526cb8d3 100644
--- a/third_party/WebKit/public/mojom/BUILD.gn
+++ b/third_party/WebKit/public/mojom/BUILD.gn
@@ -38,6 +38,10 @@
     "//mojo/common:common_custom_types",
     "//mojo/public/mojom/base",
     "//services/network/public/mojom",
+
+    # TODO(https://crbug.com/822804): Remove when mojom bindings deps checks
+    # get fixed.
+    "//services/network/public/mojom:data_pipe_interfaces",
     "//ui/gfx/geometry/mojo",
     "//url/mojom:url_mojom_gurl",
     "//url/mojom:url_mojom_origin",
diff --git a/third_party/WebKit/public/mojom/blob/blob.mojom b/third_party/WebKit/public/mojom/blob/blob.mojom
index 7792700..6cbbf820 100644
--- a/third_party/WebKit/public/mojom/blob/blob.mojom
+++ b/third_party/WebKit/public/mojom/blob/blob.mojom
@@ -4,6 +4,7 @@
 
 module blink.mojom;
 
+import "services/network/public/mojom/data_pipe_getter.mojom";
 import "services/network/public/mojom/http_request_headers.mojom";
 
 // Interface that can be implemented to be informed of certain information while
@@ -30,6 +31,9 @@
   // Creates a copy of this Blob reference.
   Clone(Blob& blob);
 
+  // Creates a reference to this Blob as a DataPipeGetter.
+  AsDataPipeGetter(network.mojom.DataPipeGetter& data_pipe_getter);
+
   // Causes the entire contents of this blob to be written into the given data
   // pipe. An optional BlobReaderClient will be informed of the result of the
   // read operation.
diff --git a/third_party/WebKit/public/platform/Platform.h b/third_party/WebKit/public/platform/Platform.h
index e5aa70c..5b3980e 100644
--- a/third_party/WebKit/public/platform/Platform.h
+++ b/third_party/WebKit/public/platform/Platform.h
@@ -47,6 +47,7 @@
 #include "WebGestureDevice.h"
 #include "WebLocalizedString.h"
 #include "WebPlatformEventType.h"
+#include "WebRTCAPIName.h"
 #include "WebSize.h"
 #include "WebSpeechSynthesizer.h"
 #include "WebString.h"
@@ -631,6 +632,8 @@
   virtual std::unique_ptr<WebImageCaptureFrameGrabber>
   CreateImageCaptureFrameGrabber();
 
+  virtual void UpdateWebRTCAPICount(WebRTCAPIName api_name) {}
+
   // WebSocket ----------------------------------------------------------
 
   // If this method returns non-null the returned object will be used to
diff --git a/third_party/WebKit/public/platform/WebHTTPBody.h b/third_party/WebKit/public/platform/WebHTTPBody.h
index 5f8d3be..16c40cd4 100644
--- a/third_party/WebKit/public/platform/WebHTTPBody.h
+++ b/third_party/WebKit/public/platform/WebHTTPBody.h
@@ -59,6 +59,7 @@
     long long file_length;  // -1 means to the end of the file.
     double modification_time;
     WebString blob_uuid;
+    mojo::ScopedMessagePipeHandle optional_blob_handle;
     // |data_pipe_getter| is a network::mojom::DataPipeGetterPtr. It's declared
     // as a generic ScopedMessagePipeHandle so it can be "cast" between Blink
     // and non-Blink variant types.
diff --git a/third_party/WebKit/public/platform/WebRTCAPIName.h b/third_party/WebKit/public/platform/WebRTCAPIName.h
new file mode 100644
index 0000000..f6288ff
--- /dev/null
+++ b/third_party/WebKit/public/platform/WebRTCAPIName.h
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WebRTCAPIName_h
+#define WebRTCAPIName_h
+
+namespace blink {
+
+// Helper enum used for histogramming calls to WebRTC APIs from JavaScript.
+// The entries are linked to UMA values in //tools/metrics/histograms/enums.xml
+// and shouldn't be renumbered or removed.
+enum class WebRTCAPIName {
+  kGetUserMedia,
+  kPeerConnection,
+  kDeprecatedPeerConnection,
+  kRTCPeerConnection,
+  kEnumerateDevices,
+  kMediaStreamRecorder,
+  kCanvasCaptureStream,
+  kVideoCaptureStream,
+  kInvalidName
+};
+
+}  // namespace blink
+
+#endif  // WebRTCAPIName_h
diff --git a/third_party/WebKit/public/platform/modules/websockets/OWNERS b/third_party/WebKit/public/platform/modules/websockets/OWNERS
new file mode 100644
index 0000000..d6fd3dac
--- /dev/null
+++ b/third_party/WebKit/public/platform/modules/websockets/OWNERS
@@ -0,0 +1,8 @@
+yhirano@chromium.org
+ricea@chromium.org
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
+
+# TEAM: blink-network-dev@chromium.org
+# COMPONENT: Blink>Network>WebSockets
diff --git a/services/network/public/mojom/websocket.mojom b/third_party/WebKit/public/platform/modules/websockets/websocket.mojom
similarity index 99%
rename from services/network/public/mojom/websocket.mojom
rename to third_party/WebKit/public/platform/modules/websockets/websocket.mojom
index d6cb515..e3302612 100644
--- a/services/network/public/mojom/websocket.mojom
+++ b/third_party/WebKit/public/platform/modules/websockets/websocket.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-module network.mojom;
+module blink.mojom;
 
 import "url/mojom/url.mojom";
 
diff --git a/third_party/WebKit/public/platform/unhandled_tap_notifier.mojom b/third_party/WebKit/public/platform/unhandled_tap_notifier.mojom
index d1d852f..398bbe7 100644
--- a/third_party/WebKit/public/platform/unhandled_tap_notifier.mojom
+++ b/third_party/WebKit/public/platform/unhandled_tap_notifier.mojom
@@ -11,6 +11,9 @@
 // This data is used to notifying the Browser to show UI for an unhandled tap if needed.
 struct UnhandledTapInfo {
     gfx.mojom.Point tapped_position_in_viewport;
+    // These values default to 0,  which indicates an undetermined value.
+    uint32 font_size_in_pixels = 0;
+    uint32 element_text_run_length = 0;
 };
 
 interface UnhandledTapNotifier {
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium
index 9305528..8ba967d 100644
--- a/third_party/libxml/README.chromium
+++ b/third_party/libxml/README.chromium
@@ -1,6 +1,6 @@
 Name: libxml
 URL: http://xmlsoft.org
-Version: 707ad080e61014ab4a6d60dc12875e233c1f673c
+Version: 2677fbf4a4a6dec69ff52265addab713fe48ad1f
 License: MIT
 License File: src/Copyright
 Security Critical: yes
diff --git a/third_party/libxml/chromium/chromium-issue-628581.patch b/third_party/libxml/chromium/chromium-issue-628581.patch
index fb5d2a4..42b7c63 100644
--- a/third_party/libxml/chromium/chromium-issue-628581.patch
+++ b/third_party/libxml/chromium/chromium-issue-628581.patch
@@ -71,7 +71,7 @@
  	unsigned long oldnbent = ctxt->nbentities;
  	xmlChar *rep;
  
-+	ent->guard = XML_ENTITY_BEING_CHECKED;
++        ent->guard = XML_ENTITY_BEING_CHECKED;
  	ent->checked = 1;
  
          ++ctxt->depth;
@@ -79,10 +79,10 @@
  				  XML_SUBSTITUTE_REF, 0, 0, 0);
          --ctxt->depth;
 +        ent->guard = XML_ENTITY_NOT_BEING_CHECKED;
- 	if ((rep == NULL) || (ctxt->errNo == XML_ERR_ENTITY_LOOP)) {
+ 	if (ctxt->errNo == XML_ERR_ENTITY_LOOP) {
  	    ent->content[0] = 0;
  	}
-@@ -7105,23 +7111,28 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
+@@ -7329,23 +7335,28 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
  	 * if its replacement text matches the production labeled
  	 * content.
  	 */
@@ -128,7 +128,7 @@
  
  	/*
  	 * Store the number of entities needing parsing for this entity
-@@ -7229,23 +7240,29 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
+@@ -7448,23 +7459,29 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
  	    else
  		user_data = ctxt->userData;
  
diff --git a/third_party/libxml/linux/xml2-config b/third_party/libxml/linux/xml2-config
index bb834c6..6ed8eb1 100755
--- a/third_party/libxml/linux/xml2-config
+++ b/third_party/libxml/linux/xml2-config
@@ -86,12 +86,12 @@
 	then
 	    if [ "-L${libdir}" = "-L/usr/lib" -o "-L${libdir}" = "-L/usr/lib64" ]
 	    then
-		echo -lxml2     -licui18n -licuuc -licudata -lm  
+		echo -lxml2      -L/usr/lib/x86_64-linux-gnu -licui18n -licuuc -licudata   -lm  
 	    else
-		echo -L${libdir} -lxml2     -licui18n -licuuc -licudata -lm  
+		echo -L${libdir} -lxml2      -L/usr/lib/x86_64-linux-gnu -licui18n -licuuc -licudata   -lm  
 	    fi
 	else
-	    echo -L${libdir} -lxml2     -licui18n -licuuc -licudata -lm   
+	    echo -L${libdir} -lxml2      -L/usr/lib/x86_64-linux-gnu -licui18n -licuuc -licudata   -lm   
 	fi
        	;;
 
diff --git a/third_party/libxml/src/HTMLparser.c b/third_party/libxml/src/HTMLparser.c
index 9adeb174..7e243e6 100644
--- a/third_party/libxml/src/HTMLparser.c
+++ b/third_party/libxml/src/HTMLparser.c
@@ -3635,7 +3635,7 @@
 	     */
 	    processed = ctxt->input->cur - ctxt->input->base;
 	    xmlBufShrink(ctxt->input->buf->buffer, processed);
-	    nbchars = xmlCharEncInput(ctxt->input->buf, 0);
+	    nbchars = xmlCharEncInput(ctxt->input->buf, 1);
 	    if (nbchars < 0) {
 		htmlParseErr(ctxt, XML_ERR_INVALID_ENCODING,
 		             "htmlCheckEncoding: encoder error\n",
diff --git a/third_party/libxml/src/configure.ac b/third_party/libxml/src/configure.ac
index ebfa702..988e32e5 100644
--- a/third_party/libxml/src/configure.ac
+++ b/third_party/libxml/src/configure.ac
@@ -769,9 +769,9 @@
     fi
 
     # warnings we'd like to see
-    EXTRA_CFLAGS="${EXTRA_CFLAGS} -pedantic -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wredundant-decls"
+    EXTRA_CFLAGS="${EXTRA_CFLAGS} -pedantic -W -Wformat -Wno-format-extra-args -Wunused -Wimplicit -Wreturn-type -Wswitch -Wcomment -Wtrigraphs -Wchar-subscripts -Wuninitialized -Wparentheses -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wredundant-decls"
     # warnings we'd like to supress
-    EXTRA_CFLAGS="${EXTRA_CFLAGS} -Wno-long-long -Wno-format-extra-args -Wno-array-bounds"
+    EXTRA_CFLAGS="${EXTRA_CFLAGS} -Wno-long-long"
     case "${host}" in
           alpha*-*-linux* )
 	       EXTRA_CFLAGS="${EXTRA_CFLAGS} -mieee"
diff --git a/third_party/libxml/src/libxml2.spec b/third_party/libxml/src/libxml2.spec
index 2b46112a..e0d24ff 100644
--- a/third_party/libxml/src/libxml2.spec
+++ b/third_party/libxml/src/libxml2.spec
@@ -203,6 +203,6 @@
 %endif # with_python3
 
 %changelog
-* Tue Jan 30 2018 Daniel Veillard <veillard@redhat.com>
+* Wed Dec 13 2017 Daniel Veillard <veillard@redhat.com>
 - upstream release 2.9.7 see http://xmlsoft.org/news.html
 
diff --git a/third_party/libxml/src/parser.c b/third_party/libxml/src/parser.c
index 072b129..6a34b27 100644
--- a/third_party/libxml/src/parser.c
+++ b/third_party/libxml/src/parser.c
@@ -147,7 +147,7 @@
 	unsigned long oldnbent = ctxt->nbentities;
 	xmlChar *rep;
 
-	ent->guard = XML_ENTITY_BEING_CHECKED;
+        ent->guard = XML_ENTITY_BEING_CHECKED;
 	ent->checked = 1;
 
         ++ctxt->depth;
@@ -155,7 +155,7 @@
 				  XML_SUBSTITUTE_REF, 0, 0, 0);
         --ctxt->depth;
         ent->guard = XML_ENTITY_NOT_BEING_CHECKED;
-	if ((rep == NULL) || (ctxt->errNo == XML_ERR_ENTITY_LOOP)) {
+	if (ctxt->errNo == XML_ERR_ENTITY_LOOP) {
 	    ent->content[0] = 0;
 	}
 
@@ -3376,9 +3376,9 @@
 	     */
 	    ctxt->input->cur -= l;
 	    GROW;
+	    ctxt->input->cur += l;
             if (ctxt->instate == XML_PARSER_EOF)
                 return(NULL);
-	    ctxt->input->cur += l;
 	    c = CUR_CHAR(l);
 	}
     }
@@ -7200,8 +7200,6 @@
 		   (ret != XML_WAR_UNDECLARED_ENTITY)) {
 	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 		     "Entity '%s' failed to parse\n", ent->name);
-            if (ent->content != NULL)
-                ent->content[0] = 0;
 	    xmlParserEntityCheck(ctxt, 0, ent, 0);
 	} else if (list != NULL) {
 	    xmlFreeNodeList(list);
@@ -12235,7 +12233,6 @@
 		    /* TODO 2.6.0 */
 		    xmlGenericError(xmlGenericErrorContext,
 				    "xmlParseChunk: encoder error\n");
-                    xmlHaltParser(ctxt);
 		    return(XML_ERR_INVALID_ENCODING);
 		}
 		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
@@ -13384,7 +13381,6 @@
 	ctxt->userData = ctxt;
     if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
     ctxt->dict = oldctxt->dict;
-    ctxt->input_id = oldctxt->input_id + 1;
     ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
     ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
     ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
@@ -13638,7 +13634,6 @@
     xmlDetectSAX2(ctxt);
     ctxt->myDoc = doc;
     /* parsing in context, i.e. as within existing content */
-    ctxt->input_id = 2;
     ctxt->instate = XML_PARSER_CONTENT;
 
     fake = xmlNewComment(NULL);
@@ -13851,7 +13846,6 @@
 	newDoc->oldNs = doc->oldNs;
     }
     ctxt->instate = XML_PARSER_CONTENT;
-    ctxt->input_id = 2;
     ctxt->depth = depth;
 
     /*
@@ -14012,11 +14006,6 @@
     if (pctx != NULL) {
         ctxt->options = pctx->options;
         ctxt->_private = pctx->_private;
-	/*
-	 * this is a subparser of pctx, so the input_id should be
-	 * incremented to distinguish from main entity
-	 */
-	ctxt->input_id = pctx->input_id + 1;
     }
 
     uri = xmlBuildURI(URL, base);
diff --git a/third_party/libxml/src/parserInternals.c b/third_party/libxml/src/parserInternals.c
index cfeb0a2..9d45e5ca 100644
--- a/third_party/libxml/src/parserInternals.c
+++ b/third_party/libxml/src/parserInternals.c
@@ -1214,7 +1214,7 @@
                 /*
                  * convert as much as possible of the buffer
                  */
-                nbchars = xmlCharEncInput(input->buf, 0);
+                nbchars = xmlCharEncInput(input->buf, 1);
             } else {
                 /*
                  * convert just enough to get
diff --git a/third_party/libxml/src/win32/Makefile.msvc b/third_party/libxml/src/win32/Makefile.msvc
index 491dc880..ff8378e 100644
--- a/third_party/libxml/src/win32/Makefile.msvc
+++ b/third_party/libxml/src/win32/Makefile.msvc
@@ -22,7 +22,6 @@
 XML_NAME = xml2
 XML_BASENAME = lib$(XML_NAME)
 XML_SO = $(XML_BASENAME).dll
-XML_RES = $(XML_BASENAME).res
 XML_IMP = $(XML_BASENAME).lib
 XML_DEF = $(XML_BASENAME).def
 XML_A = $(XML_BASENAME)_a.lib
@@ -70,11 +69,7 @@
 LIBS = $(LIBS) iconv.lib
 !endif 
 !if "$(WITH_ICU)" == "1"
-!if "$(STATIC)" == "1"
-LIBS = $(LIBS) advapi32.lib sicuuc.lib sicuin.lib sicudt.lib
-!else
-LIBS = $(LIBS) icuuc.lib icuin.lib icudt.lib
-!endif
+LIBS = $(LIBS) icu.lib
 !endif
 !if "$(WITH_ZLIB)" == "1"
 # could be named differently zdll or zlib
@@ -261,10 +256,7 @@
 	$(BINDIR)\testXPath.exe\
 	$(BINDIR)\runtest.exe\
 	$(BINDIR)\runsuite.exe\
-	$(BINDIR)\runxmlconf.exe\
 	$(BINDIR)\testapi.exe\
-	$(BINDIR)\testchar.exe\
-	$(BINDIR)\testdict.exe\
 	$(BINDIR)\testlimits.exe\
 	$(BINDIR)\testrecurse.exe
 	
@@ -375,13 +367,11 @@
 # Creates the export definition file (DEF) for libxml.
 $(XML_INTDIR)\$(XML_DEF) : $(XML_INTDIR) $(XML_DEF).src
 	$(CPP) $(CPPFLAGS) $(XML_DEF).src > $(XML_INTDIR)\$(XML_DEF)
-$(XML_INTDIR)\$(XML_RES) : $(XML_INTDIR) libxml2.rc
-	rc -Fo $(XML_INTDIR)\$(XML_RES) libxml2.rc
 
 # Creates the libxml shared object.
-$(BINDIR)\$(XML_SO) : $(BINDIR) $(XML_OBJS) $(XML_INTDIR)\$(XML_DEF) $(XML_INTDIR)\$(XML_RES)
+$(BINDIR)\$(XML_SO) : $(BINDIR) $(XML_OBJS) $(XML_INTDIR)\$(XML_DEF)
 	$(LD) $(LDFLAGS) /DLL \
-		/IMPLIB:$(BINDIR)\$(XML_IMP) /OUT:$(BINDIR)\$(XML_SO) $(XML_OBJS) $(XML_INTDIR)\$(XML_RES) $(LIBS)
+		/IMPLIB:$(BINDIR)\$(XML_IMP) /OUT:$(BINDIR)\$(XML_SO) $(XML_OBJS) $(LIBS)
 	@$(_VC_MANIFEST_EMBED_DLL)
 
 #$(BINDIR)\$(XML_SO) : $(BINDIR) $(XML_OBJS) $(XML_INTDIR)\$(XML_DEF)
diff --git a/third_party/libxml/src/win32/configure.js b/third_party/libxml/src/win32/configure.js
index dbf238c..92b9ba052 100644
--- a/third_party/libxml/src/win32/configure.js
+++ b/third_party/libxml/src/win32/configure.js
@@ -280,18 +280,6 @@
 		vf.WriteLine("DYNRUNTIME=" + (dynruntime? "1" : "0"));
 	}
 	vf.Close();
-	versionFile = "rcVersion.h"
-	vf = fso.CreateTextFile(versionFile, true);
-	vf.WriteLine("/*");
-	vf.WriteLine("  " + versionFile);
-	vf.WriteLine("  This file is generated automatically by " + WScript.ScriptName + ".");
-	vf.WriteLine("*/");
-	vf.WriteBlankLines(1);
-	vf.WriteLine("#define LIBXML_MAJOR_VERSION " + verMajor);
-	vf.WriteLine("#define LIBXML_MINOR_VERSION " + verMinor);
-	vf.WriteLine("#define LIBXML_MICRO_VERSION " + verMicro);
-	vf.WriteLine("#define LIBXML_DOTTED_VERSION " + "\"" + verMajor + "." + verMinor + "." + verMicro + "\"");
-	vf.Close()
 }
 
 /* Configures libxml. This one will generate xmlversion.h from xmlversion.h.in
diff --git a/third_party/libxml/src/win32/libxml2.rc b/third_party/libxml/src/win32/libxml2.rc
deleted file mode 100644
index c774a5e..0000000
--- a/third_party/libxml/src/win32/libxml2.rc
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <winver.h>
-#include "rcVersion.h"
-
-VS_VERSION_INFO		VERSIONINFO
-  FILEVERSION		LIBXML_MAJOR_VERSION,LIBXML_MINOR_VERSION,LIBXML_MICRO_VERSION,0
-  PRODUCTVERSION	LIBXML_MAJOR_VERSION,LIBXML_MINOR_VERSION,LIBXML_MICRO_VERSION,0
-  FILEFLAGSMASK		VS_FFI_FILEFLAGSMASK
-#ifdef _DEBUG
-  FILEFLAGS		VS_FF_DEBUG
-#else
-  FILEFLAGS		0
-#endif
-  FILEOS		VOS__WINDOWS32
-  FILETYPE		VFT_DLL
-  FILESUBTYPE	VFT2_UNKNOWN	// not used
-BEGIN
-  BLOCK "StringFileInfo"
-  BEGIN
-    BLOCK "04090000"  /* Lang = US English, Charset = ASCII */
-    BEGIN
-      VALUE "FileDescription",	"libxml2 library\0"
-      VALUE "FileVersion",	LIBXML_DOTTED_VERSION "\0"
-      VALUE "InternalName",	"libxml2.dll\0"
-      VALUE "LegalCopyright",	"Copyright (C) Daniel Veillard\0"
-      VALUE "LegalTrademarks",	"\0"
-      VALUE "OriginalFilename",	"libxml2.dll\0"
-      VALUE "ProductName",	"libxml2\0"
-      VALUE "ProductVersion",	LIBXML_DOTTED_VERSION "\0"
-      VALUE "Comments",		"For more information visit http://xmlsoft.org/\0"
-    END
-  END
-  BLOCK "VarFileInfo"
-  BEGIN
-      VALUE "Translation", 0x0409, 0  /* US English, ASCII */
-  END
-END
diff --git a/third_party/libxml/src/xmlIO.c b/third_party/libxml/src/xmlIO.c
index 8254347..f61dd05 100644
--- a/third_party/libxml/src/xmlIO.c
+++ b/third_party/libxml/src/xmlIO.c
@@ -3157,7 +3157,7 @@
 	 * convert as much as possible to the parser reading buffer.
 	 */
 	use = xmlBufUse(in->raw);
-	nbchars = xmlCharEncInput(in, 0);
+	nbchars = xmlCharEncInput(in, 1);
 	if (nbchars < 0) {
 	    xmlIOErr(XML_IO_ENCODER, NULL);
 	    in->error = XML_IO_ENCODER;
@@ -3273,7 +3273,7 @@
 	 * convert as much as possible to the parser reading buffer.
 	 */
 	use = xmlBufUse(in->raw);
-	nbchars = xmlCharEncInput(in, 0);
+	nbchars = xmlCharEncInput(in, 1);
 	if (nbchars < 0) {
 	    xmlIOErr(XML_IO_ENCODER, NULL);
 	    in->error = XML_IO_ENCODER;
diff --git a/tools/chrome_proxy/webdriver/lite_page.py b/tools/chrome_proxy/webdriver/lite_page.py
index c4eb7ccd..095b928 100644
--- a/tools/chrome_proxy/webdriver/lite_page.py
+++ b/tools/chrome_proxy/webdriver/lite_page.py
@@ -209,8 +209,8 @@
       test_driver.AddChromeArg('--force-effective-connection-type=2G')
 
       # Need to force lite page so target page doesn't fallback to Lo-Fi
-      # Set exp=alt1 to force Lite-page response.
-      test_driver.AddChromeArg('--data-reduction-proxy-experiment=alt1')
+      # Set exp=alt6 to force Lite-page response.
+      test_driver.AddChromeArg('--data-reduction-proxy-experiment=alt6')
 
       # This page is long and has many media resources.
       test_driver.LoadURL('http://check.googlezip.net/metrics/index.html')
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 5fedfaa4..b955c4d 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -27,7 +27,7 @@
 # Do NOT CHANGE this if you don't know what you're doing -- see
 # https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md
 # Reverting problematic clang rolls is safe, though.
-CLANG_REVISION = '325667'
+CLANG_REVISION = '327688'
 
 use_head_revision = bool(os.environ.get('LLVM_FORCE_HEAD_REVISION', '0')
                          in ('1', 'YES'))
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index b3fa2a3..a8795c5 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -23852,17 +23852,6 @@
   <int value="1" label="Saved"/>
 </enum>
 
-<enum name="JavaScriptAPIName">
-  <int value="0" label="GetUserMedia"/>
-  <int value="1" label="PeerConnection00"/>
-  <int value="2" label="DeprecatedPeerConnection"/>
-  <int value="3" label="RTCPeerConnection"/>
-  <int value="4" label="GetMediaDevices"/>
-  <int value="5" label="MediaStreamRecorder"/>
-  <int value="6" label="CanvasCaptureStream"/>
-  <int value="7" label="VideoCaptureStream"/>
-</enum>
-
 <enum name="JavaScriptDialogDismissalCause">
   <int value="0" label="Tab closed">The tab owning the dialog was closed</int>
   <int value="1" label="New dialog">
@@ -30301,6 +30290,53 @@
   <int value="8" label="subresource and used"/>
 </enum>
 
+<enum name="NetReportingHeaderEndpointGroupOutcome">
+  <int value="0" label="Discarded: not a dictionary"/>
+  <int value="1" label="Discarded: group not a string"/>
+  <int value="2" label="Discarded: TTL missing"/>
+  <int value="3" label="Discarded: TTL not an integer"/>
+  <int value="4" label="Discarded: TTL negative"/>
+  <int value="5" label="Discarded: endpoints missing"/>
+  <int value="6" label="Discarded: endpoints not a list"/>
+  <int value="7" label="Parsed"/>
+</enum>
+
+<enum name="NetReportingHeaderEndpointOutcome">
+  <int value="0" label="Discarded: not a dictionary"/>
+  <int value="1" label="Discarded: URL missing"/>
+  <int value="2" label="Discarded: URL not a string"/>
+  <int value="3" label="Discarded: URL invalid"/>
+  <int value="4" label="Discarded: URL insecure"/>
+  <int value="5" label="Discarded: priority not an integer"/>
+  <int value="6" label="Discarded: weight not an integer"/>
+  <int value="7" label="Discarded: weight not positive"/>
+  <int value="8" label="Removed (max-age = 0)"/>
+  <int value="9" label="Set rejected by delegate (max-age &gt; 0)"/>
+  <int value="10" label="Set (max-age &gt; 0)"/>
+</enum>
+
+<enum name="NetReportingHeaderOutcome">
+  <int value="0" label="Discarded: no ReportingService"/>
+  <int value="1" label="Discarded: invalid SSLInfo"/>
+  <int value="2" label="Discarded: cert status error"/>
+  <int value="3" label="Discarded: JSON too big"/>
+  <int value="4" label="Discarded: JSON invalid"/>
+  <int value="5" label="Parsed"/>
+</enum>
+
+<enum name="NetReportingReportOutcome">
+  <int value="0" label="Unknown"/>
+  <int value="1" label="Discarded: no URLRequestContext"/>
+  <int value="2" label="Discarded: no ReportingService"/>
+  <int value="3" label="Erased: failed"/>
+  <int value="4" label="Erased: expired"/>
+  <int value="5" label="Erased: evicted"/>
+  <int value="6" label="Erased: network changed"/>
+  <int value="7" label="Erased: browsing data removed"/>
+  <int value="8" label="Erased: Reporting shut down"/>
+  <int value="9" label="Delivered"/>
+</enum>
+
 <enum name="NetTrustAnchors">
 <!-- Generated from net/data/ssl/root_stores/root_stores.json.
 Called by update_net_trust_anchors.py.-->
@@ -37818,6 +37854,16 @@
   <int value="31" label="InternalIPC"/>
 </enum>
 
+<enum name="RendererSchedulerTaskUseCase">
+  <int value="0" label="None"/>
+  <int value="1" label="CompositorGesture"/>
+  <int value="2" label="MainThreadCustomHandling"/>
+  <int value="3" label="SynchronizedGesture"/>
+  <int value="4" label="TouchStart"/>
+  <int value="5" label="Loading"/>
+  <int value="6" label="MainThreadGesture"/>
+</enum>
+
 <enum name="RendererSchedulerThreadType">
   <int value="0" label="MainThread"/>
   <int value="1" label="UnspecifiedWorkerThread"/>
@@ -37943,6 +37989,9 @@
 </enum>
 
 <enum name="ReportingHeaderEndpointGroupOutcome">
+  <obsolete>
+    Moved to NetReportingHeaderEndpointGroupOutcome.
+  </obsolete>
   <int value="0" label="Discarded: not a dictionary"/>
   <int value="1" label="Discarded: group not a string"/>
   <int value="2" label="Discarded: TTL missing"/>
@@ -37954,6 +38003,9 @@
 </enum>
 
 <enum name="ReportingHeaderEndpointOutcome">
+  <obsolete>
+    Moved to NetReportingHeaderEndpointOutcome.
+  </obsolete>
   <int value="0" label="Discarded: not a dictionary"/>
   <int value="1" label="Discarded: endpoint missing (obsolete)"/>
   <int value="2" label="Discarded: endpoint not a string (obsolete)"/>
@@ -37976,14 +38028,21 @@
 </enum>
 
 <enum name="ReportingHeaderOutcome">
+  <obsolete>
+    Moved to NetReportingHeaderOutcome.
+  </obsolete>
   <int value="0" label="Discarded: no ReportingService"/>
   <int value="1" label="Discarded: invalid SSLInfo"/>
   <int value="2" label="Discarded: cert status error"/>
-  <int value="3" label="Discarded: invalid JSON"/>
+  <int value="3" label="Discarded: JSON invalid"/>
   <int value="4" label="Parsed"/>
+  <int value="5" label="Discarded: JSON too big"/>
 </enum>
 
 <enum name="ReportingReportOutcome">
+  <obsolete>
+    Moved to NetReportingReportOutcome.
+  </obsolete>
   <int value="0" label="Unknown"/>
   <int value="1" label="Discarded: no URLRequestContext"/>
   <int value="2" label="Discarded: no ReportingService"/>
@@ -45925,6 +45984,17 @@
   <int value="4" label="Excellent."/>
 </enum>
 
+<enum name="WebRTCAPIName">
+  <int value="0" label="GetUserMedia"/>
+  <int value="1" label="PeerConnection00"/>
+  <int value="2" label="DeprecatedPeerConnection"/>
+  <int value="3" label="RTCPeerConnection"/>
+  <int value="4" label="GetMediaDevices"/>
+  <int value="5" label="MediaStreamRecorder"/>
+  <int value="6" label="CanvasCaptureStream"/>
+  <int value="7" label="VideoCaptureStream"/>
+</enum>
+
 <enum name="WebRtcAudioCodecs">
   <int value="0" label="Unknown"/>
   <int value="1" label="Opus"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 23cfb4c9..56ea2bc 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -38031,7 +38031,7 @@
 
 <histogram name="MediaRouter.Source.CastingSource"
     enum="MediaRouterSourceTypes">
-  <owner>paezagon@chromium.org</owner>
+  <owner>amp@chromium.org</owner>
   <summary>
     The source of a Media Router session. This is recorded to keep track of what
     kind of media is being streamed.
@@ -38039,7 +38039,7 @@
 </histogram>
 
 <histogram name="MediaRouter.Source.LocalFileFormat" enum="MediaContainers">
-  <owner>paezagon@chromium.org</owner>
+  <owner>amp@chromium.org</owner>
   <summary>
     The file format of a local media Media Router session. This is recorded when
     a casting session begins to keep track of what kind of media is being
@@ -38048,7 +38048,7 @@
 </histogram>
 
 <histogram name="MediaRouter.Source.LocalFileSize" units="MB">
-  <owner>paezagon@chromium.org</owner>
+  <owner>amp@chromium.org</owner>
   <summary>
     The file size of a local media Media Router session. This is recorded when a
     casting session begins to keep track of what kind of media is being
@@ -48330,6 +48330,58 @@
   </summary>
 </histogram>
 
+<histogram name="Net.Reporting.HeaderEndpointGroupOutcome"
+    enum="NetReportingHeaderEndpointGroupOutcome">
+  <owner>juliatuttle@chromium.org</owner>
+  <summary>
+    The outcome of Reporting trying to process a single endpoint group in a
+    Report-To header once the header itself has been parsed.
+  </summary>
+</histogram>
+
+<histogram name="Net.Reporting.HeaderEndpointOutcome"
+    enum="NetReportingHeaderEndpointOutcome">
+  <owner>juliatuttle@chromium.org</owner>
+  <summary>
+    The outcome of Reporting trying to process a single endpoint in a Report-To
+    header once the header itself has been parsed.
+  </summary>
+</histogram>
+
+<histogram name="Net.Reporting.HeaderOutcome" enum="NetReportingHeaderOutcome">
+  <owner>juliatuttle@chromium.org</owner>
+  <summary>
+    The outcome of Reporting trying to process a Report-To header. Once it is
+    parsed, Reporting.HeaderEndpointOutcome records the outcome of the endpoints
+    within it.
+  </summary>
+</histogram>
+
+<histogram name="Net.Reporting.ReportDeliveredAttempts" units="attempts">
+  <owner>juliatuttle@chromium.org</owner>
+  <summary>
+    When Reporting successfully delivers a report, the number of unsuccessful
+    delivery attempts that preceded the successful one.
+  </summary>
+</histogram>
+
+<histogram name="Net.Reporting.ReportDeliveredLatency" units="ms">
+  <owner>juliatuttle@chromium.org</owner>
+  <summary>
+    The delivery latency of reports successfully delivered by Reporting. Starts
+    when the report is queued and finishes when the delivery attempt returns
+    successfully.
+  </summary>
+</histogram>
+
+<histogram name="Net.Reporting.ReportOutcome" enum="NetReportingReportOutcome">
+  <owner>juliatuttle@chromium.org</owner>
+  <summary>
+    The outcome of Reporting trying to deliver a report, recorded when the
+    report is finally erased from memory.
+  </summary>
+</histogram>
+
 <histogram name="Net.RequestTime">
   <obsolete>
     Replaced by Net.RequestTime2 due to bug in original implementation.
@@ -73270,6 +73322,18 @@
   </summary>
 </histogram>
 
+<histogram name="RendererScheduler.TaskDurationPerUseCase"
+    enum="RendererSchedulerTaskUseCase">
+  <owner>altimin@chromium.org</owner>
+  <owner>farahcharab@chromium.org</owner>
+  <summary>
+    Total duration (measured in ms) of renderer main thread tasks split by
+    scheduler use case. Use case is a scheduler's educated guess of the current
+    state of the world. See renderer/use_case.h and
+    RendererSchedulerImpl::UpdatePolicy for more details.
+  </summary>
+</histogram>
+
 <histogram name="RendererScheduler.TaskQueueManager.DelayedTaskLateness"
     units="ms">
   <obsolete>
@@ -73596,6 +73660,9 @@
 
 <histogram name="Reporting.HeaderEndpointGroupOutcome"
     enum="ReportingHeaderEndpointGroupOutcome">
+  <obsolete>
+    Moved to Net.Reporting.HeaderEndpointGroupOutcome.
+  </obsolete>
   <owner>juliatuttle@chromium.org</owner>
   <summary>
     The outcome of Reporting trying to process a single endpoint group in a
@@ -73605,6 +73672,9 @@
 
 <histogram name="Reporting.HeaderEndpointOutcome"
     enum="ReportingHeaderEndpointOutcome">
+  <obsolete>
+    Moved to Net.Reporting.HeaderEndpointOutcome.
+  </obsolete>
   <owner>juliatuttle@chromium.org</owner>
   <summary>
     The outcome of Reporting trying to process a single endpoint in a Report-To
@@ -73613,6 +73683,9 @@
 </histogram>
 
 <histogram name="Reporting.HeaderOutcome" enum="ReportingHeaderOutcome">
+  <obsolete>
+    Moved to Net.Reporting.HeaderOutcome.
+  </obsolete>
   <owner>juliatuttle@chromium.org</owner>
   <summary>
     The outcome of Reporting trying to process a Report-To header. Once it is
@@ -73622,6 +73695,9 @@
 </histogram>
 
 <histogram name="Reporting.ReportDeliveredAttempts" units="attempts">
+  <obsolete>
+    Moved to Net.Reporting.ReportDeliveredAttempts.
+  </obsolete>
   <owner>juliatuttle@chromium.org</owner>
   <summary>
     When Reporting successfully delivers a report, the number of unsuccessful
@@ -73630,6 +73706,9 @@
 </histogram>
 
 <histogram name="Reporting.ReportDeliveredLatency" units="ms">
+  <obsolete>
+    Moved to Net.Reporting.ReportDeliveredLatency.
+  </obsolete>
   <owner>juliatuttle@chromium.org</owner>
   <summary>
     The delivery latency of reports successfully delivered by Reporting. Starts
@@ -73639,6 +73718,9 @@
 </histogram>
 
 <histogram name="Reporting.ReportOutcome" enum="ReportingReportOutcome">
+  <obsolete>
+    Moved to Net.Reporting.ReportOutcome.
+  </obsolete>
   <owner>juliatuttle@chromium.org</owner>
   <summary>
     The outcome of Reporting trying to deliver a report, recorded when the
@@ -79352,6 +79434,15 @@
   </summary>
 </histogram>
 
+<histogram name="Search.ContextualSearch.All.ResultsSeen" enum="Boolean">
+  <owner>donnd@chromium.org</owner>
+  <owner>twellington@chromium.org</owner>
+  <summary>
+    Records whether the user opened the panel when it was shown. Recorded for
+    all gestures for all users when the UX is hidden. Implemented for Android.
+  </summary>
+</histogram>
+
 <histogram name="Search.ContextualSearch.Ranker.FeaturesAvailable"
     enum="Boolean">
   <owner>donnd@chromium.org</owner>
@@ -79463,6 +79554,16 @@
   </summary>
 </histogram>
 
+<histogram name="Search.ContextualSearch.Tap.ResultsSeen" enum="Boolean">
+  <owner>donnd@chromium.org</owner>
+  <owner>twellington@chromium.org</owner>
+  <summary>
+    Records whether the user opened the panel when it was shown in response to a
+    tap gesture, for all users. Recorded when the UX is hidden. Implemented for
+    Android.
+  </summary>
+</histogram>
+
 <histogram name="Search.ContextualSearchAllCapsResultsSeen"
     enum="ContextualSearchResultsSeen">
   <obsolete>
@@ -103127,14 +103228,14 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.webkitApiCount" enum="JavaScriptAPIName">
+<histogram name="WebRTC.webkitApiCount" enum="WebRTCAPIName">
   <owner>perkj@chromium.org</owner>
   <owner>mcasas@chromium.org</owner>
   <owner>emircan@chromium.org</owner>
   <summary>Counts number of calls to WebRTC APIs from JavaScript.</summary>
 </histogram>
 
-<histogram name="WebRTC.webkitApiCountPerSession" enum="JavaScriptAPIName">
+<histogram name="WebRTC.webkitApiCountPerSession" enum="WebRTCAPIName">
   <owner>perkj@chromium.org</owner>
   <summary>
     Counts the number of calls to WebRTC APIs from JavaScript once per session.
@@ -103143,7 +103244,7 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.webkitApiCountUniqueByOrigin" enum="JavaScriptAPIName">
+<histogram name="WebRTC.webkitApiCountUniqueByOrigin" enum="WebRTCAPIName">
   <obsolete>
     Deprecated as of r253828 (27 Feb 2014).
   </obsolete>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 7b6bdca..472749c 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -3169,6 +3169,12 @@
       Deprecated.
     </summary>
   </metric>
+  <metric name="WasOmniboxNavigation">
+    <summary>
+      A boolean that is set to 1 if this page was entered into the omnibox,
+      either manually or using autocomplete.
+    </summary>
+  </metric>
   <metric name="WasVoiceSearchNavigation">
     <summary>
       A boolean that is set to 1 if this page was specifically requested and
diff --git a/tools/perf/core/benchmark_sharding_map.json b/tools/perf/core/benchmark_sharding_map.json
index 5305dbd..b77c2080 100644
--- a/tools/perf/core/benchmark_sharding_map.json
+++ b/tools/perf/core/benchmark_sharding_map.json
@@ -2324,7 +2324,7 @@
     }
   },
   "Win 10 Perf": {
-    "build132-m1": {
+    "build189-a9": {
       "benchmarks": [
         "blink_perf.dom",
         "blink_perf.paint",
@@ -2343,7 +2343,7 @@
         "v8.runtime_stats.top_25"
       ]
     },
-    "build133-m1": {
+    "build190-a9": {
       "benchmarks": [
         "blink_perf.bindings",
         "blink_perf.canvas",
@@ -2370,7 +2370,7 @@
         "webrtc"
       ]
     },
-    "build134-m1": {
+    "build191-a9": {
       "benchmarks": [
         "battor.trivial_pages",
         "blink_perf.layout",
@@ -2395,7 +2395,7 @@
         "wasm"
       ]
     },
-    "build135-m1": {
+    "build192-a9": {
       "benchmarks": [
         "blink_perf.parser",
         "blink_perf.svg",
@@ -2416,7 +2416,7 @@
         "v8.detached_context_age_in_gc"
       ]
     },
-    "build136-m1": {
+    "build193-a9": {
       "benchmarks": [
         "battor.steady_state",
         "blink_perf.css",
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 3edb90f..df99d2f 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -307,16 +307,16 @@
     waterfall, 'Win 10 Perf', 'chromium-rel-win10', 'win',
     swarming=[
       {
-       'gpu': '102b:0534',
+       'gpu': '8086:5912',
        'os': 'Windows-10',
        'pool': 'Chrome-perf',
        'device_ids': [
-           'build132-m1', 'build133-m1',
-           'build134-m1', 'build135-m1', 'build136-m1'
+           'build189-a9', 'build190-a9',
+           'build191-a9', 'build192-a9', 'build193-a9'
           ],
        'perf_tests': [
-         ('media_perftests', 'build134-m1'),
-         ('views_perftests', 'build135-m1')]
+         ('media_perftests', 'build189-a9'),
+         ('views_perftests', 'build190-a9')]
       }
     ])
   waterfall = add_tester(
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 46196ae3..75ea5aff 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -182,7 +182,7 @@
  <item id="proxy_config_headless" hash_code="133221587" type="0" content_hash_code="77459277" os_list="linux,windows" file_path="headless/lib/browser/headless_url_request_context_getter.cc"/>
  <item id="proxy_config_settings" hash_code="136468456" type="0" content_hash_code="19527377" os_list="linux,windows" file_path="components/proxy_config/pref_proxy_config_tracker_impl.cc"/>
  <item id="proxy_config_system" hash_code="11258689" type="0" content_hash_code="77057929" os_list="linux,windows" file_path="net/proxy_resolution/proxy_resolution_service.cc"/>
- <item id="proxy_script_fetcher" hash_code="37531401" type="0" content_hash_code="31866133" os_list="windows" file_path="net/proxy_resolution/pac_file_fetcher_impl.cc"/>
+ <item id="proxy_script_fetcher" hash_code="37531401" type="0" deprecated="2018-03-16" content_hash_code="31866133" file_path=""/>
  <item id="puch_client_channel" hash_code="34459548" type="0" content_hash_code="92475475" os_list="linux,windows" file_path="components/invalidation/impl/push_client_channel.cc"/>
  <item id="quic_chromium_incoming_session" hash_code="87635401" type="0" content_hash_code="78573093" os_list="linux,windows" file_path="net/quic/chromium/quic_chromium_client_session.cc"/>
  <item id="quic_chromium_packet_writer" hash_code="20153177" type="0" content_hash_code="29657765" os_list="linux,windows" file_path="net/quic/chromium/quic_chromium_packet_writer.cc"/>
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn
index e97e672..4d79daecb 100644
--- a/ui/app_list/BUILD.gn
+++ b/ui/app_list/BUILD.gn
@@ -44,6 +44,8 @@
     "views/apps_grid_view.cc",
     "views/apps_grid_view.h",
     "views/apps_grid_view_folder_delegate.h",
+    "views/assistant_container_view.cc",
+    "views/assistant_container_view.h",
     "views/contents_view.cc",
     "views/contents_view.h",
     "views/expand_arrow_view.cc",
@@ -99,6 +101,7 @@
     "//base:i18n",
     "//base/third_party/dynamic_annotations",
     "//cc/paint",
+    "//chromeos:chromeos",
     "//components/keyed_service/core",
     "//components/sync",
     "//components/wallpaper",
diff --git a/ui/app_list/DEPS b/ui/app_list/DEPS
index eda8186..0784ca1 100644
--- a/ui/app_list/DEPS
+++ b/ui/app_list/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+chromeos/chromeos_switches.h",
   "+components/keyed_service/core",
   "+components/sync",
   "+components/wallpaper",
diff --git a/ui/app_list/app_list_constants.cc b/ui/app_list/app_list_constants.cc
index c99b2c55..65209f39 100644
--- a/ui/app_list/app_list_constants.cc
+++ b/ui/app_list/app_list_constants.cc
@@ -47,6 +47,11 @@
 const int kGridSelectedSize = 64;
 const int kGridSelectedCornerRadius = 8;
 
+// The preferred height for horizontal pages. For page #01 in the apps grid, it
+// includes the top/bottom 24px padding. For page #02 and all the followings,
+// it includes top 24px padding and bottom 56px padding.
+const int kHorizontalPagePreferredHeight = 623;
+
 const SkColor kFolderTitleColor = SkColorSetRGB(0x33, 0x33, 0x33);
 const SkColor kFolderTitleHintTextColor = SkColorSetRGB(0xA0, 0xA0, 0xA0);
 // Color of the folder bubble shadow.
diff --git a/ui/app_list/app_list_constants.h b/ui/app_list/app_list_constants.h
index 13b4178..2fcbe811 100644
--- a/ui/app_list/app_list_constants.h
+++ b/ui/app_list/app_list_constants.h
@@ -46,6 +46,8 @@
 APP_LIST_EXPORT extern const int kGridSelectedSize;
 APP_LIST_EXPORT extern const int kGridSelectedCornerRadius;
 
+APP_LIST_EXPORT extern const int kHorizontalPagePreferredHeight;
+
 APP_LIST_EXPORT extern const SkColor kFolderTitleColor;
 APP_LIST_EXPORT extern const SkColor kFolderTitleHintTextColor;
 APP_LIST_EXPORT extern const SkColor kFolderShadowColor;
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc
index e59c1ef..59b0cd01 100644
--- a/ui/app_list/views/apps_grid_view.cc
+++ b/ui/app_list/views/apps_grid_view.cc
@@ -61,11 +61,8 @@
 
 namespace {
 
-// The preferred width/height for apps grid. For page #01, it includes the
-// top/bottom 24px padding. For page #02 and all the followings, it includes top
-// 24px padding and bottom 56px padding.
+// The preferred width for apps grid.
 constexpr int kAppsGridPreferredWidth = 576;
-constexpr int kAppsGridPreferredHeight = 623;
 
 // 32px page break space adjustment needed to keep 48px page break space due to
 // the fact that page #02 and all the followings have bottom 56px padding.
@@ -765,7 +762,8 @@
   if (folder_delegate_)
     return GetTileGridSize();
 
-  gfx::Size size = gfx::Size(kAppsGridPreferredWidth, kAppsGridPreferredHeight);
+  gfx::Size size =
+      gfx::Size(kAppsGridPreferredWidth, kHorizontalPagePreferredHeight);
   return size;
 }
 
@@ -2338,7 +2336,7 @@
 
 gfx::Size AppsGridView::GetTileGridSize() const {
   if (!folder_delegate_)
-    return gfx::Size(kAppsGridPreferredWidth, kAppsGridPreferredHeight);
+    return gfx::Size(kAppsGridPreferredWidth, kHorizontalPagePreferredHeight);
 
   gfx::Rect rect(GetTotalTileSize());
   rect.set_size(
diff --git a/ui/app_list/views/assistant_container_view.cc b/ui/app_list/views/assistant_container_view.cc
new file mode 100644
index 0000000..7cb6d3f
--- /dev/null
+++ b/ui/app_list/views/assistant_container_view.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/app_list/views/assistant_container_view.h"
+
+#include "ui/app_list/app_list_constants.h"
+#include "ui/app_list/views/contents_view.h"
+
+namespace app_list {
+
+AssistantContainerView::AssistantContainerView(ContentsView* contents_view)
+    : contents_view_(contents_view) {}
+
+gfx::Size AssistantContainerView::CalculatePreferredSize() const {
+  if (!GetWidget()) {
+    return gfx::Size();
+  }
+  return gfx::Size(contents_view_->GetDisplayWidth(),
+                   kHorizontalPagePreferredHeight);
+}
+
+}  // namespace app_list
diff --git a/ui/app_list/views/assistant_container_view.h b/ui/app_list/views/assistant_container_view.h
new file mode 100644
index 0000000..31b144ea6
--- /dev/null
+++ b/ui/app_list/views/assistant_container_view.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_APP_LIST_VIEWS_ASSISTANT_CONTAINER_VIEW_H_
+#define UI_APP_LIST_VIEWS_ASSISTANT_CONTAINER_VIEW_H_
+
+#include "base/macros.h"
+#include "ui/app_list/views/horizontal_page.h"
+
+namespace app_list {
+
+class ContentsView;
+
+class APP_LIST_EXPORT AssistantContainerView : public HorizontalPage {
+ public:
+  explicit AssistantContainerView(ContentsView* contents_view);
+  ~AssistantContainerView() override = default;
+
+  // Overridden from views::View.
+  gfx::Size CalculatePreferredSize() const override;
+
+ private:
+  ContentsView* const contents_view_;  // Not owned.
+
+  DISALLOW_COPY_AND_ASSIGN(AssistantContainerView);
+};
+
+}  // namespace app_list
+
+#endif  // UI_APP_LIST_VIEWS_ASSISTANT_CONTAINER_VIEW_H_
diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc
index 47397a340..ad344da 100644
--- a/ui/app_list/views/contents_view.cc
+++ b/ui/app_list/views/contents_view.cc
@@ -458,6 +458,14 @@
       .height();
 }
 
+int ContentsView::GetDisplayWidth() const {
+  return display::Screen::GetScreen()
+      ->GetDisplayNearestView(GetWidget()->GetNativeView())
+      .work_area()
+      .size()
+      .width();
+}
+
 void ContentsView::FadeOutOnClose(base::TimeDelta animation_duration) {
   DoAnimation(animation_duration, layer(), 0.0f);
   DoAnimation(animation_duration, GetSearchBoxView()->layer(), 0.0f);
diff --git a/ui/app_list/views/contents_view.h b/ui/app_list/views/contents_view.h
index a2d1d72d2..ea3fa1a 100644
--- a/ui/app_list/views/contents_view.h
+++ b/ui/app_list/views/contents_view.h
@@ -154,6 +154,9 @@
   // Returns the height of current display.
   int GetDisplayHeight() const;
 
+  // Returns the width of the current display.
+  int GetDisplayWidth() const;
+
   // Starts the fade out animation when the app list is closed.
   void FadeOutOnClose(base::TimeDelta animation_duration);
 
diff --git a/ui/app_list/views/horizontal_page_container.cc b/ui/app_list/views/horizontal_page_container.cc
index 959ea19..706cf303 100644
--- a/ui/app_list/views/horizontal_page_container.cc
+++ b/ui/app_list/views/horizontal_page_container.cc
@@ -5,10 +5,12 @@
 #include "ui/app_list/views/horizontal_page_container.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "chromeos/chromeos_switches.h"
 #include "ui/app_list/app_list_constants.h"
 #include "ui/app_list/pagination_controller.h"
 #include "ui/app_list/views/app_list_view.h"
 #include "ui/app_list/views/apps_container_view.h"
+#include "ui/app_list/views/assistant_container_view.h"
 #include "ui/app_list/views/contents_view.h"
 #include "ui/chromeos/search_box/search_box_constants.h"
 #include "ui/views/controls/label.h"
@@ -33,9 +35,13 @@
   pagination_controller_.reset(new PaginationController(
       &pagination_model_, PaginationController::SCROLL_AXIS_HORIZONTAL));
 
-  apps_container_view_ = new AppsContainerView(contents_view_, model);
-
   // Add horizontal pages.
+  if (chromeos::switches::IsAssistantEnabled()) {
+    assistant_container_view_ = new AssistantContainerView(contents_view_);
+    AddHorizontalPage(assistant_container_view_);
+  }
+
+  apps_container_view_ = new AppsContainerView(contents_view_, model);
   AddHorizontalPage(apps_container_view_);
   pagination_model_.SetTotalPages(horizontal_pages_.size());
 
@@ -48,7 +54,11 @@
 }
 
 gfx::Size HorizontalPageContainer::CalculatePreferredSize() const {
-  return apps_container_view_->GetPreferredSize();
+  gfx::Size size;
+  for (auto* page : horizontal_pages_) {
+    size.SetToMax(page->GetPreferredSize());
+  }
+  return size;
 }
 
 void HorizontalPageContainer::Layout() {
diff --git a/ui/app_list/views/horizontal_page_container.h b/ui/app_list/views/horizontal_page_container.h
index 3d428f6..b25bf03 100644
--- a/ui/app_list/views/horizontal_page_container.h
+++ b/ui/app_list/views/horizontal_page_container.h
@@ -14,6 +14,7 @@
 namespace app_list {
 
 class AppsContainerView;
+class AssistantContainerView;
 class PaginationController;
 class HorizontalPage;
 
@@ -79,6 +80,9 @@
   // Owned by view hierarchy:
   AppsContainerView* apps_container_view_ = nullptr;
 
+  // Owned by view hierarchy:
+  AssistantContainerView* assistant_container_view_ = nullptr;
+
   // The child page views. Owned by the views hierarchy.
   std::vector<HorizontalPage*> horizontal_pages_;
 
diff --git a/ui/aura/hit_test_data_provider_aura.cc b/ui/aura/hit_test_data_provider_aura.cc
index 0f7600a..0f96540 100644
--- a/ui/aura/hit_test_data_provider_aura.cc
+++ b/ui/aura/hit_test_data_provider_aura.cc
@@ -22,13 +22,10 @@
   hit_test_region->frame_sink_id = window->GetFrameSinkId();
   // Checking |layer| may not be correct, since the actual layer that embeds
   // the surface may be a descendent of |layer|, instead of |layer| itself.
-  if (window->IsEmbeddingClient()) {
-    DCHECK(window->GetLocalSurfaceId().is_valid());
-    hit_test_region->local_surface_id = window->GetLocalSurfaceId();
+  if (window->IsEmbeddingClient())
     hit_test_region->flags = flags | viz::mojom::kHitTestChildSurface;
-  } else {
+  else
     hit_test_region->flags = flags | viz::mojom::kHitTestMine;
-  }
   hit_test_region->rect = rect;
   hit_test_region->transform = layer->transform();
 
diff --git a/ui/aura/mus/embed_root.cc b/ui/aura/mus/embed_root.cc
index c3b05e0..058baca 100644
--- a/ui/aura/mus/embed_root.cc
+++ b/ui/aura/mus/embed_root.cc
@@ -6,17 +6,99 @@
 
 #include "base/auto_reset.h"
 #include "base/bind.h"
+#include "ui/aura/client/focus_change_observer.h"
+#include "ui/aura/client/focus_client.h"
 #include "ui/aura/mus/embed_root_delegate.h"
 #include "ui/aura/mus/window_tree_client.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
+#include "ui/aura/window_tracker.h"
 #include "ui/aura/window_tree_host.h"
 
 namespace aura {
+namespace {
+
+// FocusClient implementation used for embedded windows. This has minimal
+// checks as to what can get focus.
+class EmbeddedFocusClient : public client::FocusClient, public WindowObserver {
+ public:
+  explicit EmbeddedFocusClient(Window* root) : root_(root) {
+    client::SetFocusClient(root, this);
+  }
+
+  ~EmbeddedFocusClient() override {
+    client::SetFocusClient(root_, nullptr);
+    if (focused_window_)
+      focused_window_->RemoveObserver(this);
+  }
+
+  // client::FocusClient:
+  void AddObserver(client::FocusChangeObserver* observer) override {
+    observers_.AddObserver(observer);
+  }
+  void RemoveObserver(client::FocusChangeObserver* observer) override {
+    observers_.RemoveObserver(observer);
+  }
+  void FocusWindow(Window* window) override {
+    if (IsValidWindowForFocus(window) && window != GetFocusedWindow())
+      FocusWindowImpl(window);
+  }
+  void ResetFocusWithinActiveWindow(Window* window) override {
+    // This is never called in the embedding case.
+    NOTREACHED();
+  }
+  Window* GetFocusedWindow() override { return focused_window_; }
+
+ private:
+  bool IsValidWindowForFocus(Window* window) const {
+    return !window || (root_->Contains(window) && window->CanFocus());
+  }
+
+  void FocusWindowImpl(Window* window) {
+    Window* previously_focused_window = focused_window_;
+
+    if (previously_focused_window)
+      previously_focused_window->RemoveObserver(this);
+    focused_window_ = window;
+    if (focused_window_)
+      focused_window_->AddObserver(this);
+
+    WindowTracker window_tracker;
+    if (previously_focused_window)
+      window_tracker.Add(previously_focused_window);
+    for (auto& observer : observers_) {
+      observer.OnWindowFocused(
+          focused_window_, window_tracker.Contains(previously_focused_window)
+                               ? previously_focused_window
+                               : nullptr);
+    }
+  }
+
+  // WindowObserver:
+  void OnWindowDestroying(Window* window) override {
+    DCHECK_EQ(window, focused_window_);
+  }
+
+  // Root of the hierarchy this is the FocusClient for.
+  Window* const root_;
+
+  Window* focused_window_ = nullptr;
+
+  base::ObserverList<client::FocusChangeObserver> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(EmbeddedFocusClient);
+};
+
+}  // namespace
 
 EmbedRoot::~EmbedRoot() {
   window_tree_client_->OnEmbedRootDestroyed(this);
+  // Makes use of window_tree_host_->window(), so needs to be destroyed before
+  // |window_tree_host_|.
+  focus_client_.reset();
 }
 
-aura::Window* EmbedRoot::window() {
+Window* EmbedRoot::window() {
   return window_tree_host_ ? window_tree_host_->window() : nullptr;
 }
 
@@ -38,6 +120,8 @@
 }
 
 void EmbedRoot::OnEmbed(std::unique_ptr<WindowTreeHost> window_tree_host) {
+  focus_client_ =
+      std::make_unique<EmbeddedFocusClient>(window_tree_host->window());
   window_tree_host_ = std::move(window_tree_host);
   delegate_->OnEmbed(window());
 }
diff --git a/ui/aura/mus/embed_root.h b/ui/aura/mus/embed_root.h
index 7e60c99..f1aa46d 100644
--- a/ui/aura/mus/embed_root.h
+++ b/ui/aura/mus/embed_root.h
@@ -20,6 +20,10 @@
 class WindowTreeClient;
 class WindowTreeHost;
 
+namespace client {
+class FocusClient;
+}
+
 // EmbedRoot represents a secondary embedding from the perspective of the
 // embedded client. More specifically an EmbedRoot allows a remote client to
 // embed this client in one of the remote client's Windows.
@@ -41,6 +45,7 @@
 
  private:
   friend class WindowTreeClient;
+  friend class WindowTreeClientPrivate;
 
   EmbedRoot(WindowTreeClient* window_tree_client,
             EmbedRootDelegate* delegate,
@@ -61,6 +66,8 @@
 
   base::UnguessableToken token_;
 
+  std::unique_ptr<client::FocusClient> focus_client_;
+
   std::unique_ptr<WindowTreeHost> window_tree_host_;
 
   base::WeakPtrFactory<EmbedRoot> weak_factory_;
diff --git a/ui/aura/mus/focus_synchronizer.h b/ui/aura/mus/focus_synchronizer.h
index b2908cb..ebacfce 100644
--- a/ui/aura/mus/focus_synchronizer.h
+++ b/ui/aura/mus/focus_synchronizer.h
@@ -27,7 +27,7 @@
 class FocusClient;
 }
 
-// FocusSynchronizer is resonsible for keeping focus in sync between aura
+// FocusSynchronizer is responsible for keeping focus in sync between aura
 // and the mus server. FocusSynchronizer may be configured in two distinct
 // ways:
 // . SetSingletonFocusClient(). Use this when a single FocusClient is shared
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index 40bcfd4..9eb720c 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -366,8 +366,7 @@
 void WindowTreeClient::ScheduleEmbed(
     ui::mojom::WindowTreeClientPtr client,
     base::OnceCallback<void(const base::UnguessableToken&)> callback) {
-  tree_->ScheduleEmbed(std::move(client),
-                       base::AdaptCallbackForRepeating(std::move(callback)));
+  tree_->ScheduleEmbed(std::move(client), std::move(callback));
 }
 
 void WindowTreeClient::EmbedUsingToken(
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc
index 034fe43..ebbc7a9 100644
--- a/ui/aura/mus/window_tree_client_unittest.cc
+++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -27,6 +27,8 @@
 #include "ui/aura/client/transient_window_client.h"
 #include "ui/aura/mus/capture_synchronizer.h"
 #include "ui/aura/mus/client_surface_embedder.h"
+#include "ui/aura/mus/embed_root.h"
+#include "ui/aura/mus/embed_root_delegate.h"
 #include "ui/aura/mus/focus_synchronizer.h"
 #include "ui/aura/mus/property_converter.h"
 #include "ui/aura/mus/window_mus.h"
@@ -2966,4 +2968,33 @@
             last_event->root_location());
 }
 
+namespace {
+
+class TestEmbedRootDelegate : public EmbedRootDelegate {
+ public:
+  TestEmbedRootDelegate() = default;
+  ~TestEmbedRootDelegate() override = default;
+
+  // EmbedRootDelegate:
+  void OnEmbedTokenAvailable(const base::UnguessableToken& token) override {}
+  void OnEmbed(Window* window) override {}
+  void OnUnembed() override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestEmbedRootDelegate);
+};
+
+}  // namespace
+
+// Verifies we don't crash when focus changes to a window in an EmbedRoot.
+TEST_F(WindowTreeClientClientTest, ChangeFocusInEmbedRootWindow) {
+  TestEmbedRootDelegate embed_root_delegate;
+  std::unique_ptr<EmbedRoot> embed_root =
+      window_tree_client_impl()->CreateEmbedRoot(&embed_root_delegate);
+  WindowTreeClientPrivate(window_tree_client_impl())
+      .CallOnEmbedFromToken(embed_root.get());
+  ASSERT_TRUE(embed_root->window());
+  window_tree_client()->OnWindowFocused(server_id(embed_root->window()));
+}
+
 }  // namespace aura
diff --git a/ui/aura/test/mus/window_tree_client_private.cc b/ui/aura/test/mus/window_tree_client_private.cc
index 6fe5dfa..cd77b24 100644
--- a/ui/aura/test/mus/window_tree_client_private.cc
+++ b/ui/aura/test/mus/window_tree_client_private.cc
@@ -4,6 +4,8 @@
 
 #include "ui/aura/test/mus/window_tree_client_private.h"
 
+#include "base/unguessable_token.h"
+#include "ui/aura/mus/embed_root.h"
 #include "ui/aura/mus/in_flight_change.h"
 #include "ui/aura/mus/window_port_mus.h"
 #include "ui/aura/mus/window_tree_client.h"
@@ -12,6 +14,11 @@
 #include "ui/display/display.h"
 
 namespace aura {
+namespace {
+
+constexpr int64_t kDisplayId = 1;
+
+}  // namespace
 
 WindowTreeClientPrivate::WindowTreeClientPrivate(
     WindowTreeClient* tree_client_impl)
@@ -34,14 +41,10 @@
 }
 
 void WindowTreeClientPrivate::OnEmbed(ui::mojom::WindowTree* window_tree) {
-  ui::mojom::WindowDataPtr root_data(ui::mojom::WindowData::New());
-  root_data->parent_id = 0;
-  root_data->window_id = next_window_id_++;
-  root_data->visible = true;
-  const int64_t display_id = 1;
   const ui::Id focused_window_id = 0;
-  tree_client_impl_->OnEmbedImpl(window_tree, std::move(root_data), display_id,
-                                 focused_window_id, true, base::nullopt);
+  tree_client_impl_->OnEmbedImpl(window_tree, CreateWindowDataForEmbed(),
+                                 kDisplayId, focused_window_id, true,
+                                 base::nullopt);
 }
 
 WindowTreeHostMus* WindowTreeClientPrivate::CallWmNewDisplayAdded(
@@ -86,6 +89,14 @@
   tree_client_impl_->OnConnect();
 }
 
+void WindowTreeClientPrivate::CallOnEmbedFromToken(EmbedRoot* embed_root) {
+  embed_root->OnScheduledEmbedForExistingClient(
+      base::UnguessableToken::Create());
+  tree_client_impl_->OnEmbedFromToken(embed_root->token(),
+                                      CreateWindowDataForEmbed(), kDisplayId,
+                                      base::Optional<viz::LocalSurfaceId>());
+}
+
 WindowTreeHostMusInitParams
 WindowTreeClientPrivate::CallCreateInitParamsForNewDisplay() {
   return tree_client_impl_->CreateInitParamsForNewDisplay();
@@ -131,4 +142,12 @@
   tree_client_impl_->WaitForInitialDisplays();
 }
 
+ui::mojom::WindowDataPtr WindowTreeClientPrivate::CreateWindowDataForEmbed() {
+  ui::mojom::WindowDataPtr root_data(ui::mojom::WindowData::New());
+  root_data->parent_id = 0;
+  root_data->window_id = next_window_id_++;
+  root_data->visible = true;
+  return root_data;
+}
+
 }  // namespace aura
diff --git a/ui/aura/test/mus/window_tree_client_private.h b/ui/aura/test/mus/window_tree_client_private.h
index 3504ae8..a2473086 100644
--- a/ui/aura/test/mus/window_tree_client_private.h
+++ b/ui/aura/test/mus/window_tree_client_private.h
@@ -28,6 +28,7 @@
 
 namespace aura {
 
+class EmbedRoot;
 class Window;
 class WindowManagerDelegate;
 class WindowMus;
@@ -66,6 +67,10 @@
 
   void CallOnConnect();
 
+  // Simulates the EmbedRoot receiving the token from the WindowTree and then
+  // the WindowTree calling OnEmbedFromToken().
+  void CallOnEmbedFromToken(EmbedRoot* embed_root);
+
   WindowTreeHostMusInitParams CallCreateInitParamsForNewDisplay();
 
   // Sets the WindowTree.
@@ -87,6 +92,8 @@
   void WaitForInitialDisplays();
 
  private:
+  ui::mojom::WindowDataPtr CreateWindowDataForEmbed();
+
   WindowTreeClient* tree_client_impl_;
   uint16_t next_window_id_ = 1u;
 
diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc
index 2541401..7383138 100644
--- a/ui/base/ui_base_switches.cc
+++ b/ui/base/ui_base_switches.cc
@@ -78,8 +78,9 @@
 // |kTopChromeMD| switch.
 const char kTopChromeMDMaterialTouchOptimized[] = "material-touch-optimized";
 
-// Classic, non-material, mode for the |kTopChromeMD| switch.
-const char kTopChromeMDNonMaterial[] = "non-material";
+// Material design mode that represents a refresh of the Chrome UI for the
+// |kTopChromeMD| switch.
+const char kTopChromeMDMaterialRefresh[] = "material-refresh";
 
 // Disable partial swap which is needed for some OpenGL drivers / emulators.
 const char kUIDisablePartialSwap[] = "ui-disable-partial-swap";
diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h
index 2ce5803..1d459b0 100644
--- a/ui/base/ui_base_switches.h
+++ b/ui/base/ui_base_switches.h
@@ -38,7 +38,7 @@
 UI_BASE_EXPORT extern const char kTopChromeMDMaterialAuto[];
 UI_BASE_EXPORT extern const char kTopChromeMDMaterialHybrid[];
 UI_BASE_EXPORT extern const char kTopChromeMDMaterialTouchOptimized[];
-UI_BASE_EXPORT extern const char kTopChromeMDNonMaterial[];
+UI_BASE_EXPORT extern const char kTopChromeMDMaterialRefresh[];
 UI_BASE_EXPORT extern const char kUIDisablePartialSwap[];
 UI_BASE_EXPORT extern const char kUseSkiaRenderer[];
 
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index 3a7b991..cd58359 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -1054,7 +1054,7 @@
 }
 
 void Layer::didUpdateMainThreadScrollingReasons() {}
-void Layer::didChangeScrollbarsHidden(bool) {}
+void Layer::didChangeScrollbarsHiddenIfOverlay(bool) {}
 
 void Layer::CollectAnimators(
     std::vector<scoped_refptr<LayerAnimator>>* animators) {
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index 9b4316b3..5127e11 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -404,7 +404,7 @@
   std::unique_ptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo(
       cc::Layer* layer) override;
   void didUpdateMainThreadScrollingReasons() override;
-  void didChangeScrollbarsHidden(bool) override;
+  void didChangeScrollbarsHiddenIfOverlay(bool) override;
 
   // Triggers a call to SwitchToLayer.
   void SwitchCCLayerForTest();
diff --git a/ui/views/animation/ink_drop_host_view.cc b/ui/views/animation/ink_drop_host_view.cc
index 11a18447..37439db9 100644
--- a/ui/views/animation/ink_drop_host_view.cc
+++ b/ui/views/animation/ink_drop_host_view.cc
@@ -298,12 +298,9 @@
 }
 
 void InkDropHostView::InstallInkDropMask(ui::Layer* ink_drop_layer) {
-// Layer masks don't work on Windows. See crbug.com/713359
-#if !defined(OS_WIN)
   ink_drop_mask_ = CreateInkDropMask();
   if (ink_drop_mask_)
     ink_drop_layer->SetMaskLayer(ink_drop_mask_->layer());
-#endif
 }
 
 void InkDropHostView::ResetInkDropMask() {
diff --git a/ui/views/controls/native/native_view_host_aura.cc b/ui/views/controls/native/native_view_host_aura.cc
index fb04f31f..6f2dfe0 100644
--- a/ui/views/controls/native/native_view_host_aura.cc
+++ b/ui/views/controls/native/native_view_host_aura.cc
@@ -143,17 +143,12 @@
 }
 
 bool NativeViewHostAura::SetCornerRadius(int corner_radius) {
-#if defined(OS_WIN)
-  // Layer masks don't work on Windows. See crbug.com/713359
-  return false;
-#else
   mask_ = views::Painter::CreatePaintedLayer(
       views::Painter::CreateSolidRoundRectPainter(SK_ColorBLACK,
                                                   corner_radius));
   mask_->layer()->SetFillsBoundsOpaquely(false);
   InstallMask();
   return true;
-#endif
 }
 
 void NativeViewHostAura::InstallClip(int x, int y, int w, int h) {
diff --git a/ui/webui/PLATFORM_OWNERS b/ui/webui/PLATFORM_OWNERS
index a4e5de4..e685160d 100644
--- a/ui/webui/PLATFORM_OWNERS
+++ b/ui/webui/PLATFORM_OWNERS
@@ -5,5 +5,6 @@
 dschuyler@chromium.org
 michaelpg@chromium.org
 pam@chromium.org
+stevenjb@chromium.org
 tommycli@chromium.org
 xiyuan@chromium.org