diff --git a/DEPS b/DEPS
index 7564ef6..1c420090 100644
--- a/DEPS
+++ b/DEPS
@@ -172,11 +172,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': '3dce06be0e24729870e0e1f21f0a0b7b80bb51ad',
+  'skia_revision': '714f8cc3ff4be40ced5183a171816bef30665fbd',
   # 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': '5703cc705e09da6b4557b29d50fcd862462ac202',
+  'v8_revision': '640360886bc99483214d3497865bf2ea884e6d5a',
   # 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.
@@ -184,7 +184,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': 'f7b3a2ac776872f59e9bc8aa0ce76c0693a0eb27',
+  'angle_revision': '322220a0b2055d5460c0176ed83c09914e5f459c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -192,7 +192,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'b54d7ad714257aadf331934849788b451a13dcd5',
+  'pdfium_revision': '762f11932e2419d59c3b0ecdc5c65817ec09d148',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -303,7 +303,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'shaderc_revision': '2dfba53b8214b6776606900fa4f8b25ee4a838ca',
+  'shaderc_revision': '13adddb32ef092b5beef3bae5e4582c8721aa92c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -871,7 +871,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '61ec88a68d6dd62cf65574db8ee56550235393bb',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c1501a6caf64b27d29618757411840b2d7c53aa5',
       'condition': 'checkout_linux',
   },
 
@@ -896,7 +896,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '41be80f6159c6c91914dbfc4dcd6b59d183f9f3b',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '23247b99321549c24e62ad45200409419423695d',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1311,7 +1311,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '1171cdd4f791b04a2f78c46dd747be305f29cce6',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'ed392790fed14fdca3f95d0d739dfe2c005f8fb8',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1512,7 +1512,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'dd55f3ca8f2ea716ca917a4aaf36f0729fe902b1',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '33cff37c603502118f668a9725234270bc260073',
+    Var('webrtc_git') + '/src.git' + '@' + '4dffa04d4f00c35414a75eb01f39cdfff024dd32',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
@@ -1579,7 +1579,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2d87f9edb4885ff4d04c52184f4b5f65ba6e6750',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b4b80864f88f23297d9745cd805e654e562ab590',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index bef49734..c609a31 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -2250,6 +2250,46 @@
     return []
 
 
+def _CheckChromeOsSyncedPrefRegistration(input_api, output_api):
+  """Warns if Chrome OS C++ files register syncable prefs as browser prefs."""
+  def FileFilter(affected_file):
+    """Includes directories known to be Chrome OS only."""
+    return input_api.FilterSourceFile(
+      affected_file,
+      white_list=('^ash/',
+                  '^chromeos/',  # Top-level src/chromeos.
+                  '/chromeos/',  # Any path component.
+                  '^components/arc',
+                  '^components/exo'),
+      black_list=(input_api.DEFAULT_BLACK_LIST))
+
+  prefs = []
+  priority_prefs = []
+  for f in input_api.AffectedFiles(file_filter=FileFilter):
+    for line_num, line in f.ChangedContents():
+      if input_api.re.search('PrefRegistrySyncable::SYNCABLE_PREF', line):
+        prefs.append('    %s:%d:' % (f.LocalPath(), line_num))
+        prefs.append('      %s' % line)
+      if input_api.re.search(
+          'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF', line):
+        priority_prefs.append('    %s:%d' % (f.LocalPath(), line_num))
+        priority_prefs.append('      %s' % line)
+
+  results = []
+  if (prefs):
+    results.append(output_api.PresubmitPromptWarning(
+        'Preferences were registered as SYNCABLE_PREF and will be controlled '
+        'by browser sync settings. If these prefs should be controlled by OS '
+        'sync settings use SYNCABLE_OS_PREF instead.\n' + '\n'.join(prefs)))
+  if (priority_prefs):
+    results.append(output_api.PresubmitPromptWarning(
+        'Preferences were registered as SYNCABLE_PRIORITY_PREF and will be '
+        'controlled by browser sync settings. If these prefs should be '
+        'controlled by OS sync settings use SYNCABLE_OS_PRIORITY_PREF '
+        'instead.\n' + '\n'.join(prefs)))
+  return results
+
+
 # TODO: add unit tests.
 def _CheckNoAbbreviationInPngFileName(input_api, output_api):
   """Makes sure there are no abbreviations in the name of PNG files.
@@ -4080,6 +4120,7 @@
   results.extend(_CheckForVersionControlConflicts(input_api, output_api))
   results.extend(_CheckPatchFiles(input_api, output_api))
   results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
+  results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api))
   results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
   results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api))
   results.extend(_CheckForInvalidOSMacros(input_api, output_api))
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py
index 1f41719..6455b91d 100755
--- a/PRESUBMIT_test.py
+++ b/PRESUBMIT_test.py
@@ -1406,6 +1406,62 @@
     self.assertEqual(0, len(warnings))
 
 
+class ChromeOsSyncedPrefRegistrationTest(unittest.TestCase):
+
+  def testWarnsOnChromeOsDirectories(self):
+    input_api = MockInputApi()
+    input_api.files = [
+      MockFile('ash/file.cc',
+               ['PrefRegistrySyncable::SYNCABLE_PREF']),
+      MockFile('chrome/browser/chromeos/file.cc',
+               ['PrefRegistrySyncable::SYNCABLE_PREF']),
+      MockFile('chromeos/file.cc',
+               ['PrefRegistrySyncable::SYNCABLE_PREF']),
+      MockFile('components/arc/file.cc',
+               ['PrefRegistrySyncable::SYNCABLE_PREF']),
+      MockFile('components/exo/file.cc',
+               ['PrefRegistrySyncable::SYNCABLE_PREF']),
+    ]
+    warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
+      input_api, MockOutputApi())
+    self.assertEqual(1, len(warnings))
+
+  def testDoesNotWarnOnSyncOsPref(self):
+    input_api = MockInputApi()
+    input_api.files = [
+      MockFile('chromeos/file.cc',
+               ['PrefRegistrySyncable::SYNCABLE_OS_PREF']),
+    ]
+    warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
+      input_api, MockOutputApi())
+    self.assertEqual(0, len(warnings))
+
+  def testDoesNotWarnOnCrossPlatformDirectories(self):
+    input_api = MockInputApi()
+    input_api.files = [
+      MockFile('chrome/browser/ui/file.cc',
+               ['PrefRegistrySyncable::SYNCABLE_PREF']),
+      MockFile('components/sync/file.cc',
+               ['PrefRegistrySyncable::SYNCABLE_PREF']),
+      MockFile('content/browser/file.cc',
+               ['PrefRegistrySyncable::SYNCABLE_PREF']),
+    ]
+    warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
+      input_api, MockOutputApi())
+    self.assertEqual(0, len(warnings))
+
+  def testSeparateWarningForPriorityPrefs(self):
+    input_api = MockInputApi()
+    input_api.files = [
+      MockFile('chromeos/file.cc',
+               ['PrefRegistrySyncable::SYNCABLE_PREF',
+                'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']),
+    ]
+    warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration(
+      input_api, MockOutputApi())
+    self.assertEqual(2, len(warnings))
+
+
 class ForwardDeclarationTest(unittest.TestCase):
   def testCheckHeadersOnlyOutsideThirdParty(self):
     mock_input_api = MockInputApi()
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index c5feb24..34e22815 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -1304,7 +1304,7 @@
 }
 
 int AppListControllerImpl::GetShelfHeight() {
-  return ShelfConfig::Get()->shelf_size();
+  return ShelfConfig::Get()->system_shelf_size();
 }
 
 void AppListControllerImpl::RecordAppLaunched(
diff --git a/ash/display/root_window_transformers.cc b/ash/display/root_window_transformers.cc
index 8a8a40d..e3438ab 100644
--- a/ash/display/root_window_transformers.cc
+++ b/ash/display/root_window_transformers.cc
@@ -102,10 +102,10 @@
     display::ManagedDisplayInfo info =
         display_manager->GetDisplayInfo(display.id());
     host_insets_ = info.GetOverscanInsetsInPixel();
-    root_window_bounds_transform_ =
+    gfx::Transform insets_and_rotation_transform =
         CreateInsetsTransform(host_insets_, display.device_scale_factor()) *
         CreateRootWindowRotationTransform(display);
-    transform_ = root_window_bounds_transform_;
+    transform_ = insets_and_rotation_transform;
     insets_and_scale_transform_ = CreateReverseRotatedInsetsTransform(
         info.GetLogicalActiveRotation(), host_insets_,
         display.device_scale_factor());
@@ -118,6 +118,8 @@
     }
 
     CHECK(transform_.GetInverse(&invert_transform_));
+    CHECK(insets_and_rotation_transform.GetInverse(
+        &root_window_bounds_transform_));
 
     root_window_bounds_transform_.Scale(1.f / display.device_scale_factor(),
                                         1.f / display.device_scale_factor());
@@ -132,8 +134,9 @@
     gfx::RectF new_bounds = gfx::RectF(gfx::SizeF(host_size));
     new_bounds.Inset(host_insets_);
     root_window_bounds_transform_.TransformRect(&new_bounds);
-    // Ignore the origin because RootWindow's insets are handled by
-    // the transform.
+
+    // Root window origin will be (0,0) except during bounds changes.
+    // Set to exactly zero to avoid rounding issues.
     // Floor the size because the bounds is no longer aligned to
     // backing pixel when |root_window_scale_| is specified
     // (850 height at 1.25 scale becomes 1062.5 for example.)
@@ -155,8 +158,21 @@
   // |gfx::Transform::GetInverse|.
   gfx::Transform invert_transform_;
 
-  // The transform of the root window bounds. This is used to calculate
-  // the size of root window.
+  // The transform of the root window bounds. This is used to calculate the size
+  // of the root window. It is the composition of the following transforms
+  //   - inverse of insets. Insets position the content area within the display.
+  //   - inverse of rotation. Rotation changes orientation of the content area.
+  //   - inverse of device scale. Scaling up content shrinks the content area.
+  //
+  // Insets also shrink the content area but this happens prior to applying the
+  // transformation in GetRootWindowBounds().
+  //
+  // Magnification does not affect the window size. Content is clipped in this
+  // case, but the magnifier allows panning to reach clipped areas.
+  //
+  // The transforms are inverted because GetTransform() is the transform from
+  // root window coordinates to host coordinates, but this transform is used in
+  // the reverse direction (derives root window bounds from display bounds).
   gfx::Transform root_window_bounds_transform_;
 
   gfx::Insets host_insets_;
diff --git a/ash/home_screen/drag_window_from_shelf_controller.cc b/ash/home_screen/drag_window_from_shelf_controller.cc
index ae2be76c..f749301 100644
--- a/ash/home_screen/drag_window_from_shelf_controller.cc
+++ b/ash/home_screen/drag_window_from_shelf_controller.cc
@@ -160,13 +160,10 @@
   if (overview_controller->InOverviewSession()) {
     const SplitViewController::SnapPosition snap_position =
         GetSnapPosition(location_in_screen);
-    // Pass non_snap_state=kNoDrag so that only snap previews show up.
-    // TODO(crbug.com/1020349): Achieve that effect another way, because this
-    // way causes incorrect animations.
     SplitViewDragIndicators::WindowDraggingState window_dragging_state =
         SplitViewDragIndicators::ComputeWindowDraggingState(
             drag_started_,
-            SplitViewDragIndicators::WindowDraggingState::kNoDrag,
+            SplitViewDragIndicators::WindowDraggingState::kFromShelf,
             snap_position);
     OverviewSession* overview_session = overview_controller->overview_session();
     overview_session->SetSplitViewDragIndicatorsWindowDraggingState(
diff --git a/ash/home_screen/drag_window_from_shelf_controller_unittest.cc b/ash/home_screen/drag_window_from_shelf_controller_unittest.cc
index ca31b1b..f166b5e6 100644
--- a/ash/home_screen/drag_window_from_shelf_controller_unittest.cc
+++ b/ash/home_screen/drag_window_from_shelf_controller_unittest.cc
@@ -447,8 +447,9 @@
   EXPECT_EQ(window1->layer()->GetTargetOpacity(), 1.f);
 }
 
-// Test there is no drag-to-snap or cannot-snap drag indicators during dragging.
-TEST_F(DragWindowFromShelfControllerTest, NoDragToSnapIndicator) {
+// Check the split view drag indicators window dragging states.
+TEST_F(DragWindowFromShelfControllerTest,
+       SplitViewDragIndicatorsWindowDraggingStates) {
   UpdateDisplay("400x400");
   const gfx::Rect shelf_bounds =
       Shelf::ForWindow(Shell::GetPrimaryRootWindow())->GetIdealBounds();
@@ -462,7 +463,7 @@
   SplitViewDragIndicators::WindowDraggingState window_dragging_state =
       overview_session->split_view_drag_indicators()
           ->current_window_dragging_state();
-  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
+  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromShelf,
             window_dragging_state);
 
   Drag(gfx::Point(0, 200), 0.5f, 0.5f);
@@ -471,6 +472,22 @@
   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapLeft,
             window_dragging_state);
 
+  Drag(gfx::Point(0, 300), 0.5f, 0.5f);
+  window_dragging_state = overview_session->split_view_drag_indicators()
+                              ->current_window_dragging_state();
+  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromShelf,
+            window_dragging_state);
+  Drag(gfx::Point(0, 200), 0.5f, 0.5f);
+  window_dragging_state = overview_session->split_view_drag_indicators()
+                              ->current_window_dragging_state();
+  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapLeft,
+            window_dragging_state);
+  Drag(gfx::Point(200, 200), 0.5f, 0.5f);
+  window_dragging_state = overview_session->split_view_drag_indicators()
+                              ->current_window_dragging_state();
+  EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromShelf,
+            window_dragging_state);
+
   EndDrag(shelf_bounds.CenterPoint(),
           /*velocity_y=*/base::nullopt);
 }
diff --git a/ash/host/transformer_helper.cc b/ash/host/transformer_helper.cc
index 0d9afdb3..9a39dd4 100644
--- a/ash/host/transformer_helper.cc
+++ b/ash/host/transformer_helper.cc
@@ -44,7 +44,7 @@
   gfx::Rect GetRootWindowBounds(const gfx::Size& host_size) const override {
     gfx::Rect bounds(host_size);
     gfx::RectF new_bounds(ui::ConvertRectToDIP(root_window_->layer(), bounds));
-    transform_.TransformRect(&new_bounds);
+    GetInverseTransform().TransformRect(&new_bounds);
     return gfx::Rect(gfx::ToFlooredSize(new_bounds.size()));
   }
 
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h
index 7f5fe61..e497f62 100644
--- a/ash/public/cpp/ash_features.h
+++ b/ash/public/cpp/ash_features.h
@@ -98,8 +98,7 @@
 // Enables the Virtual Desks feature.
 ASH_PUBLIC_EXPORT extern const base::Feature kVirtualDesks;
 
-// Enables the touchpad 3-finger gestures to switch desks. It also changes tab
-// scrubbing as well as overview highlight to use 4-finger gestures.
+// Enables the touchpad 4-finger gestures to switch desks.
 // This flag is only effective if the Virtual Desks feature is enabled (see
 // `kVirtualDesks`).
 ASH_PUBLIC_EXPORT extern const base::Feature kVirtualDesksGestures;
diff --git a/ash/public/cpp/shelf_config.h b/ash/public/cpp/shelf_config.h
index 7681315c..02cdd8bf 100644
--- a/ash/public/cpp/shelf_config.h
+++ b/ash/public/cpp/shelf_config.h
@@ -60,6 +60,9 @@
   // Size of the shelf when an app is visible in tablet mode.
   int in_app_shelf_size() const;
 
+  // Size of the shelf when not in tablet mode, or when no apps are visible.
+  int system_shelf_size() const;
+
   // Size of the hotseat, which contains the scrollable shelf in tablet mode.
   int hotseat_size() const;
 
@@ -164,6 +167,11 @@
   // Updates |is_dense_| and notifies all observers of the update.
   void UpdateIsDense();
 
+  // Gets the current shelf size.
+  // |ignore_in_app_state| - Whether the returned shelf size should be
+  //                         calculated as if is_in_app() returns false.
+  int GetShelfSize(bool ignore_in_app_state) const;
+
   // Whether shelf is currently standard or dense.
   bool is_dense_;
 
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc
index 985463cd..5b8bd676d 100644
--- a/ash/shelf/scrollable_shelf_view.cc
+++ b/ash/shelf/scrollable_shelf_view.cc
@@ -1153,7 +1153,16 @@
     return;
 
   if (GetShelf()->IsHorizontalAlignment()) {
-    ScrollByXOffset(CalculatePageScrollingOffset(event->x_offset() < 0),
+    const float x_offset = event->x_offset();
+    const float y_offset = event->y_offset();
+    // If the shelf is bottom aligned, we can scroll over the shelf contents if
+    // the scroll is horizontal or vertical (in the case of a mousewheel
+    // scroll). We take the biggest offset difference of the vertical and
+    // horizontal components to determine the offset to scroll over the
+    // contents.
+    float max_absolute_offset =
+        abs(x_offset) > abs(y_offset) ? x_offset : y_offset;
+    ScrollByXOffset(CalculatePageScrollingOffset(max_absolute_offset < 0),
                     /*animating=*/true);
   } else {
     ScrollByYOffset(CalculatePageScrollingOffset(event->y_offset() < 0),
diff --git a/ash/shelf/scrollable_shelf_view_unittest.cc b/ash/shelf/scrollable_shelf_view_unittest.cc
index 7522846..e5d0401f 100644
--- a/ash/shelf/scrollable_shelf_view_unittest.cc
+++ b/ash/shelf/scrollable_shelf_view_unittest.cc
@@ -467,4 +467,41 @@
   EXPECT_EQ(hotseat_background.right() - 4, last_tappable_view_bounds.right());
 }
 
+// Verifies that doing a mousewheel scroll on the scrollable shelf does scroll
+// forward.
+TEST_F(ScrollableShelfViewTest, ScrollWithMouseWheel) {
+  // The scroll threshold. Taken from |KScrollOffsetThreshold| in
+  // scrollable_shelf_view.cc.
+  constexpr int scroll_threshold = 20;
+  AddAppShortcutsUntilOverflow();
+
+  ASSERT_EQ(ScrollableShelfView::kShowRightArrowButton,
+            scrollable_shelf_view_->layout_strategy_for_test());
+
+  // Do a mousewheel scroll with a positive offset bigger than the scroll
+  // threshold to scroll forward. Unlike touchpad scrolls, mousewheel scrolls
+  // can only be along the cross axis.
+  GetEventGenerator()->MoveMouseTo(
+      scrollable_shelf_view_->GetBoundsInScreen().CenterPoint());
+  GetEventGenerator()->MoveMouseWheel(0, -(scroll_threshold + 1));
+  ASSERT_EQ(ScrollableShelfView::kShowLeftArrowButton,
+            scrollable_shelf_view_->layout_strategy_for_test());
+
+  // Do a mousewheel scroll with a negative offset bigger than the scroll
+  // threshold to scroll backwards.
+  GetEventGenerator()->MoveMouseWheel(0, scroll_threshold + 1);
+  ASSERT_EQ(ScrollableShelfView::kShowRightArrowButton,
+            scrollable_shelf_view_->layout_strategy_for_test());
+
+  // Do a mousewheel scroll with an offset smaller than the scroll
+  // threshold should be ignored.
+  GetEventGenerator()->MoveMouseWheel(0, scroll_threshold);
+  ASSERT_EQ(ScrollableShelfView::kShowRightArrowButton,
+            scrollable_shelf_view_->layout_strategy_for_test());
+
+  GetEventGenerator()->MoveMouseWheel(0, -scroll_threshold);
+  ASSERT_EQ(ScrollableShelfView::kShowRightArrowButton,
+            scrollable_shelf_view_->layout_strategy_for_test());
+}
+
 }  // namespace ash
diff --git a/ash/shelf/shelf_config.cc b/ash/shelf/shelf_config.cc
index 7763f777..52905c0 100644
--- a/ash/shelf/shelf_config.cc
+++ b/ash/shelf/shelf_config.cc
@@ -122,24 +122,17 @@
 }
 
 int ShelfConfig::shelf_size() const {
-  // Before the hotseat redesign, the shelf always has the same size.
-  if (!chromeos::switches::ShouldShowShelfHotseat())
-    return 56;
-
-  // In clamshell mode, the shelf always has the same size.
-  if (!IsTabletMode())
-    return 48;
-
-  if (is_in_app())
-    return in_app_shelf_size();
-
-  return is_dense_ ? 48 : 56;
+  return GetShelfSize(false /*ignore_in_app_state*/);
 }
 
 int ShelfConfig::in_app_shelf_size() const {
   return is_dense_ ? 36 : 40;
 }
 
+int ShelfConfig::system_shelf_size() const {
+  return GetShelfSize(true /*ignore_in_app_state*/);
+}
+
 int ShelfConfig::hotseat_size() const {
   if (!chromeos::switches::ShouldShowShelfHotseat() || !IsTabletMode()) {
     return shelf_size();
@@ -218,6 +211,21 @@
   OnShelfConfigUpdated();
 }
 
+int ShelfConfig::GetShelfSize(bool ignore_in_app_state) const {
+  // Before the hotseat redesign, the shelf always has the same size.
+  if (!chromeos::switches::ShouldShowShelfHotseat())
+    return 56;
+
+  // In clamshell mode, the shelf always has the same size.
+  if (!IsTabletMode())
+    return 48;
+
+  if (!ignore_in_app_state && is_in_app())
+    return in_app_shelf_size();
+
+  return is_dense_ ? 48 : 56;
+}
+
 SkColor ShelfConfig::GetShelfControlButtonColor() const {
   if (chromeos::switches::ShouldShowShelfHotseat() && IsTabletMode() &&
       Shell::Get()->session_controller()->GetSessionState() ==
diff --git a/ash/shelf/shelf_config_unittest.cc b/ash/shelf/shelf_config_unittest.cc
index 4b4717c..2a9f3e3 100644
--- a/ash/shelf/shelf_config_unittest.cc
+++ b/ash/shelf/shelf_config_unittest.cc
@@ -104,11 +104,15 @@
   std::unique_ptr<views::Widget> widget = CreateTestWidget();
   GetAppListTestHelper()->CheckVisibility(false);
   const int tablet_dense_in_app = ShelfConfig::Get()->shelf_size();
+  const int system_shelf_tablet_dense_in_app =
+      ShelfConfig::Get()->system_shelf_size();
   const int control_tablet_dense_in_app = ShelfConfig::Get()->control_size();
 
   widget->Close();
   GetAppListTestHelper()->CheckVisibility(true);
   const int tablet_dense_home = ShelfConfig::Get()->shelf_size();
+  const int system_shelf_tablet_dense_home =
+      ShelfConfig::Get()->system_shelf_size();
   const int control_tablet_dense_home = ShelfConfig::Get()->control_size();
 
   UpdateDisplay("1000x1000");
@@ -116,22 +120,30 @@
   widget = CreateTestWidget();
   GetAppListTestHelper()->CheckVisibility(false);
   const int tablet_standard_in_app = ShelfConfig::Get()->shelf_size();
+  const int system_shelf_tablet_standard_in_app =
+      ShelfConfig::Get()->system_shelf_size();
   const int control_tablet_standard_in_app = ShelfConfig::Get()->control_size();
 
   widget->Close();
   GetAppListTestHelper()->CheckVisibility(true);
   const int tablet_standard_home = ShelfConfig::Get()->shelf_size();
+  const int system_shelf_tablet_standard_home =
+      ShelfConfig::Get()->system_shelf_size();
   const int control_tablet_standard_home = ShelfConfig::Get()->control_size();
 
   SetTabletMode(false);
   ASSERT_FALSE(IsTabletMode());
   GetAppListTestHelper()->Dismiss();
   const int clamshell_home = ShelfConfig::Get()->shelf_size();
+  const int system_shelf_clamshell_home =
+      ShelfConfig::Get()->system_shelf_size();
   const int control_clamshell_home = ShelfConfig::Get()->control_size();
 
   widget = CreateTestWidget();
   widget->Maximize();
   const int clamshell_in_app = ShelfConfig::Get()->shelf_size();
+  const int system_shelf_clamshell_in_app =
+      ShelfConfig::Get()->system_shelf_size();
   const int control_clamshell_in_app = ShelfConfig::Get()->control_size();
 
   EXPECT_LT(tablet_dense_in_app, tablet_standard_in_app);
@@ -145,6 +157,14 @@
   EXPECT_EQ(control_clamshell_in_app, control_clamshell_home);
   EXPECT_LT(control_clamshell_home, control_tablet_standard_in_app);
   EXPECT_EQ(control_tablet_standard_in_app, control_tablet_standard_home);
+
+  // System shelf size should return size that matches out-of-app (home) state.
+  EXPECT_EQ(system_shelf_tablet_dense_in_app, tablet_dense_home);
+  EXPECT_EQ(system_shelf_tablet_dense_home, tablet_dense_home);
+  EXPECT_EQ(system_shelf_tablet_standard_in_app, tablet_standard_home);
+  EXPECT_EQ(system_shelf_tablet_standard_home, tablet_standard_home);
+  EXPECT_EQ(system_shelf_clamshell_home, clamshell_home);
+  EXPECT_EQ(system_shelf_clamshell_in_app, clamshell_home);
 }
 
 // Make sure that we consider ourselves inside an app when appropriate.
diff --git a/ash/utility/transformer_util.cc b/ash/utility/transformer_util.cc
index 4e4e6c3..3eb966e 100644
--- a/ash/utility/transformer_util.cc
+++ b/ash/utility/transformer_util.cc
@@ -13,16 +13,12 @@
 namespace ash {
 namespace {
 
-// Round near zero value to zero.
-void RoundNearZero(gfx::Transform* transform) {
-  const float kEpsilon = 0.001f;
-  SkMatrix44& matrix = transform->matrix();
-  for (int x = 0; x < 4; ++x) {
-    for (int y = 0; y < 4; ++y) {
-      if (std::abs(SkMScalarToFloat(matrix.get(x, y))) < kEpsilon)
-        matrix.set(x, y, SkFloatToMScalar(0.0f));
-    }
-  }
+display::Display::Rotation RotationBetween(
+    display::Display::Rotation old_rotation,
+    display::Display::Rotation new_rotation) {
+  return static_cast<display::Display::Rotation>(
+      display::Display::Rotation::ROTATE_0 +
+      ((new_rotation - old_rotation) + 4) % 4);
 }
 
 }  // namespace
@@ -30,26 +26,10 @@
 gfx::Transform CreateRotationTransform(display::Display::Rotation old_rotation,
                                        display::Display::Rotation new_rotation,
                                        const gfx::SizeF& size_to_rotate) {
-  const int rotation_angle = 90 * (((new_rotation - old_rotation) + 4) % 4);
-  gfx::Transform rotate;
-  switch (rotation_angle) {
-    case 0:
-      break;
-    case 90:
-      rotate.Translate(size_to_rotate.height(), 0);
-      rotate.Rotate(90);
-      break;
-    case 180:
-      rotate.Translate(size_to_rotate.width(), size_to_rotate.height());
-      rotate.Rotate(180);
-      break;
-    case 270:
-      rotate.Translate(0, size_to_rotate.width());
-      rotate.Rotate(270);
-      break;
-  }
-  RoundNearZero(&rotate);
-  return rotate;
+  gfx::Transform transform = display::Display::GetRotationTransform(
+      RotationBetween(old_rotation, new_rotation), size_to_rotate);
+
+  return transform;
 }
 
 gfx::OverlayTransform DisplayRotationToOverlayTransform(
diff --git a/ash/wm/gestures/wm_gesture_handler.cc b/ash/wm/gestures/wm_gesture_handler.cc
index c52c116..aec50f4 100644
--- a/ash/wm/gestures/wm_gesture_handler.cc
+++ b/ash/wm/gestures/wm_gesture_handler.cc
@@ -47,7 +47,7 @@
   return true;
 }
 
-// Handles horizontal 3-finger scroll by switching desks if possible.
+// Handles horizontal 4-finger scroll by switching desks if possible.
 // Returns true if the gesture was handled.
 bool HandleDesksSwitchHorizontalScroll(float scroll_x) {
   DCHECK(CanHandleVirtualDesksGestures());
@@ -126,18 +126,17 @@
     if (std::fabs(scroll_x) < std::fabs(scroll_y))
       return Handle3FingerVerticalScroll(scroll_y);
 
-    if (can_handle_desks_gestures_)
-      return HandleDesksSwitchHorizontalScroll(scroll_x);
+    return MoveOverviewSelection(finger_count, scroll_x, scroll_y);
   }
 
-  return MoveOverviewSelection(finger_count, scroll_x, scroll_y);
+  return finger_count == 4 && can_handle_desks_gestures_ &&
+         HandleDesksSwitchHorizontalScroll(scroll_x);
 }
 
 bool WmGestureHandler::MoveOverviewSelection(int finger_count,
                                              float scroll_x,
                                              float scroll_y) {
-  const int required_finger_count = can_handle_desks_gestures_ ? 4 : 3;
-  if (finger_count != required_finger_count)
+  if (finger_count != 3)
     return false;
 
   auto* overview_controller = Shell::Get()->overview_controller();
diff --git a/ash/wm/gestures/wm_gesture_handler_unittest.cc b/ash/wm/gestures/wm_gesture_handler_unittest.cc
index fe1ab6d..d7fab8bf 100644
--- a/ash/wm/gestures/wm_gesture_handler_unittest.cc
+++ b/ash/wm/gestures/wm_gesture_handler_unittest.cc
@@ -23,6 +23,9 @@
 
 namespace {
 
+constexpr int kNumFingersForHighlight = 3;
+constexpr int kNumFingersForDesksSwitch = 4;
+
 bool InOverviewSession() {
   return Shell::Get()->overview_controller()->InOverviewSession();
 }
@@ -32,10 +35,6 @@
          features::IsVirtualDesksGesturesEnabled();
 }
 
-int GetNumFingersForHighlight() {
-  return CanHandleVirtualDesksGestures() ? 4 : 3;
-}
-
 const aura::Window* GetHighlightedWindow() {
   return InOverviewSession() ? GetOverviewHighlightedWindow() : nullptr;
 }
@@ -72,7 +71,7 @@
     DeskSwitchAnimationWaiter waiter;
     const float x_offset =
         (scroll_left ? -1 : 1) * WmGestureHandler::kHorizontalThresholdDp;
-    Scroll(x_offset, 0, /*fingers=*/3);
+    Scroll(x_offset, 0, kNumFingersForDesksSwitch);
     waiter.Wait();
   }
 
@@ -123,7 +122,7 @@
   auto scroll_until_window_highlighted = [this](float x_offset,
                                                 float y_offset) {
     do {
-      Scroll(x_offset, y_offset, GetNumFingersForHighlight());
+      Scroll(x_offset, y_offset, kNumFingersForHighlight);
     } while (!GetHighlightedWindow());
   };
 
@@ -154,10 +153,10 @@
 // Tests that a mostly horizontal scroll does not trigger overview.
 TEST_P(WmGestureHandlerTest, HorizontalScrolls) {
   const float long_scroll = 2 * WmGestureHandler::kVerticalThresholdDp;
-  Scroll(long_scroll + 100, -long_scroll, GetNumFingersForHighlight());
+  Scroll(long_scroll + 100, -long_scroll, kNumFingersForHighlight);
   EXPECT_FALSE(InOverviewSession());
 
-  Scroll(-long_scroll - 100, -long_scroll, GetNumFingersForHighlight());
+  Scroll(-long_scroll - 100, -long_scroll, kNumFingersForHighlight);
   EXPECT_FALSE(InOverviewSession());
 }
 
@@ -209,7 +208,7 @@
   // Tests that since there is no previous desk, we remain on the same desk when
   // scrolling right.
   const float long_scroll = WmGestureHandler::kHorizontalThresholdDp;
-  Scroll(long_scroll, 0.f, 3);
+  Scroll(long_scroll, 0.f, kNumFingersForDesksSwitch);
   EXPECT_EQ(desk_controller->desks()[0].get(), desk_controller->active_desk());
 }
 
@@ -224,16 +223,17 @@
   const float short_scroll = WmGestureHandler::kHorizontalThresholdDp - 10.f;
   const float long_scroll = WmGestureHandler::kHorizontalThresholdDp;
   // Tests that a short horizontal scroll does not switch desks.
-  Scroll(short_scroll, 0.f, 3);
+  Scroll(short_scroll, 0.f, kNumFingersForDesksSwitch);
   EXPECT_EQ(desk_controller->desks()[0].get(), desk_controller->active_desk());
 
   // Tests that a scroll that meets the horizontal requirements, but is mostly
   // vertical does not switch desks.
-  Scroll(long_scroll, long_scroll + 10.f, 3);
+  Scroll(long_scroll, long_scroll + 10.f, kNumFingersForDesksSwitch);
   EXPECT_EQ(desk_controller->desks()[0].get(), desk_controller->active_desk());
 
   // Tests that a vertical scroll does not switch desks.
-  Scroll(0.f, WmGestureHandler::kVerticalThresholdDp, 3);
+  Scroll(0.f, WmGestureHandler::kVerticalThresholdDp,
+         kNumFingersForDesksSwitch);
   EXPECT_EQ(desk_controller->desks()[0].get(), desk_controller->active_desk());
 }
 
@@ -248,7 +248,7 @@
 
   const float long_scroll = WmGestureHandler::kHorizontalThresholdDp * 3;
   DeskSwitchAnimationWaiter waiter;
-  Scroll(-long_scroll, 0, 3);
+  Scroll(-long_scroll, 0, kNumFingersForDesksSwitch);
   waiter.Wait();
   EXPECT_EQ(desk_controller->desks()[1].get(), desk_controller->active_desk());
 }
diff --git a/ash/wm/splitview/split_view_drag_indicators.cc b/ash/wm/splitview/split_view_drag_indicators.cc
index 8088237..33105c7 100644
--- a/ash/wm/splitview/split_view_drag_indicators.cc
+++ b/ash/wm/splitview/split_view_drag_indicators.cc
@@ -160,12 +160,6 @@
       WindowDraggingState window_dragging_state,
       WindowDraggingState previous_window_dragging_state,
       bool can_dragged_window_be_snapped) {
-    // In split view, the labels never show, and they do not need to be updated.
-    if (SplitViewController::Get(GetWidget()->GetNativeWindow())
-            ->InSplitViewMode()) {
-      return;
-    }
-
     // No top label for dragging from the top in portrait orientation.
     if (window_dragging_state == WindowDraggingState::kFromTop &&
         !IsCurrentScreenOrientationLandscape() && !is_right_or_bottom_) {
@@ -274,19 +268,25 @@
     previous_window_dragging_state_ = window_dragging_state_;
     window_dragging_state_ = window_dragging_state;
 
+    const bool previews_only =
+        window_dragging_state == WindowDraggingState::kFromShelf ||
+        SplitViewController::Get(GetWidget()->GetNativeWindow())
+            ->InSplitViewMode();
     const bool can_dragged_window_be_snapped =
         dragged_window_ && CanSnapInSplitview(dragged_window_);
-    left_rotated_view_->OnWindowDraggingStateChanged(
-        window_dragging_state, previous_window_dragging_state_,
-        can_dragged_window_be_snapped);
-    right_rotated_view_->OnWindowDraggingStateChanged(
-        window_dragging_state, previous_window_dragging_state_,
-        can_dragged_window_be_snapped);
+    if (!previews_only) {
+      left_rotated_view_->OnWindowDraggingStateChanged(
+          window_dragging_state, previous_window_dragging_state_,
+          can_dragged_window_be_snapped);
+      right_rotated_view_->OnWindowDraggingStateChanged(
+          window_dragging_state, previous_window_dragging_state_,
+          can_dragged_window_be_snapped);
+    }
     left_highlight_view_->OnWindowDraggingStateChanged(
-        window_dragging_state, previous_window_dragging_state_,
+        window_dragging_state, previous_window_dragging_state_, previews_only,
         can_dragged_window_be_snapped);
     right_highlight_view_->OnWindowDraggingStateChanged(
-        window_dragging_state, previous_window_dragging_state_,
+        window_dragging_state, previous_window_dragging_state_, previews_only,
         can_dragged_window_be_snapped);
 
     if (window_dragging_state != WindowDraggingState::kNoDrag ||
diff --git a/ash/wm/splitview/split_view_drag_indicators.h b/ash/wm/splitview/split_view_drag_indicators.h
index 379273c..08999fe6 100644
--- a/ash/wm/splitview/split_view_drag_indicators.h
+++ b/ash/wm/splitview/split_view_drag_indicators.h
@@ -55,6 +55,11 @@
     // snapped in split view.
     kFromTop,
 
+    // Started dragging from the shelf. Split view is supported. Not currently
+    // dragging in a snap area, or the dragged window is not eligible to be
+    // snapped in split view.
+    kFromShelf,
+
     // Currently dragging in the |SplitViewController::LEFT| snap area, and the
     // dragged window is eligible to be snapped in split view.
     kToSnapLeft,
diff --git a/ash/wm/splitview/split_view_drag_indicators_unittest.cc b/ash/wm/splitview/split_view_drag_indicators_unittest.cc
index 476692e..788930a 100644
--- a/ash/wm/splitview/split_view_drag_indicators_unittest.cc
+++ b/ash/wm/splitview/split_view_drag_indicators_unittest.cc
@@ -415,6 +415,25 @@
       SplitViewDragIndicators::WindowDraggingState::kToSnapRight, gfx::Point());
   check_helper(indicator.get(), to_int(IndicatorType::kRightHighlight));
 
+  // Verify that only snap previews are shown for window dragging from shelf.
+  indicator->SetWindowDraggingState(
+      SplitViewDragIndicators::WindowDraggingState::kNoDrag, gfx::Point());
+  indicator->SetWindowDraggingState(
+      SplitViewDragIndicators::WindowDraggingState::kFromShelf, gfx::Point());
+  check_helper(indicator.get(), 0);
+  indicator->SetWindowDraggingState(
+      SplitViewDragIndicators::WindowDraggingState::kToSnapLeft, gfx::Point());
+  check_helper(indicator.get(), to_int(IndicatorType::kLeftHighlight));
+  indicator->SetWindowDraggingState(
+      SplitViewDragIndicators::WindowDraggingState::kFromShelf, gfx::Point());
+  check_helper(indicator.get(), 0);
+  indicator->SetWindowDraggingState(
+      SplitViewDragIndicators::WindowDraggingState::kToSnapRight, gfx::Point());
+  check_helper(indicator.get(), to_int(IndicatorType::kRightHighlight));
+  indicator->SetWindowDraggingState(
+      SplitViewDragIndicators::WindowDraggingState::kFromShelf, gfx::Point());
+  check_helper(indicator.get(), 0);
+
   ScreenOrientationControllerTestApi orientation_api(
       Shell::Get()->screen_orientation_controller());
   // Verify that everything is visible in state
diff --git a/ash/wm/splitview/split_view_highlight_view.cc b/ash/wm/splitview/split_view_highlight_view.cc
index bf4e9e4..d121ebd 100644
--- a/ash/wm/splitview/split_view_highlight_view.cc
+++ b/ash/wm/splitview/split_view_highlight_view.cc
@@ -177,6 +177,7 @@
 void SplitViewHighlightView::OnWindowDraggingStateChanged(
     SplitViewDragIndicators::WindowDraggingState window_dragging_state,
     SplitViewDragIndicators::WindowDraggingState previous_window_dragging_state,
+    bool previews_only,
     bool can_dragged_window_be_snapped) {
   // No top indicator for dragging from the top in portrait orientation.
   if (window_dragging_state ==
@@ -212,10 +213,6 @@
     return;
   }
 
-  const bool previews_only =
-      SplitViewController::Get(GetWidget()->GetNativeWindow())
-          ->InSplitViewMode();
-
   if (previous_preview_position != SplitViewController::NONE) {
     // There was a snap preview showing, but now the user has dragged away from
     // the edge of the screen, so that the preview should go away.
diff --git a/ash/wm/splitview/split_view_highlight_view.h b/ash/wm/splitview/split_view_highlight_view.h
index 9298b0c..7e1d5316 100644
--- a/ash/wm/splitview/split_view_highlight_view.h
+++ b/ash/wm/splitview/split_view_highlight_view.h
@@ -45,11 +45,15 @@
   void SetColor(SkColor color);
 
   // Called to update the opacity of the highlights view on transition from
-  // |previous_window_dragging_state| to |window_dragging_state|.
+  // |previous_window_dragging_state| to |window_dragging_state|. If
+  // |previews_only|, then there shall be no visible drag indicators except for
+  // snap previews. The highlights are white if |can_dragged_window_be_snapped|,
+  // black otherwise.
   void OnWindowDraggingStateChanged(
       SplitViewDragIndicators::WindowDraggingState window_dragging_state,
       SplitViewDragIndicators::WindowDraggingState
           previous_window_dragging_state,
+      bool previews_only,
       bool can_dragged_window_be_snapped);
 
  private:
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 4b35482..8399302 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -460,6 +460,8 @@
     "process/process_iterator.h",
     "process/process_metrics.cc",
     "process/process_metrics.h",
+    "profiler/arm_cfi_table.cc",
+    "profiler/arm_cfi_table.h",
     "profiler/frame.cc",
     "profiler/frame.h",
     "profiler/metadata_recorder.cc",
@@ -2647,6 +2649,7 @@
     "process/process_metrics_unittest.cc",
     "process/process_unittest.cc",
     "process/process_util_unittest.cc",
+    "profiler/arm_cfi_table_unittest.cc",
     "profiler/metadata_recorder_unittest.cc",
     "profiler/sample_metadata_unittest.cc",
     "profiler/stack_copier_suspend_unittest.cc",
diff --git a/base/allocator/partition_allocator/page_allocator_internals_fuchsia.h b/base/allocator/partition_allocator/page_allocator_internals_fuchsia.h
index 77710a7..8486fa81 100644
--- a/base/allocator/partition_allocator/page_allocator_internals_fuchsia.h
+++ b/base/allocator/partition_allocator/page_allocator_internals_fuchsia.h
@@ -169,8 +169,21 @@
   ZX_CHECK(status == ZX_OK, status);
 }
 
+void DiscardSystemPagesInternal(void* address, size_t length) {
+  // TODO(https://crbug.com/1022062): Mark pages as discardable, rather than
+  // forcibly de-committing them immediately, when Fuchsia supports it.
+  uint64_t address_int = reinterpret_cast<uint64_t>(address);
+  zx_status_t status = zx::vmar::root_self()->op_range(
+      ZX_VMO_OP_DECOMMIT, address_int, length, nullptr, 0);
+  ZX_CHECK(status == ZX_OK, status);
+}
+
 void DecommitSystemPagesInternal(void* address, size_t length) {
-  DiscardSystemPages(address, length);
+  // TODO(https://crbug.com/1022062): Review whether this implementation is
+  // still appropriate once DiscardSystemPagesInternal() migrates to a "lazy"
+  // discardable API.
+  DiscardSystemPagesInternal(address, length);
+
   SetSystemPagesAccessInternal(address, length, PageInaccessible);
 }
 
@@ -181,10 +194,6 @@
   return true;
 }
 
-void DiscardSystemPagesInternal(void* address, size_t length) {
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
 }  // namespace base
 
 #endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNALS_FUCHSIA_H_
diff --git a/base/metrics/histogram_macros.h b/base/metrics/histogram_macros.h
index 6edb65a..4a691e4 100644
--- a/base/metrics/histogram_macros.h
+++ b/base/metrics/histogram_macros.h
@@ -18,9 +18,6 @@
 // the histogram should take, see
 // https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md
 
-// TODO(rkaplow): Link to proper documentation on metric creation once we have
-// it in a good state.
-
 // All of these macros must be called with |name| as a runtime constant - it
 // doesn't have to literally be a constant, but it must be the same string on
 // all calls from a particular call site. If this rule is violated, it is
@@ -327,10 +324,11 @@
         name, sample, min, max, bucket_count,                                  \
         base::HistogramBase::kUmaStabilityHistogramFlag)
 
-#define UMA_STABILITY_HISTOGRAM_ENUMERATION(name, sample, enum_max)            \
-    INTERNAL_HISTOGRAM_ENUMERATION_WITH_FLAG(                                  \
-        name, sample, enum_max,                                                \
-        base::HistogramBase::kUmaStabilityHistogramFlag)
+#define UMA_STABILITY_HISTOGRAM_ENUMERATION(name, ...)                  \
+  INTERNAL_UMA_HISTOGRAM_ENUMERATION_GET_MACRO(                         \
+      __VA_ARGS__, INTERNAL_UMA_HISTOGRAM_ENUMERATION_SPECIFY_BOUNDARY, \
+      INTERNAL_UMA_HISTOGRAM_ENUMERATION_DEDUCE_BOUNDARY)               \
+  (name, __VA_ARGS__, base::HistogramBase::kUmaStabilityHistogramFlag)
 
 #define UMA_STABILITY_HISTOGRAM_LONG_TIMES(name, sample) \
   STATIC_HISTOGRAM_POINTER_BLOCK(                        \
diff --git a/base/profiler/arm_cfi_table.cc b/base/profiler/arm_cfi_table.cc
new file mode 100644
index 0000000..a9593b4
--- /dev/null
+++ b/base/profiler/arm_cfi_table.cc
@@ -0,0 +1,160 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/profiler/arm_cfi_table.h"
+
+#include <algorithm>
+
+namespace base {
+
+namespace {
+
+// The value of index when the function does not have unwind information.
+constexpr uint32_t kNoUnwindInformation = 0xFFFF;
+
+// The mask on the CFI row data that is used to get the high 14 bits and
+// multiply it by 4 to get CFA offset. Since the last 2 bits are masked out, a
+// shift is not necessary.
+constexpr uint16_t kCFAMask = 0xfffc;
+
+// The mask on the CFI row data that is used to get the low 2 bits and multiply
+// it by 4 to get the return address offset.
+constexpr uint16_t kReturnAddressMask = 0x3;
+constexpr uint16_t kReturnAddressShift = 2;
+
+// The CFI data in UNW_DATA table starts with number of rows (N) encoded as
+// uint16_t, followed by N 4 byte rows. The CFIDataRow represents a single row
+// of CFI data of a function in the table. Since we cast the memory at the
+// address after the address of number of rows into an array of CFIDataRow, the
+// size of the struct should be 4 bytes and the order of the members is fixed
+// according to the given format. The first 2 bytes is the address of function
+// and last 2 bytes is the CFI data for the offset.
+struct CFIDataRow {
+  // The address of the instruction as an offset from the start of the
+  // function.
+  uint16_t addr_offset;
+  // Represents the CFA and RA offsets to get information about next stack
+  // frame. This is the CFI data at the point before executing the instruction
+  // at |addr_offset| from the start of the function.
+  uint16_t cfi_data;
+
+  // Helper functions to convert the to ArmCFITable::FrameEntry
+  size_t ra_offset() const {
+    return (cfi_data & kReturnAddressMask) << kReturnAddressShift;
+  }
+  size_t cfa_offset() const { return cfi_data & kCFAMask; }
+};
+
+static_assert(sizeof(CFIDataRow) == 4,
+              "The CFIDataEntry struct must be exactly 4 bytes to ensure "
+              "correct parsing of input data");
+
+}  // namespace
+
+// static
+std::unique_ptr<ArmCFITable> ArmCFITable::Parse(span<const uint8_t> cfi_data) {
+  BufferIterator<const uint8_t> cfi_iterator(cfi_data);
+
+  const uint32_t* unw_index_count = cfi_iterator.Object<uint32_t>();
+  if (unw_index_count == nullptr || *unw_index_count == 0U)
+    return nullptr;
+
+  auto function_addresses = cfi_iterator.Span<uint32_t>(*unw_index_count);
+  auto entry_data_indices = cfi_iterator.Span<uint16_t>(*unw_index_count);
+  if (function_addresses.size() != *unw_index_count ||
+      entry_data_indices.size() != *unw_index_count)
+    return nullptr;
+
+  // The UNW_DATA table data is right after the end of UNW_INDEX table.
+  auto entry_data = cfi_iterator.Span<uint8_t>(
+      (cfi_iterator.total_size() - cfi_iterator.position()) / sizeof(uint8_t));
+  return std::make_unique<ArmCFITable>(function_addresses, entry_data_indices,
+                                       entry_data);
+}
+
+ArmCFITable::ArmCFITable(span<const uint32_t> function_addresses,
+                         span<const uint16_t> entry_data_indices,
+                         span<const uint8_t> entry_data)
+    : function_addresses_(function_addresses),
+      entry_data_indices_(entry_data_indices),
+      entry_data_(entry_data) {
+  DCHECK_EQ(function_addresses.size(), entry_data_indices.size());
+}
+
+ArmCFITable::~ArmCFITable() = default;
+
+Optional<ArmCFITable::FrameEntry> ArmCFITable::FindEntryForAddress(
+    uintptr_t address) const {
+  DCHECK(!function_addresses_.empty());
+
+  // Find the required function address in UNW_INDEX as the last function lower
+  // or equal to |address| (the value right before the result of upper_bound(),
+  // if any).
+  auto func_it = std::upper_bound(function_addresses_.begin(),
+                                  function_addresses_.end(), address);
+  // If no function comes before |address|, no CFI entry  is returned.
+  if (func_it == function_addresses_.begin())
+    return nullopt;
+  --func_it;
+
+  uint32_t func_start_addr = *func_it;
+  size_t row_num = func_it - function_addresses_.begin();
+  uint16_t index = entry_data_indices_[row_num];
+  DCHECK_LE(func_start_addr, address);
+
+  if (index == kNoUnwindInformation)
+    return nullopt;
+
+  // The unwind data for the current function is at a 2 bytes offset of the
+  // index found in UNW_INDEX table.
+  if (entry_data_.size() <= index * sizeof(uint16_t))
+    return nullopt;
+  BufferIterator<const uint8_t> entry_iterator(entry_data_);
+  entry_iterator.Seek(index * sizeof(uint16_t));
+
+  // The value of first 2 bytes is the CFI data row count for the function.
+  const uint16_t* row_count = entry_iterator.Object<uint16_t>();
+  if (row_count == nullptr)
+    return nullopt;
+  // And the actual CFI rows start after 2 bytes from the |unwind_data|. Cast
+  // the data into an array of CFIUnwindDataRow since the struct is designed to
+  // represent each row. We should be careful to read only |row_count| number of
+  // elements in the array.
+  auto function_cfi = entry_iterator.Span<CFIDataRow>(*row_count);
+  if (function_cfi.size() != *row_count)
+    return nullopt;
+
+  FrameEntry last_frame_entry = {0, 0};
+  // Iterate through all function entries to find a range covering |address|.
+  // In practice, the majority of functions contain very few entries.
+  for (const auto& entry : function_cfi) {
+    // The return address of the function is the instruction that is not yet
+    // been executed. The CFI row specifies the unwind info before executing the
+    // given instruction. If the given address is equal to the instruction
+    // offset, then use the current row. Or use the row with highest address
+    // less than the given address.
+    if (func_start_addr + entry.addr_offset > address)
+      break;
+
+    uint32_t cfa_offset = entry.cfa_offset();
+    if (cfa_offset == 0)
+      return nullopt;
+    last_frame_entry.cfa_offset = cfa_offset;
+
+    uint32_t ra_offset = entry.ra_offset();
+    // The RA offset of the last specified row should be used, if unspecified.
+    // Update |last_ra_offset| only if valid for this row. Otherwise, tthe last
+    // valid |last_ra_offset| is used. TODO(ssid): This should be fixed in the
+    // format and we should always output ra offset.
+    if (ra_offset)
+      last_frame_entry.ra_offset = ra_offset;
+
+    if (last_frame_entry.ra_offset == 0)
+      return nullopt;
+  }
+
+  return last_frame_entry;
+}
+
+}  // namespace base
\ No newline at end of file
diff --git a/base/profiler/arm_cfi_table.h b/base/profiler/arm_cfi_table.h
new file mode 100644
index 0000000..73b719a
--- /dev/null
+++ b/base/profiler/arm_cfi_table.h
@@ -0,0 +1,75 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_PROFILER_ARM_CFI_TABLE_H_
+#define BASE_PROFILER_ARM_CFI_TABLE_H_
+
+#include <memory>
+
+#include "base/containers/buffer_iterator.h"
+#include "base/containers/span.h"
+#include "base/macros.h"
+#include "base/optional.h"
+
+namespace base {
+
+// This class implements methods to read and parse the arm Call Frame
+// Information (CFI) for Chrome, which contains tables for unwinding Chrome
+// functions. For detailed description of the format, see
+// extract_unwind_tables.py.
+class BASE_EXPORT ArmCFITable {
+ public:
+  // The CFI information that correspond to an instruction. {0, 0} is a valid
+  // entry and should be interpreted as the default rule:
+  // .cfa: sp; .cfa = lr (link register).
+  struct FrameEntry {
+    // The offset of the call frame address (CFA) of previous function, relative
+    // to the current stack pointer. Rule for unwinding CFA:
+    // .cfa: sp + cfa_offset.
+    uint16_t cfa_offset = 0;
+    // The offset of location of return address (RA), relative to the previous
+    // call frame address. Rule for unwinding RA:
+    // .ra = *(cfa - ra_offset).
+    uint16_t ra_offset = 0;
+  };
+
+  // Parses |cfi_data| and creates a ArmCFITable that reads from it.
+  // |cfi_data| is required to remain valid for the lifetime of the object.
+  static std::unique_ptr<ArmCFITable> Parse(span<const uint8_t> cfi_data);
+
+  ArmCFITable(span<const uint32_t> function_addresses,
+              span<const uint16_t> entry_data_indices,
+              span<const uint8_t> entry_data);
+  ~ArmCFITable();
+
+  // Finds the CFI row for the given |address| in terms of offset from the
+  // start of the current binary. Concurrent calls are thread safe.
+  Optional<FrameEntry> FindEntryForAddress(uintptr_t address) const;
+
+  size_t GetTableSizeForTesting() const { return function_addresses_.size(); }
+
+ private:
+  // The UNW_INDEX table allows readers to map functions start addresses to
+  // that function's respective entry in the UNW_DATA table.
+  //   - A function's start address is at 0x123, and
+  //   - function_addresses_[2] == 0x123, and
+  //   - entry_data_indices_[2] = 42, then
+  //   - entry_data_[42] is the corresponding entry in the UNW_DATA table for
+  //     the function with the start address of 0x123
+  //
+  // Note that function_addresses is sorted to facilitate easy lookup.
+  const span<const uint32_t> function_addresses_;
+  const span<const uint16_t> entry_data_indices_;
+
+  // A reference to the UNW_DATA table. Each entry in the UNW_DATA table
+  // corresponds to a function, which in turn corresponds to an array of
+  // CFIDataRows. (see arm_cfi_reader.cc).
+  const span<const uint8_t> entry_data_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArmCFITable);
+};
+
+}  // namespace base
+
+#endif  // BASE_PROFILER_ARM_CFI_TABLE_H_
diff --git a/base/profiler/arm_cfi_table_unittest.cc b/base/profiler/arm_cfi_table_unittest.cc
new file mode 100644
index 0000000..07a48d1
--- /dev/null
+++ b/base/profiler/arm_cfi_table_unittest.cc
@@ -0,0 +1,174 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/profiler/arm_cfi_table.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+bool operator==(const ArmCFITable::FrameEntry& a,
+                const ArmCFITable::FrameEntry& b) {
+  return a.cfa_offset == b.cfa_offset && a.ra_offset == b.ra_offset;
+}
+
+TEST(ArmCFITableTest, Parse) {
+  auto parse_cfi = [](std::vector<uint16_t> data) {
+    return ArmCFITable::Parse(
+        {reinterpret_cast<const uint8_t*>(data.data()), data.size() * 2});
+  };
+
+  auto reader = parse_cfi({0x01, 0x00, 0x0, 0x0, 0xffff});
+  EXPECT_TRUE(reader);
+  EXPECT_EQ(1U, reader->GetTableSizeForTesting());
+}
+
+TEST(ArmCFITableTest, FindEntryForAddress) {
+  // Input is generated from the CFI file:
+  // STACK CFI INIT 1000 500
+  // STACK CFI 1002 .cfa: sp 272 + .ra: .cfa -4 + ^ r4: .cfa -16 +
+  // STACK CFI 1008 .cfa: sp 544 + .r1: .cfa -0 + ^ r4: .cfa -16 + ^
+  // STACK CFI 1040 .cfa: sp 816 + .r1: .cfa -0 + ^ r4: .cfa -16 + ^
+  // STACK CFI 1050 .cfa: sp 816 + .ra: .cfa -8 + ^ r4: .cfa -16 + ^
+  // STACK CFI 1080 .cfa: sp 544 + .r1: .cfa -0 + ^ r4: .cfa -16 + ^
+  //
+  // STACK CFI INIT 2000 22
+  // STACK CFI 2004 .cfa: sp 16 + .ra: .cfa -12 + ^ r4: .cfa -16 + ^
+  // STACK CFI 2008 .cfa: sp 16 + .ra: .cfa -12 + ^ r4: .cfa -16 + ^
+  //
+  // STACK CFI INIT 2024 100
+  // STACK CFI 2030 .cfa: sp 48 + .ra: .cfa -12 + ^ r4: .cfa -16 + ^
+  // STACK CFI 2100 .cfa: sp 64 + .r1: .cfa -0 + ^ r4: .cfa -16 + ^
+  //
+  // STACK CFI INIT 2200 10
+  // STACK CFI 2204 .cfa: sp 44 + .ra: .cfa -8 + ^ r4: .cfa -16 + ^
+  const uint16_t input_data[] = {// UNW_INDEX size
+                                 0x07, 0x0,
+
+                                 // UNW_INDEX function_addresses (4 byte rows).
+                                 0x1000, 0x0, 0x1502, 0x0, 0x2000, 0x0, 0x2024,
+                                 0x0, 0x2126, 0x0, 0x2200, 0x0, 0x2212, 0x0,
+
+                                 // UNW_INDEX entry_data_indices (2 byte rows).
+                                 0x0, 0xffff, 0xb, 0x10, 0xffff, 0x15, 0xffff,
+
+                                 // UNW_DATA table.
+                                 0x5, 0x2, 0x111, 0x8, 0x220, 0x40, 0x330, 0x50,
+                                 0x332, 0x80, 0x220, 0x2, 0x4, 0x13, 0x8, 0x13,
+                                 0x2, 0xc, 0x33, 0xdc, 0x40, 0x1, 0x4, 0x2e};
+
+  auto reader = ArmCFITable::Parse(
+      {reinterpret_cast<const uint8_t*>(input_data), sizeof(input_data) * 2});
+  EXPECT_EQ(7U, reader->GetTableSizeForTesting());
+
+  EXPECT_FALSE(reader->FindEntryForAddress(0x01));
+  EXPECT_FALSE(reader->FindEntryForAddress(0x100));
+  EXPECT_FALSE(reader->FindEntryForAddress(0x1502));
+  EXPECT_FALSE(reader->FindEntryForAddress(0x3000));
+  EXPECT_FALSE(reader->FindEntryForAddress(0x2212));
+
+  auto expect_frame = [&](ArmCFITable::FrameEntry expected, uintptr_t address) {
+    auto result = reader->FindEntryForAddress(address);
+    EXPECT_TRUE(result.has_value());
+    EXPECT_EQ(expected, *result);
+  };
+
+  expect_frame({0x110, 0x4}, 0x1002);
+  expect_frame({0x110, 0x4}, 0x1003);
+  expect_frame({0x220, 0x4}, 0x1008);
+  expect_frame({0x220, 0x4}, 0x1009);
+  expect_frame({0x220, 0x4}, 0x1039);
+  expect_frame({0x220, 0x8}, 0x1080);
+  expect_frame({0x220, 0x8}, 0x1100);
+  expect_frame({0x0, 0x0}, 0x2024);
+  expect_frame({0x30, 0xc}, 0x2050);
+  expect_frame({0x2c, 0x8}, 0x2208);
+  expect_frame({0x2c, 0x8}, 0x2210);
+}
+
+TEST(ArmCFITableTest, InvalidTable) {
+  auto parse_cfi_and_find =
+      [](std::vector<uint16_t> data,
+         uintptr_t address) -> Optional<ArmCFITable::FrameEntry> {
+    auto reader = ArmCFITable::Parse(
+        {reinterpret_cast<const uint8_t*>(data.data()), data.size() * 2});
+    if (!reader)
+      return base::nullopt;
+    return reader->FindEntryForAddress(address);
+  };
+
+  // No data.
+  EXPECT_FALSE(parse_cfi_and_find({}, 0x0));
+
+  // Empty UNW_INDEX.
+  EXPECT_FALSE(parse_cfi_and_find({0x00, 0x00}, 0x0));
+
+  // Missing UNW_INDEX data.
+  EXPECT_FALSE(parse_cfi_and_find({0x01, 0x00}, 0x0));
+
+  // No unwind info for address.
+  EXPECT_FALSE(parse_cfi_and_find({0x02, 0x00, 0x0, 0x0, 0xffff}, 0x0));
+
+  // entry_data_indices out of bound.
+  EXPECT_FALSE(parse_cfi_and_find(
+      {
+          // UNW_INDEX size
+          0x01,
+          0x0,
+          // UNW_INDEX
+          0x1000,
+          0x0,
+          0x0,
+          // UNW_DATA
+          0x5,
+      },
+      0x1000));
+
+  EXPECT_FALSE(parse_cfi_and_find(
+      {
+          // UNW_INDEX size
+          0x01,
+          0x0,
+          // UNW_INDEX
+          0x1000,
+          0x0,
+          0x0,
+      },
+      0x1000));
+
+  // Missing CFIDataRow.
+  EXPECT_FALSE(parse_cfi_and_find(
+      {
+          // UNW_INDEX size
+          0x01,
+          0x0,
+          // UNW_INDEX
+          0x1000,
+          0x0,
+          0x0,
+          // UNW_DATA
+          0x5,
+          0x0,
+      },
+      0x1000));
+
+  // Invalid CFIDataRow.
+  EXPECT_FALSE(parse_cfi_and_find(
+      {
+          // UNW_INDEX size
+          0x01,
+          0x0,
+          // UNW_INDEX
+          0x1000,
+          0x0,
+          0x0,
+          // UNW_DATA
+          0x1,
+          0x2,
+          0x0,
+      },
+      0x1002));
+}
+
+}  // namespace base
\ No newline at end of file
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 0c617e18..98cfdd47 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8897528717233543120
\ No newline at end of file
+8897503639019477520
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index a413d78..d33a210 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8897529567853951504
\ No newline at end of file
+8897506421733316256
\ No newline at end of file
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 7446dd4..9e8db5bb 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2213,6 +2213,33 @@
       frame->render_passes.back()->has_transparent_background;
 #endif
 
+  if (last_draw_render_frame_metadata_) {
+    const float last_root_scroll_offset_y =
+        last_draw_render_frame_metadata_->root_scroll_offset
+            .value_or(gfx::Vector2dF())
+            .y();
+
+    const float new_root_scroll_offset_y =
+        metadata.root_scroll_offset.value().y();
+
+    if (!MathUtil::IsWithinEpsilon(last_root_scroll_offset_y,
+                                   new_root_scroll_offset_y)) {
+      viz::VerticalScrollDirection new_vertical_scroll_direction =
+          (last_root_scroll_offset_y < new_root_scroll_offset_y)
+              ? viz::VerticalScrollDirection::kDown
+              : viz::VerticalScrollDirection::kUp;
+
+      // Changes in vertical scroll direction happen instantaneously. This being
+      // the case, a new vertical scroll direction should only be present in the
+      // singular metadata for the render frame in which the direction change
+      // occurred. If the vertical scroll direction detected here matches that
+      // which we've previously cached, then this frame is not the instant in
+      // which the direction change occurred and is therefore not propagated.
+      if (last_vertical_scroll_direction_ != new_vertical_scroll_direction)
+        metadata.new_vertical_scroll_direction = new_vertical_scroll_direction;
+    }
+  }
+
   bool allocate_new_local_surface_id =
 #if !defined(OS_ANDROID)
       last_draw_render_frame_metadata_ &&
@@ -2374,6 +2401,17 @@
 
   if (render_frame_metadata_observer_) {
     last_draw_render_frame_metadata_ = MakeRenderFrameMetadata(frame);
+
+    // We cache the value of any new vertical scroll direction so that we can
+    // accurately determine when the next change in vertical scroll direction
+    // occurs. Note that |kNull| is only used to indicate the absence of a
+    // vertical scroll direction and should therefore be ignored.
+    if (last_draw_render_frame_metadata_->new_vertical_scroll_direction !=
+        viz::VerticalScrollDirection::kNull) {
+      last_vertical_scroll_direction_ =
+          last_draw_render_frame_metadata_->new_vertical_scroll_direction;
+    }
+
     render_frame_metadata_observer_->OnRenderFrameSubmission(
         *last_draw_render_frame_metadata_, &metadata,
         active_tree()->TakeForceSendMetadataRequest());
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 73f79db8..2ae154e1 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -1251,6 +1251,12 @@
   base::Optional<RenderFrameMetadata> last_draw_render_frame_metadata_;
   viz::ChildLocalSurfaceIdAllocator child_local_surface_id_allocator_;
 
+  // Indicates the direction of the last vertical scroll of the root layer.
+  // Until the first vertical scroll occurs, this value is |kNull|. Note that
+  // once this value is updated, it will never return to |kNull|.
+  viz::VerticalScrollDirection last_vertical_scroll_direction_ =
+      viz::VerticalScrollDirection::kNull;
+
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 
   PresentationTimeCallbackBuffer presentation_time_callbacks_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 5a2b09e..9784156e 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -12786,6 +12786,89 @@
   EXPECT_TRUE(selection_2.end.visible());
 }
 
+TEST_F(LayerTreeHostImplTest,
+       VerticalScrollDirectionChangesPassedToRenderFrameMetadata) {
+  // Set up the viewport.
+  SetupViewportLayersInnerScrolls(gfx::Size(50, 50), gfx::Size(100, 100));
+  host_impl_->active_tree()->SetDeviceViewportRect(gfx::Rect(50, 50));
+
+  // Set up the render frame metadata observer.
+  auto observer = std::make_unique<TestRenderFrameMetadataObserver>(false);
+  auto* observer_ptr = observer.get();
+  host_impl_->SetRenderFrameObserver(std::move(observer));
+  EXPECT_FALSE(observer_ptr->last_metadata());
+
+  // Our test will be comprised of multiple legs, each leg consisting of a
+  // distinct scroll event and an expectation regarding the vertical scroll
+  // direction passed to the render frame metadata.
+  typedef struct {
+    gfx::Vector2d scroll_delta;
+    viz::VerticalScrollDirection expected_vertical_scroll_direction;
+  } TestLeg;
+
+  std::vector<TestLeg> test_legs;
+
+  // Initially, vertical scroll direction should be |kNull| indicating absence.
+  test_legs.push_back({/*scroll_delta=*/gfx::Vector2d(),
+                       /*expected_vertical_scroll_direction=*/viz::
+                           VerticalScrollDirection::kNull});
+
+  // Scrolling to the right should not affect vertical scroll direction.
+  test_legs.push_back({/*scroll_delta=*/gfx::Vector2d(10, 0),
+                       /*expected_vertical_scroll_direction=*/viz::
+                           VerticalScrollDirection::kNull});
+
+  // After scrolling down, the vertical scroll direction should be |kDown|.
+  test_legs.push_back({/*scroll_delta=*/gfx::Vector2d(0, 10),
+                       /*expected_vertical_scroll_direction=*/viz::
+                           VerticalScrollDirection::kDown});
+
+  // If we scroll down again, the vertical scroll direction should be |kNull| as
+  // there was no change in vertical scroll direction.
+  test_legs.push_back({/*scroll_delta=*/gfx::Vector2d(0, 10),
+                       /*expected_vertical_scroll_direction=*/viz::
+                           VerticalScrollDirection::kNull});
+
+  // Scrolling to the left should not affect last vertical scroll direction.
+  test_legs.push_back({/*scroll_delta=*/gfx::Vector2d(-10, 0),
+                       /*expected_vertical_scroll_direction=*/viz::
+                           VerticalScrollDirection::kNull});
+
+  // After scrolling up, the vertical scroll direction should be |kUp|.
+  test_legs.push_back({/*scroll_delta=*/gfx::Vector2d(0, -10),
+                       /*expected_vertical_scroll_direction=*/viz::
+                           VerticalScrollDirection::kUp});
+
+  // If we scroll up again, the vertical scroll direction should be |kNull| as
+  // there was no change in vertical scroll direction.
+  test_legs.push_back({/*scroll_delta=*/gfx::Vector2d(0, -10),
+                       /*expected_vertical_scroll_direction=*/viz::
+                           VerticalScrollDirection::kNull});
+
+  // Iterate over all legs of our test.
+  for (auto& test_leg : test_legs) {
+    // If the test leg contains a scroll, perform it.
+    if (!test_leg.scroll_delta.IsZero()) {
+      host_impl_->ScrollBegin(BeginState(gfx::Point()).get(),
+                              InputHandler::WHEEL);
+      host_impl_->ScrollBy(
+          UpdateState(gfx::Point(), test_leg.scroll_delta).get());
+    }
+
+    // Trigger draw.
+    host_impl_->SetNeedsRedraw();
+    DrawFrame();
+
+    // Assert our expectation regarding the vertical scroll direction.
+    EXPECT_EQ(test_leg.expected_vertical_scroll_direction,
+              observer_ptr->last_metadata()->new_vertical_scroll_direction);
+
+    // If the test leg contains a scroll, end it.
+    if (!test_leg.scroll_delta.IsZero())
+      host_impl_->ScrollEnd(EndState().get());
+  }
+}
+
 // Tests ScrollBy() to see if the method sets the scroll tree's currently
 // scrolling node and the ScrollState properly.
 TEST_F(LayerTreeHostImplTest, ScrollByScrollingNode) {
diff --git a/cc/trees/render_frame_metadata.cc b/cc/trees/render_frame_metadata.cc
index b666e9c..158f4a6 100644
--- a/cc/trees/render_frame_metadata.cc
+++ b/cc/trees/render_frame_metadata.cc
@@ -45,7 +45,8 @@
          root_layer_size == other.root_layer_size &&
          has_transparent_background == other.has_transparent_background &&
 #endif
-         local_surface_id_allocation == other.local_surface_id_allocation;
+         local_surface_id_allocation == other.local_surface_id_allocation &&
+         new_vertical_scroll_direction == other.new_vertical_scroll_direction;
 }
 
 bool RenderFrameMetadata::operator!=(const RenderFrameMetadata& other) const {
diff --git a/cc/trees/render_frame_metadata.h b/cc/trees/render_frame_metadata.h
index 400eeaef..8d71c87 100644
--- a/cc/trees/render_frame_metadata.h
+++ b/cc/trees/render_frame_metadata.h
@@ -11,6 +11,7 @@
 #include "cc/cc_export.h"
 #include "components/viz/common/quads/selection.h"
 #include "components/viz/common/surfaces/local_surface_id_allocation.h"
+#include "components/viz/common/vertical_scroll_direction.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/size_f.h"
@@ -75,6 +76,14 @@
   float top_controls_height = 0.f;
   float top_controls_shown_ratio = 0.f;
 
+  // Indicates a change in the vertical scroll direction of the root layer since
+  // the last drawn render frame. If no change occurred, this value is |kNull|.
+  // Note that if a scroll in a given direction occurs, the scroll is completed,
+  // and then another scroll in the *same* direction occurs, we will not
+  // consider the second scroll event to have caused a change in direction.
+  viz::VerticalScrollDirection new_vertical_scroll_direction =
+      viz::VerticalScrollDirection::kNull;
+
 #if defined(OS_ANDROID)
   // Used to position Android bottom bar, whose position is computed by the
   // renderer compositor.
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 2d86698..0951a667 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2787,7 +2787,7 @@
     "java/src/org/chromium/chrome/browser/rappor/RapporServiceBridge.java",
     "java/src/org/chromium/chrome/browser/rlz/RevenueStats.java",
     "java/src/org/chromium/chrome/browser/rlz/RlzPingHandler.java",
-    "java/src/org/chromium/chrome/browser/safe_browsing/FileTypePolicies.java",
+    "java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingBridge.java",
     "java/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceFactory.java",
     "java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java",
     "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridge.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 20ff3fe..9b7b8d70 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -433,6 +433,7 @@
   "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandlingStrategy.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/TabCreationMode.java",
+  "java/src/org/chromium/chrome/browser/customtabs/content/TabObserverRegistrar.java",
   "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java",
   "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityModule.java",
   "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegate.java",
@@ -1425,7 +1426,7 @@
   "java/src/org/chromium/chrome/browser/rappor/RapporServiceBridge.java",
   "java/src/org/chromium/chrome/browser/rlz/RevenueStats.java",
   "java/src/org/chromium/chrome/browser/rlz/RlzPingHandler.java",
-  "java/src/org/chromium/chrome/browser/safe_browsing/FileTypePolicies.java",
+  "java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingBridge.java",
   "java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetrics.java",
   "java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java",
   "java/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceFactory.java",
@@ -1578,7 +1579,6 @@
   "java/src/org/chromium/chrome/browser/tab/TabImportanceManager.java",
   "java/src/org/chromium/chrome/browser/tab/TabHelpers.java",
   "java/src/org/chromium/chrome/browser/tab/TabObserver.java",
-  "java/src/org/chromium/chrome/browser/tab/TabObserverRegistrar.java",
   "java/src/org/chromium/chrome/browser/tab/TabParentIntent.java",
   "java/src/org/chromium/chrome/browser/tab/TabRedirectHandler.java",
   "java/src/org/chromium/chrome/browser/tab/TabState.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java
index 17c370c..a8d57a51 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java
@@ -30,6 +30,7 @@
 import org.chromium.chrome.browser.notifications.NotificationPlatformBridge;
 import org.chromium.chrome.browser.notifications.chime.ChimeSession;
 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
+import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.privacy.BrowsingDataBridge;
 import org.chromium.chrome.browser.profiles.ProfileManagerUtils;
@@ -239,9 +240,13 @@
                 Settings.System.getInt(ContextUtils.getApplicationContext().getContentResolver(),
                         Settings.System.TEXT_SHOW_PASSWORD, 1)
                 == 1;
-        if (PrefServiceBridge.getInstance().getPasswordEchoEnabled() == systemEnabled) return;
+        if (PrefServiceBridge.getInstance().getBoolean(Pref.WEBKIT_PASSWORD_ECHO_ENABLED)
+                == systemEnabled) {
+            return;
+        }
 
-        PrefServiceBridge.getInstance().setPasswordEchoEnabled(systemEnabled);
+        PrefServiceBridge.getInstance().setBoolean(
+                Pref.WEBKIT_PASSWORD_ECHO_ENABLED, systemEnabled);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/CurrentPageVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/CurrentPageVerifier.java
index f39fd6e..0eb8337 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/CurrentPageVerifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/CurrentPageVerifier.java
@@ -4,19 +4,23 @@
 
 package org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller;
 
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import org.chromium.base.ObserverList;
 import org.chromium.base.Promise;
 import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityModel;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
+import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabObserver;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.content_public.browser.NavigationHandle;
 
 import java.lang.annotation.Retention;
@@ -24,10 +28,6 @@
 
 import javax.inject.Inject;
 
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
 /**
  * Checks whether the currently seen web page belongs to a verified origin and updates the
  * {@link TrustedWebActivityModel} accordingly.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java
index 1e4c3e46..07886697 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java
@@ -7,11 +7,11 @@
 import androidx.annotation.NonNull;
 
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
+import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbarCoordinator;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabObserver;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
 import org.chromium.content_public.common.BrowserControlsState;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
index 04ad13f..094a4152 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
@@ -43,7 +43,6 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabAssociatedApp;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.tab.TabRedirectHandler;
 import org.chromium.chrome.browser.tabmodel.AsyncTabParams;
 import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserverRegistrar.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/TabObserverRegistrar.java
similarity index 95%
rename from chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserverRegistrar.java
rename to chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/TabObserverRegistrar.java
index b48cff7..05029b2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabObserverRegistrar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/TabObserverRegistrar.java
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.tab;
+package org.chromium.chrome.browser.customtabs.content;
 
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.metrics.PageLoadMetrics;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
 
 import java.util.HashSet;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
index 4ae1f8e..864a9e56 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
@@ -33,6 +33,7 @@
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
+import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
@@ -42,7 +43,6 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabObserver;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.chrome.browser.util.UrlUtilitiesJni;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarColorController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarColorController.java
index 7e6c937..ff8c798 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarColorController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarColorController.java
@@ -6,12 +6,12 @@
 
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
+import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.InflationObserver;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
 import org.chromium.chrome.browser.ui.styles.ChromeColors;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java
index dd235b27..92513b01 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadLocationDialogBridge.java
@@ -13,7 +13,6 @@
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.download.R;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
@@ -117,8 +116,7 @@
             final DirectoryOption dir = dirs.get(0);
             if (dir.type == DirectoryOption.DownloadLocationDirectoryType.DEFAULT) {
                 assert(!TextUtils.isEmpty(dir.location));
-                PrefServiceBridge.getInstance().setDownloadAndSaveFileDefaultDirectory(
-                        dir.location);
+                setDownloadAndSaveFileDefaultDirectory(dir.location);
                 DownloadLocationDialogBridgeJni.get().onComplete(
                         mNativeDownloadLocationDialogBridge, DownloadLocationDialogBridge.this,
                         mSuggestedPath);
@@ -194,8 +192,7 @@
 
         // Update native with new path.
         if (mNativeDownloadLocationDialogBridge != 0) {
-            PrefServiceBridge.getInstance().setDownloadAndSaveFileDefaultDirectory(
-                    directoryOption.location);
+            setDownloadAndSaveFileDefaultDirectory(directoryOption.location);
 
             RecordHistogram.recordEnumeratedHistogram(
                     "MobileDownload.Location.Dialog.DirectoryType", directoryOption.type,
@@ -222,11 +219,27 @@
         }
     }
 
+    /**
+     * @return The stored download default directory.
+     */
+    public static String getDownloadDefaultDirectory() {
+        return DownloadLocationDialogBridgeJni.get().getDownloadDefaultDirectory();
+    }
+
+    /**
+     * @param directory New directory to set as the download default directory.
+     */
+    public static void setDownloadAndSaveFileDefaultDirectory(String directory) {
+        DownloadLocationDialogBridgeJni.get().setDownloadAndSaveFileDefaultDirectory(directory);
+    }
+
     @NativeMethods
     interface Natives {
         void onComplete(long nativeDownloadLocationDialogBridge,
                 DownloadLocationDialogBridge caller, String returnedPath);
         void onCanceled(
                 long nativeDownloadLocationDialogBridge, DownloadLocationDialogBridge caller);
+        String getDownloadDefaultDirectory();
+        void setDownloadAndSaveFileDefaultDirectory(String directory);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeController.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeController.java
index c288dfb..694a7d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/WebContentsDarkModeController.java
@@ -11,6 +11,7 @@
 import org.chromium.base.ApplicationState;
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.ApplicationStatus.ApplicationStateListener;
+import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 
@@ -51,7 +52,7 @@
      * @param enabled the new state of the web content dark mode
      */
     private static void enableWebContentsDarkMode(boolean enabled) {
-        PrefServiceBridge.getInstance().setForceWebContentsDarkModeEnabled(enabled);
+        PrefServiceBridge.getInstance().setBoolean(Pref.WEBKIT_FORCE_DARK_MODE_ENABLED, enabled);
     }
 
     private static boolean shouldEnableWebContentsDarkMode() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
index c33c3fe1..0d3b6f30 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -38,6 +38,7 @@
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.chrome.browser.notifications.channels.SiteChannelsManager;
 import org.chromium.chrome.browser.permissions.PermissionFieldTrial;
+import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.preferences.website.SingleCategoryPreferences;
@@ -629,7 +630,8 @@
         // The Android framework applies a fallback vibration pattern for the sound when the device
         // is in vibrate mode, there is no custom pattern, and the vibration default has been
         // disabled. To truly prevent vibration, provide a custom empty pattern.
-        boolean vibrateEnabled = PrefServiceBridge.getInstance().isNotificationsVibrateEnabled();
+        boolean vibrateEnabled =
+                PrefServiceBridge.getInstance().getBoolean(Pref.NOTIFICATIONS_VIBRATE_ENABLED);
         if (!vibrateEnabled) {
             vibrationPattern = EMPTY_VIBRATION_PATTERN;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
index 00cd2cd9..475435e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
@@ -204,18 +204,6 @@
         return PrefServiceBridgeJni.get().getAcceptCookiesManagedByCustodian();
     }
 
-    // TODO(crbug.com/1016957): Inline downstream.
-    public boolean isBlockThirdPartyCookiesEnabled() {
-        return getBoolean(Pref.BLOCK_THIRD_PARTY_COOKIES);
-    }
-
-    /**
-     * @return Whether vibration is enabled for notifications.
-     */
-    public boolean isNotificationsVibrateEnabled() {
-        return PrefServiceBridgeJni.get().getNotificationsVibrateEnabled();
-    }
-
     /**
      * @return Whether geolocation information can be shared with content.
      */
@@ -245,10 +233,6 @@
         return PrefServiceBridgeJni.get().getAllowLocationManagedByCustodian();
     }
 
-    public boolean getPasswordEchoEnabled() {
-        return PrefServiceBridgeJni.get().getPasswordEchoEnabled();
-    }
-
     /**
      * @return Whether EULA has been accepted by the user.
      */
@@ -285,55 +269,6 @@
     }
 
     /**
-     * @return the last account username associated with sync.
-     */
-    public String getSyncLastAccountName() {
-        return PrefServiceBridgeJni.get().getSyncLastAccountName();
-    }
-
-    /**
-     * @return Whether Safe Browsing Extended Reporting is currently enabled.
-     */
-    public boolean isSafeBrowsingExtendedReportingEnabled() {
-        return PrefServiceBridgeJni.get().getSafeBrowsingExtendedReportingEnabled();
-    }
-
-    /**
-     * @param enabled Whether Safe Browsing Extended Reporting should be enabled.
-     */
-    public void setSafeBrowsingExtendedReportingEnabled(boolean enabled) {
-        PrefServiceBridgeJni.get().setSafeBrowsingExtendedReportingEnabled(enabled);
-    }
-
-    /**
-     * @return Whether Safe Browsing Extended Reporting is managed
-     */
-    public boolean isSafeBrowsingExtendedReportingManaged() {
-        return PrefServiceBridgeJni.get().getSafeBrowsingExtendedReportingManaged();
-    }
-
-    /**
-     * @return Whether Safe Browsing is currently enabled.
-     */
-    public boolean isSafeBrowsingEnabled() {
-        return PrefServiceBridgeJni.get().getSafeBrowsingEnabled();
-    }
-
-    /**
-     * @param enabled Whether Safe Browsing should be enabled.
-     */
-    public void setSafeBrowsingEnabled(boolean enabled) {
-        PrefServiceBridgeJni.get().setSafeBrowsingEnabled(enabled);
-    }
-
-    /**
-     * @return Whether Safe Browsing is managed
-     */
-    public boolean isSafeBrowsingManaged() {
-        return PrefServiceBridgeJni.get().getSafeBrowsingManaged();
-    }
-
-    /**
      * @return Whether there is a user set value for kNetworkPredictionOptions.  This should only be
      * used for preference migration. See http://crbug.com/334602
      */
@@ -372,40 +307,6 @@
     }
 
     /**
-     * @return Whether the web service to resolve navigation error is enabled.
-     */
-    public boolean isResolveNavigationErrorEnabled() {
-        return PrefServiceBridgeJni.get().getResolveNavigationErrorEnabled();
-    }
-
-    /**
-     * @return Whether the web service to resolve navigation error is configured by policy.
-     */
-    public boolean isResolveNavigationErrorManaged() {
-        return PrefServiceBridgeJni.get().getResolveNavigationErrorManaged();
-    }
-
-    /**
-     * Sets whether the web service to resolve navigation error should be enabled.
-     */
-    public void setResolveNavigationErrorEnabled(boolean enabled) {
-        PrefServiceBridgeJni.get().setResolveNavigationErrorEnabled(enabled);
-    }
-
-    // TODO(crbug.com/1016957): Inline downstream.
-    public void setBlockThirdPartyCookiesEnabled(boolean enabled) {
-        setBoolean(Pref.BLOCK_THIRD_PARTY_COOKIES, enabled);
-    }
-
-    public void setNotificationsVibrateEnabled(boolean enabled) {
-        PrefServiceBridgeJni.get().setNotificationsVibrateEnabled(enabled);
-    }
-
-    public void setPasswordEchoEnabled(boolean enabled) {
-        PrefServiceBridgeJni.get().setPasswordEchoEnabled(enabled);
-    }
-
-    /**
      * @return Whether the setting to allow popups is configured by policy
      */
     public boolean isPopupsManaged() {
@@ -597,27 +498,6 @@
         return PrefServiceBridgeJni.get().isMetricsReportingManaged();
     }
 
-    /**
-     * @return The stored download default directory.
-     */
-    public String getDownloadDefaultDirectory() {
-        return PrefServiceBridgeJni.get().getDownloadDefaultDirectory();
-    }
-
-    /**
-     * @param directory New directory to set as the download default directory.
-     */
-    public void setDownloadAndSaveFileDefaultDirectory(String directory) {
-        PrefServiceBridgeJni.get().setDownloadAndSaveFileDefaultDirectory(directory);
-    }
-
-    /**
-     * @param enabled The value to set whether or not ForceWebContentsDarkMode is enabled.
-     */
-    public void setForceWebContentsDarkModeEnabled(boolean enabled) {
-        PrefServiceBridgeJni.get().setForceWebContentsDarkModeEnabled(enabled);
-    }
-
     public void setContentSettingForPattern(int contentSettingType, String pattern, int setting) {
         PrefServiceBridgeJni.get().setContentSettingForPattern(
                 contentSettingType, pattern, setting);
@@ -654,7 +534,6 @@
         boolean getAllowLocationUserModifiable();
         boolean getLocationAllowedByPolicy();
         boolean getAllowLocationManagedByCustodian();
-        boolean getPasswordEchoEnabled();
         boolean getFirstRunEulaAccepted();
         boolean getCameraEnabled();
         void setCameraEnabled(boolean enabled);
@@ -664,8 +543,6 @@
         void setMicEnabled(boolean enabled);
         boolean getMicUserModifiable();
         boolean getMicManagedByCustodian();
-        boolean getResolveNavigationErrorEnabled();
-        boolean getResolveNavigationErrorManaged();
         boolean getIncognitoModeEnabled();
         boolean getIncognitoModeManaged();
         boolean getSensorsEnabled();
@@ -677,32 +554,18 @@
         void setClipboardEnabled(boolean enabled);
         boolean getAllowLocationEnabled();
         boolean getNotificationsEnabled();
-        boolean getNotificationsVibrateEnabled();
         void setAllowLocationEnabled(boolean enabled);
         void setNotificationsEnabled(boolean enabled);
-        void setNotificationsVibrateEnabled(boolean enabled);
-        void setPasswordEchoEnabled(boolean enabled);
         void setSensorsEnabled(boolean enabled);
         void setSoundEnabled(boolean enabled);
         boolean canPrefetchAndPrerender();
-        boolean getSafeBrowsingExtendedReportingEnabled();
-        void setSafeBrowsingExtendedReportingEnabled(boolean enabled);
-        boolean getSafeBrowsingExtendedReportingManaged();
-        boolean getSafeBrowsingEnabled();
-        void setSafeBrowsingEnabled(boolean enabled);
-        boolean getSafeBrowsingManaged();
         boolean getNetworkPredictionManaged();
         boolean obsoleteNetworkPredictionOptionsHasUserSetting();
         boolean getNetworkPredictionEnabled();
         void setNetworkPredictionEnabled(boolean enabled);
-        void setResolveNavigationErrorEnabled(boolean enabled);
         void setEulaAccepted();
-        String getSyncLastAccountName();
         boolean isMetricsReportingEnabled();
         void setMetricsReportingEnabled(boolean enabled);
         boolean isMetricsReportingManaged();
-        String getDownloadDefaultDirectory();
-        void setDownloadAndSaveFileDefaultDirectory(String directory);
-        void setForceWebContentsDarkModeEnabled(boolean enabled);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java
index 7a085ea..efbeb0b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadDirectoryAdapter.java
@@ -18,8 +18,8 @@
 
 import org.chromium.chrome.browser.download.DirectoryOption;
 import org.chromium.chrome.browser.download.DownloadDirectoryProvider;
+import org.chromium.chrome.browser.download.DownloadLocationDialogBridge;
 import org.chromium.chrome.browser.download.DownloadUtils;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.download.R;
 
 import java.util.ArrayList;
@@ -169,7 +169,7 @@
 
         int selectedId = NO_SELECTED_ITEM_ID;
 
-        String defaultLocation = PrefServiceBridge.getInstance().getDownloadDefaultDirectory();
+        String defaultLocation = DownloadLocationDialogBridge.getDownloadDefaultDirectory();
         for (int i = 0; i < getCount(); i++) {
             DirectoryOption option = (DirectoryOption) getItem(i);
             if (option == null) continue;
@@ -193,7 +193,7 @@
             DirectoryOption option = (DirectoryOption) getItem(i);
             if (option == null) continue;
             if (option.availableSpace > 0) {
-                PrefServiceBridge.getInstance().setDownloadAndSaveFileDefaultDirectory(
+                DownloadLocationDialogBridge.setDownloadAndSaveFileDefaultDirectory(
                         option.location);
                 mSelectedPosition = i;
                 return i;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreferenceAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreferenceAdapter.java
index 8000f56..90a16fc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreferenceAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/download/DownloadLocationPreferenceAdapter.java
@@ -17,8 +17,8 @@
 
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.download.DirectoryOption;
+import org.chromium.chrome.browser.download.DownloadLocationDialogBridge;
 import org.chromium.chrome.browser.download.DownloadUtils;
-import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.download.R;
 
 /**
@@ -95,7 +95,7 @@
         if (option == null) return;
 
         // Update the native pref, which persists the download directory selected by the user.
-        PrefServiceBridge.getInstance().setDownloadAndSaveFileDefaultDirectory(option.location);
+        DownloadLocationDialogBridge.setDownloadAndSaveFileDefaultDirectory(option.location);
 
         mSelectedPosition = selectedId;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
index f3a6aba..8df9f36 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
@@ -52,6 +52,7 @@
 import org.chromium.chrome.browser.preferences.Preferences;
 import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.safe_browsing.SafeBrowsingBridge;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
 import org.chromium.chrome.browser.signin.UnifiedConsentServiceBridge;
 import org.chromium.chrome.browser.sync.GoogleServiceAuthError;
@@ -350,11 +351,11 @@
         } else if (PREF_SEARCH_SUGGESTIONS.equals(key)) {
             mPrefServiceBridge.setBoolean(Pref.SEARCH_SUGGEST_ENABLED, (boolean) newValue);
         } else if (PREF_SAFE_BROWSING.equals(key)) {
-            mPrefServiceBridge.setSafeBrowsingEnabled((boolean) newValue);
+            mPrefServiceBridge.setBoolean(Pref.SAFE_BROWSING_ENABLED, (boolean) newValue);
         } else if (PREF_SAFE_BROWSING_SCOUT_REPORTING.equals(key)) {
-            mPrefServiceBridge.setSafeBrowsingExtendedReportingEnabled((boolean) newValue);
+            SafeBrowsingBridge.setSafeBrowsingExtendedReportingEnabled((boolean) newValue);
         } else if (PREF_NAVIGATION_ERROR.equals(key)) {
-            mPrefServiceBridge.setResolveNavigationErrorEnabled((boolean) newValue);
+            mPrefServiceBridge.setBoolean(Pref.ALTERNATE_ERROR_PAGES_ENABLED, (boolean) newValue);
         } else if (PREF_USAGE_AND_CRASH_REPORTING.equals(key)) {
             UmaSessionStats.changeMetricsReportingConsent((boolean) newValue);
         } else if (PREF_URL_KEYED_ANONYMIZED_DATA.equals(key)) {
@@ -553,10 +554,11 @@
         updateSyncPreferences();
 
         mSearchSuggestions.setChecked(mPrefServiceBridge.getBoolean(Pref.SEARCH_SUGGEST_ENABLED));
-        mNavigationError.setChecked(mPrefServiceBridge.isResolveNavigationErrorEnabled());
-        mSafeBrowsing.setChecked(mPrefServiceBridge.isSafeBrowsingEnabled());
+        mNavigationError.setChecked(
+                mPrefServiceBridge.getBoolean(Pref.ALTERNATE_ERROR_PAGES_ENABLED));
+        mSafeBrowsing.setChecked(mPrefServiceBridge.getBoolean(Pref.SAFE_BROWSING_ENABLED));
         mSafeBrowsingReporting.setChecked(
-                mPrefServiceBridge.isSafeBrowsingExtendedReportingEnabled());
+                SafeBrowsingBridge.isSafeBrowsingExtendedReportingEnabled());
         mUsageAndCrashReporting.setChecked(
                 mPrivacyPrefManager.isUsageAndCrashReportingPermittedByUser());
         mUrlKeyedAnonymizedData.setChecked(
@@ -618,16 +620,16 @@
         return preference -> {
             String key = preference.getKey();
             if (PREF_NAVIGATION_ERROR.equals(key)) {
-                return mPrefServiceBridge.isResolveNavigationErrorManaged();
+                return mPrefServiceBridge.isManagedPreference(Pref.ALTERNATE_ERROR_PAGES_ENABLED);
             }
             if (PREF_SEARCH_SUGGESTIONS.equals(key)) {
                 return mPrefServiceBridge.isManagedPreference(Pref.SEARCH_SUGGEST_ENABLED);
             }
             if (PREF_SAFE_BROWSING_SCOUT_REPORTING.equals(key)) {
-                return mPrefServiceBridge.isSafeBrowsingExtendedReportingManaged();
+                return SafeBrowsingBridge.isSafeBrowsingExtendedReportingManaged();
             }
             if (PREF_SAFE_BROWSING.equals(key)) {
-                return mPrefServiceBridge.isSafeBrowsingManaged();
+                return mPrefServiceBridge.isManagedPreference(Pref.SAFE_BROWSING_ENABLED);
             }
             if (PREF_USAGE_AND_CRASH_REPORTING.equals(key)) {
                 return mPrefServiceBridge.isMetricsReportingManaged();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
index f5aec0c4..eef88b3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
@@ -519,7 +519,7 @@
         } else if (THIRD_PARTY_COOKIES_TOGGLE_KEY.equals(preference.getKey())) {
             prefServiceBridge.setBoolean(Pref.BLOCK_THIRD_PARTY_COOKIES, ((boolean) newValue));
         } else if (NOTIFICATIONS_VIBRATE_TOGGLE_KEY.equals(preference.getKey())) {
-            prefServiceBridge.setNotificationsVibrateEnabled((boolean) newValue);
+            prefServiceBridge.setBoolean(Pref.NOTIFICATIONS_VIBRATE_ENABLED, (boolean) newValue);
         }
         return true;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/FileTypePolicies.java b/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/FileTypePolicies.java
deleted file mode 100644
index 956105f..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/FileTypePolicies.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.safe_browsing;
-
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.NativeMethods;
-
-/**
- * This class reports UMA values based on files' extensions.
- */
-@JNINamespace("safe_browsing")
-public final class FileTypePolicies {
-    /**
-     * @param path The file path.
-     * @return The UMA value for the file.
-     */
-    public static int umaValueForFile(String path) {
-        return FileTypePoliciesJni.get().umaValueForFile(path);
-    }
-
-    @NativeMethods
-    interface Natives {
-        int umaValueForFile(String path);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingBridge.java
new file mode 100644
index 0000000..37d43ea
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingBridge.java
@@ -0,0 +1,53 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.safe_browsing;
+
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
+
+/**
+ * Bridge providing access to native-side Safe Browsing data.
+ */
+@JNINamespace("safe_browsing")
+public final class SafeBrowsingBridge {
+    /**
+     * Reports UMA values based on files' extensions.
+     *
+     * @param path The file path.
+     * @return The UMA value for the file.
+     */
+    public static int umaValueForFile(String path) {
+        return SafeBrowsingBridgeJni.get().umaValueForFile(path);
+    }
+
+    /**
+     * @return Whether Safe Browsing Extended Reporting is currently enabled.
+     */
+    public static boolean isSafeBrowsingExtendedReportingEnabled() {
+        return SafeBrowsingBridgeJni.get().getSafeBrowsingExtendedReportingEnabled();
+    }
+
+    /**
+     * @param enabled Whether Safe Browsing Extended Reporting should be enabled.
+     */
+    public static void setSafeBrowsingExtendedReportingEnabled(boolean enabled) {
+        SafeBrowsingBridgeJni.get().setSafeBrowsingExtendedReportingEnabled(enabled);
+    }
+
+    /**
+     * @return Whether Safe Browsing Extended Reporting is managed
+     */
+    public static boolean isSafeBrowsingExtendedReportingManaged() {
+        return SafeBrowsingBridgeJni.get().getSafeBrowsingExtendedReportingManaged();
+    }
+
+    @NativeMethods
+    interface Natives {
+        int umaValueForFile(String path);
+        boolean getSafeBrowsingExtendedReportingEnabled();
+        void setSafeBrowsingExtendedReportingEnabled(boolean enabled);
+        boolean getSafeBrowsingExtendedReportingManaged();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
index ea85686..8dd9684d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
@@ -34,6 +34,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.consent_auditor.ConsentAuditorFeature;
 import org.chromium.chrome.browser.externalauth.UserRecoverableErrorHandler;
+import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.sync.SyncUserDataWiper;
 import org.chromium.components.signin.AccountIdProvider;
@@ -436,8 +437,8 @@
     private void runStateMachineAndSignin(boolean settingsClicked) {
         mConfirmSyncDataStateMachine = new ConfirmSyncDataStateMachine(getContext(),
                 getChildFragmentManager(),
-                PrefServiceBridge.getInstance().getSyncLastAccountName(), mSelectedAccountName,
-                new ConfirmImportSyncDataDialog.Listener() {
+                PrefServiceBridge.getInstance().getString(Pref.SYNC_LAST_ACCOUNT_NAME),
+                mSelectedAccountName, new ConfirmImportSyncDataDialog.Listener() {
                     @Override
                     public void onConfirm(boolean wipeData) {
                         mConfirmSyncDataStateMachine = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java
index d2705c39d..0ec5a65 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java
@@ -14,6 +14,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
+import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.ChromeSigninController;
@@ -38,8 +39,8 @@
     public static boolean launchSigninPromoIfNeeded(final Activity activity) {
         ChromePreferenceManager preferenceManager = ChromePreferenceManager.getInstance();
         int currentMajorVersion = ChromeVersionInfo.getProductMajorVersion();
-        boolean wasSignedIn =
-                TextUtils.isEmpty(PrefServiceBridge.getInstance().getSyncLastAccountName());
+        boolean wasSignedIn = TextUtils.isEmpty(
+                PrefServiceBridge.getInstance().getString(Pref.SYNC_LAST_ACCOUNT_NAME));
 
         Supplier<Set<String>> accountNamesSupplier =
                 () -> new ArraySet<>(AccountManagerFacade.get().tryGetGoogleAccountNames());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java
index 1ca7009..6d1e626 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/SplashController.java
@@ -23,13 +23,13 @@
 import org.chromium.base.metrics.CachedMetrics;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.CompositorView;
+import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.flags.FeatureUtilities;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.lifecycle.InflationObserver;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 32522f3..1abb84d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -39,6 +39,7 @@
 import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider.CustomTabsUiType;
 import org.chromium.chrome.browser.customtabs.CustomTabAppMenuPropertiesDelegate;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
+import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.features.ImmersiveModeController;
 import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbarCoordinator;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
@@ -49,7 +50,6 @@
 import org.chromium.chrome.browser.tab.TabBrowserControlsState;
 import org.chromium.chrome.browser.tab.TabDelegateFactory;
 import org.chromium.chrome.browser.tab.TabObserver;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.ui.widget.TintedDrawable;
 import org.chromium.chrome.browser.usage_stats.UsageStatsService;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivityTabController.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivityTabController.java
index 622bc8a..dbb0a54 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivityTabController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivityTabController.java
@@ -14,8 +14,8 @@
 import org.chromium.chrome.browser.browserservices.BrowserServicesActivityTabController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
 import org.chromium.chrome.browser.customtabs.content.TabCreationMode;
+import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 
 import javax.inject.Inject;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java
index a79ffe3d..eccc54a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java
@@ -18,8 +18,8 @@
 import org.chromium.base.FileUtils;
 import org.chromium.base.StrictModeContext;
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.webapk.lib.common.WebApkCommonUtils;
 import org.chromium.webapk.lib.common.splash.SplashLayout;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/dependency_injection/WebappActivityComponent.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/dependency_injection/WebappActivityComponent.java
index 5fb752c..c8b6732e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/dependency_injection/WebappActivityComponent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/dependency_injection/WebappActivityComponent.java
@@ -6,11 +6,11 @@
 
 import org.chromium.chrome.browser.customtabs.CustomTabCompositorContentInitializer;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
+import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbarCoordinator;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityComponent;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.webapps.SplashController;
 import org.chromium.chrome.browser.webapps.WebappActivityTabController;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImpl.java
index 02fd884..46451c1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webshare/ShareServiceImpl.java
@@ -19,7 +19,7 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.base.task.TaskRunner;
 import org.chromium.base.task.TaskTraits;
-import org.chromium.chrome.browser.safe_browsing.FileTypePolicies;
+import org.chromium.chrome.browser.safe_browsing.SafeBrowsingBridge;
 import org.chromium.chrome.browser.share.ShareHelper;
 import org.chromium.chrome.browser.share.ShareParams;
 import org.chromium.chrome.browser.share.ShareSheetCoordinator;
@@ -197,7 +197,7 @@
 
         for (SharedFile file : files) {
             RecordHistogram.recordSparseHistogram(
-                    "WebShare.Unverified", FileTypePolicies.umaValueForFile(file.name));
+                    "WebShare.Unverified", SafeBrowsingBridge.umaValueForFile(file.name));
         }
 
         for (SharedFile file : files) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
index 261e685..cbef307 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
@@ -39,6 +39,7 @@
 import org.chromium.chrome.browser.engagement.SiteEngagementService;
 import org.chromium.chrome.browser.permissions.PermissionDialogController;
 import org.chromium.chrome.browser.permissions.PermissionTestRule;
+import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.website.ContentSettingValues;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -458,7 +459,9 @@
 
         // Disable notification vibration in preferences.
         TestThreadUtils.runOnUiThreadBlocking(
-                () -> PrefServiceBridge.getInstance().setNotificationsVibrateEnabled(false));
+                ()
+                        -> PrefServiceBridge.getInstance().setBoolean(
+                                Pref.NOTIFICATIONS_VIBRATE_ENABLED, false));
 
         Notification notification = showAndGetNotification("MyNotification", notificationOptions);
 
@@ -508,8 +511,9 @@
 
         // By default, vibration is enabled in notifications.
         TestThreadUtils.runOnUiThreadBlocking(
-                () -> Assert.assertTrue(
-                                PrefServiceBridge.getInstance().isNotificationsVibrateEnabled()));
+                ()
+                        -> Assert.assertTrue(PrefServiceBridge.getInstance().getBoolean(
+                                Pref.NOTIFICATIONS_VIBRATE_ENABLED)));
 
         Notification notification = showAndGetNotification("MyNotification", "{ vibrate: 42 }");
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/CurrentPageVerifierTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/CurrentPageVerifierTest.java
index 366e687..63c05670 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/CurrentPageVerifierTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/CurrentPageVerifierTest.java
@@ -26,10 +26,10 @@
 import org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.CurrentPageVerifier.VerificationStatus;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
+import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabObserver;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
index c64c2e1..4d00e58 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
@@ -49,7 +49,6 @@
 import org.chromium.chrome.browser.init.StartupTabPreloader;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabObserverRegistrar;
 import org.chromium.chrome.browser.tab_activity_glue.ReparentingTask;
 import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
 import org.chromium.chrome.browser.tabmodel.TabModel;
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index b5af0e38..c203838 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -2121,22 +2121,12 @@
       </if>
 
       <!-- "Install web app" confirmation bubble -->
-      <if expr="use_titlecase">
-        <message name="IDS_INSTALL_TO_OS_LAUNCH_SURFACE_BUBBLE_TITLE" desc="In Title Case: Title of the bubble for installing a web app to the operating system.">
-          Install App?
-        </message>
-        <message name="IDS_INSTALL_PWA_BUTTON_LABEL" desc="In Title Case: Text for button that installs a web app to the operating system.">
-          Install
-        </message>
-      </if>
-      <if expr="not use_titlecase">
-        <message name="IDS_INSTALL_TO_OS_LAUNCH_SURFACE_BUBBLE_TITLE" desc="Title of the bubble for installing a web app to the operating system.">
-          Install app?
-        </message>
-        <message name="IDS_INSTALL_PWA_BUTTON_LABEL" desc="Text for button that installs a web app to the operating system.">
-          Install
-        </message>
-      </if>
+      <message name="IDS_INSTALL_TO_OS_LAUNCH_SURFACE_BUBBLE_TITLE" desc="Title of the bubble for installing a web app to the operating system.">
+        Install app?
+      </message>
+      <message name="IDS_INSTALL_PWA_BUTTON_LABEL" desc="Text for button that installs a web app to the operating system.">
+        Install
+      </message>
 
       <message name="IDS_BOOKMARK_APP_AX_BUBBLE_NAME_LABEL" desc="Text preceding the name of a bookmark app, read by spoken feedback.">
         Shortcut name
@@ -6281,6 +6271,9 @@
         <message name="IDS_TAB_GROUP_HEADER_CXMENU_CLOSE_GROUP" desc="The label of the tab group header context menu item for closing all tabs in the current group.">
           Close group
         </message>
+        <message name="IDS_TAB_GROUP_HEADER_CXMENU_SEND_FEEDBACK" desc="The label of the tab group header context menu item for sending feedback for tab groups.">
+          Send feedback
+        </message>
       </if>
       <if expr="use_titlecase">
         <message name="IDS_TAB_GROUP_HEADER_CXMENU_NEW_TAB_IN_GROUP" desc="In Title Case: The label of the tab group header context menu item for adding a new tab into the current group.">
@@ -6292,6 +6285,9 @@
         <message name="IDS_TAB_GROUP_HEADER_CXMENU_CLOSE_GROUP" desc="In Title Case: The label of the tab group header context menu item for closing all tabs in the current group.">
           Close Group
         </message>
+        <message name="IDS_TAB_GROUP_HEADER_CXMENU_SEND_FEEDBACK" desc="In Title Case: The label of the tab group header context menu item for sending feedback for tab groups.">
+          Send Feedback
+        </message>
       </if>
 
       <!-- Application window menu -->
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_GROUP_HEADER_CXMENU_SEND_FEEDBACK.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_GROUP_HEADER_CXMENU_SEND_FEEDBACK.png.sha1
new file mode 100644
index 0000000..33cc310
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAB_GROUP_HEADER_CXMENU_SEND_FEEDBACK.png.sha1
@@ -0,0 +1 @@
+32c74b1aab28c0e1f103680824096530db7a053a
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index b9d6988..b292bff 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1584,6 +1584,8 @@
     "sharing/sharing_sync_preference.h",
     "sharing/sharing_utils.cc",
     "sharing/sharing_utils.h",
+    "sharing/sms/sms_fetch_request_handler.cc",
+    "sharing/sms/sms_fetch_request_handler.h",
     "sharing/sms/sms_flags.cc",
     "sharing/sms/sms_flags.h",
     "sharing/sms/sms_remote_fetcher.cc",
@@ -2865,8 +2867,6 @@
       "search_engines/template_url_service_factory_android.h",
       "sharing/shared_clipboard/shared_clipboard_message_handler_android.cc",
       "sharing/shared_clipboard/shared_clipboard_message_handler_android.h",
-      "sharing/sms/sms_fetch_request_handler.cc",
-      "sharing/sms/sms_fetch_request_handler.h",
       "signin/identity_services_provider_android.cc",
       "signin/signin_manager_android_factory.cc",
       "signin/signin_manager_android_factory.h",
diff --git a/chrome/browser/android/preferences/pref_service_bridge.cc b/chrome/browser/android/preferences/pref_service_bridge.cc
index e75d7f82..7b80ffe 100644
--- a/chrome/browser/android/preferences/pref_service_bridge.cc
+++ b/chrome/browser/android/preferences/pref_service_bridge.cc
@@ -39,8 +39,6 @@
 #include "components/metrics/metrics_pref_names.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
-#include "components/signin/public/base/signin_pref_names.h"
 #include "components/web_resource/web_resource_pref_names.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -312,53 +310,10 @@
       prefs::kNetworkPredictionOptions);
 }
 
-static jboolean JNI_PrefServiceBridge_GetPasswordEchoEnabled(JNIEnv* env) {
-  return GetPrefService()->GetBoolean(prefs::kWebKitPasswordEchoEnabled);
-}
-
-static jboolean JNI_PrefServiceBridge_GetSafeBrowsingExtendedReportingEnabled(
-    JNIEnv* env) {
-  return safe_browsing::IsExtendedReportingEnabled(*GetPrefService());
-}
-
-static void JNI_PrefServiceBridge_SetSafeBrowsingExtendedReportingEnabled(
-    JNIEnv* env,
-    jboolean enabled) {
-  safe_browsing::SetExtendedReportingPrefAndMetric(
-      GetPrefService(), enabled,
-      safe_browsing::SBER_OPTIN_SITE_ANDROID_SETTINGS);
-}
-
-static jboolean JNI_PrefServiceBridge_GetSafeBrowsingExtendedReportingManaged(
-    JNIEnv* env) {
-  PrefService* pref_service = GetPrefService();
-  return pref_service->IsManagedPreference(
-      prefs::kSafeBrowsingScoutReportingEnabled);
-}
-
-static jboolean JNI_PrefServiceBridge_GetSafeBrowsingEnabled(JNIEnv* env) {
-  return GetPrefService()->GetBoolean(prefs::kSafeBrowsingEnabled);
-}
-
-static void JNI_PrefServiceBridge_SetSafeBrowsingEnabled(
-    JNIEnv* env,
-    jboolean enabled) {
-  GetPrefService()->SetBoolean(prefs::kSafeBrowsingEnabled, enabled);
-}
-
-static jboolean JNI_PrefServiceBridge_GetSafeBrowsingManaged(JNIEnv* env) {
-  return GetPrefService()->IsManagedPreference(prefs::kSafeBrowsingEnabled);
-}
-
 static jboolean JNI_PrefServiceBridge_GetNotificationsEnabled(JNIEnv* env) {
   return GetBooleanForContentSetting(ContentSettingsType::NOTIFICATIONS);
 }
 
-static jboolean JNI_PrefServiceBridge_GetNotificationsVibrateEnabled(
-    JNIEnv* env) {
-  return GetPrefService()->GetBoolean(prefs::kNotificationsVibrateEnabled);
-}
-
 static jboolean JNI_PrefServiceBridge_GetAllowLocationEnabled(JNIEnv* env) {
   return GetBooleanForContentSetting(ContentSettingsType::GEOLOCATION);
 }
@@ -383,16 +338,6 @@
   return IsContentSettingManagedByCustodian(ContentSettingsType::GEOLOCATION);
 }
 
-static jboolean JNI_PrefServiceBridge_GetResolveNavigationErrorEnabled(
-    JNIEnv* env) {
-  return GetPrefService()->GetBoolean(prefs::kAlternateErrorPagesEnabled);
-}
-
-static jboolean JNI_PrefServiceBridge_GetResolveNavigationErrorManaged(
-    JNIEnv* env) {
-  return GetPrefService()->IsManagedPreference(
-      prefs::kAlternateErrorPagesEnabled);
-}
 static jboolean JNI_PrefServiceBridge_GetIncognitoModeEnabled(JNIEnv* env) {
   PrefService* prefs = GetPrefService();
   IncognitoModePrefs::Availability incognito_pref =
@@ -543,30 +488,11 @@
       allow ? CONTENT_SETTING_ASK : CONTENT_SETTING_BLOCK);
 }
 
-static void JNI_PrefServiceBridge_SetNotificationsVibrateEnabled(
-    JNIEnv* env,
-    jboolean enabled) {
-  GetPrefService()->SetBoolean(prefs::kNotificationsVibrateEnabled, enabled);
-}
-
 static jboolean JNI_PrefServiceBridge_CanPrefetchAndPrerender(JNIEnv* env) {
   return chrome_browser_net::CanPrefetchAndPrerenderUI(GetPrefService()) ==
       chrome_browser_net::NetworkPredictionStatus::ENABLED;
 }
 
-static ScopedJavaLocalRef<jstring> JNI_PrefServiceBridge_GetSyncLastAccountName(
-    JNIEnv* env) {
-  return ConvertUTF8ToJavaString(
-      env, GetPrefService()->GetString(prefs::kGoogleServicesLastUsername));
-}
-
-static void JNI_PrefServiceBridge_SetPasswordEchoEnabled(
-    JNIEnv* env,
-    jboolean passwordEchoEnabled) {
-  GetPrefService()->SetBoolean(prefs::kWebKitPasswordEchoEnabled,
-                               passwordEchoEnabled);
-}
-
 static jboolean JNI_PrefServiceBridge_GetCameraEnabled(JNIEnv* env) {
   return GetBooleanForContentSetting(ContentSettingsType::MEDIASTREAM_CAMERA);
 }
@@ -610,12 +536,6 @@
       prefs::kNetworkPredictionOptions) != NULL;
 }
 
-static void JNI_PrefServiceBridge_SetResolveNavigationErrorEnabled(
-    JNIEnv* env,
-    jboolean enabled) {
-  GetPrefService()->SetBoolean(prefs::kAlternateErrorPagesEnabled, enabled);
-}
-
 static jboolean JNI_PrefServiceBridge_GetFirstRunEulaAccepted(JNIEnv* env) {
   return g_browser_process->local_state()->GetBoolean(prefs::kEulaAccepted);
 }
@@ -636,28 +556,8 @@
       out);
 }
 
-static ScopedJavaLocalRef<jstring>
-JNI_PrefServiceBridge_GetDownloadDefaultDirectory(JNIEnv* env) {
-  return ConvertUTF8ToJavaString(
-      env, GetPrefService()->GetString(prefs::kDownloadDefaultDirectory));
-}
-
-static void JNI_PrefServiceBridge_SetDownloadAndSaveFileDefaultDirectory(
-    JNIEnv* env,
-    const JavaParamRef<jstring>& directory) {
-  base::FilePath path(ConvertJavaStringToUTF8(env, directory));
-  GetPrefService()->SetFilePath(prefs::kDownloadDefaultDirectory, path);
-  GetPrefService()->SetFilePath(prefs::kSaveFileDefaultDirectory, path);
-}
-
 const char* PrefServiceBridge::GetPrefNameExposedToJava(int pref_index) {
   DCHECK_GE(pref_index, 0);
   DCHECK_LT(pref_index, Pref::PREF_NUM_PREFS);
   return kPrefsExposedToJava[pref_index];
 }
-
-static void JNI_PrefServiceBridge_SetForceWebContentsDarkModeEnabled(
-    JNIEnv* env,
-    jboolean enabled) {
-  GetPrefService()->SetBoolean(prefs::kWebKitForceDarkModeEnabled, enabled);
-}
diff --git a/chrome/browser/android/preferences/prefs.h b/chrome/browser/android/preferences/prefs.h
index 9072af8b..7cffe70 100644
--- a/chrome/browser/android/preferences/prefs.h
+++ b/chrome/browser/android/preferences/prefs.h
@@ -21,6 +21,7 @@
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/payments/core/payment_prefs.h"
 #include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/signin/public/base/signin_pref_names.h"
 #include "components/translate/core/browser/translate_pref_names.h"
 
 // A preference exposed to Java.
@@ -41,6 +42,7 @@
   USAGE_STATS_ENABLED,
   OFFLINE_PREFETCH_USER_SETTING_ENABLED,
   SAFE_BROWSING_EXTENDED_REPORTING_OPT_IN_ALLOWED,
+  SAFE_BROWSING_ENABLED,
   PASSWORD_MANAGER_ONBOARDING_STATE,
   SEARCH_SUGGEST_ENABLED,
   REMEMBER_PASSWORDS_ENABLED,
@@ -58,6 +60,11 @@
   ENABLE_DO_NOT_TRACK,
   PRINTING_ENABLED,
   OFFER_TRANSLATE_ENABLED,
+  NOTIFICATIONS_VIBRATE_ENABLED,
+  ALTERNATE_ERROR_PAGES_ENABLED,
+  SYNC_LAST_ACCOUNT_NAME,
+  WEBKIT_PASSWORD_ECHO_ENABLED,
+  WEBKIT_FORCE_DARK_MODE_ENABLED,
   // PREF_NUM_PREFS must be the last entry.
   PREF_NUM_PREFS
 };
@@ -86,6 +93,7 @@
     prefs::kUsageStatsEnabled,
     offline_pages::prefetch_prefs::kUserSettingEnabled,
     prefs::kSafeBrowsingExtendedReportingOptInAllowed,
+    prefs::kSafeBrowsingEnabled,
     password_manager::prefs::kPasswordManagerOnboardingState,
     prefs::kSearchSuggestEnabled,
     password_manager::prefs::kCredentialsEnableService,
@@ -103,6 +111,11 @@
     prefs::kEnableDoNotTrack,
     prefs::kPrintingEnabled,
     prefs::kOfferTranslateEnabled,
+    prefs::kNotificationsVibrateEnabled,
+    prefs::kAlternateErrorPagesEnabled,
+    prefs::kGoogleServicesLastUsername,
+    prefs::kWebKitPasswordEchoEnabled,
+    prefs::kWebKitForceDarkModeEnabled,
 };
 
 #endif  // CHROME_BROWSER_ANDROID_PREFERENCES_PREFS_H_
diff --git a/chrome/browser/android/preferences/prefs_unittest.cc b/chrome/browser/android/preferences/prefs_unittest.cc
index 8de90f3..2f6fb66b 100644
--- a/chrome/browser/android/preferences/prefs_unittest.cc
+++ b/chrome/browser/android/preferences/prefs_unittest.cc
@@ -64,6 +64,7 @@
             GetPrefName(OFFLINE_PREFETCH_USER_SETTING_ENABLED));
   EXPECT_EQ(prefs::kSafeBrowsingExtendedReportingOptInAllowed,
             GetPrefName(SAFE_BROWSING_EXTENDED_REPORTING_OPT_IN_ALLOWED));
+  EXPECT_EQ(prefs::kSafeBrowsingEnabled, GetPrefName(SAFE_BROWSING_ENABLED));
   EXPECT_EQ(password_manager::prefs::kPasswordManagerOnboardingState,
             GetPrefName(PASSWORD_MANAGER_ONBOARDING_STATE));
   EXPECT_EQ(prefs::kSearchSuggestEnabled, GetPrefName(SEARCH_SUGGEST_ENABLED));
@@ -94,6 +95,16 @@
   EXPECT_EQ(prefs::kPrintingEnabled, GetPrefName(PRINTING_ENABLED));
   EXPECT_EQ(prefs::kOfferTranslateEnabled,
             GetPrefName(OFFER_TRANSLATE_ENABLED));
+  EXPECT_EQ(prefs::kNotificationsVibrateEnabled,
+            GetPrefName(NOTIFICATIONS_VIBRATE_ENABLED));
+  EXPECT_EQ(prefs::kAlternateErrorPagesEnabled,
+            GetPrefName(ALTERNATE_ERROR_PAGES_ENABLED));
+  EXPECT_EQ(prefs::kGoogleServicesLastUsername,
+            GetPrefName(SYNC_LAST_ACCOUNT_NAME));
+  EXPECT_EQ(prefs::kWebKitPasswordEchoEnabled,
+            GetPrefName(WEBKIT_PASSWORD_ECHO_ENABLED));
+  EXPECT_EQ(prefs::kWebKitForceDarkModeEnabled,
+            GetPrefName(WEBKIT_FORCE_DARK_MODE_ENABLED));
 
   // If this check fails, a pref is missing a test case above.
   EXPECT_EQ(Pref::PREF_NUM_PREFS, pref_count_);
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index dea0f6b..fb05f6d 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -260,10 +260,11 @@
       </if>
 
       <include name="IDR_IDENTITY_API_SCOPE_APPROVAL_MANIFEST" file="resources\identity_scope_approval_dialog\manifest.json" type="BINDATA" />
-      <include name="IDR_INLINE_LOGIN_HTML" file="resources\inline_login\inline_login.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" preprocess="true" />
-      <include name="IDR_INLINE_LOGIN_CSS" file="resources\inline_login\inline_login.css" flattenhtml="true" type="BINDATA" preprocess="true" />
-      <include name="IDR_INLINE_LOGIN_JS" file="resources\inline_login\inline_login.js" flattenhtml="true" type="BINDATA" />
-      <include name="IDR_GAIA_AUTH_AUTHENTICATOR_JS" file="resources\gaia_auth_host\authenticator.js" flattenhtml="true" type="BINDATA" />
+
+      <include name="IDR_INLINE_LOGIN_HTML" file="resources\inline_login\inline_login.html" compress="gzip" flattenhtml="true" allowexternalscript="true" type="BINDATA" preprocess="true" />
+      <include name="IDR_INLINE_LOGIN_CSS" file="resources\inline_login\inline_login.css" compress="gzip" flattenhtml="true" type="BINDATA" preprocess="true" />
+      <include name="IDR_INLINE_LOGIN_JS" file="resources\inline_login\inline_login.js" compress="gzip" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_GAIA_AUTH_AUTHENTICATOR_JS" file="resources\gaia_auth_host\authenticator.js" compress="gzip" flattenhtml="true" type="BINDATA" />
 
       <include name="IDR_INSPECT_CSS" file="resources\inspect\inspect.css" compress="gzip" flattenhtml="true" type="BINDATA" />
       <include name="IDR_INSPECT_HTML" file="resources\inspect\inspect.html" compress="gzip" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
@@ -361,8 +362,8 @@
         <include name="IDR_ACCOUNT_MANAGER_WELCOME_JS" file="resources\chromeos\account_manager_welcome.js" type="BINDATA" compress="gzip" />
         <include name="IDR_ACCOUNT_MIGRATION_WELCOME_HTML" file="resources\chromeos\account_migration_welcome.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
         <include name="IDR_ACCOUNT_MIGRATION_WELCOME_JS" file="resources\chromeos\account_migration_welcome.js" flattenhtml="true" type="BINDATA" compress="gzip" />
-        <include name="IDR_ACCOUNT_MIGRATION_BROWSER_PROXY_HTML" file="resources\chromeos\account_migration_browser_proxy.html" type="BINDATA" />
-        <include name="IDR_ACCOUNT_MIGRATION_BROWSER_PROXY_JS" file="resources\chromeos\account_migration_browser_proxy.js" type="BINDATA" />
+        <include name="IDR_ACCOUNT_MIGRATION_BROWSER_PROXY_HTML" file="resources\chromeos\account_migration_browser_proxy.html" type="BINDATA" compress="gzip" />
+        <include name="IDR_ACCOUNT_MIGRATION_BROWSER_PROXY_JS" file="resources\chromeos\account_migration_browser_proxy.js" type="BINDATA" compress="gzip" />
         <include name="IDR_ACCOUNT_MANAGER_ERROR_HTML" file="resources\chromeos\account_manager_error.html" allowexternalscript="true" type="BINDATA" compress="gzip" preprocess="true"/>
         <include name="IDR_ACCOUNT_MANAGER_ERROR_JS" file="resources\chromeos\account_manager_error.js" type="BINDATA" compress="gzip" />
         <if expr="_google_chrome">
@@ -370,14 +371,14 @@
           <include name="IDR_ACCOUNT_MANAGER_WELCOME_2X_PNG" file="resources\chromeos\account_manager_welcome_2x.png" type="BINDATA" compress="gzip" />
           <include name="IDR_ACCOUNT_MANAGER_WELCOME_GOOGLE_LOGO_SVG" file="resources\chromeos\googleg.svg" type="BINDATA" compress="gzip" />
         </if>
-        <include name="IDR_PASSWORD_CHANGE_HTML" file="resources\chromeos\password_change\password_change.html" flattenhtml="true" type="BINDATA" />
-        <include name="IDR_PASSWORD_CHANGE_JS" file="resources\chromeos\password_change\password_change.js" flattenhtml="true" type="BINDATA" />
-        <include name="IDR_PASSWORD_CHANGE_CSS" file="resources\chromeos\password_change\password_change.css" flattenhtml="true" type="BINDATA" />
-        <include name="IDR_PASSWORD_CHANGE_AUTHENTICATOR_JS" file="resources\gaia_auth_host\password_change_authenticator.js" flattenhtml="true" type="BINDATA" />
-        <include name="IDR_CONFIRM_PASSWORD_CHANGE_HTML" file="resources\chromeos\password_change\confirm_password_change.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
-        <include name="IDR_CONFIRM_PASSWORD_CHANGE_JS" file="resources\chromeos\password_change\confirm_password_change.js" type="chrome_html" />
-        <include name="IDR_URGENT_PASSWORD_EXPIRY_NOTIFICATION_HTML" file="resources\chromeos\password_change\urgent_password_expiry_notification.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
-        <include name="IDR_URGENT_PASSWORD_EXPIRY_NOTIFICATION_JS" file="resources\chromeos\password_change\urgent_password_expiry_notification.js" type="chrome_html" />
+        <include name="IDR_PASSWORD_CHANGE_HTML" file="resources\chromeos\password_change\password_change.html" flattenhtml="true" type="BINDATA" compress="gzip" />
+        <include name="IDR_PASSWORD_CHANGE_JS" file="resources\chromeos\password_change\password_change.js" flattenhtml="true" type="BINDATA" compress="gzip" />
+        <include name="IDR_PASSWORD_CHANGE_CSS" file="resources\chromeos\password_change\password_change.css" flattenhtml="true" type="BINDATA" compress="gzip" />
+        <include name="IDR_PASSWORD_CHANGE_AUTHENTICATOR_JS" file="resources\gaia_auth_host\password_change_authenticator.js" flattenhtml="true" type="BINDATA" compress="gzip" />
+        <include name="IDR_CONFIRM_PASSWORD_CHANGE_HTML" file="resources\chromeos\password_change\confirm_password_change.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" compress="gzip" />
+        <include name="IDR_CONFIRM_PASSWORD_CHANGE_JS" file="resources\chromeos\password_change\confirm_password_change.js" type="chrome_html" compress="gzip" />
+        <include name="IDR_URGENT_PASSWORD_EXPIRY_NOTIFICATION_HTML" file="resources\chromeos\password_change\urgent_password_expiry_notification.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" compress="gzip" />
+        <include name="IDR_URGENT_PASSWORD_EXPIRY_NOTIFICATION_JS" file="resources\chromeos\password_change\urgent_password_expiry_notification.js" type="chrome_html" compress="gzip" />
 
         <include name="IDR_CROSH_BUILTIN_MANIFEST" file="resources\chromeos\crosh_builtin\manifest.json" type="BINDATA" />
 
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 2ed8d36..f21bf87 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -518,7 +518,7 @@
     content::BrowserContext* context) {
   Profile* profile = Profile::FromBrowserContext(context);
   return std::make_unique<ProtocolHandlerRegistry>(
-      profile, new FakeProtocolHandlerRegistryDelegate());
+      profile, std::make_unique<FakeProtocolHandlerRegistryDelegate>());
 }
 
 class ClearDomainReliabilityTester {
diff --git a/chrome/browser/browsing_data/counters/site_settings_counter_unittest.cc b/chrome/browser/browsing_data/counters/site_settings_counter_unittest.cc
index 7fc3947..0411a06 100644
--- a/chrome/browser/browsing_data/counters/site_settings_counter_unittest.cc
+++ b/chrome/browser/browsing_data/counters/site_settings_counter_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/browsing_data/counters/site_settings_counter.h"
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/containers/flat_set.h"
 #include "base/test/simple_test_clock.h"
@@ -81,7 +83,7 @@
     zoom_map_ = nullptr;
 #endif
     handler_registry_ = std::make_unique<ProtocolHandlerRegistry>(
-        profile(), new TestProtocolHandlerRegistryDelegate());
+        profile(), std::make_unique<TestProtocolHandlerRegistryDelegate>());
 
     counter_ = std::make_unique<SiteSettingsCounter>(
         map(), zoom_map(), handler_registry(), profile_->GetPrefs());
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.cc b/chrome/browser/custom_handlers/protocol_handler_registry.cc
index f1551c6..d9250066 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry.cc
@@ -6,7 +6,6 @@
 
 #include <stddef.h>
 
-#include <memory>
 #include <utility>
 
 #include "base/bind.h"
@@ -120,9 +119,9 @@
 
 ProtocolHandlerRegistry::ProtocolHandlerRegistry(
     content::BrowserContext* context,
-    Delegate* delegate)
+    std::unique_ptr<Delegate> delegate)
     : context_(context),
-      delegate_(delegate),
+      delegate_(std::move(delegate)),
       enabled_(true),
       is_loading_(false),
       is_loaded_(false) {}
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.h b/chrome/browser/custom_handlers/protocol_handler_registry.h
index 614b1b0..f7536d97 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry.h
+++ b/chrome/browser/custom_handlers/protocol_handler_registry.h
@@ -62,8 +62,9 @@
     virtual void OnProtocolHandlerRegistryChanged() = 0;
   };
 
-  // Creates a new instance. Assumes ownership of |delegate|.
-  ProtocolHandlerRegistry(content::BrowserContext* context, Delegate* delegate);
+  // Creates a new instance.
+  ProtocolHandlerRegistry(content::BrowserContext* context,
+                          std::unique_ptr<Delegate> delegate);
   ~ProtocolHandlerRegistry() override;
 
   void AddObserver(Observer* observer);
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_factory.cc b/chrome/browser/custom_handlers/protocol_handler_registry_factory.cc
index 4f725d2c..76f55ebe 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry_factory.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry_factory.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
 
+#include <memory>
+
 #include "base/memory/singleton.h"
 #include "build/build_config.h"
 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
@@ -55,7 +57,7 @@
 KeyedService* ProtocolHandlerRegistryFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   ProtocolHandlerRegistry* registry = new ProtocolHandlerRegistry(
-      context, new ProtocolHandlerRegistry::Delegate());
+      context, std::make_unique<ProtocolHandlerRegistry::Delegate>());
 
 #if defined(OS_CHROMEOS)
   // If installing defaults, they must be installed prior calling
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
index 87c13bf..92903843 100644
--- a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
+++ b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
@@ -213,8 +213,10 @@
   // Returns a new registry, initializing it if |initialize| is true.
   // Caller assumes ownership for the object
   void SetUpRegistry(bool initialize) {
-    delegate_ = new FakeDelegate();
-    registry_.reset(new ProtocolHandlerRegistry(profile(), delegate()));
+    auto delegate = std::make_unique<FakeDelegate>();
+    delegate_ = delegate.get();
+    registry_.reset(
+        new ProtocolHandlerRegistry(profile(), std::move(delegate)));
     if (initialize) registry_->InitProtocolSettings();
   }
 
diff --git a/chrome/browser/download/android/download_location_dialog_bridge_impl.cc b/chrome/browser/download/android/download_location_dialog_bridge_impl.cc
index ca239413..639aa4b0 100644
--- a/chrome/browser/download/android/download_location_dialog_bridge_impl.cc
+++ b/chrome/browser/download/android/download_location_dialog_bridge_impl.cc
@@ -9,6 +9,9 @@
 #include "base/metrics/histogram_macros.h"
 #include "chrome/android/chrome_jni_headers/DownloadLocationDialogBridge_jni.h"
 #include "chrome/browser/download/android/download_controller.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_service.h"
 #include "ui/android/window_android.h"
 
 DownloadLocationDialogBridgeImpl::DownloadLocationDialogBridgeImpl()
@@ -94,3 +97,24 @@
     std::move(location_callback_).Run(result, std::move(file_path));
   }
 }
+
+static base::android::ScopedJavaLocalRef<jstring>
+JNI_DownloadLocationDialogBridge_GetDownloadDefaultDirectory(JNIEnv* env) {
+  PrefService* pref_service =
+      ProfileManager::GetActiveUserProfile()->GetOriginalProfile()->GetPrefs();
+
+  return base::android::ConvertUTF8ToJavaString(
+      env, pref_service->GetString(prefs::kDownloadDefaultDirectory));
+}
+
+static void
+JNI_DownloadLocationDialogBridge_SetDownloadAndSaveFileDefaultDirectory(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jstring>& directory) {
+  PrefService* pref_service =
+      ProfileManager::GetActiveUserProfile()->GetOriginalProfile()->GetPrefs();
+
+  base::FilePath path(base::android::ConvertJavaStringToUTF8(env, directory));
+  pref_service->SetFilePath(prefs::kDownloadDefaultDirectory, path);
+  pref_service->SetFilePath(prefs::kSaveFileDefaultDirectory, path);
+}
diff --git a/chrome/browser/feedback/feedback_dialog_utils.cc b/chrome/browser/feedback/feedback_dialog_utils.cc
index 903f948..a60ba8d 100644
--- a/chrome/browser/feedback/feedback_dialog_utils.cc
+++ b/chrome/browser/feedback/feedback_dialog_utils.cc
@@ -47,7 +47,7 @@
   return GURL();
 }
 
-Profile* GetFeedbackProfile(Browser* browser) {
+Profile* GetFeedbackProfile(const Browser* browser) {
   Profile* profile =
       browser ? browser->profile()
               : ProfileManager::GetLastUsedProfileAllowedByPolicy();
diff --git a/chrome/browser/feedback/feedback_dialog_utils.h b/chrome/browser/feedback/feedback_dialog_utils.h
index ff049e6..56fabbd 100644
--- a/chrome/browser/feedback/feedback_dialog_utils.h
+++ b/chrome/browser/feedback/feedback_dialog_utils.h
@@ -19,7 +19,7 @@
 GURL GetTargetTabUrl(SessionID session_id, int index);
 
 // Get the profile that should be used to open the feedback dialog.
-Profile* GetFeedbackProfile(Browser* browser);
+Profile* GetFeedbackProfile(const Browser* browser);
 
 }  // namespace chrome
 
diff --git a/chrome/browser/feedback/show_feedback_page.cc b/chrome/browser/feedback/show_feedback_page.cc
index 3a493f8d..c10b9ad9 100644
--- a/chrome/browser/feedback/show_feedback_page.cc
+++ b/chrome/browser/feedback/show_feedback_page.cc
@@ -37,6 +37,7 @@
     case kFeedbackSourceAsh:
     case kFeedbackSourceAssistant:
     case kFeedbackSourceBrowserCommand:
+    case kFeedbackSourceDesktopTabGroups:
     case kFeedbackSourceMdSettingsAboutPage:
     case kFeedbackSourceOldSettingsAboutPage:
       return true;
@@ -47,7 +48,7 @@
 #endif
 }  // namespace
 
-void ShowFeedbackPage(Browser* browser,
+void ShowFeedbackPage(const Browser* browser,
                       FeedbackSource source,
                       const std::string& description_template,
                       const std::string& description_placeholder_text,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 5ddceea..766daf8 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -2328,7 +2328,7 @@
   {
     "name": "happiness-tracking-surveys-for-desktop",
     "owners": [ "//chrome/browser/ui/hats/OWNERS" ],
-    "expiry_milestone": 80
+    "expiry_milestone": 82
   },
   {
     "name": "happiness-tracking-surveys-for-desktop-demo",
@@ -2336,7 +2336,7 @@
     // A debugging and demo flag to allow UI/dev/testing team to always show the UI
     // components for the survey without being limited by the triggering mechanism.
     // This flag should expire along with the above feature flag.
-    "expiry_milestone": 80
+    "expiry_milestone": 82
   },
   {
     "name": "hardware-media-key-handling",
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index 73077e6..3208b37 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -572,6 +572,15 @@
   TestSimplePlayback("bear-flac-cenc.mp4");
 }
 
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4_OPUS) {
+  // MP4 without MSE is not support yet, http://crbug.com/170793.
+  if (CurrentSourceType() != SrcType::MSE) {
+    DVLOG(0) << "Skipping test; Can only play MP4 encrypted streams by MSE.";
+    return;
+  }
+  TestSimplePlayback("bear-opus-cenc.mp4");
+}
+
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) {
   // MP4 without MSE is not support yet, http://crbug.com/170793.
   if (CurrentSourceType() != SrcType::MSE) {
diff --git a/chrome/browser/media/encrypted_media_supported_types_browsertest.cc b/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
index 8409932..ec73a22 100644
--- a/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
@@ -110,7 +110,6 @@
 class EncryptedMediaSupportedTypesTest : public InProcessBrowserTest {
  protected:
   EncryptedMediaSupportedTypesTest() {
-    audio_webm_codecs_.push_back("opus");
     audio_webm_codecs_.push_back("vorbis");
 
     video_webm_codecs_.push_back("vp8");
@@ -136,6 +135,9 @@
     invalid_codecs_.push_back("hev1.1.6.L93.B0");
 #endif
 
+    // Opus is supported in both MP4 and WebM.
+    opus_codecs_.push_back("opus");
+
     // New multi-part VP9 codecs are allowed in both MP4 and WebM.
     // For vp9 codec string format, see https://www.webmproject.org/vp9/mp4/
     vp9_profile0_codecs_.push_back("vp09.00.10.08");
@@ -185,6 +187,7 @@
   const CodecVector& video_mp4_hi10p_codecs() const {
     return video_mp4_hi10p_codecs_;
   }
+  const CodecVector& opus_codecs() const { return opus_codecs_; }
   const CodecVector& vp9_profile0_codecs() const {
     return vp9_profile0_codecs_;
   }
@@ -402,6 +405,7 @@
   CodecVector audio_mp4_flac_codecs_;
   CodecVector video_mp4_codecs_;
   CodecVector video_mp4_hi10p_codecs_;
+  CodecVector opus_codecs_;
   CodecVector vp9_profile0_codecs_;
   CodecVector vp9_profile2_codecs_;
   CodecVector av1_codecs_;
@@ -526,6 +530,8 @@
                                         video_webm_codecs()));
   EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType,
                                         audio_webm_codecs()));
+  EXPECT_SUCCESS(
+      IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType, opus_codecs()));
   EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType,
                                         audio_mp4_flac_codecs()));
   EXPECT_PROPRIETARY(
@@ -592,6 +598,8 @@
   // Non-video WebM codecs.
   EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType,
                                             audio_webm_codecs()));
+  EXPECT_UNSUPPORTED(
+      IsSupportedByKeySystem(kClearKey, kVideoWebMMimeType, opus_codecs()));
 
   // Invalid or non-Webm video codecs.
   EXPECT_UNSUPPORTED(
@@ -606,6 +614,8 @@
   // Valid audio types.
   EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType,
                                         audio_webm_codecs()));
+  EXPECT_SUCCESS(
+      IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType, opus_codecs()));
 
   // Non-audio WebM codecs.
   EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kClearKey, kAudioWebMMimeType,
@@ -646,6 +656,8 @@
   // Non-video MP4 codecs.
   EXPECT_UNSUPPORTED(
       IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType, audio_mp4_codecs()));
+  EXPECT_UNSUPPORTED(
+      IsSupportedByKeySystem(kClearKey, kVideoMP4MimeType, opus_codecs()));
 
   // Invalid or non-MP4 codecs.
   EXPECT_UNSUPPORTED(
@@ -660,6 +672,8 @@
   // Valid audio types.
   EXPECT_PROPRIETARY(
       IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType, audio_mp4_codecs()));
+  EXPECT_SUCCESS(
+      IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType, opus_codecs()));
   EXPECT_SUCCESS(IsSupportedByKeySystem(kClearKey, kAudioMP4MimeType,
                                         audio_mp4_flac_codecs()));
 
@@ -731,6 +745,8 @@
                                     video_webm_codecs()));
   EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioWebMMimeType,
                                     audio_webm_codecs()));
+  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioWebMMimeType,
+                                    opus_codecs()));
   EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioMP4MimeType,
                                     audio_mp4_flac_codecs()));
   EXPECT_ECK_PROPRIETARY(IsSupportedByKeySystem(
@@ -798,6 +814,8 @@
   // Non-video WebM codecs.
   EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
       kExternalClearKey, kVideoWebMMimeType, audio_webm_codecs()));
+  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kExternalClearKey,
+                                            kVideoWebMMimeType, opus_codecs()));
 
   // Invalid or non-Webm codecs.
   EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
@@ -813,6 +831,8 @@
   // Valid audio types.
   EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioWebMMimeType,
                                     audio_webm_codecs()));
+  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioWebMMimeType,
+                                    opus_codecs()));
 
   // Non-audio WebM codecs.
   EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
@@ -848,6 +868,8 @@
   // Non-video MP4 codecs.
   EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
       kExternalClearKey, kVideoMP4MimeType, audio_mp4_codecs()));
+  EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kExternalClearKey,
+                                            kVideoMP4MimeType, opus_codecs()));
 
   // Invalid or non-MP4 codecs.
   EXPECT_UNSUPPORTED(IsSupportedByKeySystem(
@@ -864,6 +886,8 @@
   EXPECT_ECK_PROPRIETARY(IsSupportedByKeySystem(
       kExternalClearKey, kAudioMP4MimeType, audio_mp4_codecs()));
   EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioMP4MimeType,
+                                    opus_codecs()));
+  EXPECT_ECK(IsSupportedByKeySystem(kExternalClearKey, kAudioMP4MimeType,
                                     audio_mp4_flac_codecs()));
 
   // Non-audio MP4 codecs.
@@ -953,12 +977,16 @@
                                            video_webm_codecs()));
   EXPECT_WV_SUCCESS(IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType,
                                            audio_webm_codecs()));
+  EXPECT_WV_SUCCESS(
+      IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType, opus_codecs()));
   EXPECT_WV_SUCCESS(IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType,
                                            audio_mp4_flac_codecs()));
   EXPECT_WV_PROPRIETARY(
       IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType, video_mp4_codecs()));
   EXPECT_WV_PROPRIETARY(
       IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, audio_mp4_codecs()));
+  EXPECT_WV_SUCCESS(
+      IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, opus_codecs()));
 }
 
 IN_PROC_BROWSER_TEST_F(EncryptedMediaSupportedTypesWidevineTest,
@@ -1015,6 +1043,8 @@
   // Non-video WebM codecs.
   EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType,
                                             audio_webm_codecs()));
+  EXPECT_UNSUPPORTED(
+      IsSupportedByKeySystem(kWidevine, kVideoWebMMimeType, opus_codecs()));
 
   // Invalid or non-Webm codecs.
   EXPECT_UNSUPPORTED(
@@ -1031,6 +1061,8 @@
   // Valid audio types.
   EXPECT_WV_SUCCESS(IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType,
                                            audio_webm_codecs()));
+  EXPECT_WV_SUCCESS(
+      IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType, opus_codecs()));
 
   // Non-audio WebM codecs.
   EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kAudioWebMMimeType,
@@ -1065,6 +1097,8 @@
   // Non-video MP4 codecs.
   EXPECT_UNSUPPORTED(
       IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType, audio_mp4_codecs()));
+  EXPECT_UNSUPPORTED(
+      IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType, opus_codecs()));
   EXPECT_UNSUPPORTED(IsSupportedByKeySystem(kWidevine, kVideoMP4MimeType,
                                             audio_mp4_flac_codecs()));
 
@@ -1081,6 +1115,8 @@
   // Valid audio types.
   EXPECT_WV_PROPRIETARY(
       IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, audio_mp4_codecs()));
+  EXPECT_WV_SUCCESS(
+      IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType, opus_codecs()));
   EXPECT_WV_SUCCESS(IsSupportedByKeySystem(kWidevine, kAudioMP4MimeType,
                                            audio_mp4_flac_codecs()));
 
diff --git a/chrome/browser/metrics/first_web_contents_profiler.cc b/chrome/browser/metrics/first_web_contents_profiler.cc
index babe86f..da19d86 100644
--- a/chrome/browser/metrics/first_web_contents_profiler.cc
+++ b/chrome/browser/metrics/first_web_contents_profiler.cc
@@ -14,8 +14,11 @@
 #include "build/build_config.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "components/startup_metric_utils/browser/startup_metric_utils.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -24,34 +27,56 @@
 
 namespace {
 
+// Reasons for which profiling is deemed complete. Logged in UMA (do not re-
+// order or re-assign).
+enum class FinishReason {
+  // All metrics were successfully gathered.
+  kDone = 0,
+  // Abandon if blocking UI was shown during startup.
+  kAbandonBlockingUI = 1,
+  // Abandon if the WebContents is hidden (lowers scheduling priority).
+  kAbandonContentHidden = 2,
+  // Abandon if the WebContents is destroyed.
+  kAbandonContentDestroyed = 3,
+  // Abandon if the WebContents navigates away from its initial page.
+  kAbandonNewNavigation = 4,
+  // Abandon if the WebContents fails to load (e.g. network error, etc.).
+  kAbandonNavigationError = 5,
+  // Abandon if no WebContents was visible at the beginning of startup
+  kAbandonNoInitiallyVisibleContent = 6,
+  kMaxValue = kAbandonNoInitiallyVisibleContent
+};
+
+void RecordFinishReason(FinishReason finish_reason) {
+  UMA_HISTOGRAM_ENUMERATION("Startup.FirstWebContents.FinishReason",
+                            finish_reason);
+}
+
 class FirstWebContentsProfiler : public content::WebContentsObserver {
  public:
   FirstWebContentsProfiler(content::WebContents* web_contents,
                            startup_metric_utils::WebContentsWorkload workload);
 
  private:
-  // Reasons for which profiling is deemed complete. Logged in UMA (do not re-
-  // order or re-assign).
-  enum FinishReason {
-    // All metrics were successfully gathered.
-    DONE = 0,
-    // Abandon if blocking UI was shown during startup.
-    ABANDON_BLOCKING_UI = 1,
-    // Abandon if the content is hidden (lowers scheduling priority).
-    ABANDON_CONTENT_HIDDEN = 2,
-    // Abandon if the content is destroyed.
-    ABANDON_CONTENT_DESTROYED = 3,
-    // Abandon if the WebContents navigates away from its initial page.
-    ABANDON_NEW_NAVIGATION = 4,
-    // Abandon if the WebContents fails to load (e.g. network error, etc.).
-    ABANDON_NAVIGATION_ERROR = 5,
-    ENUM_MAX
+  // Steps of main frame navigation in a WebContents.
+  enum class NavigationStep {
+    // DidStartNavigation() is invalid
+    // DidFinishNavigation() transitions to kNavigationFinished
+    // DidFirstVisuallyNonEmptyPaint() is invalid
+    kNavigationStarted,
+
+    // DidStartNavigation() stops profiling with kAbandonNewNavigation
+    // DidFinishNavigation() is invalid
+    // DidFirstVisuallyNonEmptyPaint() stops profiling with kDone
+    kNavigationFinished,
   };
 
   ~FirstWebContentsProfiler() override = default;
 
   // content::WebContentsObserver:
   void DidFirstVisuallyNonEmptyPaint() override;
+  void DidStartNavigation(
+      content::NavigationHandle* navigation_handle) override;
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
   void OnVisibilityChanged(content::Visibility visibility) override;
@@ -60,11 +85,8 @@
   // Logs |finish_reason| to UMA and deletes this FirstWebContentsProfiler.
   void FinishedCollectingMetrics(FinishReason finish_reason);
 
-  // Whether an attempt was made to collect the "MainNavigationStart/Finished"
-  // metrics.
-  bool collected_main_navigation_metrics_;
-
   const startup_metric_utils::WebContentsWorkload workload_;
+  NavigationStep navigation_step_ = NavigationStep::kNavigationStarted;
 
   DISALLOW_COPY_AND_ASSIGN(FirstWebContentsProfiler);
 };
@@ -72,13 +94,17 @@
 FirstWebContentsProfiler::FirstWebContentsProfiler(
     content::WebContents* web_contents,
     startup_metric_utils::WebContentsWorkload workload)
-    : content::WebContentsObserver(web_contents),
-      collected_main_navigation_metrics_(false),
-      workload_(workload) {}
+    : content::WebContentsObserver(web_contents), workload_(workload) {
+  // FirstWebContentsProfiler is always created with a WebContents that started
+  // but did not finish navigating.
+  DCHECK(web_contents->GetController().GetPendingEntry());
+}
 
 void FirstWebContentsProfiler::DidFirstVisuallyNonEmptyPaint() {
+  DCHECK_EQ(navigation_step_, NavigationStep::kNavigationFinished);
+
   if (startup_metric_utils::WasMainWindowStartupInterrupted()) {
-    FinishedCollectingMetrics(FinishReason::ABANDON_BLOCKING_UI);
+    FinishedCollectingMetrics(FinishReason::kAbandonBlockingUI);
     return;
   }
 
@@ -88,42 +114,48 @@
                                   ->GetProcess()
                                   ->GetInitTimeForNavigationMetrics());
 
-  FinishedCollectingMetrics(FinishReason::DONE);
+  FinishedCollectingMetrics(FinishReason::kDone);
+}
+
+void FirstWebContentsProfiler::DidStartNavigation(
+    content::NavigationHandle* navigation_handle) {
+  // Ignore subframe navigations and same-document navigations.
+  if (!navigation_handle->IsInMainFrame() ||
+      navigation_handle->IsSameDocument()) {
+    return;
+  }
+
+  // DidFinishNavigation() should have been called to finish the preceding
+  // navigation.
+  DCHECK_EQ(navigation_step_, NavigationStep::kNavigationFinished);
+
+  // Abandon profiling on a top-level navigation to a different page as it:
+  //   (1) is no longer a fair timing; and
+  //   (2) can cause http://crbug.com/525209 where the first paint didn't fire
+  //       for the initial content but fires after a lot of idle time when the
+  //       user finally navigates to another page that does trigger it.
+  FinishedCollectingMetrics(FinishReason::kAbandonNewNavigation);
 }
 
 void FirstWebContentsProfiler::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
-  if (collected_main_navigation_metrics_) {
-    // Abandon profiling on a top-level navigation to a different page as it:
-    //   (1) is no longer a fair timing; and
-    //   (2) can cause http://crbug.com/525209 where one of the timing
-    //       heuristics (e.g. first paint) didn't fire for the initial content
-    //       but fires after a lot of idle time when the user finally navigates
-    //       to another page that does trigger it.
-    //
-    // TODO(https://crbug.com/1020549): Determine whether
-    // Startup.FirstWebContents.NonEmptyPaint2 can be recorded for a non-initial
-    // navigation if there are multiple DidStartNavigation() before the first
-    // paint.
-    if (navigation_handle->IsInMainFrame() &&
-        navigation_handle->HasCommitted() &&
-        !navigation_handle->IsSameDocument()) {
-      FinishedCollectingMetrics(FinishReason::ABANDON_NEW_NAVIGATION);
-    }
+  // Ignore subframe navigations and same-document navigations.
+  if (!navigation_handle->IsInMainFrame() ||
+      navigation_handle->IsSameDocument()) {
+    return;
+  }
+
+  DCHECK_EQ(navigation_step_, NavigationStep::kNavigationStarted);
+  navigation_step_ = NavigationStep::kNavigationFinished;
+
+  if (!navigation_handle->HasCommitted() ||
+      navigation_handle->IsErrorPage()) {
+    FinishedCollectingMetrics(FinishReason::kAbandonNavigationError);
     return;
   }
 
   if (startup_metric_utils::WasMainWindowStartupInterrupted()) {
-    FinishedCollectingMetrics(FinishReason::ABANDON_BLOCKING_UI);
-    return;
-  }
-
-  // The first navigation has to be the main frame's.
-  DCHECK(navigation_handle->IsInMainFrame());
-
-  if (!navigation_handle->HasCommitted() ||
-      navigation_handle->IsErrorPage()) {
-    FinishedCollectingMetrics(FinishReason::ABANDON_NAVIGATION_ERROR);
+    FinishedCollectingMetrics(FinishReason::kAbandonBlockingUI);
     return;
   }
 
@@ -131,7 +163,6 @@
       navigation_handle->NavigationStart(), workload_);
   startup_metric_utils::RecordFirstWebContentsMainNavigationFinished(
       base::TimeTicks::Now());
-  collected_main_navigation_metrics_ = true;
 }
 
 void FirstWebContentsProfiler::OnVisibilityChanged(
@@ -139,18 +170,17 @@
   if (visibility != content::Visibility::VISIBLE) {
     // Stop profiling if the content gets hidden as its load may be
     // deprioritized and timing it becomes meaningless.
-    FinishedCollectingMetrics(FinishReason::ABANDON_CONTENT_HIDDEN);
+    FinishedCollectingMetrics(FinishReason::kAbandonContentHidden);
   }
 }
 
 void FirstWebContentsProfiler::WebContentsDestroyed() {
-  FinishedCollectingMetrics(FinishReason::ABANDON_CONTENT_DESTROYED);
+  FinishedCollectingMetrics(FinishReason::kAbandonContentDestroyed);
 }
 
 void FirstWebContentsProfiler::FinishedCollectingMetrics(
     FinishReason finish_reason) {
-  UMA_HISTOGRAM_ENUMERATION("Startup.FirstWebContents.FinishReason",
-                            finish_reason, FinishReason::ENUM_MAX);
+  RecordFinishReason(finish_reason);
   delete this;
 }
 
@@ -163,15 +193,25 @@
 
   const BrowserList* browser_list = BrowserList::GetInstance();
 
-  const auto first_browser = browser_list->begin();
-  if (first_browser == browser_list->end())
-    return;
+  Browser* visible_browser = nullptr;
+  for (Browser* browser : *browser_list) {
+    if (browser->window()->IsVisible()) {
+      visible_browser = browser;
+      break;
+    }
+  }
 
-  const TabStripModel* tab_strip = (*first_browser)->tab_strip_model();
+  if (!visible_browser) {
+    RecordFinishReason(FinishReason::kAbandonNoInitiallyVisibleContent);
+    return;
+  }
+
+  const TabStripModel* tab_strip = visible_browser->tab_strip_model();
   DCHECK(!tab_strip->empty());
 
   content::WebContents* web_contents = tab_strip->GetActiveWebContents();
   DCHECK(web_contents);
+  DCHECK_EQ(web_contents->GetVisibility(), content::Visibility::VISIBLE);
 
   const bool single_tab = browser_list->size() == 1 && tab_strip->count() == 1;
 
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
index 6a65f41..f3cdee9 100644
--- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
+++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
@@ -41,15 +41,13 @@
   return OptimizationGuideTopHostProvider::CreateIfAllowed(browser_context);
 }
 
-// Logs |optimization_target_decision| for |optimization_target| and the
-// |optimization_type_decision| for |optimization_type| in the current
-// navigation's OptimizationGuideNavigationData;
-void LogDecisions(
+// Logs |optimization_target_decision| for |optimization_target| in the current
+// navigation's OptimizationGuideNavigationData.
+void LogOptimizationTargetDecision(
     content::NavigationHandle* navigation_handle,
     optimization_guide::proto::OptimizationTarget optimization_target,
-    optimization_guide::OptimizationTargetDecision optimization_target_decision,
-    optimization_guide::proto::OptimizationType optimization_type,
-    optimization_guide::OptimizationTypeDecision optimization_type_decision) {
+    optimization_guide::OptimizationTargetDecision
+        optimization_target_decision) {
   OptimizationGuideWebContentsObserver*
       optimization_guide_web_contents_observer =
           OptimizationGuideWebContentsObserver::FromWebContents(
@@ -62,10 +60,54 @@
           ->GetOrCreateOptimizationGuideNavigationData(navigation_handle);
   navigation_data->SetDecisionForOptimizationTarget(
       optimization_target, optimization_target_decision);
+}
+
+// Logs the |optimization_type_decision| for |optimization_type| in the current
+// navigation's OptimizationGuideNavigationData.
+void LogOptimizationTypeDecision(
+    content::NavigationHandle* navigation_handle,
+    optimization_guide::proto::OptimizationType optimization_type,
+    optimization_guide::OptimizationTypeDecision optimization_type_decision) {
+  OptimizationGuideWebContentsObserver*
+      optimization_guide_web_contents_observer =
+          OptimizationGuideWebContentsObserver::FromWebContents(
+              navigation_handle->GetWebContents());
+  if (!optimization_guide_web_contents_observer)
+    return;
+
+  OptimizationGuideNavigationData* navigation_data =
+      optimization_guide_web_contents_observer
+          ->GetOrCreateOptimizationGuideNavigationData(navigation_handle);
   navigation_data->SetDecisionForOptimizationType(optimization_type,
                                                   optimization_type_decision);
 }
 
+// Returns the OptimizationGuideDecision from |optimization_target_decision|.
+optimization_guide::OptimizationGuideDecision
+GetOptimizationGuideDecisionFromOptimizationTargetDecision(
+    optimization_guide::OptimizationTargetDecision
+        optimization_target_decision) {
+  switch (optimization_target_decision) {
+    case optimization_guide::OptimizationTargetDecision::kPageLoadDoesNotMatch:
+    case optimization_guide::OptimizationTargetDecision::
+        kModelNotAvailableOnClient:
+    case optimization_guide::OptimizationTargetDecision::
+        kModelPredictionHoldback:
+      return optimization_guide::OptimizationGuideDecision::kFalse;
+    case optimization_guide::OptimizationTargetDecision::kPageLoadMatches:
+      return optimization_guide::OptimizationGuideDecision::kTrue;
+    case optimization_guide::OptimizationTargetDecision::kDeciderNotInitialized:
+    default:
+      return optimization_guide::OptimizationGuideDecision::kUnknown;
+  }
+  static_assert(
+      optimization_guide::OptimizationTargetDecision::kMaxValue ==
+          optimization_guide::OptimizationTargetDecision::
+              kDeciderNotInitialized,
+      "This function should be updated when a new OptimizationTargetDecision "
+      "is added");
+}
+
 // Returns the OptimizationGuideDecision from |optimization_type_decision|.
 optimization_guide::OptimizationGuideDecision
 GetOptimizationGuideDecisionFromOptimizationTypeDecision(
@@ -92,32 +134,24 @@
       "added");
 }
 
-// Returns the OptimizationGuideDecision based on |optimization_target_decision|
-// and |optimization_guide_decision|. If either resolves to false,
-// then the decision will be false. Otherwise, resolves to true or unknown.
-optimization_guide::OptimizationGuideDecision ResolveOptimizationGuideDecision(
-    optimization_guide::OptimizationTargetDecision optimization_target_decision,
-    optimization_guide::OptimizationTypeDecision optimization_type_decision) {
-  switch (optimization_target_decision) {
-    case optimization_guide::OptimizationTargetDecision::kPageLoadDoesNotMatch:
-    case optimization_guide::OptimizationTargetDecision::
-        kModelNotAvailableOnClient:
-    case optimization_guide::OptimizationTargetDecision::
-        kModelPredictionHoldback:
+// Returns the OptimizationGuideDecision based on |decisions|
+// 1) If any decision is false, return false.
+// 2) If all decisions are true, return true.
+// 3) Otherwise, return unknown.
+optimization_guide::OptimizationGuideDecision ResolveOptimizationGuideDecisions(
+    std::vector<optimization_guide::OptimizationGuideDecision> decisions) {
+  bool has_unknown_decision = false;
+  for (const auto decision : decisions) {
+    if (decision == optimization_guide::OptimizationGuideDecision::kFalse)
       return optimization_guide::OptimizationGuideDecision::kFalse;
-    case optimization_guide::OptimizationTargetDecision::kPageLoadMatches:
-      return GetOptimizationGuideDecisionFromOptimizationTypeDecision(
-          optimization_type_decision);
-    case optimization_guide::OptimizationTargetDecision::kDeciderNotInitialized:
-    default:
-      return optimization_guide::OptimizationGuideDecision::kUnknown;
+
+    if (decision == optimization_guide::OptimizationGuideDecision::kUnknown)
+      has_unknown_decision = true;
   }
-  static_assert(
-      optimization_guide::OptimizationTargetDecision::kMaxValue ==
-          optimization_guide::OptimizationTargetDecision::
-              kDeciderNotInitialized,
-      "This function should be updated when a new OptimizationTargetDecision "
-      "is added");
+
+  return has_unknown_decision
+             ? optimization_guide::OptimizationGuideDecision::kUnknown
+             : optimization_guide::OptimizationGuideDecision::kTrue;
 }
 
 }  // namespace
@@ -194,28 +228,18 @@
 }
 
 optimization_guide::OptimizationGuideDecision
-OptimizationGuideKeyedService::CanApplyOptimization(
+OptimizationGuideKeyedService::ShouldTargetNavigation(
     content::NavigationHandle* navigation_handle,
-    optimization_guide::proto::OptimizationTarget optimization_target,
-    optimization_guide::proto::OptimizationType optimization_type,
-    optimization_guide::OptimizationMetadata* optimization_metadata) {
+    optimization_guide::proto::OptimizationTarget optimization_target) {
   if (!hints_manager_) {
-    // We are not initialized yet, so return unknown.
-    LogDecisions(
+    // We are not initialized yet, just return unknown.
+    LogOptimizationTargetDecision(
         navigation_handle, optimization_target,
-        optimization_guide::OptimizationTargetDecision::kDeciderNotInitialized,
-        optimization_type,
-        optimization_guide::OptimizationTypeDecision::kDeciderNotInitialized);
+        optimization_guide::OptimizationTargetDecision::kDeciderNotInitialized);
     return optimization_guide::OptimizationGuideDecision::kUnknown;
   }
 
   optimization_guide::OptimizationTargetDecision optimization_target_decision;
-  optimization_guide::OptimizationTypeDecision optimization_type_decision;
-  hints_manager_->CanApplyOptimization(
-      navigation_handle, optimization_target, optimization_type,
-      &optimization_target_decision, &optimization_type_decision,
-      optimization_metadata);
-
   if (prediction_manager_) {
     optimization_target_decision = prediction_manager_->ShouldTargetNavigation(
         navigation_handle, optimization_target);
@@ -225,13 +249,63 @@
       optimization_target_decision = optimization_guide::
           OptimizationTargetDecision::kModelPredictionHoldback;
     }
+  } else {
+    DCHECK(hints_manager_);
+    optimization_guide::OptimizationTypeDecision
+        unused_optimization_type_decision;
+    hints_manager_->CanApplyOptimization(
+        navigation_handle, optimization_target,
+        optimization_guide::proto::OPTIMIZATION_NONE,
+        &optimization_target_decision, &unused_optimization_type_decision,
+        /*optimization_metadata=*/nullptr);
   }
 
-  LogDecisions(navigation_handle, optimization_target,
-               optimization_target_decision, optimization_type,
-               optimization_type_decision);
-  return ResolveOptimizationGuideDecision(optimization_target_decision,
-                                          optimization_type_decision);
+  LogOptimizationTargetDecision(navigation_handle, optimization_target,
+                                optimization_target_decision);
+  return GetOptimizationGuideDecisionFromOptimizationTargetDecision(
+      optimization_target_decision);
+}
+
+optimization_guide::OptimizationGuideDecision
+OptimizationGuideKeyedService::CanApplyOptimization(
+    content::NavigationHandle* navigation_handle,
+    optimization_guide::proto::OptimizationType optimization_type,
+    optimization_guide::OptimizationMetadata* optimization_metadata) {
+  DCHECK(hints_manager_);
+
+  optimization_guide::OptimizationTargetDecision
+      unused_optimization_target_decision;
+  optimization_guide::OptimizationTypeDecision optimization_type_decision;
+  hints_manager_->CanApplyOptimization(
+      navigation_handle, optimization_guide::proto::OPTIMIZATION_TARGET_UNKNOWN,
+      optimization_type, &unused_optimization_target_decision,
+      &optimization_type_decision, optimization_metadata);
+
+  LogOptimizationTypeDecision(navigation_handle, optimization_type,
+                              optimization_type_decision);
+  return GetOptimizationGuideDecisionFromOptimizationTypeDecision(
+      optimization_type_decision);
+}
+
+optimization_guide::OptimizationGuideDecision
+OptimizationGuideKeyedService::ShouldTargetNavigationAndCanApplyOptimization(
+    content::NavigationHandle* navigation_handle,
+    optimization_guide::proto::OptimizationTarget optimization_target,
+    optimization_guide::proto::OptimizationType optimization_type,
+    optimization_guide::OptimizationMetadata* optimization_metadata) {
+  optimization_guide::OptimizationGuideDecision
+      optimization_target_guide_decision =
+          ShouldTargetNavigation(navigation_handle, optimization_target);
+
+  // Get both decisions regardless of what the first decision is for logging
+  // purposes.
+
+  optimization_guide::OptimizationGuideDecision
+      optimization_type_guide_decision = CanApplyOptimization(
+          navigation_handle, optimization_type, optimization_metadata);
+
+  return ResolveOptimizationGuideDecisions(
+      {optimization_target_guide_decision, optimization_type_guide_decision});
 }
 
 void OptimizationGuideKeyedService::ClearData() {
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
index c74ada8..6781027 100644
--- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
+++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
@@ -78,8 +78,17 @@
           optimization_types,
       const std::vector<optimization_guide::proto::OptimizationTarget>&
           optimization_targets) override;
+  optimization_guide::OptimizationGuideDecision ShouldTargetNavigation(
+      content::NavigationHandle* navigation_handle,
+      optimization_guide::proto::OptimizationTarget optimization_target)
+      override;
   optimization_guide::OptimizationGuideDecision CanApplyOptimization(
       content::NavigationHandle* navigation_handle,
+      optimization_guide::proto::OptimizationType optimization_type,
+      optimization_guide::OptimizationMetadata* optimization_metadata) override;
+  optimization_guide::OptimizationGuideDecision
+  ShouldTargetNavigationAndCanApplyOptimization(
+      content::NavigationHandle* navigation_handle,
       optimization_guide::proto::OptimizationTarget optimization_target,
       optimization_guide::proto::OptimizationType optimization_type,
       optimization_guide::OptimizationMetadata* optimization_metadata) override;
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc
index 2901920..24bd717 100644
--- a/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc
+++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc
@@ -83,22 +83,52 @@
     OptimizationGuideKeyedService* service =
         OptimizationGuideKeyedServiceFactory::GetForProfile(
             Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
-    last_optimization_guide_decision_ = service->CanApplyOptimization(
+    last_should_target_navigation_decision_ = service->ShouldTargetNavigation(
         navigation_handle,
-        optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
-        optimization_guide::proto::NOSCRIPT, /*optimization_metadata=*/nullptr);
+        optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
+    last_can_apply_optimization_decision_ = service->CanApplyOptimization(
+        navigation_handle, optimization_guide::proto::NOSCRIPT,
+        /*optimization_metadata=*/nullptr);
+    last_optimization_guide_decision_ =
+        service->ShouldTargetNavigationAndCanApplyOptimization(
+            navigation_handle,
+            optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
+            optimization_guide::proto::NOSCRIPT,
+            /*optimization_metadata=*/nullptr);
   }
 
   // Returns the last optimization guide decision that was returned by the
-  // OptimizationGuideKeyedService.
+  // OptimizationGuideKeyedService's
+  // ShouldTargetNavigationAndCanApplyOptimization() method.
   optimization_guide::OptimizationGuideDecision
   last_optimization_guide_decision() const {
     return last_optimization_guide_decision_;
   }
 
+  // Returns the last optimization guide decision that was returned by the
+  // OptimizationGuideKeyedService's ShouldTargetNavigation() method.
+  optimization_guide::OptimizationGuideDecision
+  last_should_target_navigation_decision() {
+    return last_should_target_navigation_decision_;
+  }
+
+  // Returns the last optimization guide decision that was returned by the
+  // OptimizationGuideKeyedService's CanApplyOptimization() method.
+  optimization_guide::OptimizationGuideDecision
+  last_can_apply_optimization_decision() {
+    return last_can_apply_optimization_decision_;
+  }
+
  private:
   optimization_guide::OptimizationGuideDecision
-      last_optimization_guide_decision_;
+      last_optimization_guide_decision_ =
+          optimization_guide::OptimizationGuideDecision::kUnknown;
+  optimization_guide::OptimizationGuideDecision
+      last_should_target_navigation_decision_ =
+          optimization_guide::OptimizationGuideDecision::kUnknown;
+  optimization_guide::OptimizationGuideDecision
+      last_can_apply_optimization_decision_ =
+          optimization_guide::OptimizationGuideDecision::kUnknown;
 };
 
 }  // namespace
@@ -217,8 +247,22 @@
         ->ReportEffectiveConnectionTypeForTesting(effective_connection_type);
   }
 
-  // Returns the last decision seen by the consumer of the
-  // OptimizationGuideKeyedService.
+  // Returns the last decision from the CanApplyOptimization() method seen by
+  // the consumer of the OptimizationGuideKeyedService.
+  optimization_guide::OptimizationGuideDecision
+  last_should_target_navigation_decision() {
+    return consumer_->last_should_target_navigation_decision();
+  }
+
+  // Returns the last decision from the CanApplyOptimization() method seen by
+  // the consumer of the OptimizationGuideKeyedService.
+  optimization_guide::OptimizationGuideDecision
+  last_can_apply_optimization_decision() {
+    return consumer_->last_can_apply_optimization_decision();
+  }
+
+  // Returns the last decision from the ShouldTargetAndCanApplyOptimization()
+  // method seen by the consumer of the OptimizationGuideKeyedService.
   optimization_guide::OptimizationGuideDecision last_consumer_decision() {
     return consumer_->last_optimization_guide_decision();
   }
@@ -275,6 +319,10 @@
 
   histogram_tester.ExpectTotalCount("OptimizationGuide.LoadedHint.Result", 0);
   // There is a hint that matches this URL but it wasn't loaded.
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_should_target_navigation_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kUnknown,
+            last_can_apply_optimization_decision());
   EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kUnknown,
             last_consumer_decision());
 }
@@ -308,7 +356,11 @@
   histogram_tester.ExpectUniqueSample(
       "OptimizationGuide.HintCache.PageMatch.AtCommit", true, 1);
 
-  // We had a hint but it wasn't loaded and it was painful enough.
+  // We had a hint and it was loaded and it was painful enough.
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_should_target_navigation_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_can_apply_optimization_decision());
   EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
             last_consumer_decision());
   // Expect that the optimization guide UKM was recorded.
@@ -348,6 +400,10 @@
 
   // We had a matching hint but the page load was not painful.
   EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
+            last_should_target_navigation_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_can_apply_optimization_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
             last_consumer_decision());
   histogram_tester.ExpectUniqueSample(
       "OptimizationGuide.TargetDecision.PainfulPageLoad",
@@ -395,6 +451,10 @@
                                      true, 1);
   // Hint is still applicable so we expect it to be allowed to be applied.
   EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_should_target_navigation_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_can_apply_optimization_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
             last_consumer_decision());
   // Make sure hint cache match UMA was logged.
   histogram_tester.ExpectUniqueSample(
@@ -438,6 +498,10 @@
   // attempt to load a hint but still fail.
   histogram_tester.ExpectUniqueSample("OptimizationGuide.LoadedHint.Result",
                                       false, 1);
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_should_target_navigation_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
+            last_can_apply_optimization_decision());
   EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
             last_consumer_decision());
   histogram_tester.ExpectUniqueSample(
@@ -484,6 +548,10 @@
   // There should be a hint that matches this URL.
   histogram_tester.ExpectUniqueSample("OptimizationGuide.LoadedHint.Result",
                                       true, 1);
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_should_target_navigation_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
+            last_can_apply_optimization_decision());
   EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
             last_consumer_decision());
   histogram_tester.ExpectUniqueSample(
@@ -529,6 +597,10 @@
   // There should be a hint that matches this URL.
   histogram_tester.ExpectUniqueSample("OptimizationGuide.LoadedHint.Result",
                                       true, 1);
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_should_target_navigation_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
+            last_can_apply_optimization_decision());
   EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
             last_consumer_decision());
   histogram_tester.ExpectUniqueSample(
@@ -731,6 +803,10 @@
   histogram_tester.ExpectUniqueSample("OptimizationGuide.LoadedHint.Result",
                                       true, 1);
   EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
+            last_should_target_navigation_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_can_apply_optimization_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
             last_consumer_decision());
   histogram_tester.ExpectUniqueSample(
       "OptimizationGuide.TargetDecision.PainfulPageLoad",
@@ -781,6 +857,10 @@
   histogram_tester.ExpectUniqueSample("OptimizationGuide.LoadedHint.Result",
                                       true, 1);
   EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
+            last_should_target_navigation_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue,
+            last_can_apply_optimization_decision());
+  EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse,
             last_consumer_decision());
   histogram_tester.ExpectUniqueSample(
       "OptimizationGuide.TargetDecision.PainfulPageLoad",
diff --git a/chrome/browser/resources/chromeos/chromevox/background/output.js b/chrome/browser/resources/chromeos/chromevox/background/output.js
index 67cbb8e..ea2119aac 100644
--- a/chrome/browser/resources/chromeos/chromevox/background/output.js
+++ b/chrome/browser/resources/chromeos/chromevox/background/output.js
@@ -978,7 +978,12 @@
     var node = opt_node || null;
 
     this.formatOptions_ = {speech: true, braille: false, auralStyle: false};
-    this.format_(node, formatStr, this.speechBuffer_, this.speechRulesStr_);
+    this.format_({
+      node: node,
+      outputFormat: formatStr,
+      outputBuffer: this.speechBuffer_,
+      outputRuleString: this.speechRulesStr_
+    });
 
     return this;
   },
@@ -995,7 +1000,12 @@
     var node = opt_node || null;
 
     this.formatOptions_ = {speech: false, braille: true, auralStyle: false};
-    this.format_(node, formatStr, this.brailleBuffer_, this.brailleRulesStr_);
+    this.format_({
+      node: node,
+      outputFormat: formatStr,
+      outputBuffer: this.brailleBuffer_,
+      outputRuleString: this.brailleRulesStr_
+    });
     return this;
   },
 
@@ -1181,17 +1191,34 @@
 
   /**
    * Format the node given the format specifier.
-   * @param {AutomationNode} node
-   * @param {string|!Object} format The output format either specified as an
-   * output template string or a parsed output format tree.
-   * @param {!Array<Spannable>} buff Buffer to receive rendered output.
-   * @param {!OutputRulesStr} ruleStr
-   * @param {!AutomationNode=} opt_prevNode
-   * @param {!Object<string,(string|number|boolean|Function|Array<string>)>=}
-   *     opt_properties
+   * Please see below for more information on arguments.
+   * node: The AutomationNode of interest.
+   * outputFormat: The output format either specified as an output template
+   * string or a parsed output format tree.
+   * outputBuffer: Buffer to receive rendered output.
+   * outputRuleString: Used for logging and recording output.
+   * opt_prevNode: Optional argument. Helps provide context for certain speech
+   * output.
+   * opt_speechProps: Optional argument. Used to specify how speech should be
+   * verbalized; can specify pitch, rate, language, etc.
+   * @param {!{
+   *    node: AutomationNode,
+   *    outputFormat: (string|!Object),
+   *    outputBuffer: !Array<Spannable>,
+   *    outputRuleString: !OutputRulesStr,
+   *    opt_prevNode: (!AutomationNode|undefined),
+   *    opt_speechProps: (!Output.SpeechProperties|undefined)
+   * }} params An object containing all required and optional parameters.
    * @private
    */
-  format_: function(node, format, buff, ruleStr, opt_prevNode, opt_properties) {
+  format_: function(params) {
+    var node = params['node'];
+    var format = params['outputFormat'];
+    var buff = params['outputBuffer'];
+    var ruleStr = params['outputRuleString'];
+    var prevNode = params['opt_prevNode'];
+    var speechProps = params['opt_speechProps'];
+
     var tokens = [];
     var args = null;
 
@@ -1203,7 +1230,6 @@
       tokens = [format];
     }
 
-    var speechProps = opt_properties || null;
     tokens.forEach(function(token) {
       // Ignore empty tokens.
       if (!token) {
@@ -1268,7 +1294,7 @@
           }
         } else if (token == 'name') {
           options.annotation.push(token);
-          var earcon = node ? this.findEarcon_(node, opt_prevNode) : null;
+          var earcon = node ? this.findEarcon_(node, prevNode) : null;
           if (earcon) {
             options.annotation.push(earcon);
           }
@@ -1360,7 +1386,12 @@
             ruleStr.writeTokenWithValue(token, node.name);
           } else {
             ruleStr.writeToken(token);
-            this.format_(node, '$descendants', buff, ruleStr);
+            this.format_({
+              node: node,
+              outputFormat: '$descendants',
+              outputBuffer: buff,
+              outputRuleString: ruleStr
+            });
           }
         } else if (token == 'indexInParent') {
           if (node.parent) {
@@ -1389,19 +1420,34 @@
           var msg = Output.RESTRICTION_STATE_MAP[node.restriction];
           if (msg) {
             ruleStr.writeToken(token);
-            this.format_(node, '@' + msg, buff, ruleStr);
+            this.format_({
+              node: node,
+              outputFormat: '@' + msg,
+              outputBuffer: buff,
+              outputRuleString: ruleStr
+            });
           }
         } else if (token == 'checked') {
           var msg = Output.CHECKED_STATE_MAP[node.checked];
           if (msg) {
             ruleStr.writeToken(token);
-            this.format_(node, '@' + msg, buff, ruleStr);
+            this.format_({
+              node: node,
+              outputFormat: '@' + msg,
+              outputBuffer: buff,
+              outputRuleString: ruleStr
+            });
           }
         } else if (token == 'pressed') {
           var msg = Output.PRESSED_STATE_MAP[node.checked];
           if (msg) {
             ruleStr.writeToken(token);
-            this.format_(node, '@' + msg, buff, ruleStr);
+            this.format_({
+              node: node,
+              outputFormat: '@' + msg,
+              outputBuffer: buff,
+              outputRuleString: ruleStr
+            });
           }
         } else if (token == 'state') {
           if (node.state) {
@@ -1409,7 +1455,12 @@
               var stateInfo = Output.STATE_INFO_[s];
               if (stateInfo && !stateInfo.isRoleSpecific && stateInfo.on) {
                 ruleStr.writeToken(token);
-                this.format_(node, '$' + s, buff, ruleStr);
+                this.format_({
+                  node: node,
+                  outputFormat: '$' + s,
+                  outputBuffer: buff,
+                  outputRuleString: ruleStr
+                });
               }
             }.bind(this));
           }
@@ -1423,7 +1474,12 @@
             var formatString = tree.firstChild.nextSibling;
             if (node) {
               ruleStr.writeToken(token);
-              this.format_(node, formatString, buff, ruleStr);
+              this.format_({
+                node: node,
+                outputFormat: formatString,
+                outputBuffer: buff,
+                outputRuleString: ruleStr
+              });
             }
           }
         } else if (token == 'descendants') {
@@ -1466,7 +1522,12 @@
         } else if (token == 'joinedDescendants') {
           var unjoined = [];
           ruleStr.write('joinedDescendants {');
-          this.format_(node, '$descendants', unjoined, ruleStr);
+          this.format_({
+            node: node,
+            outputFormat: '$descendants',
+            outputBuffer: unjoined,
+            outputRuleString: ruleStr
+          });
           this.append_(buff, unjoined.join(' '), options);
           ruleStr.write(
               '}: ' + (unjoined.length ? unjoined.join(' ') : 'EMPTY') + '\n');
@@ -1533,12 +1594,15 @@
             ruleStr.writeTokenWithValue(token, value);
           } else {
             ruleStr.write(token);
-            this.format_(
-                node, `@cell_summary($if($tableCellAriaRowIndex,
-                               $tableCellAriaRowIndex, $tableCellRowIndex),
+            this.format_({
+              node: node,
+              outputFormat: ` @cell_summary($if($tableCellAriaRowIndex,
+                      $tableCellAriaRowIndex, $tableCellRowIndex),
                     $if($tableCellAriaColumnIndex, $tableCellAriaColumnIndex,
-                        $tableCellColumnIndex))`,
-                buff, ruleStr);
+                      $tableCellColumnIndex))`,
+              outputBuffer: buff,
+              outputRuleString: ruleStr
+            });
           }
         } else if (token == 'node') {
           if (!tree.firstChild) {
@@ -1548,13 +1612,11 @@
           var relationName = tree.firstChild.value;
           if (relationName == 'tableCellColumnHeaders') {
             // Skip output when previous position falls on the same column.
-            while (opt_prevNode &&
-                   !AutomationPredicate.cellLike(opt_prevNode)) {
-              opt_prevNode = opt_prevNode.parent;
+            while (prevNode && !AutomationPredicate.cellLike(prevNode)) {
+              prevNode = prevNode.parent;
             }
-            if (opt_prevNode &&
-                opt_prevNode.tableCellColumnIndex ==
-                    node.tableCellColumnIndex) {
+            if (prevNode &&
+                prevNode.tableCellColumnIndex == node.tableCellColumnIndex) {
               return;
             }
 
@@ -1587,7 +1649,12 @@
         } else if (token == 'nameOrTextContent') {
           if (node.name && node.nameFrom != NameFromType.CONTENTS) {
             ruleStr.writeToken(token);
-            this.format_(node, '$name', buff, ruleStr);
+            this.format_({
+              node: node,
+              outputFormat: '$name',
+              outputBuffer: buff,
+              outputRuleString: ruleStr
+            });
             return;
           }
 
@@ -1647,7 +1714,12 @@
             ruleStr.writeTokenWithValue(token, String(node.posInSet));
           } else {
             ruleStr.writeToken(token);
-            this.format_(node, '$indexInParent', buff, ruleStr);
+            this.format_({
+              node: node,
+              outputFormat: '$indexInParent',
+              outputBuffer: buff,
+              outputRuleString: ruleStr
+            });
           }
         } else if (token == 'setSize') {
           var size = node.setSize ? node.setSize : 0;
@@ -1661,10 +1733,20 @@
             var attrib = cond.value.slice(1);
             if (Output.isTruthy(node, attrib)) {
               ruleStr.write(attrib + '==true => ');
-              this.format_(node, cond.nextSibling, buff, ruleStr);
+              this.format_({
+                node: node,
+                outputFormat: cond.nextSibling,
+                outputBuffer: buff,
+                outputRuleString: ruleStr
+              });
             } else if (Output.isFalsey(node, attrib)) {
               ruleStr.write(attrib + '==false => ');
-              this.format_(node, cond.nextSibling.nextSibling, buff, ruleStr);
+              this.format_({
+                node: node,
+                outputFormat: cond.nextSibling.nextSibling,
+                outputBuffer: buff,
+                outputRuleString: ruleStr
+              });
             }
           } else if (token == 'nif') {
             ruleStr.writeToken(token);
@@ -1672,10 +1754,20 @@
             var attrib = cond.value.slice(1);
             if (Output.isFalsey(node, attrib)) {
               ruleStr.write(attrib + '==false => ');
-              this.format_(node, cond.nextSibling, buff, ruleStr);
+              this.format_({
+                node: node,
+                outputFormat: cond.nextSibling,
+                outputBuffer: buff,
+                outputRuleString: ruleStr
+              });
             } else if (Output.isTruthy(node, attrib)) {
               ruleStr.write(attrib + '==true => ');
-              this.format_(node, cond.nextSibling.nextSibling, buff, ruleStr);
+              this.format_({
+                node: node,
+                outputFormat: cond.nextSibling.nextSibling,
+                outputBuffer: buff,
+                outputRuleString: ruleStr
+              });
             }
           } else if (token == 'earcon') {
             // Ignore unless we're generating speech output.
@@ -1723,7 +1815,12 @@
               return;
             }
             var msgBuff = [];
-            this.format_(node, curArg, msgBuff, ruleStr);
+            this.format_({
+              node: node,
+              outputFormat: curArg,
+              outputBuffer: msgBuff,
+              outputRuleString: ruleStr
+            });
             // Fill in empty string if nothing was formatted.
             if (!msgBuff.length) {
               msgBuff = [''];
@@ -1762,7 +1859,12 @@
             return;
           }
           var argBuff = [];
-          this.format_(node, arg, argBuff, ruleStr);
+          this.format_({
+            node: node,
+            outputFormat: arg,
+            outputBuffer: argBuff,
+            outputRuleString: ruleStr
+          });
           var namedArgs = {COUNT: Number(argBuff[0])};
           msg = new goog.i18n.MessageFormat(msg).format(namedArgs);
         }
@@ -1960,9 +2062,13 @@
           localStorage['useVerboseMode'] == 'true') {
         rule.navigation = 'leave';
         ruleStr.writeRule(rule);
-        this.format_(
-            formatPrevNode, eventBlock[rule.role].leave, buff, ruleStr,
-            prevNode);
+        this.format_({
+          node: formatPrevNode,
+          outputFormat: eventBlock[rule.role].leave,
+          outputBuffer: buff,
+          outputRuleString: ruleStr,
+          opt_prevNode: prevNode
+        });
       }
     }
 
@@ -1996,7 +2102,13 @@
         var enterFormat = rule.output ?
             eventBlock[rule.role]['enter'][rule.output] :
             eventBlock[rule.role]['enter'];
-        this.format_(formatNode, enterFormat, buff, ruleStr, prevNode);
+        this.format_({
+          node: formatNode,
+          outputFormat: enterFormat,
+          outputBuffer: buff,
+          outputRuleString: ruleStr,
+          opt_prevNode: prevNode
+        });
 
         if (this.formatOptions_.braille && buff.length) {
           var nodeSpan = this.mergeBraille_(buff);
@@ -2053,8 +2165,13 @@
       }
     }
     ruleStr.writeRule(rule);
-    this.format_(
-        node, eventBlock[rule.role][rule.output], buff, ruleStr, prevNode);
+    this.format_({
+      node: node,
+      outputFormat: eventBlock[rule.role][rule.output],
+      outputBuffer: buff,
+      outputRuleString: ruleStr,
+      opt_prevNode: prevNode
+    });
 
     // Restore braille and add an annotation for this node.
     if (this.formatOptions_.braille) {
@@ -2185,7 +2302,12 @@
 
     // Undelayed hints.
     if (node.errorMessage) {
-      this.format_(node, '$node(errorMessage)', buff, ruleStr, undefined, {});
+      this.format_({
+        node: node,
+        outputFormat: '$node(errorMessage)',
+        outputBuffer: buff,
+        outputRuleString: ruleStr
+      });
     }
 
     // Hints should be delayed.
@@ -2195,44 +2317,66 @@
     ruleStr.write('hint_: ');
     if (EventSourceState.get() == EventSourceType.TOUCH_GESTURE) {
       if (node.state[StateType.EDITABLE]) {
-        this.format_(
-            node,
-            node.state[StateType.FOCUSED] ? '@hint_is_editing' :
-                                            '@hint_double_tap_to_edit',
-            buff, ruleStr, undefined, hintProperties);
+        this.format_({
+          node: node,
+          outputFormat: node.state[StateType.FOCUSED] ?
+              '@hint_is_editing' :
+              '@hint_double_tap_to_edit',
+          outputBuffer: buff,
+          outputRuleString: ruleStr,
+          opt_speechProps: hintProperties
+        });
         return;
       }
 
       var isWithinVirtualKeyboard = AutomationUtil.getAncestors(node).find(
           (n) => n.role == RoleType.KEYBOARD);
       if (node.defaultActionVerb != 'none' && !isWithinVirtualKeyboard) {
-        this.format_(
-            node, '@hint_double_tap', buff, ruleStr, undefined, hintProperties);
+        this.format_({
+          node: node,
+          outputFormat: '@hint_double_tap',
+          outputBuffer: buff,
+          outputRuleString: ruleStr,
+          opt_speechProps: hintProperties
+        });
       }
 
       var enteredVirtualKeyboard =
           uniqueAncestors.find((n) => n.role == RoleType.KEYBOARD);
       if (enteredVirtualKeyboard) {
-        this.format_(
-            node, '@hint_touch_type', buff, ruleStr, undefined, hintProperties);
+        this.format_({
+          node: node,
+          outputFormat: '@hint_touch_type',
+          outputBuffer: buff,
+          outputRuleString: ruleStr,
+          opt_speechProps: hintProperties
+        });
       }
 
       return;
     }
 
     if (node.state[StateType.EDITABLE] && cvox.ChromeVox.isStickyPrefOn) {
-      this.format_(
-          node, '@sticky_mode_enabled', buff, ruleStr, undefined,
-          hintProperties);
+      this.format_({
+        node: node,
+        outputFormat: '@sticky_mode_enabled',
+        outputBuffer: buff,
+        outputRuleString: ruleStr,
+        opt_speechProps: hintProperties
+      });
     }
 
     if (node.state[StateType.EDITABLE] && node.state[StateType.FOCUSED] &&
         !this.formatOptions_.braille) {
       if (node.state[StateType.MULTILINE] ||
           node.state[StateType.RICHLY_EDITABLE])
-        this.format_(
-            node, '@hint_search_within_text_field', buff, ruleStr, undefined,
-            hintProperties);
+        this.format_({
+          node: node,
+          outputFormat: '@hint_search_within_text_field',
+          outputBuffer: buff,
+          outputRuleString: ruleStr,
+          opt_speechProps: hintProperties
+        });
     }
 
     if (node.placeholder) {
@@ -2247,23 +2391,41 @@
     }
 
     if (AutomationPredicate.checkable(node)) {
-      this.format_(
-          node, '@hint_checkable', buff, ruleStr, undefined, hintProperties);
+      this.format_({
+        node: node,
+        outputFormat: '@hint_checkable',
+        outputBuffer: buff,
+        outputRuleString: ruleStr,
+        opt_speechProps: hintProperties
+      });
     } else if (AutomationPredicate.clickable(node)) {
-      this.format_(
-          node, '@hint_clickable', buff, ruleStr, undefined, hintProperties);
+      this.format_({
+        node: node,
+        outputFormat: '@hint_clickable',
+        outputBuffer: buff,
+        outputRuleString: ruleStr,
+        opt_speechProps: hintProperties
+      });
     }
 
     if (node.autoComplete == 'list' || node.autoComplete == 'both' ||
         node.state[StateType.AUTOFILL_AVAILABLE]) {
-      this.format_(
-          node, '@hint_autocomplete_list', buff, ruleStr, undefined,
-          hintProperties);
+      this.format_({
+        node: node,
+        outputFormat: '@hint_autocomplete_list',
+        outputBuffer: buff,
+        outputRuleString: ruleStr,
+        opt_speechProps: hintProperties
+      });
     }
     if (node.autoComplete == 'inline' || node.autoComplete == 'both') {
-      this.format_(
-          node, '@hint_autocomplete_inline', buff, ruleStr, undefined,
-          hintProperties);
+      this.format_({
+        node: node,
+        outputFormat: '@hint_autocomplete_inline',
+        outputBuffer: buff,
+        outputRuleString: ruleStr,
+        opt_speechProps: hintProperties
+      });
     }
     if (node.accessKey) {
       this.append_(buff, Msgs.getMsg('access_key', [node.accessKey]));
@@ -2273,19 +2435,34 @@
     // Ancestry based hints.
     if (uniqueAncestors.find(
             /** @type {function(?) : boolean} */ (AutomationPredicate.table))) {
-      this.format_(
-          node, '@hint_table', buff, ruleStr, undefined, hintProperties);
+      this.format_({
+        node: node,
+        outputFormat: '@hint_table',
+        outputBuffer: buff,
+        outputRuleString: ruleStr,
+        opt_speechProps: hintProperties
+      });
     }
     if (uniqueAncestors.find(/** @type {function(?) : boolean} */ (
             AutomationPredicate.roles([RoleType.MENU, RoleType.MENU_BAR])))) {
-      this.format_(
-          node, '@hint_menu', buff, ruleStr, undefined, hintProperties);
+      this.format_({
+        node: node,
+        outputFormat: '@hint_menu',
+        outputBuffer: buff,
+        outputRuleString: ruleStr,
+        opt_speechProps: hintProperties
+      });
     }
     if (uniqueAncestors.find(/** @type {function(?) : boolean} */ (function(n) {
           return !!n.details;
         }))) {
-      this.format_(
-          node, '@hint_details', buff, ruleStr, undefined, hintProperties);
+      this.format_({
+        node: node,
+        outputFormat: '@hint_details',
+        outputBuffer: buff,
+        outputRuleString: ruleStr,
+        opt_speechProps: hintProperties
+      });
     }
   },
 
diff --git a/chrome/browser/resources/safe_browsing/download_file_types.asciipb b/chrome/browser/resources/safe_browsing/download_file_types.asciipb
index b0fdb39..c5b15ed 100644
--- a/chrome/browser/resources/safe_browsing/download_file_types.asciipb
+++ b/chrome/browser/resources/safe_browsing/download_file_types.asciipb
@@ -8,7 +8,7 @@
 ##
 ## Top level settings
 ##
-version_id: 37
+version_id: 38
 sampled_ping_probability: 0.01
 max_archived_binaries_to_report: 10
 default_file_type {
@@ -1224,6 +1224,18 @@
   }
 }
 file_types {
+  # MS Access database
+  # Similar to mdb
+  extension: "accdb"
+  uma_value: 388
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_WINDOWS
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: ALLOW_AUTO_OPEN
+  }
+}
+file_types {
   # ActiveX Control
   extension: "ocx"
   uma_value: 90
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn
index 3d7379a..66a09ea 100644
--- a/chrome/browser/safe_browsing/BUILD.gn
+++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -245,7 +245,7 @@
       }
     } else if (safe_browsing_mode == 2) {
       sources += [
-        "android/file_type_policies.cc",
+        "android/safe_browsing_bridge.cc",
         "android/services_delegate_android.cc",
         "android/services_delegate_android.h",
         "telemetry/android/android_telemetry_service.cc",
diff --git a/chrome/browser/safe_browsing/android/file_type_policies.cc b/chrome/browser/safe_browsing/android/file_type_policies.cc
deleted file mode 100644
index 17a4598..0000000
--- a/chrome/browser/safe_browsing/android/file_type_policies.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/safe_browsing/file_type_policies.h"
-
-#include "base/android/jni_string.h"
-#include "base/files/file_path.h"
-#include "chrome/android/chrome_jni_headers/FileTypePolicies_jni.h"
-
-namespace safe_browsing {
-
-static jint JNI_FileTypePolicies_UmaValueForFile(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jstring>& path) {
-  base::FilePath file_path(ConvertJavaStringToUTF8(env, path));
-  return safe_browsing::FileTypePolicies::GetInstance()->UmaValueForFile(
-      file_path);
-}
-
-}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/android/safe_browsing_bridge.cc b/chrome/browser/safe_browsing/android/safe_browsing_bridge.cc
new file mode 100644
index 0000000..11c62ee
--- /dev/null
+++ b/chrome/browser/safe_browsing/android/safe_browsing_bridge.cc
@@ -0,0 +1,55 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_string.h"
+#include "base/files/file_path.h"
+#include "chrome/android/chrome_jni_headers/SafeBrowsingBridge_jni.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/safe_browsing/file_type_policies.h"
+#include "components/prefs/pref_service.h"
+#include "components/safe_browsing/common/safe_browsing_prefs.h"
+
+using base::android::JavaParamRef;
+
+namespace {
+
+PrefService* GetPrefService() {
+  return ProfileManager::GetActiveUserProfile()
+      ->GetOriginalProfile()
+      ->GetPrefs();
+}
+
+}  // namespace
+
+namespace safe_browsing {
+
+static jint JNI_SafeBrowsingBridge_UmaValueForFile(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jstring>& path) {
+  base::FilePath file_path(ConvertJavaStringToUTF8(env, path));
+  return safe_browsing::FileTypePolicies::GetInstance()->UmaValueForFile(
+      file_path);
+}
+
+static jboolean JNI_SafeBrowsingBridge_GetSafeBrowsingExtendedReportingEnabled(
+    JNIEnv* env) {
+  return safe_browsing::IsExtendedReportingEnabled(*GetPrefService());
+}
+
+static void JNI_SafeBrowsingBridge_SetSafeBrowsingExtendedReportingEnabled(
+    JNIEnv* env,
+    jboolean enabled) {
+  safe_browsing::SetExtendedReportingPrefAndMetric(
+      GetPrefService(), enabled,
+      safe_browsing::SBER_OPTIN_SITE_ANDROID_SETTINGS);
+}
+
+static jboolean JNI_SafeBrowsingBridge_GetSafeBrowsingExtendedReportingManaged(
+    JNIEnv* env) {
+  PrefService* pref_service = GetPrefService();
+  return pref_service->IsManagedPreference(
+      prefs::kSafeBrowsingScoutReportingEnabled);
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
index 3bb0590..49ea9fa 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
@@ -43,7 +43,7 @@
     "ChromeCleanupExtensions", base::FEATURE_DISABLED_BY_DEFAULT};
 
 const base::Feature kChromeCleanupProtobufIPCFeature{
-    "ChromeCleanupProtobufIPC", base::FEATURE_DISABLED_BY_DEFAULT};
+    "ChromeCleanupProtobufIPC", base::FEATURE_ENABLED_BY_DEFAULT};
 
 bool IsSRTPromptFeatureEnabled() {
   return base::FeatureList::IsEnabled(kChromeCleanupInBrowserPromptFeature);
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc b/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc
index 0e2bed83b..7216d5bf 100644
--- a/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc
+++ b/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc
@@ -97,7 +97,8 @@
         /* gcm_driver= */ nullptr,
         /* device_info_tracker= */ nullptr,
         /* local_device_info_provider= */ nullptr,
-        /* sync_service */ nullptr);
+        /* sync_service */ nullptr,
+        /* sms_fetcher= */ nullptr);
   }
 
   base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chrome/browser/sharing/mock_sharing_service.cc b/chrome/browser/sharing/mock_sharing_service.cc
index 0d1c6020..5143a53 100644
--- a/chrome/browser/sharing/mock_sharing_service.cc
+++ b/chrome/browser/sharing/mock_sharing_service.cc
@@ -27,6 +27,7 @@
           /*gcm_driver=*/nullptr,
           /*device_info_tracker=*/nullptr,
           /*local_device_info_provider=*/nullptr,
-          /*sync_service*/ nullptr) {}
+          /*sync_service*/ nullptr,
+          /*sms_fetcher=*/nullptr) {}
 
 MockSharingService::~MockSharingService() = default;
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc
index d33aa94..4f2deac9 100644
--- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc
+++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc
@@ -81,7 +81,8 @@
         /* gcm_driver= */ nullptr,
         /* device_info_tracker= */ nullptr,
         /* local_device_info_provider= */ nullptr,
-        /* sync_service */ nullptr);
+        /* sync_service */ nullptr,
+        /* sms_fetcher= */ nullptr);
   }
 
   base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chrome/browser/sharing/sharing_service.cc b/chrome/browser/sharing/sharing_service.cc
index 5031af30..066c79eb 100644
--- a/chrome/browser/sharing/sharing_service.cc
+++ b/chrome/browser/sharing/sharing_service.cc
@@ -60,7 +60,8 @@
     gcm::GCMDriver* gcm_driver,
     syncer::DeviceInfoTracker* device_info_tracker,
     syncer::LocalDeviceInfoProvider* local_device_info_provider,
-    syncer::SyncService* sync_service)
+    syncer::SyncService* sync_service,
+    content::SmsFetcher* sms_fetcher)
     : sync_prefs_(std::move(sync_prefs)),
       vapid_key_manager_(std::move(vapid_key_manager)),
       sharing_device_registration_(std::move(sharing_device_registration)),
@@ -105,7 +106,8 @@
   }
 
   if (sharing_device_registration_->IsSmsFetcherSupported()) {
-    sms_fetch_request_handler_ = std::make_unique<SmsFetchRequestHandler>();
+    sms_fetch_request_handler_ =
+        std::make_unique<SmsFetchRequestHandler>(sms_fetcher);
     fcm_handler_->AddSharingHandler(
         chrome_browser_sharing::SharingMessage::kSmsFetchRequest,
         sms_fetch_request_handler_.get());
diff --git a/chrome/browser/sharing/sharing_service.h b/chrome/browser/sharing/sharing_service.h
index f89a437..e7da32ab 100644
--- a/chrome/browser/sharing/sharing_service.h
+++ b/chrome/browser/sharing/sharing_service.h
@@ -34,6 +34,10 @@
 #include "chrome/browser/sharing/sharing_service_proxy_android.h"
 #endif  // defined(OS_ANDROID)
 
+namespace content {
+class SmsFetcher;
+}
+
 namespace gcm {
 class GCMDriver;
 }  // namespace gcm
@@ -83,7 +87,8 @@
       gcm::GCMDriver* gcm_driver,
       syncer::DeviceInfoTracker* device_info_tracker,
       syncer::LocalDeviceInfoProvider* local_device_info_provider,
-      syncer::SyncService* sync_service);
+      syncer::SyncService* sync_service,
+      content::SmsFetcher* sms_fetcher);
   ~SharingService() override;
 
   // Returns the device matching |guid|, or nullptr if no match was found.
diff --git a/chrome/browser/sharing/sharing_service_factory.cc b/chrome/browser/sharing/sharing_service_factory.cc
index 186e317..9ed6009 100644
--- a/chrome/browser/sharing/sharing_service_factory.cc
+++ b/chrome/browser/sharing/sharing_service_factory.cc
@@ -27,6 +27,7 @@
 #include "components/sync_device_info/device_info_sync_service.h"
 #include "components/sync_device_info/local_device_info_provider.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/browser/sms_fetcher.h"
 
 namespace {
 constexpr char kServiceName[] = "SharingService";
@@ -98,11 +99,14 @@
       std::make_unique<SharingMessageSender>(fcm_sender.get(), sync_prefs.get(),
                                              local_device_info_provider);
 
+  content::SmsFetcher* sms_fetcher = content::SmsFetcher::Get(context);
+
   return new SharingService(
       profile, std::move(sync_prefs), std::move(vapid_key_manager),
       std::move(sharing_device_registration), std::move(fcm_sender),
       std::move(fcm_handler), std::move(sharing_message_sender), gcm_driver,
-      device_info_tracker, local_device_info_provider, sync_service);
+      device_info_tracker, local_device_info_provider, sync_service,
+      sms_fetcher);
 }
 
 content::BrowserContext* SharingServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/sharing/sharing_service_unittest.cc b/chrome/browser/sharing/sharing_service_unittest.cc
index 56bda61..abcd825 100644
--- a/chrome/browser/sharing/sharing_service_unittest.cc
+++ b/chrome/browser/sharing/sharing_service_unittest.cc
@@ -223,7 +223,8 @@
           base::WrapUnique(sharing_message_sender_), nullptr,
           fake_device_info_sync_service.GetDeviceInfoTracker(),
           fake_device_info_sync_service.GetLocalDeviceInfoProvider(),
-          &test_sync_service_);
+          &test_sync_service_,
+          /* sms_fetcher= */ nullptr);
     }
     task_environment_.RunUntilIdle();
     return sharing_service_.get();
diff --git a/chrome/browser/sharing/sms/sms_fetch_request_handler.cc b/chrome/browser/sharing/sms/sms_fetch_request_handler.cc
index 7507c19c..43f3ecf 100644
--- a/chrome/browser/sharing/sms/sms_fetch_request_handler.cc
+++ b/chrome/browser/sharing/sms/sms_fetch_request_handler.cc
@@ -6,8 +6,12 @@
 
 #include "base/logging.h"
 #include "components/sync/protocol/sharing_sms_fetch_message.pb.h"
+#include "content/public/browser/sms_fetcher.h"
+#include "url/gurl.h"
+#include "url/origin.h"
 
-SmsFetchRequestHandler::SmsFetchRequestHandler() = default;
+SmsFetchRequestHandler::SmsFetchRequestHandler(content::SmsFetcher* fetcher)
+    : fetcher_(fetcher) {}
 
 SmsFetchRequestHandler::~SmsFetchRequestHandler() = default;
 
@@ -15,6 +19,41 @@
     chrome_browser_sharing::SharingMessage message,
     SharingMessageHandler::DoneCallback done_callback) {
   DCHECK(message.has_sms_fetch_request());
-  // TODO(crbug.com/1015645): implementation left pending deliberately.
-  NOTIMPLEMENTED();
+
+  auto origin = url::Origin::Create(GURL(message.sms_fetch_request().origin()));
+  auto request = std::make_unique<Request>(this, fetcher_, origin,
+                                           std::move(done_callback));
+  requests_.insert(std::move(request));
+}
+
+void SmsFetchRequestHandler::RemoveRequest(Request* request) {
+  requests_.erase(request);
+}
+
+SmsFetchRequestHandler::Request::Request(
+    SmsFetchRequestHandler* handler,
+    content::SmsFetcher* fetcher,
+    const url::Origin& origin,
+    SharingMessageHandler::DoneCallback respond_callback)
+    : handler_(handler),
+      fetcher_(fetcher),
+      origin_(origin),
+      respond_callback_(std::move(respond_callback)) {
+  fetcher_->Subscribe(origin_, this);
+}
+
+SmsFetchRequestHandler::Request::~Request() {
+  fetcher_->Unsubscribe(origin_, this);
+}
+
+void SmsFetchRequestHandler::Request::OnReceive(
+    const std::string& one_time_code,
+    const std::string& sms) {
+  auto response = std::make_unique<chrome_browser_sharing::ResponseMessage>();
+  response->mutable_sms_fetch_response()->set_sms(sms);
+  response->mutable_sms_fetch_response()->set_one_time_code(one_time_code);
+
+  std::move(respond_callback_).Run(std::move(response));
+
+  handler_->RemoveRequest(this);
 }
diff --git a/chrome/browser/sharing/sms/sms_fetch_request_handler.h b/chrome/browser/sharing/sms/sms_fetch_request_handler.h
index 92d062c..170c555 100644
--- a/chrome/browser/sharing/sms/sms_fetch_request_handler.h
+++ b/chrome/browser/sharing/sms/sms_fetch_request_handler.h
@@ -5,14 +5,23 @@
 #ifndef CHROME_BROWSER_SHARING_SMS_SMS_FETCH_REQUEST_HANDLER_H_
 #define CHROME_BROWSER_SHARING_SMS_SMS_FETCH_REQUEST_HANDLER_H_
 
+#include "base/bind.h"
+#include "base/containers/flat_set.h"
+#include "base/containers/unique_ptr_adapters.h"
 #include "base/macros.h"
 #include "chrome/browser/sharing/sharing_message_handler.h"
 #include "components/sync/protocol/sharing_message.pb.h"
+#include "content/public/browser/sms_fetcher.h"
+#include "url/origin.h"
+
+namespace content {
+class SmsFetcher;
+}
 
 // Handles incoming messages for the sms fetcher feature.
 class SmsFetchRequestHandler : public SharingMessageHandler {
  public:
-  SmsFetchRequestHandler();
+  explicit SmsFetchRequestHandler(content::SmsFetcher* fetcher);
   ~SmsFetchRequestHandler() override;
 
   // SharingMessageHandler
@@ -20,6 +29,39 @@
                  SharingMessageHandler::DoneCallback done_callback) override;
 
  private:
+  // Request represents an incoming request from a remote SmsService.
+  // It manages subscribing and unsubscribing for SMSes in SmsFetcher and
+  // responding to the callback.
+  // It also lets SmsFetchRequestHandler know when the request is fulfilled
+  // to allow its memory to be freed.
+  class Request : public content::SmsFetcher::Subscriber {
+   public:
+    Request(SmsFetchRequestHandler* handler,
+            content::SmsFetcher* fetcher,
+            const url::Origin& origin,
+            SharingMessageHandler::DoneCallback respond_callback);
+    ~Request() override;
+
+    void OnReceive(const std::string& one_time_code,
+                   const std::string& sms) override;
+
+   private:
+    SmsFetchRequestHandler* handler_;
+    content::SmsFetcher* fetcher_;
+    const url::Origin& origin_;
+    SharingMessageHandler::DoneCallback respond_callback_;
+
+    DISALLOW_COPY_AND_ASSIGN(Request);
+  };
+
+  void RemoveRequest(Request* Request);
+
+  // |fetcher_| is safe because it is owned by BrowserContext, which also
+  // owns (transitively, via SharingService) this class.
+  content::SmsFetcher* fetcher_;
+  base::flat_set<std::unique_ptr<Request>, base::UniquePtrComparator> requests_;
+  base::WeakPtrFactory<SmsFetchRequestHandler> weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(SmsFetchRequestHandler);
 };
 
diff --git a/chrome/browser/sharing/sms/sms_fetch_request_handler_unittest.cc b/chrome/browser/sharing/sms/sms_fetch_request_handler_unittest.cc
new file mode 100644
index 0000000..1193be2
--- /dev/null
+++ b/chrome/browser/sharing/sms/sms_fetch_request_handler_unittest.cc
@@ -0,0 +1,138 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sharing/sms/sms_fetch_request_handler.h"
+
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/sharing/sharing_message_handler.h"
+#include "components/sync/protocol/sharing_message.pb.h"
+#include "content/public/browser/sms_fetcher.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+using base::BindLambdaForTesting;
+using chrome_browser_sharing::ResponseMessage;
+using chrome_browser_sharing::SharingMessage;
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::StrictMock;
+
+namespace {
+
+class MockSmsFetcher : public content::SmsFetcher {
+ public:
+  MockSmsFetcher() = default;
+  ~MockSmsFetcher() = default;
+
+  MOCK_METHOD2(Subscribe,
+               void(const url::Origin& origin, Subscriber* subscriber));
+  MOCK_METHOD2(Unsubscribe,
+               void(const url::Origin& origin, Subscriber* subscriber));
+  MOCK_METHOD0(HasSubscribers, bool());
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockSmsFetcher);
+};
+
+SharingMessage CreateRequest(const std::string& origin) {
+  SharingMessage message;
+  message.mutable_sms_fetch_request()->set_origin(origin);
+  return message;
+}
+
+}  // namespace
+
+TEST(SmsFetchRequestHandlerTest, Basic) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  StrictMock<MockSmsFetcher> fetcher;
+  SmsFetchRequestHandler handler(&fetcher);
+  SharingMessage message = CreateRequest("https://a.com");
+
+  base::RunLoop loop;
+
+  content::SmsFetcher::Subscriber* subscriber;
+  EXPECT_CALL(fetcher, Subscribe(_, _)).WillOnce(SaveArg<1>(&subscriber));
+  EXPECT_CALL(fetcher, Unsubscribe(_, _));
+
+  handler.OnMessage(
+      message,
+      BindLambdaForTesting([&loop](std::unique_ptr<ResponseMessage> response) {
+        EXPECT_TRUE(response->has_sms_fetch_response());
+        EXPECT_EQ("123", response->sms_fetch_response().one_time_code());
+        EXPECT_EQ("hello", response->sms_fetch_response().sms());
+        loop.Quit();
+      }));
+
+  subscriber->OnReceive("123", "hello");
+
+  loop.Run();
+}
+
+TEST(SmsFetchRequestHandlerTest, OutOfOrder) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  StrictMock<MockSmsFetcher> fetcher;
+  SmsFetchRequestHandler handler(&fetcher);
+  SharingMessage message = CreateRequest("https://a.com");
+
+  base::RunLoop loop1;
+
+  content::SmsFetcher::Subscriber* request1;
+  EXPECT_CALL(fetcher, Subscribe(_, _)).WillOnce(SaveArg<1>(&request1));
+  EXPECT_CALL(fetcher, Unsubscribe(_, _)).Times(2);
+
+  handler.OnMessage(
+      message,
+      BindLambdaForTesting([&loop1](std::unique_ptr<ResponseMessage> response) {
+        EXPECT_TRUE(response->has_sms_fetch_response());
+        EXPECT_EQ("first", response->sms_fetch_response().sms());
+        loop1.Quit();
+      }));
+
+  base::RunLoop loop2;
+
+  content::SmsFetcher::Subscriber* request2;
+  EXPECT_CALL(fetcher, Subscribe(_, _)).WillOnce(SaveArg<1>(&request2));
+
+  handler.OnMessage(
+      message,
+      BindLambdaForTesting([&loop2](std::unique_ptr<ResponseMessage> response) {
+        EXPECT_TRUE(response->has_sms_fetch_response());
+        EXPECT_EQ("second", response->sms_fetch_response().sms());
+        loop2.Quit();
+      }));
+
+  request2->OnReceive("2", "second");
+
+  loop2.Run();
+
+  request1->OnReceive("1", "first");
+
+  loop1.Run();
+}
+
+TEST(SmsFetchRequestHandlerTest, HangingRequestUnsubscribedUponDestruction) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  StrictMock<MockSmsFetcher> fetcher;
+
+  SmsFetchRequestHandler handler(&fetcher);
+  SharingMessage message = CreateRequest("https://a.com");
+  content::SmsFetcher::Subscriber* subscriber;
+  EXPECT_CALL(fetcher, Subscribe(_, _)).WillOnce(SaveArg<1>(&subscriber));
+
+  // Expects Unsubscribe to be called when SmsFetchRequestHandler goes out of
+  // scope.
+  EXPECT_CALL(fetcher, Unsubscribe(_, _));
+
+  // Leaves the request deliberately hanging without a response to assert
+  // that it gets cleaned up.
+  handler.OnMessage(
+      message,
+      BindLambdaForTesting([&](std::unique_ptr<ResponseMessage> response) {}));
+}
diff --git a/chrome/browser/sharing/sms/sms_remote_fetcher.cc b/chrome/browser/sharing/sms/sms_remote_fetcher.cc
index 476b6c4..8626913 100644
--- a/chrome/browser/sharing/sms/sms_remote_fetcher.cc
+++ b/chrome/browser/sharing/sms/sms_remote_fetcher.cc
@@ -11,12 +11,18 @@
 #include "chrome/browser/sharing/sms/sms_flags.h"
 #include "components/sync_device_info/device_info.h"
 #include "content/public/browser/browser_context.h"
+#include "url/origin.h"
+
+namespace {
+const uint32_t kDefaultTimeoutSeconds = 60;
+}  // namespace
 
 void FetchRemoteSms(
     content::BrowserContext* context,
     const url::Origin& origin,
     base::OnceCallback<void(base::Optional<std::string>)> callback) {
   if (!base::FeatureList::IsEnabled(kSmsFetchRequestHandler)) {
+    std::move(callback).Run(base::nullopt);
     return;
   }
 
@@ -25,21 +31,39 @@
   SharingService::SharingDeviceList devices =
       sharing_service->GetDeviceCandidates(
           sync_pb::SharingSpecificFields::SMS_FETCHER);
-  for (const std::unique_ptr<syncer::DeviceInfo>& info : devices) {
-    chrome_browser_sharing::SharingMessage sharing_message;
 
-    sharing_service->SendMessageToDevice(
-        info->guid(), kSendMessageTimeout, std::move(sharing_message),
-        base::BindOnce(
-            [](SharingSendMessageResult result,
-               std::unique_ptr<chrome_browser_sharing::ResponseMessage>
-                   response) {
-              // TODO(crbug.com/1015645): implementation pending.
-              NOTIMPLEMENTED();
-            }));
-
-    // Sends to the first device that has the capability enabled.
-    // TODO(crbug.com/1015645): figure out the routing strategy.
-    break;
+  if (devices.empty()) {
+    // No devices available to call.
+    std::move(callback).Run(base::nullopt);
+    return;
   }
+
+  // Sends to the first device that has the capability enabled.
+  // TODO(crbug.com/1015645): figure out the routing strategy, possibly
+  // requiring UX to allow the users to specify the device.
+  const std::unique_ptr<syncer::DeviceInfo>& device = devices.front();
+
+  chrome_browser_sharing::SharingMessage request;
+
+  request.mutable_sms_fetch_request()->set_origin(origin.Serialize());
+
+  sharing_service->SendMessageToDevice(
+      device->guid(), base::TimeDelta::FromSeconds(kDefaultTimeoutSeconds),
+      std::move(request),
+      base::BindOnce(
+          [](base::OnceCallback<void(base::Optional<std::string>)> callback,
+             SharingSendMessageResult result,
+             std::unique_ptr<chrome_browser_sharing::ResponseMessage>
+                 response) {
+            if (result != SharingSendMessageResult::kSuccessful) {
+              std::move(callback).Run(base::nullopt);
+              return;
+            }
+
+            DCHECK(response);
+            DCHECK(response->has_sms_fetch_response());
+
+            std::move(callback).Run(response->sms_fetch_response().sms());
+          },
+          std::move(callback)));
 }
diff --git a/chrome/browser/sharing/sms/sms_remote_fetcher_unittest.cc b/chrome/browser/sharing/sms/sms_remote_fetcher_unittest.cc
new file mode 100644
index 0000000..f83d73c
--- /dev/null
+++ b/chrome/browser/sharing/sms/sms_remote_fetcher_unittest.cc
@@ -0,0 +1,169 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sharing/sms/sms_remote_fetcher.h"
+
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/sharing/mock_sharing_service.h"
+#include "chrome/browser/sharing/sharing_service.h"
+#include "chrome/browser/sharing/sharing_service_factory.h"
+#include "chrome/browser/sharing/sms/sms_flags.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/sync/protocol/sharing_message.pb.h"
+#include "content/public/browser/sms_fetcher.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+using base::BindLambdaForTesting;
+using chrome_browser_sharing::ResponseMessage;
+using chrome_browser_sharing::SharingMessage;
+using ::testing::_;
+using ::testing::ByMove;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::SaveArg;
+
+MockSharingService* CreateSharingService(content::BrowserContext* context) {
+  return static_cast<MockSharingService*>(
+      SharingServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+          context, base::BindRepeating([](content::BrowserContext* context) {
+            return static_cast<std::unique_ptr<KeyedService>>(
+                std::make_unique<MockSharingService>());
+          })));
+}
+
+url::Origin GetOriginForURL(const std::string url) {
+  return url::Origin::Create(GURL(url));
+}
+
+std::unique_ptr<syncer::DeviceInfo> CreateDevice() {
+  return std::make_unique<syncer::DeviceInfo>(
+      "guid1", "name", "chrome_version", "user_agent",
+      sync_pb::SyncEnums_DeviceType_TYPE_PHONE, "device_id",
+      base::SysInfo::HardwareInfo(),
+      /*last_updated_timestamp=*/base::Time::Now(),
+      /*send_tab_to_self_receiving_enabled=*/false,
+      /*sharing_info=*/base::nullopt);
+}
+
+TEST(SmsRemoteFetcherTest, DisabledByDefault) {
+  content::BrowserTaskEnvironment task_environment;
+  TestingProfile profile;
+
+  base::RunLoop loop;
+
+  FetchRemoteSms(
+      &profile, GetOriginForURL("a.com"),
+      BindLambdaForTesting([&loop](base::Optional<std::string> result) {
+        ASSERT_FALSE(result);
+        loop.Quit();
+      }));
+
+  loop.Run();
+}
+
+TEST(SmsRemoteFetcherTest, NoDevicesAvailable) {
+  base::test::ScopedFeatureList flags;
+  content::BrowserTaskEnvironment task_environment;
+  TestingProfile profile;
+
+  flags.InitAndEnableFeature(kSmsFetchRequestHandler);
+
+  MockSharingService* service = CreateSharingService(&profile);
+
+  std::vector<std::unique_ptr<syncer::DeviceInfo>> devices;
+  EXPECT_CALL(*service, GetDeviceCandidates(_))
+      .WillOnce(Return(ByMove(std::move(devices))));
+
+  base::RunLoop loop;
+
+  FetchRemoteSms(
+      &profile, GetOriginForURL("a.com"),
+      BindLambdaForTesting([&loop](base::Optional<std::string> result) {
+        ASSERT_FALSE(result);
+        loop.Quit();
+      }));
+
+  loop.Run();
+}
+
+TEST(SmsRemoteFetcherTest, OneDevice) {
+  base::test::ScopedFeatureList flags;
+  content::BrowserTaskEnvironment task_environment;
+  TestingProfile profile;
+
+  flags.InitAndEnableFeature(kSmsFetchRequestHandler);
+
+  MockSharingService* service = CreateSharingService(&profile);
+
+  std::vector<std::unique_ptr<syncer::DeviceInfo>> devices;
+
+  devices.push_back(CreateDevice());
+
+  EXPECT_CALL(*service, GetDeviceCandidates(_))
+      .WillOnce(Return(ByMove(std::move(devices))));
+  base::RunLoop loop;
+
+  EXPECT_CALL(*service, SendMessageToDevice(_, _, _, _))
+      .WillOnce(Invoke([&](const std::string& device_guid,
+                           base::TimeDelta response_timeout,
+                           chrome_browser_sharing::SharingMessage message,
+                           SharingMessageSender::ResponseCallback callback) {
+        auto response = std::make_unique<ResponseMessage>();
+        response->mutable_sms_fetch_response()->set_sms("hello");
+        std::move(callback).Run(SharingSendMessageResult::kSuccessful,
+                                std::move(response));
+      }));
+
+  FetchRemoteSms(
+      &profile, GetOriginForURL("a.com"),
+      BindLambdaForTesting([&loop](base::Optional<std::string> result) {
+        ASSERT_TRUE(result);
+        ASSERT_EQ("hello", result);
+        loop.Quit();
+      }));
+
+  loop.Run();
+}
+
+TEST(SmsRemoteFetcherTest, OneDeviceTimesOut) {
+  base::test::ScopedFeatureList flags;
+  content::BrowserTaskEnvironment task_environment;
+  TestingProfile profile;
+
+  flags.InitAndEnableFeature(kSmsFetchRequestHandler);
+
+  MockSharingService* service = CreateSharingService(&profile);
+
+  std::vector<std::unique_ptr<syncer::DeviceInfo>> devices;
+
+  devices.push_back(CreateDevice());
+
+  EXPECT_CALL(*service, GetDeviceCandidates(_))
+      .WillOnce(Return(ByMove(std::move(devices))));
+  base::RunLoop loop;
+
+  EXPECT_CALL(*service, SendMessageToDevice(_, _, _, _))
+      .WillOnce(Invoke([&](const std::string& device_guid,
+                           base::TimeDelta response_timeout,
+                           chrome_browser_sharing::SharingMessage message,
+                           SharingMessageSender::ResponseCallback callback) {
+        std::move(callback).Run(SharingSendMessageResult::kAckTimeout,
+                                std::make_unique<ResponseMessage>());
+      }));
+
+  FetchRemoteSms(
+      &profile, GetOriginForURL("a.com"),
+      BindLambdaForTesting([&loop](base::Optional<std::string> result) {
+        ASSERT_FALSE(result);
+        loop.Quit();
+      }));
+
+  loop.Run();
+}
diff --git a/chrome/browser/ui/app_list/search/drive_quick_access_provider.cc b/chrome/browser/ui/app_list/search/drive_quick_access_provider.cc
index e4f003e..5d1e37d 100644
--- a/chrome/browser/ui/app_list/search/drive_quick_access_provider.cc
+++ b/chrome/browser/ui/app_list/search/drive_quick_access_provider.cc
@@ -94,6 +94,7 @@
 
 void DriveQuickAccessProvider::Start(const base::string16& query) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  ClearResultsSilently();
   if (!query.empty())
     return;
 
@@ -102,7 +103,6 @@
       "Apps.AppList.DriveQuickAccessProvider.TimeFromFetchToZeroStateStart",
       base::TimeTicks::Now() - latest_fetch_start_time_);
 
-  ClearResultsSilently();
   // Results are launched via DriveFS, so DriveFS must be mounted.
   bool drive_fs_mounted = drive_service_ && drive_service_->IsMounted();
   LogDriveFSMounted(drive_fs_mounted);
diff --git a/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc b/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
index d996ec13..46c5f7f 100644
--- a/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
+++ b/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
@@ -189,7 +189,7 @@
   size_t node_count = out_update2.nodes.size();
 
   // We should have far more updates this time around.
-  ASSERT_GE(node_count, 8U);
+  EXPECT_GE(node_count, 7U);
 
   int text_field_update_index = -1;
   for (size_t i = 0; i < node_count; ++i) {
diff --git a/chrome/browser/ui/ash/tab_scrubber.cc b/chrome/browser/ui/ash/tab_scrubber.cc
index 1d1c7b7..00996f1 100644
--- a/chrome/browser/ui/ash/tab_scrubber.cc
+++ b/chrome/browser/ui/ash/tab_scrubber.cc
@@ -8,7 +8,6 @@
 
 #include <algorithm>
 
-#include "ash/public/cpp/ash_features.h"
 #include "ash/shell.h"
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
@@ -26,17 +25,6 @@
 #include "ui/events/event_utils.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
 
-namespace {
-
-int GetRequiredNumberOfFingers() {
-  return ash::features::IsVirtualDesksEnabled() &&
-                 ash::features::IsVirtualDesksGesturesEnabled()
-             ? 4
-             : 3;
-}
-
-}  // namespace
-
 // static
 TabScrubber* TabScrubber::GetInstance() {
   static TabScrubber* instance = nullptr;
@@ -79,8 +67,7 @@
   return activate_timer_.IsRunning();
 }
 
-TabScrubber::TabScrubber()
-    : required_finger_count_(GetRequiredNumberOfFingers()) {
+TabScrubber::TabScrubber() {
   // TODO(mash): Add window server API to observe swipe gestures. Observing
   // gestures on browser windows is not sufficient, as this feature works when
   // the cursor is over the shelf, desktop, etc. https://crbug.com/796366
@@ -100,7 +87,7 @@
     return;
   }
 
-  if (event->finger_count() != required_finger_count_)
+  if (event->finger_count() != 3)
     return;
 
   Browser* browser = GetActiveBrowser();
diff --git a/chrome/browser/ui/ash/tab_scrubber.h b/chrome/browser/ui/ash/tab_scrubber.h
index d172624..d425a644 100644
--- a/chrome/browser/ui/ash/tab_scrubber.h
+++ b/chrome/browser/ui/ash/tab_scrubber.h
@@ -76,9 +76,6 @@
 
   void UpdateHighlightedTab(Tab* new_tab, int new_index);
 
-  // The required number of fingers to perform tab scrubbing, which can be
-  // affected by some Virtual Desks flags.
-  const int required_finger_count_;
   // Are we currently scrubbing?.
   bool scrubbing_ = false;
   // The last browser we used for scrubbing, NULL if |scrubbing_| is false and
diff --git a/chrome/browser/ui/ash/tab_scrubber_browsertest.cc b/chrome/browser/ui/ash/tab_scrubber_browsertest.cc
index e811926..74c0fc4 100644
--- a/chrome/browser/ui/ash/tab_scrubber_browsertest.cc
+++ b/chrome/browser/ui/ash/tab_scrubber_browsertest.cc
@@ -8,7 +8,6 @@
 #include <utility>
 
 #include "ash/display/event_transformation_handler.h"
-#include "ash/public/cpp/ash_features.h"
 #include "ash/shell.h"
 #include "base/command_line.h"
 #include "base/macros.h"
@@ -32,12 +31,7 @@
 
 namespace {
 
-int GetFingerCountForScrubbing() {
-  return ash::features::IsVirtualDesksEnabled() &&
-                 ash::features::IsVirtualDesksGesturesEnabled()
-             ? 4
-             : 3;
-}
+constexpr int kScrubbingGestureFingerCount = 3;
 
 // Waits until the immersive mode reveal ends, and therefore the top view of
 // the browser is no longer visible.
@@ -87,8 +81,7 @@
 }  // namespace
 
 class TabScrubberTest : public InProcessBrowserTest,
-                        public TabStripModelObserver,
-                        public ::testing::WithParamInterface<bool> {
+                        public TabStripModelObserver {
  public:
   TabScrubberTest() = default;
 
@@ -97,17 +90,6 @@
   }
 
   // InProcessBrowserTest:
-  void SetUp() override {
-    if (GetParam()) {
-      scoped_feature_list_.InitWithFeatures(
-          /*enabled_features=*/{ash::features::kVirtualDesks,
-                                ash::features::kVirtualDesksGestures},
-          /*disabled_features=*/{});
-    }
-
-    InProcessBrowserTest::SetUp();
-  }
-
   void SetUpOnMainThread() override {
     TabScrubber::GetInstance()->use_default_activation_delay_ = false;
     // Disable external monitor scaling of coordinates.
@@ -173,7 +155,7 @@
                  GetStartX(browser, active_index, direction);
     ui::ScrollEvent scroll_event(ui::ET_SCROLL, gfx::Point(0, 0),
                                  ui::EventTimeForNow(), 0, offset, 0, offset, 0,
-                                 GetFingerCountForScrubbing());
+                                 kScrubbingGestureFingerCount);
     event_generator->Dispatch(&scroll_event);
   }
 
@@ -267,7 +249,7 @@
         : event_generator_(event_generator) {
       ui::ScrollEvent fling_cancel(ui::ET_SCROLL_FLING_CANCEL, gfx::Point(),
                                    time_for_next_event_, 0, 0, 0, 0, 0,
-                                   GetFingerCountForScrubbing());
+                                   kScrubbingGestureFingerCount);
       event_generator->Dispatch(&fling_cancel);
       if (TabScrubber::GetInstance()->IsActivationPending())
         TabScrubber::GetInstance()->FinishScrub(true);
@@ -276,7 +258,7 @@
     ~ScrollGenerator() {
       ui::ScrollEvent fling_start(
           ui::ET_SCROLL_FLING_START, gfx::Point(), time_for_next_event_, 0,
-          last_x_offset_, 0, last_x_offset_, 0, GetFingerCountForScrubbing());
+          last_x_offset_, 0, last_x_offset_, 0, kScrubbingGestureFingerCount);
       event_generator_->Dispatch(&fling_start);
       if (TabScrubber::GetInstance()->IsActivationPending())
         TabScrubber::GetInstance()->FinishScrub(true);
@@ -286,7 +268,7 @@
       time_for_next_event_ += base::TimeDelta::FromMilliseconds(100);
       ui::ScrollEvent scroll(ui::ET_SCROLL, gfx::Point(), time_for_next_event_,
                              0, x_offset, 0, x_offset, 0,
-                             GetFingerCountForScrubbing());
+                             kScrubbingGestureFingerCount);
       last_x_offset_ = x_offset;
       event_generator_->Dispatch(&scroll);
       if (TabScrubber::GetInstance()->IsActivationPending())
@@ -308,13 +290,11 @@
     return std::make_unique<ui::test::EventGenerator>(root, window);
   }
 
-  base::test::ScopedFeatureList scoped_feature_list_;
-
   DISALLOW_COPY_AND_ASSIGN(TabScrubberTest);
 };
 
 // Swipe a single tab in each direction.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, Single) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, Single) {
   AddTabs(browser(), 1);
 
   Scrub(browser(), 0, EACH_TAB);
@@ -329,7 +309,7 @@
 }
 
 // Swipe 4 tabs in each direction. Each of the tabs should become active.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, Multi) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, Multi) {
   AddTabs(browser(), 4);
 
   Scrub(browser(), 0, EACH_TAB);
@@ -349,7 +329,7 @@
   EXPECT_EQ(4, browser()->tab_strip_model()->active_index());
 }
 
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, MultiBrowser) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, MultiBrowser) {
   AddTabs(browser(), 1);
   Scrub(browser(), 0, EACH_TAB);
   EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
@@ -365,7 +345,7 @@
 }
 
 // Tests that tab scrubbing works correctly for a full-screen browser.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, FullScreenBrowser) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, FullScreenBrowser) {
   // Initializes the position of mouse. Makes the mouse away from the tabstrip
   // to prevent any interference on this test.
   ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(
@@ -397,7 +377,7 @@
 
 // Swipe 4 tabs in each direction with an extra swipe within each. The same
 // 4 tabs should become active.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, Repeated) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, Repeated) {
   AddTabs(browser(), 4);
 
   Scrub(browser(), 0, REPEAT_TABS);
@@ -420,7 +400,7 @@
 // Confirm that we get the last tab made active when we skip tabs.
 // These tests have 5 total tabs. We will only received scroll events
 // on tabs 0, 2 and 4.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, Skipped) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, Skipped) {
   AddTabs(browser(), 4);
 
   Scrub(browser(), 0, SKIP_TABS);
@@ -437,7 +417,7 @@
 }
 
 // Confirm that nothing happens when the swipe is small.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, NoChange) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, NoChange) {
   AddTabs(browser(), 1);
 
   SendScrubSequence(browser(), -1, 1);
@@ -448,7 +428,7 @@
 }
 
 // Confirm that very large swipes go to the beginning and and of the tabstrip.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, Bounds) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, Bounds) {
   AddTabs(browser(), 1);
 
   SendScrubSequence(browser(), -10000, 0);
@@ -458,7 +438,7 @@
   EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
 }
 
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, DeleteHighlighted) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, DeleteHighlighted) {
   AddTabs(browser(), 1);
 
   SendScrubEvent(browser(), 0);
@@ -469,7 +449,7 @@
 }
 
 // Delete the currently highlighted tab. Make sure the TabScrubber is aware.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, DeleteBeforeHighlighted) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, DeleteBeforeHighlighted) {
   AddTabs(browser(), 2);
 
   SendScrubEvent(browser(), 1);
@@ -480,7 +460,7 @@
 }
 
 // Move the currently highlighted tab and confirm it gets tracked.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, MoveHighlighted) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, MoveHighlighted) {
   AddTabs(browser(), 1);
 
   SendScrubEvent(browser(), 0);
@@ -493,7 +473,7 @@
 
 // Move a tab to before the highlighted one. Make sure that the highlighted tab
 // index is updated correctly.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, MoveBefore) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, MoveBefore) {
   AddTabs(browser(), 2);
 
   SendScrubEvent(browser(), 1);
@@ -506,7 +486,7 @@
 
 // Move a tab to after the highlighted one. Make sure that the highlighted tab
 // index is updated correctly.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, MoveAfter) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, MoveAfter) {
   AddTabs(browser(), 2);
 
   SendScrubEvent(browser(), 1);
@@ -516,7 +496,7 @@
 }
 
 // Close the browser while an activation is pending.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, CloseBrowser) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, CloseBrowser) {
   AddTabs(browser(), 1);
 
   SendScrubEvent(browser(), 0);
@@ -527,7 +507,7 @@
 
 // In an RTL layout, swipe 4 tabs in each direction. Each of the tabs should
 // become active.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, RTLMulti) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, RTLMulti) {
   base::i18n::SetICUDefaultLocale("ar");
   ASSERT_TRUE(base::i18n::IsRTL());
 
@@ -553,7 +533,7 @@
 // In an RTL layout, confirm that we get the last tab made active when we skip
 // tabs. These tests have 5 total tabs. We will only received scroll events
 // on tabs 0, 2 and 4.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, RTLSkipped) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, RTLSkipped) {
   base::i18n::SetICUDefaultLocale("ar");
   ASSERT_TRUE(base::i18n::IsRTL());
 
@@ -574,7 +554,7 @@
 
 // In an RTL layout, move a tab to before the highlighted one. Make sure that
 // the highlighted tab index is updated correctly.
-IN_PROC_BROWSER_TEST_P(TabScrubberTest, RTLMoveBefore) {
+IN_PROC_BROWSER_TEST_F(TabScrubberTest, RTLMoveBefore) {
   base::i18n::SetICUDefaultLocale("ar");
   ASSERT_TRUE(base::i18n::IsRTL());
 
@@ -587,5 +567,3 @@
   browser()->tab_strip_model()->MoveSelectedTabsTo(2);
   EXPECT_EQ(0, TabScrubber::GetInstance()->highlighted_tab());
 }
-
-INSTANTIATE_TEST_SUITE_P(, TabScrubberTest, ::testing::Bool());
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h
index 696d3066..726cfe7 100644
--- a/chrome/browser/ui/chrome_pages.h
+++ b/chrome/browser/ui/chrome_pages.h
@@ -54,6 +54,7 @@
   kFeedbackSourceSadTabPage,
   kFeedbackSourceSupervisedUserInterstitial,
   kFeedbackSourceAssistant,
+  kFeedbackSourceDesktopTabGroups,
 
   // Must be last.
   kFeedbackSourceCount,
@@ -68,7 +69,7 @@
 
 // ShowFeedbackPage() uses |browser| to determine the URL of the current tab.
 // |browser| should be NULL if there are no currently open browser windows.
-void ShowFeedbackPage(Browser* browser,
+void ShowFeedbackPage(const Browser* browser,
                       FeedbackSource source,
                       const std::string& description_template,
                       const std::string& description_placeholder_text,
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
index 8e203a50..2fe4982 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
@@ -869,7 +869,7 @@
 };
 
 TEST_F(ContentSettingBubbleModelTest, RPHAllow) {
-  ProtocolHandlerRegistry registry(profile(), new FakeDelegate());
+  ProtocolHandlerRegistry registry(profile(), std::make_unique<FakeDelegate>());
   registry.InitProtocolSettings();
 
   const GURL page_url("http://toplevel.example/");
@@ -934,7 +934,7 @@
 }
 
 TEST_F(ContentSettingBubbleModelTest, RPHDefaultDone) {
-  ProtocolHandlerRegistry registry(profile(), new FakeDelegate());
+  ProtocolHandlerRegistry registry(profile(), std::make_unique<FakeDelegate>());
   registry.InitProtocolSettings();
 
   const GURL page_url("http://toplevel.example/");
diff --git a/chrome/browser/ui/layout_constants.cc b/chrome/browser/ui/layout_constants.cc
index 066506c..6aa08f0 100644
--- a/chrome/browser/ui/layout_constants.cc
+++ b/chrome/browser/ui/layout_constants.cc
@@ -71,6 +71,8 @@
       return touch_ui ? 4 : 6;
     case TABSTRIP_TOOLBAR_OVERLAP:
       return 1;
+    case TOOLBAR_BUTTON_HEIGHT:
+      return touch_ui ? 48 : 28;
     case TOOLBAR_ELEMENT_PADDING:
       return touch_ui ? 0 : 4;
     case TOOLBAR_STANDARD_SPACING:
diff --git a/chrome/browser/ui/layout_constants.h b/chrome/browser/ui/layout_constants.h
index d77dcc3..42231b34 100644
--- a/chrome/browser/ui/layout_constants.h
+++ b/chrome/browser/ui/layout_constants.h
@@ -91,6 +91,9 @@
   // non-pixel-aligned drawing goes in.  See https://crbug.com/765723.
   TABSTRIP_TOOLBAR_OVERLAP,
 
+  // The total height, including icons and insets, of buttons in the toolbar.
+  TOOLBAR_BUTTON_HEIGHT,
+
   // Additional horizontal padding between the elements in the toolbar.
   TOOLBAR_ELEMENT_PADDING,
 
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
index 3ebc1285..dd71ba1 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
+++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
@@ -49,6 +49,26 @@
 
 }  // anonymous namespace
 
+class ThumbnailTabHelper::ScopedCapture {
+ public:
+  explicit ScopedCapture(ThumbnailTabHelper* helper) : helper_(helper) {
+    if (helper->web_contents()) {
+      helper->web_contents()->IncrementCapturerCount(gfx::ScaleToFlooredSize(
+          GetMinimumThumbnailSize(), kMinThumbnailScaleFactor));
+      captured_ = true;
+    }
+  }
+
+  ~ScopedCapture() {
+    if (captured_ && helper_->web_contents())
+      helper_->web_contents()->DecrementCapturerCount();
+  }
+
+ private:
+  ThumbnailTabHelper* const helper_;
+  bool captured_ = false;
+};
+
 ThumbnailTabHelper::ThumbnailTabHelper(content::WebContents* contents)
     : content::WebContentsObserver(contents),
       last_visibility_(web_contents()->GetVisibility()) {}
@@ -61,8 +81,13 @@
     bool is_being_observed) {
   if (is_being_observed_ != is_being_observed) {
     is_being_observed_ = is_being_observed;
-    if (is_being_observed && !captured_loaded_thumbnail_since_tab_hidden_)
-      StartVideoCapture();
+    if (is_being_observed && !captured_loaded_thumbnail_since_tab_hidden_) {
+      scoped_capture_ = std::make_unique<ScopedCapture>(this);
+      if (GetView())
+        StartVideoCapture();
+    } else if (!is_being_observed) {
+      scoped_capture_.reset();
+    }
   }
 }
 
@@ -119,6 +144,7 @@
       tab_load_tracker->GetLoadingState(web_contents()) ==
           resource_coordinator::TabLoadTracker::LoadingState::LOADED) {
     captured_loaded_thumbnail_since_tab_hidden_ = true;
+    scoped_capture_.reset();
   }
 }
 
@@ -126,25 +152,19 @@
   if (video_capturer_)
     return;
 
-  // Increment the reference count now. This should (in theory) cause the
-  // creation of a host view, which we'll use below (but see crbug.com/1020782).
-  web_contents()->IncrementCapturerCount(gfx::ScaleToFlooredSize(
-      GetMinimumThumbnailSize(), kMinThumbnailScaleFactor));
+  // This can be triggered by someone starting to observe a web contents by
+  // incrementing its capture count, or it can happen opportunistically when a
+  // renderer is available, because we want to capture thumbnails while we can
+  // before a page is frozen or swapped out.
 
-  // Get the WebContents' main view.
   content::RenderWidgetHostView* const source_view = GetView();
-  if (!source_view) {
-    web_contents()->DecrementCapturerCount();
-    return;
-  }
+  DCHECK(source_view);
 
   // Get the source size and scale.
   const float scale_factor = source_view->GetDeviceScaleFactor();
   const gfx::Size source_size = source_view->GetViewBounds().size();
-  if (source_size.IsEmpty()) {
-    web_contents()->DecrementCapturerCount();
+  if (source_size.IsEmpty())
     return;
-  }
 
   // Figure out how large we want the capture target to be.
   last_frame_capture_info_ =
@@ -166,10 +186,8 @@
 
 void ThumbnailTabHelper::StopVideoCapture() {
   if (video_capturer_) {
-    if (web_contents())
-      web_contents()->DecrementCapturerCount();
     video_capturer_->Stop();
-    video_capturer_ = nullptr;
+    video_capturer_.reset();
   }
 }
 
@@ -194,6 +212,16 @@
     captured_loaded_thumbnail_since_tab_hidden_ = false;
 }
 
+void ThumbnailTabHelper::RenderViewReady() {
+  if (!captured_loaded_thumbnail_since_tab_hidden_)
+    StartVideoCapture();
+}
+
+void ThumbnailTabHelper::RenderViewDeleted(
+    content::RenderViewHost* render_view_host) {
+  StopVideoCapture();
+}
+
 void ThumbnailTabHelper::OnFrameCaptured(
     base::ReadOnlySharedMemoryRegion data,
     ::media::mojom::VideoFrameInfoPtr info,
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
index 5e490614..0ee99e8 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
+++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
@@ -32,6 +32,7 @@
 
  private:
   class ThumanailImageImpl;
+  class ScopedCapture;
   friend class content::WebContentsUserData<ThumbnailTabHelper>;
   friend class ThumanailImageImpl;
 
@@ -70,6 +71,8 @@
   void OnVisibilityChanged(content::Visibility visibility) override;
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
+  void RenderViewReady() override;
+  void RenderViewDeleted(content::RenderViewHost* render_view_host) override;
 
   // viz::mojom::FrameSinkVideoConsumer:
   void OnFrameCaptured(
@@ -122,6 +125,10 @@
   // of the WebContents is incremented/decremented when a capturer is set/unset.
   std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer_;
 
+  // Scoped request for video capture. Ensures we always decrement the counter
+  // once per increment.
+  std::unique_ptr<ScopedCapture> scoped_capture_;
+
   // The thumbnail maintained by this instance.
   scoped_refptr<ThumbnailImage> thumbnail_ =
       base::MakeRefCounted<ThumbnailImage>(this);
diff --git a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc
index c13b615..ebc9310 100644
--- a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc
+++ b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc
@@ -185,6 +185,8 @@
           this,
           base::Bind(&WebUITabStripContainerView::CloseContainer,
                      base::Unretained(this)))) {
+  animation_.SetTweenType(gfx::Tween::Type::FAST_OUT_SLOW_IN);
+
   SetVisible(false);
   // TODO(crbug.com/1010589) WebContents are initially assumed to be visible by
   // default unless explicitly hidden. The WebContents need to be set to hidden
@@ -238,23 +240,20 @@
                                views::MaximumFlexSizeRule::kPreferred)
                                .WithOrder(1));
 
-  // TODO(999557): Correctly configure the size (height, minimum width).
+  // TODO(999557): also update this in response to touch mode changes.
+  const int button_height = GetLayoutConstant(TOOLBAR_BUTTON_HEIGHT);
+  tab_counter->SetMinSize(gfx::Size(button_height, button_height));
+  tab_counter->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_CENTER);
 
   // TODO(999557): Install an inkdrop.
 
   // TODO(999557): Add a roundrect border, like below but more like spec.
   // tab_counter->SetBorder(views::CreateRoundedRectBorder(
-  //     1,
+  //     2,
   //     views::LayoutProvider::Get()->GetCornerRadiusMetric(
   //         views::EMPHASIS_MEDIUM),
   //     gfx::kGoogleGrey300));
 
-  // TODO(999557): I'd like to do this instead of making this be a LabelButton.
-  // But Button is not concrete... ?
-  // tab_counter->SetLayoutManager(std::make_unique<views::FillLayout>());
-  // auto* tab_count_label = tab_counter->AddChildView(
-  //     std::make_unique<views::Label>(base::string16()));*/
-
   tab_counter_model_observer_ =
       std::make_unique<TabCounterModelObserver>(tab_counter.get());
   browser_->tab_strip_model()->AddObserver(tab_counter_model_observer_.get());
@@ -271,8 +270,10 @@
     bool target_visible) {
   if (target_visible) {
     SetVisible(true);
+    animation_.SetSlideDuration(base::TimeDelta::FromMilliseconds(250));
     animation_.Show();
   } else {
+    animation_.SetSlideDuration(base::TimeDelta::FromMilliseconds(200));
     animation_.Hide();
   }
   auto_closer_->set_enabled(target_visible);
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index ec950d3c..8e56d4b0 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -401,7 +401,7 @@
 // LocationBarView, public views::View implementation:
 
 bool LocationBarView::HasFocus() const {
-  return omnibox_view_->model()->has_focus();
+  return omnibox_view_ && omnibox_view_->model()->has_focus();
 }
 
 void LocationBarView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
index 334e4ef..d14a743a 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -491,6 +491,9 @@
   return model_->profile();
 }
 
+const Browser* BrowserTabStripController::GetBrowser() const {
+  return browser();
+}
 ////////////////////////////////////////////////////////////////////////////////
 // BrowserTabStripController, TabStripModelObserver implementation:
 
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
index 4ff9587..665f074 100644
--- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -91,6 +91,7 @@
       BrowserFrameActiveState active_state) const override;
   base::string16 GetAccessibleTabName(const Tab* tab) const override;
   Profile* GetProfile() const override;
+  const Browser* GetBrowser() const override;
 
   // TabStripModelObserver implementation:
   void OnTabStripModelChanged(
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
index 20cd407a..d9f3afef 100644
--- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
+++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
@@ -229,6 +229,10 @@
   return nullptr;
 }
 
+const Browser* FakeBaseTabStripController::GetBrowser() const {
+  return nullptr;
+}
+
 void FakeBaseTabStripController::SetActiveIndex(int new_index) {
   active_index_ = new_index;
   selection_model_.SetSelectedIndex(active_index_);
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
index 26fa3f3e..84403e50 100644
--- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
@@ -75,6 +75,7 @@
       BrowserFrameActiveState active_state) const override;
   base::string16 GetAccessibleTabName(const Tab* tab) const override;
   Profile* GetProfile() const override;
+  const Browser* GetBrowser() const override;
 
  private:
   void SetActiveIndex(int new_index);
diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h
index d7be336c..d4d4f4c 100644
--- a/chrome/browser/ui/views/tabs/tab_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_controller.h
@@ -10,6 +10,7 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/ui_base_types.h"
 
+class Browser;
 class Tab;
 class TabGroupVisualData;
 class TabGroupId;
@@ -198,6 +199,8 @@
 
   virtual void AddNewTabInGroup(TabGroupId group) = 0;
 
+  virtual const Browser* GetBrowser() = 0;
+
  protected:
   virtual ~TabController() {}
 };
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
index 2ea9ad45..8359ccd 100644
--- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
@@ -15,6 +15,7 @@
 #include "base/no_destructor.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_group_visual_data.h"
 #include "chrome/browser/ui/views/bubble_menu_item_factory.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
@@ -41,6 +42,7 @@
 constexpr int TAB_GROUP_HEADER_CXMENU_NEW_TAB_IN_GROUP = 13;
 constexpr int TAB_GROUP_HEADER_CXMENU_UNGROUP = 14;
 constexpr int TAB_GROUP_HEADER_CXMENU_CLOSE_GROUP = 15;
+constexpr int TAB_GROUP_HEADER_CXMENU_FEEDBACK = 16;
 
 // Returns our hard-coded set of colors.
 const std::vector<std::pair<SkColor, base::string16>>& GetColorPickerList() {
@@ -163,6 +165,16 @@
   close_menu_item->SetBorder(views::CreateEmptyBorder(menu_item_border_inset));
   menu_items_container->AddChildView(std::move(close_menu_item));
 
+  menu_items_container->AddChildView(std::make_unique<views::Separator>());
+
+  std::unique_ptr<views::LabelButton> feedback_menu_item = CreateBubbleMenuItem(
+      TAB_GROUP_HEADER_CXMENU_FEEDBACK,
+      l10n_util::GetStringUTF16(IDS_TAB_GROUP_HEADER_CXMENU_SEND_FEEDBACK),
+      &menu_button_listener_);
+  feedback_menu_item->SetBorder(
+      views::CreateEmptyBorder(menu_item_border_inset));
+  menu_items_container->AddChildView(std::move(feedback_menu_item));
+
   views::FlexLayout* menu_layout_manager_ =
       SetLayoutManager(std::make_unique<views::FlexLayout>());
   menu_layout_manager_->SetOrientation(views::LayoutOrientation::kVertical);
@@ -202,7 +214,6 @@
   switch (sender->GetID()) {
     case TAB_GROUP_HEADER_CXMENU_NEW_TAB_IN_GROUP:
       tab_controller_->AddNewTabInGroup(group_);
-
       break;
     case TAB_GROUP_HEADER_CXMENU_UNGROUP:
       anchor_view_->RemoveObserverFromWidget(sender->GetWidget());
@@ -211,6 +222,16 @@
     case TAB_GROUP_HEADER_CXMENU_CLOSE_GROUP:
       tab_controller_->CloseAllTabsInGroup(group_);
       break;
+    case TAB_GROUP_HEADER_CXMENU_FEEDBACK: {
+      const Browser* browser = tab_controller_->GetBrowser();
+      chrome::ShowFeedbackPage(
+          browser, chrome::FeedbackSource::kFeedbackSourceDesktopTabGroups,
+          std::string() /* description_template */,
+          std::string() /* description_placeholder_text */,
+          std::string("DESKTOP_TAB_GROUPS") /* category_tag */,
+          std::string() /* extra_diagnostics */);
+      break;
+    }
     default:
       NOTREACHED();
   }
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index b78d383..a9e2b324 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1951,6 +1951,10 @@
 void TabStrip::AddNewTabInGroup(TabGroupId group) {
   controller_->AddNewTabInGroup(group);
 }
+
+const Browser* TabStrip::GetBrowser() {
+  return controller_->GetBrowser();
+}
 ///////////////////////////////////////////////////////////////////////////////
 // TabStrip, views::AccessiblePaneView overrides:
 
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index 5b9e119b..6c92809 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -42,6 +42,7 @@
 #include "ui/views/view_targeter_delegate.h"
 #include "ui/views/widget/widget_observer.h"
 
+class Browser;
 class NewTabButton;
 class StackedTabStripLayout;
 class Tab;
@@ -297,6 +298,7 @@
   void CloseAllTabsInGroup(TabGroupId group) override;
   void UngroupAllTabsInGroup(TabGroupId group) override;
   void AddNewTabInGroup(TabGroupId group) override;
+  const Browser* GetBrowser() override;
 
   // MouseWatcherListener:
   void MouseMovedOutOfHost() override;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h
index fda59604..dfb8140 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h
@@ -174,6 +174,8 @@
 
   // Returns the profile associated with the Tabstrip.
   virtual Profile* GetProfile() const = 0;
+
+  virtual const Browser* GetBrowser() const = 0;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_TABS_TAB_STRIP_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc
index 7f5e51c..842ce2a 100644
--- a/chrome/browser/ui/views/tabs/tab_unittest.cc
+++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -134,6 +134,8 @@
 
   void AddNewTabInGroup(TabGroupId group) override {}
 
+  const Browser* GetBrowser() override { return nullptr; }
+
   void SetTabColors(SkColor bg_color_active,
                     SkColor fg_color_active,
                     SkColor bg_color_inactive,
diff --git a/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.cc b/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.cc
index b3f6200..a9b5b792 100644
--- a/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.cc
+++ b/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.cc
@@ -23,9 +23,9 @@
   auto* webui = dialog->GetWebUIForTest();
   auto* web_contents = webui->GetWebContents();
   content::WaitForLoadStop(web_contents);
-  web_contents->GetRenderViewHost()->SetWebUIProperty(
+  web_contents->GetMainFrame()->SetWebUIProperty(
       "expectedUrl", chrome::kChromeUIAccountMigrationWelcomeURL);
-  web_contents->GetRenderViewHost()->SetWebUIProperty("expectedEmail",
-                                                      account_email);
+  web_contents->GetMainFrame()->SetWebUIProperty("expectedEmail",
+                                                 account_email);
   SetWebUIInstance(webui);
 }
diff --git a/chrome/browser/ui/webui/constrained_web_dialog_ui.cc b/chrome/browser/ui/webui/constrained_web_dialog_ui.cc
index 12f77178..3a0975b 100644
--- a/chrome/browser/ui/webui/constrained_web_dialog_ui.cc
+++ b/chrome/browser/ui/webui/constrained_web_dialog_ui.cc
@@ -79,14 +79,14 @@
   ui::WebDialogDelegate* dialog_delegate = delegate->GetWebDialogDelegate();
   std::vector<WebUIMessageHandler*> handlers;
   dialog_delegate->GetWebUIMessageHandlers(&handlers);
-  RenderViewHost* render_view_host = render_frame_host->GetRenderViewHost();
-  render_view_host->SetWebUIProperty("dialogArguments",
-                                     dialog_delegate->GetDialogArgs());
+  render_frame_host->SetWebUIProperty("dialogArguments",
+                                      dialog_delegate->GetDialogArgs());
   for (WebUIMessageHandler* handler : handlers) {
     web_ui()->AddMessageHandler(base::WrapUnique(handler));
   }
 
-  dialog_delegate->OnDialogShown(web_ui(), render_view_host);
+  dialog_delegate->OnDialogShown(web_ui(),
+                                 render_frame_host->GetRenderViewHost());
 }
 
 void ConstrainedWebDialogUI::OnDialogCloseMessage(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
index 9edda51b..52d3842a 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -84,7 +84,7 @@
   base::PostTaskAndReplyWithResult(
       FROM_HERE,
       {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
-      base::BindOnce(&GetSettingsOnBlockingPool, printer.id(), basic_info,
+      base::BindOnce(&GetSettingsOnBlockingTaskRunner, printer.id(), basic_info,
                      PrinterSemanticCapsAndDefaults::Papers(),
                      has_secure_protocol, nullptr),
       base::BindOnce(&CapabilitiesFetched, std::move(policies), std::move(cb)));
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
index 84ecb34..b71affa1 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
@@ -76,9 +76,9 @@
     return base::Value();
   }
 
-  return GetSettingsOnBlockingPool(device_name, basic_info, additional_papers,
-                                   /* has_secure_protocol */ false,
-                                   print_backend);
+  return GetSettingsOnBlockingTaskRunner(
+      device_name, basic_info, additional_papers,
+      /* has_secure_protocol */ false, print_backend);
 }
 
 std::string GetDefaultPrinterAsync() {
diff --git a/chrome/browser/vr/speech_recognizer.cc b/chrome/browser/vr/speech_recognizer.cc
index f79f76a..4d53096 100644
--- a/chrome/browser/vr/speech_recognizer.cc
+++ b/chrome/browser/vr/speech_recognizer.cc
@@ -308,8 +308,8 @@
 SpeechRecognizer::~SpeechRecognizer() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (speech_recognizer_on_io_) {
-    content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
-                                       speech_recognizer_on_io_.release());
+    base::DeleteSoon(FROM_HERE, {content::BrowserThread::IO},
+                     speech_recognizer_on_io_.release());
   }
 }
 
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index b21fb05..87a9ad3 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -139,6 +139,7 @@
     "web_app_install_manager_unittest.cc",
     "web_app_install_task_unittest.cc",
     "web_app_registrar_unittest.cc",
+    "web_app_sync_bridge_unittest.cc",
   ]
 
   deps = [
@@ -154,6 +155,7 @@
     "//content/public/browser",
     "//content/test:test_support",
     "//skia",
+    "//testing/gtest",
   ]
 
   if (is_chromeos) {
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.cc b/chrome/browser/web_applications/web_app_sync_bridge.cc
index 6717771f7..37438fac 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge.cc
+++ b/chrome/browser/web_applications/web_app_sync_bridge.cc
@@ -36,6 +36,17 @@
 
 namespace {
 
+bool AreAppsLocallyInstalledByDefault() {
+#if defined(OS_CHROMEOS)
+  // On Chrome OS, sync always locally installs an app.
+  return true;
+#else
+  return false;
+#endif
+}
+
+}  // namespace
+
 std::unique_ptr<syncer::EntityData> CreateSyncEntityData(const WebApp& app) {
   auto entity_data = std::make_unique<syncer::EntityData>();
   entity_data->name = app.name();
@@ -85,17 +96,6 @@
   app->SetSyncData(std::move(parsed_sync_data));
 }
 
-bool AreAppsLocallyInstalledByDefault() {
-#if defined(OS_CHROMEOS)
-  // On Chrome OS, sync always locally installs an app.
-  return true;
-#else
-  return false;
-#endif
-}
-
-}  // namespace
-
 WebAppSyncBridge::WebAppSyncBridge(
     Profile* profile,
     AbstractWebAppDatabaseFactory* database_factory,
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.h b/chrome/browser/web_applications/web_app_sync_bridge.h
index 68fcbeb8..95b8f704 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge.h
+++ b/chrome/browser/web_applications/web_app_sync_bridge.h
@@ -71,6 +71,20 @@
   // An access to read-only registry. Does an upcast to read-only type.
   const WebAppRegistrar& registrar() const { return *registrar_; }
 
+  // syncer::ModelTypeSyncBridge:
+  std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
+      override;
+  base::Optional<syncer::ModelError> MergeSyncData(
+      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+      syncer::EntityChangeList entity_data) override;
+  base::Optional<syncer::ModelError> ApplySyncChanges(
+      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+      syncer::EntityChangeList entity_changes) override;
+  void GetData(StorageKeyList storage_keys, DataCallback callback) override;
+  void GetAllDataForDebugging(DataCallback callback) override;
+  std::string GetClientTag(const syncer::EntityData& entity_data) override;
+  std::string GetStorageKey(const syncer::EntityData& entity_data) override;
+
  private:
   void CheckRegistryUpdateData(const RegistryUpdateData& update_data) const;
 
@@ -101,20 +115,6 @@
   void ApplySyncChangesToRegistrar(
       std::unique_ptr<RegistryUpdateData> update_local_data);
 
-  // syncer::ModelTypeSyncBridge:
-  std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
-      override;
-  base::Optional<syncer::ModelError> MergeSyncData(
-      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
-      syncer::EntityChangeList entity_data) override;
-  base::Optional<syncer::ModelError> ApplySyncChanges(
-      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
-      syncer::EntityChangeList entity_changes) override;
-  void GetData(StorageKeyList storage_keys, DataCallback callback) override;
-  void GetAllDataForDebugging(DataCallback callback) override;
-  std::string GetClientTag(const syncer::EntityData& entity_data) override;
-  std::string GetStorageKey(const syncer::EntityData& entity_data) override;
-
   std::unique_ptr<WebAppDatabase> database_;
   WebAppRegistrarMutable* const registrar_;
   SyncInstallDelegate* const install_delegate_;
@@ -126,6 +126,9 @@
   DISALLOW_COPY_AND_ASSIGN(WebAppSyncBridge);
 };
 
+std::unique_ptr<syncer::EntityData> CreateSyncEntityData(const WebApp& app);
+void ApplySyncDataToApp(const sync_pb::WebAppSpecifics& sync_data, WebApp* app);
+
 }  // namespace web_app
 
 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_SYNC_BRIDGE_H_
diff --git a/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc b/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc
new file mode 100644
index 0000000..31ede9b
--- /dev/null
+++ b/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc
@@ -0,0 +1,201 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/web_app_sync_bridge.h"
+
+#include <memory>
+
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/web_applications/components/web_app_constants.h"
+#include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/test/test_web_app_database_factory.h"
+#include "chrome/browser/web_applications/test/test_web_app_registry_controller.h"
+#include "chrome/browser/web_applications/test/web_app_test.h"
+#include "chrome/browser/web_applications/web_app.h"
+#include "components/sync/model/data_batch.h"
+#include "components/sync/protocol/web_app_specifics.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace web_app {
+
+namespace {
+
+bool IsSyncDataEqual(const WebApp& expected_app,
+                     const syncer::EntityData& entity_data) {
+  if (!entity_data.specifics.has_web_app())
+    return false;
+
+  const GURL sync_launch_url(entity_data.specifics.web_app().launch_url());
+  if (expected_app.app_id() != GenerateAppIdFromURL(sync_launch_url))
+    return false;
+
+  auto app_from_sync = std::make_unique<WebApp>(expected_app.app_id());
+  // ApplySyncDataToApp enforces kSync source on |app_from_sync|.
+  ApplySyncDataToApp(entity_data.specifics.web_app(), app_from_sync.get());
+  return expected_app == *app_from_sync;
+}
+
+bool SyncDataBatchMatchesRegistry(
+    const Registry& registry,
+    std::unique_ptr<syncer::DataBatch> data_batch) {
+  if (!data_batch || !data_batch->HasNext())
+    return false;
+
+  syncer::KeyAndData key_and_data1 = data_batch->Next();
+  if (!IsSyncDataEqual(*registry.at(key_and_data1.first),
+                       *key_and_data1.second)) {
+    return false;
+  }
+
+  if (!data_batch->HasNext())
+    return false;
+
+  syncer::KeyAndData key_and_data2 = data_batch->Next();
+  if (!IsSyncDataEqual(*registry.at(key_and_data2.first),
+                       *key_and_data2.second)) {
+    return false;
+  }
+
+  return !data_batch->HasNext();
+}
+
+}  // namespace
+
+class WebAppSyncBridgeTest : public WebAppTest {
+ public:
+  void SetUp() override {
+    WebAppTest::SetUp();
+
+    test_registry_controller_ =
+        std::make_unique<TestWebAppRegistryController>();
+    test_registry_controller_->SetUp(profile());
+  }
+
+  void TearDown() override {
+    test_registry_controller_.reset();
+
+    WebAppTest::TearDown();
+  }
+
+  void InitSyncBridge() { controller().Init(); }
+
+  std::unique_ptr<WebApp> CreateWebApp(const std::string& url) {
+    const GURL launch_url(url);
+    const AppId app_id = GenerateAppIdFromURL(launch_url);
+
+    auto web_app = std::make_unique<WebApp>(app_id);
+    web_app->SetLaunchUrl(launch_url);
+    web_app->SetUserDisplayMode(DisplayMode::kStandalone);
+    web_app->SetName("Name");
+    return web_app;
+  }
+
+  std::unique_ptr<WebApp> CreateWebAppWithSyncOnlyFields(
+      const std::string& url) {
+    const GURL launch_url(url);
+    const AppId app_id = GenerateAppIdFromURL(launch_url);
+
+    auto web_app = std::make_unique<WebApp>(app_id);
+    web_app->AddSource(Source::kSync);
+    web_app->SetLaunchUrl(launch_url);
+    web_app->SetUserDisplayMode(DisplayMode::kStandalone);
+    return web_app;
+  }
+
+  void InsertAppIntoRegistry(Registry* registry, std::unique_ptr<WebApp> app) {
+    AppId app_id = app->app_id();
+    ASSERT_FALSE(base::Contains(*registry, app_id));
+    registry->emplace(std::move(app_id), std::move(app));
+  }
+
+  void InsertAppCopyIntoRegistry(Registry* registry, const WebApp& app) {
+    registry->emplace(app.app_id(), std::make_unique<WebApp>(app));
+  }
+
+ protected:
+  TestWebAppRegistryController& controller() {
+    return *test_registry_controller_;
+  }
+  syncer::MockModelTypeChangeProcessor& processor() {
+    return controller().processor();
+  }
+  TestWebAppDatabaseFactory& database_factory() {
+    return controller().database_factory();
+  }
+  WebAppSyncBridge& sync_bridge() { return controller().sync_bridge(); }
+
+ private:
+  std::unique_ptr<TestWebAppRegistryController> test_registry_controller_;
+};
+
+TEST_F(WebAppSyncBridgeTest, GetData) {
+  Registry registry;
+
+  std::unique_ptr<WebApp> synced_app1 =
+      CreateWebAppWithSyncOnlyFields("https://example.com/app1/");
+  {
+    WebApp::SyncData sync_data;
+    sync_data.name = "Sync Name";
+    sync_data.theme_color = SK_ColorCYAN;
+    synced_app1->SetSyncData(std::move(sync_data));
+  }
+  InsertAppIntoRegistry(&registry, std::move(synced_app1));
+
+  std::unique_ptr<WebApp> synced_app2 =
+      CreateWebAppWithSyncOnlyFields("https://example.com/app2/");
+  // sync_data is empty for this app.
+  InsertAppIntoRegistry(&registry, std::move(synced_app2));
+
+  std::unique_ptr<WebApp> policy_app = CreateWebApp("https://example.org/");
+  policy_app->AddSource(Source::kPolicy);
+  InsertAppIntoRegistry(&registry, std::move(policy_app));
+
+  database_factory().WriteRegistry(registry);
+
+  EXPECT_CALL(processor(), ModelReadyToSync(testing::_)).Times(1);
+  InitSyncBridge();
+
+  {
+    WebAppSyncBridge::StorageKeyList storage_keys;
+    storage_keys.push_back("unknown");
+    for (const Registry::value_type& id_and_web_app : registry)
+      storage_keys.push_back(id_and_web_app.first);
+
+    base::RunLoop run_loop;
+    sync_bridge().GetData(
+        std::move(storage_keys),
+        base::BindLambdaForTesting(
+            [&](std::unique_ptr<syncer::DataBatch> data_batch) {
+              EXPECT_TRUE(SyncDataBatchMatchesRegistry(registry,
+                                                       std::move(data_batch)));
+              run_loop.Quit();
+            }));
+    run_loop.Run();
+  }
+
+  {
+    base::RunLoop run_loop;
+    sync_bridge().GetAllDataForDebugging(base::BindLambdaForTesting(
+        [&](std::unique_ptr<syncer::DataBatch> data_batch) {
+          EXPECT_TRUE(
+              SyncDataBatchMatchesRegistry(registry, std::move(data_batch)));
+          run_loop.Quit();
+        }));
+    run_loop.Run();
+  }
+}
+
+TEST_F(WebAppSyncBridgeTest, Identities) {
+  std::unique_ptr<WebApp> app =
+      CreateWebAppWithSyncOnlyFields("https://example.com/");
+  std::unique_ptr<syncer::EntityData> entity_data = CreateSyncEntityData(*app);
+
+  EXPECT_EQ(app->app_id(), sync_bridge().GetClientTag(*entity_data));
+  EXPECT_EQ(app->app_id(), sync_bridge().GetStorageKey(*entity_data));
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_components_browsertest.cc b/chrome/browser/web_components_browsertest.cc
index a28ee2a..a3f8dd39 100644
--- a/chrome/browser/web_components_browsertest.cc
+++ b/chrome/browser/web_components_browsertest.cc
@@ -35,21 +35,14 @@
   ui_test_utils::NavigateToURL(browser(), url);
   constexpr char kScript[] =
       R"({
-          let link = document.createElement('link');
-          link.setAttribute('rel','import');
-          let div = document.createElement('div');
-          try { div.createShadowRoot(); } catch {}
-          try { document.registerElement('test-element'); } catch {}
-          const observer = new ReportingObserver((reports, observer) => {
-            var needed = ['HTMLImports','ElementCreateShadowRoot',
-               'DocumentRegisterElement'];
-            for (const report of reports) {
-              needed = needed.filter(item => item !== report.body.id);
-            }
-            var allEnabled = needed.length == 0;
-            window.domAutomationController.send(allEnabled);
-          }, {types: ['deprecation'], buffered: true});
-          observer.observe();
+          const htmlImportsEnabled = 'import' in
+            document.createElement('link');
+          const customElementsV0Enabled = 'registerElement' in document;
+          const shadowDomV0Enabled = 'createShadowRoot' in
+            document.createElement('div');
+          const allEnabled = htmlImportsEnabled && customElementsV0Enabled
+            && shadowDomV0Enabled;
+          window.domAutomationController.send(allEnabled);
          })";
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
diff --git a/chrome/browser/win/conflicts/inspection_results_cache.cc b/chrome/browser/win/conflicts/inspection_results_cache.cc
index 739b0580..181614c 100644
--- a/chrome/browser/win/conflicts/inspection_results_cache.cc
+++ b/chrome/browser/win/conflicts/inspection_results_cache.cc
@@ -10,8 +10,10 @@
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/files/important_file_writer.h"
 #include "base/hash/md5.h"
 #include "base/pickle.h"
+#include "base/strings/string_piece.h"
 
 namespace {
 
@@ -232,6 +234,10 @@
 
   base::Pickle pickle =
       SerializeInspectionResultsCache(inspection_results_cache);
-  return base::WriteFile(file_path, static_cast<const char*>(pickle.data()),
-                         pickle.size()) == static_cast<int>(pickle.size());
+
+  // TODO(1022041): Investigate if using WriteFileAtomically() in a
+  // CONTINUE_ON_SHUTDOWN sequence can cause too many corrupted caches.
+  return base::ImportantFileWriter::WriteFileAtomically(
+      file_path, base::StringPiece(static_cast<const char*>(pickle.data()),
+                                   pickle.size()));
 }
diff --git a/chrome/browser/win/conflicts/module_blacklist_cache_util.cc b/chrome/browser/win/conflicts/module_blacklist_cache_util.cc
index 69a972c5..afa94ea 100644
--- a/chrome/browser/win/conflicts/module_blacklist_cache_util.cc
+++ b/chrome/browser/win/conflicts/module_blacklist_cache_util.cc
@@ -161,6 +161,8 @@
       sizeof(third_party_dlls::PackedListModule) * blacklisted_modules.size());
   file_contents.append(std::begin(md5_digest->a), std::end(md5_digest->a));
 
+  // TODO(1022041): Investigate if using WriteFileAtomically() in a
+  // CONTINUE_ON_SHUTDOWN sequence doesn't cause too many corrupted caches.
   return base::ImportantFileWriter::WriteFileAtomically(
       module_blacklist_cache_path, file_contents);
 }
diff --git a/chrome/browser/win/conflicts/module_database.cc b/chrome/browser/win/conflicts/module_database.cc
index 2a60f2c4d..ed7b841d 100644
--- a/chrome/browser/win/conflicts/module_database.cc
+++ b/chrome/browser/win/conflicts/module_database.cc
@@ -132,7 +132,7 @@
   static base::LazySequencedTaskRunner g_distinct_task_runner =
       LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(
           base::TaskTraits(base::ThreadPool(), base::TaskPriority::BEST_EFFORT,
-                           base::TaskShutdownBehavior::BLOCK_SHUTDOWN));
+                           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
 
   return base::FeatureList::IsEnabled(kDistinctModuleDatabaseSequence)
              ? g_distinct_task_runner.Get()
diff --git a/chrome/browser/win/conflicts/module_inspector.cc b/chrome/browser/win/conflicts/module_inspector.cc
index ea7148b..727e3143 100644
--- a/chrome/browser/win/conflicts/module_inspector.cc
+++ b/chrome/browser/win/conflicts/module_inspector.cc
@@ -91,7 +91,7 @@
       cache_task_runner_(base::CreateSequencedTaskRunner(
           {base::ThreadPool(), base::MayBlock(),
            base::TaskPriority::BEST_EFFORT,
-           base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})),
       inspection_results_cache_read_(false),
       flush_inspection_results_timer_(
           FROM_HERE,
diff --git a/chrome/credential_provider/eventlog/BUILD.gn b/chrome/credential_provider/eventlog/BUILD.gn
index 8f982e64..7b5f120 100644
--- a/chrome/credential_provider/eventlog/BUILD.gn
+++ b/chrome/credential_provider/eventlog/BUILD.gn
@@ -28,7 +28,7 @@
     "gcp_eventlog_provider.cc",
   ]
 
-  if (!is_asan) {
+  if (!is_asan && !use_clang_coverage) {
     no_default_deps = true
     ldflags = [ "/NOENTRY" ]
   }
diff --git a/chrome/services/cups_proxy/BUILD.gn b/chrome/services/cups_proxy/BUILD.gn
index 170ac17a..a8912e54 100644
--- a/chrome/services/cups_proxy/BUILD.gn
+++ b/chrome/services/cups_proxy/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/features.gni")
 import("//printing/buildflags/buildflags.gni")
+import("//testing/test.gni")
 
 assert(is_chromeos, "Non-ChromeOS builds must not depend on this")
 assert(use_cups, "Non-CUPS builds must not depend on this")
@@ -54,7 +55,7 @@
   ]
 }
 
-source_set("unit_tests") {
+test("libcups_unittests") {
   testonly = true
   sources = [
     "ipp_validator_unittest.cc",
@@ -62,16 +63,23 @@
     "socket_manager_unittest.cc",
   ]
 
+  configs += [ "//printing:cups" ]
+
   deps = [
     ":cups_proxy",
     ":test_support",
     "//base",
+    "//base/test:test_support",
+    "//chrome/common",
     "//chrome/services/cups_proxy/public/cpp",
     "//chrome/services/cups_proxy/public/cpp:unit_tests",
+    "//chrome/services/cups_proxy/test:test_support",
+    "//chromeos",
+    "//testing/gmock",
     "//testing/gtest",
   ]
 
   data = [
-    "//chrome/test/data/cups_proxy",
+    "//chrome/services/cups_proxy/test/data",
   ]
 }
diff --git a/chrome/services/cups_proxy/socket_manager_unittest.cc b/chrome/services/cups_proxy/socket_manager_unittest.cc
index 6194d5bd..b4bc162 100644
--- a/chrome/services/cups_proxy/socket_manager_unittest.cc
+++ b/chrome/services/cups_proxy/socket_manager_unittest.cc
@@ -16,6 +16,7 @@
 #include "chrome/services/cups_proxy/fake_cups_proxy_service_delegate.h"
 #include "chrome/services/cups_proxy/public/cpp/type_conversions.h"
 #include "chrome/services/cups_proxy/socket_manager.h"
+#include "chrome/services/cups_proxy/test/paths.h"
 #include "net/base/io_buffer.h"
 #include "net/socket/unix_domain_client_socket_posix.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -23,22 +24,17 @@
 namespace cups_proxy {
 namespace {
 
-// CupsProxy testing data relative path.
-const base::FilePath::CharType kCupsProxyDataDirectory[] =
-    FILE_PATH_LITERAL("cups_proxy");
-
 // Returns base::nullopt on failure.
 base::Optional<std::string> GetTestFile(std::string test_name) {
   base::ScopedAllowBlockingForTesting allow_blocking;
 
   // Build file path.
   base::FilePath path;
-  if (!base::PathService::Get(chrome::DIR_TEST_DATA, &path)) {
+  if (!base::PathService::Get(Paths::DIR_TEST_DATA, &path)) {
     return base::nullopt;
   }
 
-  path = path.Append(kCupsProxyDataDirectory)
-             .Append(FILE_PATH_LITERAL(test_name))
+  path = path.Append(FILE_PATH_LITERAL(test_name))
              .AddExtension(FILE_PATH_LITERAL(".bin"));
 
   // Read in file contents.
diff --git a/chrome/services/cups_proxy/test/BUILD.gn b/chrome/services/cups_proxy/test/BUILD.gn
new file mode 100644
index 0000000..134f5d7
--- /dev/null
+++ b/chrome/services/cups_proxy/test/BUILD.gn
@@ -0,0 +1,29 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+import("//printing/buildflags/buildflags.gni")
+import("//testing/test.gni")
+
+assert(is_chromeos, "Non-ChromeOS builds must not depend on this")
+assert(use_cups, "Non-CUPS builds must not depend on this")
+
+source_set("test_support") {
+  testonly = true
+  sources = [
+    "libcups_test_suite.cc",
+    "libcups_test_suite.h",
+    "paths.cc",
+    "paths.h",
+    "run_all_unittests.cc",
+  ]
+
+  deps = [
+    "//base",
+    "//base/test:test_support",
+    "//mojo/core/embedder",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
diff --git a/chrome/services/cups_proxy/test/DEPS b/chrome/services/cups_proxy/test/DEPS
new file mode 100644
index 0000000..9243dcd6
--- /dev/null
+++ b/chrome/services/cups_proxy/test/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+mojo/core/embedder",
+]
diff --git a/chrome/test/data/cups_proxy/basic_handshake.bin b/chrome/services/cups_proxy/test/data/basic_handshake.bin
similarity index 100%
rename from chrome/test/data/cups_proxy/basic_handshake.bin
rename to chrome/services/cups_proxy/test/data/basic_handshake.bin
Binary files differ
diff --git a/chrome/services/cups_proxy/test/libcups_test_suite.cc b/chrome/services/cups_proxy/test/libcups_test_suite.cc
new file mode 100644
index 0000000..0f9142c33
--- /dev/null
+++ b/chrome/services/cups_proxy/test/libcups_test_suite.cc
@@ -0,0 +1,21 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/services/cups_proxy/test/libcups_test_suite.h"
+
+#include "chrome/services/cups_proxy/test/paths.h"
+
+namespace cups_proxy {
+
+LibCupsTestSuite::LibCupsTestSuite(int argc, char** argv)
+    : base::TestSuite(argc, argv) {}
+
+LibCupsTestSuite::~LibCupsTestSuite() = default;
+
+void LibCupsTestSuite::Initialize() {
+  base::TestSuite::Initialize();
+  Paths::RegisterPathProvider();
+}
+
+}  // namespace cups_proxy
diff --git a/chrome/services/cups_proxy/test/libcups_test_suite.h b/chrome/services/cups_proxy/test/libcups_test_suite.h
new file mode 100644
index 0000000..cf6342f
--- /dev/null
+++ b/chrome/services/cups_proxy/test/libcups_test_suite.h
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_SERVICES_CUPS_PROXY_TEST_LIBCUPS_TEST_SUITE_H_
+#define CHROME_SERVICES_CUPS_PROXY_TEST_LIBCUPS_TEST_SUITE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/test/test_suite.h"
+
+namespace cups_proxy {
+
+class LibCupsTestSuite : public base::TestSuite {
+ public:
+  LibCupsTestSuite(int argc, char** argv);
+  ~LibCupsTestSuite() override;
+
+ protected:
+  // base::TestSuite:
+  void Initialize() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LibCupsTestSuite);
+};
+
+}  // namespace cups_proxy
+
+#endif  // CHROME_SERVICES_CUPS_PROXY_TEST_LIBCUPS_TEST_SUITE_H_
diff --git a/chrome/services/cups_proxy/test/paths.cc b/chrome/services/cups_proxy/test/paths.cc
new file mode 100644
index 0000000..3f9cfa93
--- /dev/null
+++ b/chrome/services/cups_proxy/test/paths.cc
@@ -0,0 +1,44 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/services/cups_proxy/test/paths.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+
+namespace cups_proxy {
+
+bool PathProvider(int key, base::FilePath* result) {
+  base::FilePath cur;
+  switch (key) {
+    // The following are only valid in the development environment, and
+    // will fail if executed from an installed executable (because the
+    // generated path won't exist).
+    case Paths::DIR_TEST_DATA:
+      if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &cur))
+        return false;
+      cur = cur.Append(FILE_PATH_LITERAL("chrome"));
+      cur = cur.Append(FILE_PATH_LITERAL("services"));
+      cur = cur.Append(FILE_PATH_LITERAL("cups_proxy"));
+      cur = cur.Append(FILE_PATH_LITERAL("test"));
+      cur = cur.Append(FILE_PATH_LITERAL("data"));
+      if (!base::PathExists(cur))  // we don't want to create this
+        return false;
+      break;
+    default:
+      return false;
+  }
+
+  *result = cur;
+  return true;
+}
+
+// This cannot be done as a static initializer sadly since Visual Studio will
+// eliminate this object file if there is no direct entry point into it.
+void Paths::RegisterPathProvider() {
+  base::PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
+}
+
+}  // namespace cups_proxy
diff --git a/chrome/services/cups_proxy/test/paths.h b/chrome/services/cups_proxy/test/paths.h
new file mode 100644
index 0000000..05da0ea
--- /dev/null
+++ b/chrome/services/cups_proxy/test/paths.h
@@ -0,0 +1,26 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_SERVICES_CUPS_PROXY_TEST_PATHS_H_
+#define CHROME_SERVICES_CUPS_PROXY_TEST_PATHS_H_
+
+namespace cups_proxy {
+
+class Paths {
+ public:
+  enum {
+    PATH_START = 1000,
+
+    // Valid only in development and testing environments.
+    DIR_TEST_DATA,
+    PATH_END
+  };
+
+  // Call once to register the provider for the path keys defined above.
+  static void RegisterPathProvider();
+};
+
+}  // namespace cups_proxy
+
+#endif  // CHROME_SERVICES_CUPS_PROXY_TEST_PATHS_H_
diff --git a/chrome/services/cups_proxy/test/run_all_unittests.cc b/chrome/services/cups_proxy/test/run_all_unittests.cc
new file mode 100644
index 0000000..c74b0dbb
--- /dev/null
+++ b/chrome/services/cups_proxy/test/run_all_unittests.cc
@@ -0,0 +1,19 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/test/launcher/unit_test_launcher.h"
+#include "build/build_config.h"
+#include "mojo/core/embedder/embedder.h"
+
+#include "chrome/services/cups_proxy/test/libcups_test_suite.h"
+
+int main(int argc, char** argv) {
+  cups_proxy::LibCupsTestSuite test_suite(argc, argv);
+  mojo::core::Init();
+  return base::LaunchUnitTests(argc, argv,
+                               base::Bind(&cups_proxy::LibCupsTestSuite::Run,
+                                          base::Unretained(&test_suite)));
+}
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 4e4c7a0..68ab98d9 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4017,6 +4017,8 @@
       "../browser/sharing/shared_clipboard/shared_clipboard_test_base.h",
       "../browser/sharing/shared_clipboard/shared_clipboard_ui_controller_unittest.cc",
       "../browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc",
+      "../browser/sharing/sms/sms_fetch_request_handler_unittest.cc",
+      "../browser/sharing/sms/sms_remote_fetcher_unittest.cc",
       "../browser/ui/autofill/payments/local_card_migration_bubble_controller_impl_unittest.cc",
       "../browser/ui/autofill/payments/save_card_bubble_controller_impl_unittest.cc",
       "../browser/ui/bluetooth/bluetooth_chooser_controller_unittest.cc",
@@ -4802,9 +4804,6 @@
     data_deps += [ "//testing/buildbot/filters:chromeos_filters" ]
     sources -=
         [ "../browser/policy/cloud/user_policy_signin_service_unittest.cc" ]
-    if (use_cups) {
-      deps += [ "//chrome/services/cups_proxy:unit_tests" ]
-    }
   }
   if (use_x11) {
     deps += [ "//ui/events/devices" ]
diff --git a/chrome/test/data/webui/certificate_viewer_ui_test-inl.h b/chrome/test/data/webui/certificate_viewer_ui_test-inl.h
index ef83f514..f03ff5f 100644
--- a/chrome/test/data/webui/certificate_viewer_ui_test-inl.h
+++ b/chrome/test/data/webui/certificate_viewer_ui_test-inl.h
@@ -47,7 +47,7 @@
   content::WebContents* webui_webcontents = dialog->webui_->GetWebContents();
   content::WaitForLoadStop(webui_webcontents);
   content::WebUI* webui = webui_webcontents->GetWebUI();
-  webui_webcontents->GetRenderViewHost()->SetWebUIProperty(
+  webui_webcontents->GetMainFrame()->SetWebUIProperty(
       "expectedUrl", chrome::kChromeUICertificateViewerURL);
   SetWebUIInstance(webui);
 }
diff --git a/chromecast/base/cast_features.cc b/chromecast/base/cast_features.cc
index 3ebfa6a..790cc22 100644
--- a/chromecast/base/cast_features.cc
+++ b/chromecast/base/cast_features.cc
@@ -153,7 +153,7 @@
 
 // Uses unified IPC QueryableData bindings backend instead of v8 injection.
 const base::Feature kUseQueryableDataBackend{"use_queryable_data_backend",
-                                             base::FEATURE_ENABLED_BY_DEFAULT};
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
 
 const base::Feature kEnableSideGesturePassThrough{
     "enable_side_gesture_pass_through", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromecast/browser/cast_network_contexts.cc b/chromecast/browser/cast_network_contexts.cc
index 5b4a476..68e2fee 100644
--- a/chromecast/browser/cast_network_contexts.cc
+++ b/chromecast/browser/cast_network_contexts.cc
@@ -128,6 +128,7 @@
       network::mojom::URLLoaderFactoryParams::New();
   params->process_id = network::mojom::kBrowserProcessId;
   params->is_corb_enabled = false;
+  params->is_trusted = true;
   GetSystemContext()->CreateURLLoaderFactory(
       system_url_loader_factory_.BindNewPipeAndPassReceiver(),
       std::move(params));
diff --git a/chromecast/browser/webview/web_content_controller.cc b/chromecast/browser/webview/web_content_controller.cc
index 3bab7f8..4717de6b 100644
--- a/chromecast/browser/webview/web_content_controller.cc
+++ b/chromecast/browser/webview/web_content_controller.cc
@@ -394,6 +394,15 @@
   current_render_frame_set_.erase(render_frame_host);
 }
 
+void WebContentController::RenderFrameHostChanged(
+    content::RenderFrameHost* old_host,
+    content::RenderFrameHost* new_host) {
+  // The surface ID may have changed, so trigger a new commit to re-issue the
+  // draw quad.
+  if (surface_)
+    surface_->Commit();
+}
+
 void WebContentController::OnJsClientInstanceRegistered(
     int process_id,
     int routing_id,
diff --git a/chromecast/browser/webview/web_content_controller.h b/chromecast/browser/webview/web_content_controller.h
index 942f099..682bd19 100644
--- a/chromecast/browser/webview/web_content_controller.h
+++ b/chromecast/browser/webview/web_content_controller.h
@@ -89,6 +89,8 @@
   // content::WebContentsObserver
   void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
   void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
+  void RenderFrameHostChanged(content::RenderFrameHost* old_host,
+                              content::RenderFrameHost* new_host) override;
 
   // JsClientInstance::Observer
   void OnJsClientInstanceRegistered(int process_id,
diff --git a/chromecast/graphics/cast_window_tree_host_aura.cc b/chromecast/graphics/cast_window_tree_host_aura.cc
index 82000ec..86627c9b 100644
--- a/chromecast/graphics/cast_window_tree_host_aura.cc
+++ b/chromecast/graphics/cast_window_tree_host_aura.cc
@@ -5,6 +5,7 @@
 #include "chromecast/graphics/cast_window_tree_host_aura.h"
 
 #include "ui/aura/null_window_targeter.h"
+#include "ui/gfx/geometry/size_conversions.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 namespace chromecast {
@@ -33,11 +34,13 @@
 }
 
 gfx::Rect CastWindowTreeHostAura::GetTransformedRootWindowBoundsInPixels(
-    const gfx::Size& host_size_in_pixels) const {
-  gfx::RectF new_bounds(WindowTreeHost::GetTransformedRootWindowBoundsInPixels(
-      host_size_in_pixels));
-  new_bounds.set_origin(gfx::PointF());
-  return gfx::ToEnclosingRect(new_bounds);
+    const gfx::Size& size_in_pixels) const {
+  gfx::RectF new_bounds = gfx::RectF(gfx::Rect(size_in_pixels));
+  GetInverseRootTransform().TransformRect(&new_bounds);
+
+  // Root window origin will be (0,0) except during bounds changes.
+  // Set to exactly zero to avoid rounding issues.
+  return gfx::Rect(gfx::ToCeiledSize(new_bounds.size()));
 }
 
 }  // namespace chromecast
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index 1a0717d..78e1066dc 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -1357,7 +1357,6 @@
   UpdateMediaState();
 }
 
-
 void AssistantManagerServiceImpl::OnPlaybackStateChange(
     const MediaStatus& status) {
   if (media_session_)
diff --git a/chromeos/services/assistant/media_session/assistant_media_session.cc b/chromeos/services/assistant/media_session/assistant_media_session.cc
index 31bbbc9..84c0699d 100644
--- a/chromeos/services/assistant/media_session/assistant_media_session.cc
+++ b/chromeos/services/assistant/media_session/assistant_media_session.cc
@@ -4,7 +4,10 @@
 
 #include "chromeos/services/assistant/media_session/assistant_media_session.h"
 
+#include <utility>
+
 #include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chromeos/services/assistant/assistant_manager_service_impl.h"
 #include "services/media_session/public/cpp/features.h"
@@ -25,7 +28,10 @@
 AssistantMediaSession::AssistantMediaSession(
     mojom::Client* client,
     AssistantManagerServiceImpl* assistant_manager)
-    : assistant_manager_service_(assistant_manager), client_(client) {}
+    : assistant_manager_service_(assistant_manager),
+      client_(client),
+      ducking_observers_(base::MakeRefCounted<
+                         base::ObserverListThreadSafe<DuckingObserver>>()) {}
 
 AssistantMediaSession::~AssistantMediaSession() {
   AbandonAudioFocusIfNeeded();
@@ -52,20 +58,18 @@
   std::move(callback).Run(std::move(info));
 }
 
-// TODO(b/135064564): Update StartDucking() and StopDucking() after volume
-// control API for media streams is implemented.
 void AssistantMediaSession::StartDucking() {
   if (is_ducking_)
     return;
   is_ducking_ = true;
-  Suspend(SuspendType::kSystem);
+  NotifyDucking(FROM_HERE);
 }
 
 void AssistantMediaSession::StopDucking() {
   if (!is_ducking_)
     return;
   is_ducking_ = false;
-  Resume(SuspendType::kSystem);
+  NotifyDucking(FROM_HERE);
 }
 
 void AssistantMediaSession::Suspend(SuspendType suspend_type) {
@@ -133,6 +137,40 @@
   internal_audio_focus_id_ = base::UnguessableToken::Null();
 }
 
+void AssistantMediaSession::NotifyMediaSessionMetadataChanged(
+    const assistant_client::MediaStatus& status) {
+  media_session::MediaMetadata metadata;
+
+  metadata.title = base::UTF8ToUTF16(status.metadata.title);
+  metadata.artist = base::UTF8ToUTF16(status.metadata.artist);
+  metadata.album = base::UTF8ToUTF16(status.metadata.album);
+
+  bool metadata_changed = metadata_ != metadata;
+  if (!metadata_changed)
+    return;
+
+  metadata_ = metadata;
+
+  current_track_ = status.track_type;
+
+  for (auto& observer : observers_)
+    observer->MediaSessionMetadataChanged(this->metadata_);
+}
+
+void AssistantMediaSession::AddDuckingObserver(DuckingObserver* observer) {
+  ducking_observers_->AddObserver(observer);
+  if (is_ducking_)
+    observer->SetDucking(is_ducking_);
+}
+
+void AssistantMediaSession::RemoveDuckingObserver(DuckingObserver* observer) {
+  ducking_observers_->RemoveObserver(observer);
+}
+
+base::WeakPtr<AssistantMediaSession> AssistantMediaSession::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
+
 void AssistantMediaSession::EnsureServiceConnection() {
   DCHECK(base::FeatureList::IsEnabled(
       media_session::features::kMediaSessionService));
@@ -174,26 +212,6 @@
   NotifyMediaSessionInfoChanged();
 }
 
-void AssistantMediaSession::NotifyMediaSessionMetadataChanged(
-    const assistant_client::MediaStatus& status) {
-  media_session::MediaMetadata metadata;
-
-  metadata.title = base::UTF8ToUTF16(status.metadata.title);
-  metadata.artist = base::UTF8ToUTF16(status.metadata.artist);
-  metadata.album = base::UTF8ToUTF16(status.metadata.album);
-
-  bool metadata_changed = metadata_ != metadata;
-  if (!metadata_changed)
-    return;
-
-  metadata_ = metadata;
-
-  current_track_ = status.track_type;
-
-  for (auto& observer : observers_)
-    observer->MediaSessionMetadataChanged(this->metadata_);
-}
-
 media_session::mojom::MediaSessionInfoPtr
 AssistantMediaSession::GetMediaSessionInfoInternal() {
   media_session::mojom::MediaSessionInfoPtr info(
@@ -240,8 +258,10 @@
   return audio_focus_state_ == State::SUSPENDED;
 }
 
-base::WeakPtr<AssistantMediaSession> AssistantMediaSession::GetWeakPtr() {
-  return weak_factory_.GetWeakPtr();
+void AssistantMediaSession::NotifyDucking(const base::Location& location) {
+  ducking_observers_->Notify(
+      location, &AssistantMediaSession::DuckingObserver::SetDucking,
+      is_ducking_);
 }
 
 }  // namespace assistant
diff --git a/chromeos/services/assistant/media_session/assistant_media_session.h b/chromeos/services/assistant/media_session/assistant_media_session.h
index 9705692..defea5e 100644
--- a/chromeos/services/assistant/media_session/assistant_media_session.h
+++ b/chromeos/services/assistant/media_session/assistant_media_session.h
@@ -6,6 +6,8 @@
 #define CHROMEOS_SERVICES_ASSISTANT_MEDIA_SESSION_ASSISTANT_MEDIA_SESSION_H_
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/observer_list_threadsafe.h"
 #include "base/timer/timer.h"
 #include "base/unguessable_token.h"
 #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
@@ -32,6 +34,12 @@
  public:
   enum class State { ACTIVE, SUSPENDED, INACTIVE };
 
+  class DuckingObserver {
+   public:
+    virtual ~DuckingObserver() = default;
+    virtual void SetDucking(bool is_ducking) = 0;
+  };
+
   explicit AssistantMediaSession(
       mojom::Client* client,
       AssistantManagerServiceImpl* assistant_manager);
@@ -49,8 +57,6 @@
       override;
   void PreviousTrack() override {}
   void NextTrack() override {}
-  void NotifyMediaSessionMetadataChanged(
-      const assistant_client::MediaStatus& status);
   void SkipAd() override {}
   void Seek(base::TimeDelta seek_time) override {}
   void Stop(SuspendType suspend_type) override {}
@@ -65,6 +71,12 @@
   void RequestAudioFocus(media_session::mojom::AudioFocusType audio_focus_type);
   void AbandonAudioFocusIfNeeded();
 
+  void NotifyMediaSessionMetadataChanged(
+      const assistant_client::MediaStatus& status);
+
+  void AddDuckingObserver(DuckingObserver* observer);
+  void RemoveDuckingObserver(DuckingObserver* observer);
+
   base::WeakPtr<AssistantMediaSession> GetWeakPtr();
 
   // Returns internal audio focus id.
@@ -98,6 +110,8 @@
   // Returns if the session is currently suspended.
   bool IsSuspended() const;
 
+  void NotifyDucking(const base::Location& from_here);
+
   // The current metadata associated with the current media session.
   media_session::MediaMetadata metadata_;
 
@@ -119,6 +133,9 @@
   // StopDucking().
   bool is_ducking_ = false;
 
+  scoped_refptr<base::ObserverListThreadSafe<DuckingObserver>>
+      ducking_observers_;
+
   // If the media session has acquired audio focus then this will contain a
   // pointer to that requests AudioFocusRequestClient.
   mojo::Remote<media_session::mojom::AudioFocusRequestClient>
diff --git a/chromeos/services/assistant/platform/audio_device_owner.cc b/chromeos/services/assistant/platform/audio_device_owner.cc
index 3943b8f..46d77141a 100644
--- a/chromeos/services/assistant/platform/audio_device_owner.cc
+++ b/chromeos/services/assistant/platform/audio_device_owner.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <utility>
 
+#include "chromeos/services/assistant/media_session/assistant_media_session.h"
 #include "media/audio/audio_device_description.h"
 #include "media/base/limits.h"
 #include "services/media_session/public/mojom/media_session.mojom.h"
@@ -70,13 +71,17 @@
 AudioDeviceOwner::AudioDeviceOwner(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     scoped_refptr<base::SequencedTaskRunner> background_task_runner,
-    const std::string& device_id)
+    const std::string& device_id,
+    AssistantMediaSession* media_session)
     : main_task_runner_(task_runner),
       background_task_runner_(background_task_runner),
-      device_id_(device_id) {}
+      device_id_(device_id),
+      media_session_(media_session) {}
 
 AudioDeviceOwner::~AudioDeviceOwner() {
   DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
+  if (output_device_)
+    media_session_->RemoveDuckingObserver(this);
 }
 
 void AudioDeviceOwner::StartOnMainThread(
@@ -121,20 +126,34 @@
 
 void AudioDeviceOwner::StopOnBackgroundThread() {
   DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  base::AutoLock lock(lock_);
+  media_session_->RemoveDuckingObserver(this);
   output_device_.reset();
-  if (delegate_) {
-    delegate_->OnStopped();
-    delegate_ = nullptr;
+  {
+    base::AutoLock lock(lock_);
+    if (delegate_) {
+      delegate_->OnStopped();
+      delegate_ = nullptr;
+    }
   }
 }
 
+void AudioDeviceOwner::SetDucking(bool is_ducking) {
+  // |output_device_| is only accessed on background thread.
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
+
+  constexpr double kDuckingVolume = 0.2;
+  if (output_device_)
+    output_device_->SetVolume(is_ducking ? kDuckingVolume : 1.0);
+}
+
 void AudioDeviceOwner::StartDeviceOnBackgroundThread(
     mojo::PendingRemote<audio::mojom::StreamFactory> stream_factory) {
   DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
   output_device_ = std::make_unique<audio::OutputDevice>(
       std::move(stream_factory), audio_param_, this, device_id_);
   output_device_->Play();
+
+  media_session_->AddDuckingObserver(this);
 }
 
 int AudioDeviceOwner::Render(base::TimeDelta delay,
diff --git a/chromeos/services/assistant/platform/audio_device_owner.h b/chromeos/services/assistant/platform/audio_device_owner.h
index 5d04752d..4ad2ae8 100644
--- a/chromeos/services/assistant/platform/audio_device_owner.h
+++ b/chromeos/services/assistant/platform/audio_device_owner.h
@@ -11,6 +11,7 @@
 
 #include "base/component_export.h"
 #include "base/macros.h"
+#include "chromeos/services/assistant/media_session/assistant_media_session.h"
 #include "libassistant/shared/public/platform_audio_output.h"
 #include "media/base/audio_block_fifo.h"
 #include "media/base/audio_parameters.h"
@@ -23,12 +24,14 @@
 namespace assistant {
 
 class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioDeviceOwner
-    : public media::AudioRendererSink::RenderCallback {
+    : public media::AudioRendererSink::RenderCallback,
+      AssistantMediaSession::DuckingObserver {
  public:
   AudioDeviceOwner(
       scoped_refptr<base::SequencedTaskRunner> task_runner,
       scoped_refptr<base::SequencedTaskRunner> background_task_runner,
-      const std::string& device_id);
+      const std::string& device_id,
+      AssistantMediaSession* media_session);
   ~AudioDeviceOwner() override;
 
   void StartOnMainThread(
@@ -38,6 +41,9 @@
 
   void StopOnBackgroundThread();
 
+  // AssistantMediaSession::DuckingObserver overrides:
+  void SetDucking(bool is_ducking) override;
+
   // media::AudioRenderSink::RenderCallback overrides:
   int Render(base::TimeDelta delay,
              base::TimeTicks delay_timestamp,
@@ -78,6 +84,8 @@
   assistant_client::OutputStreamFormat format_;
   media::AudioParameters audio_param_;
 
+  AssistantMediaSession* media_session_;
+
   DISALLOW_COPY_AND_ASSIGN(AudioDeviceOwner);
 };
 
diff --git a/chromeos/services/assistant/platform/audio_output_provider_impl.cc b/chromeos/services/assistant/platform/audio_output_provider_impl.cc
index 4b23aba8..066e74b 100644
--- a/chromeos/services/assistant/platform/audio_output_provider_impl.cc
+++ b/chromeos/services/assistant/platform/audio_output_provider_impl.cc
@@ -48,7 +48,8 @@
             std::make_unique<AudioStreamHandler>(task_runner)),
         device_owner_(std::make_unique<AudioDeviceOwner>(task_runner,
                                                          background_task_runner,
-                                                         device_id)) {}
+                                                         device_id,
+                                                         media_session)) {}
 
   ~AudioOutputImpl() override {
     // This ensures that it will be executed after StartOnMainThread.
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc
index ffcd6053..196fd86 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -295,6 +295,10 @@
 
   bool get_unmask_details_returned =
       ready_to_start_authentication_.IsSignaled();
+  bool user_is_opted_in = AuthenticationRequiresUnmaskDetails();
+  bool should_wait_to_authenticate =
+      user_is_opted_in && !get_unmask_details_returned;
+
   // Logging metrics.
 #if !defined(OS_IOS)
   if (should_log_latency_metrics) {
@@ -307,12 +311,14 @@
         GetOrCreateFIDOAuthenticator()->IsUserOptedIn());
   }
 #endif
-  if (AuthenticationRequiresUnmaskDetails() && !get_unmask_details_returned) {
-    // On desktop, shows the verify pending dialog.
+
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
+  // On desktop, show the verify pending dialog for opted-in user.
+  if (user_is_opted_in)
     ShowVerifyPendingDialog();
 #endif
 
+  if (should_wait_to_authenticate) {
     // Wait for |ready_to_start_authentication_| to be signaled by
     // OnDidGetUnmaskDetails() or until timeout before calling Authenticate().
     base::PostTaskAndReplyWithResult(
diff --git a/components/download/internal/common/download_stats.cc b/components/download/internal/common/download_stats.cc
index 90c6c0f..3d52c81 100644
--- a/components/download/internal/common/download_stats.cc
+++ b/components/download/internal/common/download_stats.cc
@@ -471,6 +471,7 @@
     FILE_PATH_LITERAL(".weba"),             // 385
     FILE_PATH_LITERAL(".webm"),             // 386
     FILE_PATH_LITERAL(".xbm"),              // 387
+    FILE_PATH_LITERAL(".accdb"),            // 388
     // NOTE! When you add a type here, please add the UMA value as a comment.
     // These must all match DownloadItem.DangerousFileType in
     // enums.xml. From 263 onward, they should also match
diff --git a/components/metrics/stability_metrics_helper.cc b/components/metrics/stability_metrics_helper.cc
index ab177a2..d110acd 100644
--- a/components/metrics/stability_metrics_helper.cc
+++ b/components/metrics/stability_metrics_helper.cc
@@ -6,6 +6,7 @@
 
 #include <stdint.h>
 
+#include <string>
 #include <vector>
 
 #include "base/logging.h"
@@ -200,6 +201,7 @@
 
 void StabilityMetricsHelper::IncreaseRendererCrashCount() {
   IncrementPrefValue(prefs::kStabilityRendererCrashCount);
+  RecordStabilityEvent(StabilityEventType::kRendererCrash);
 }
 
 void StabilityMetricsHelper::IncreaseGpuCrashCount() {
@@ -229,8 +231,7 @@
   base::RecordAction(base::UserMetricsAction("PageLoad"));
   IncrementPrefValue(prefs::kStabilityPageLoadCount);
   IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount);
-  // We need to save the prefs, as page load count is a critical stat, and it
-  // might be lost due to a crash :-(.
+  RecordStabilityEvent(StabilityEventType::kPageLoad);
 }
 
 void StabilityMetricsHelper::LogRendererCrash(
@@ -252,6 +253,7 @@
         NOTREACHED();
 #endif
         IncrementPrefValue(prefs::kStabilityExtensionRendererCrashCount);
+        RecordStabilityEvent(StabilityEventType::kExtensionCrash);
 
         base::UmaHistogramSparse("CrashExitCodes.Extension",
                                  MapCrashExitCodeForHistogram(exit_code));
@@ -260,7 +262,7 @@
               "Stability.CrashedProcessAge.Extension", uptime.value());
         }
       } else {
-        IncrementPrefValue(prefs::kStabilityRendererCrashCount);
+        IncreaseRendererCrashCount();
 
         base::UmaHistogramSparse("CrashExitCodes.Renderer",
                                  MapCrashExitCodeForHistogram(exit_code));
@@ -350,4 +352,11 @@
   IncrementPrefValue(prefs::kStabilityRendererHangCount);
 }
 
+// static
+void StabilityMetricsHelper::RecordStabilityEvent(
+    StabilityEventType stability_event_type) {
+  UMA_STABILITY_HISTOGRAM_ENUMERATION("Stability.Experimental.Counts",
+                                      stability_event_type);
+}
+
 }  // namespace metrics
diff --git a/components/metrics/stability_metrics_helper.h b/components/metrics/stability_metrics_helper.h
index ec82e02..53ae758 100644
--- a/components/metrics/stability_metrics_helper.h
+++ b/components/metrics/stability_metrics_helper.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_METRICS_STABILITY_METRICS_HELPER_H_
 #define COMPONENTS_METRICS_STABILITY_METRICS_HELPER_H_
 
+#include <string>
+
 #include "base/macros.h"
 #include "base/optional.h"
 #include "base/process/kill.h"
@@ -15,6 +17,18 @@
 
 namespace metrics {
 
+// The values here correspond to values in the Stability message in
+// system_profile.proto. It is intentional that we're only tracking a subset,
+// but more values can get added to this.
+// This must stay 1-1 with the StabilityEventType enum in enums.xml.
+enum class StabilityEventType {
+  kPageLoad = 2,
+  kRendererCrash = 3,
+  kExtensionCrash = 5,
+  kBrowserCrash = 16,
+  kMaxValue = kBrowserCrash
+};
+
 class SystemProfileProto;
 
 // StabilityMetricsHelper is a class that providers functionality common to
@@ -67,6 +81,9 @@
   // platform to use the new data. Server-side currently assumes Android-only.
   void IncreaseGpuCrashCount();
 
+  // Records a histogram for the input |stability_event_type|.
+  static void RecordStabilityEvent(StabilityEventType stability_event_type);
+
  private:
   // Increments an Integer pref value specified by |path|.
   void IncrementPrefValue(const char* path);
diff --git a/components/metrics/stability_metrics_provider.cc b/components/metrics/stability_metrics_provider.cc
index ea8e307..f13597fa 100644
--- a/components/metrics/stability_metrics_provider.cc
+++ b/components/metrics/stability_metrics_provider.cc
@@ -4,9 +4,12 @@
 
 #include "components/metrics/stability_metrics_provider.h"
 
+#include <string>
+
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
 #include "components/metrics/metrics_pref_names.h"
+#include "components/metrics/stability_metrics_helper.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "third_party/metrics_proto/system_profile.pb.h"
@@ -110,54 +113,58 @@
 
   int pref_value = 0;
 
-  if (GetPrefValue(prefs::kStabilityLaunchCount, &pref_value))
+  if (GetAndClearPrefValue(prefs::kStabilityLaunchCount, &pref_value))
     stability->set_launch_count(pref_value);
 
-  if (GetPrefValue(prefs::kStabilityCrashCount, &pref_value))
+  if (GetAndClearPrefValue(prefs::kStabilityCrashCount, &pref_value))
     stability->set_crash_count(pref_value);
 
 #if defined(OS_ANDROID)
-  if (GetPrefValue(prefs::kStabilityCrashCountDueToGmsCoreUpdate,
-                   &pref_value)) {
+  if (GetAndClearPrefValue(prefs::kStabilityCrashCountDueToGmsCoreUpdate,
+                           &pref_value)) {
     stability->set_crash_count_due_to_gms_core_update(pref_value);
   }
 #endif
 
-  if (GetPrefValue(prefs::kStabilityIncompleteSessionEndCount, &pref_value))
+  if (GetAndClearPrefValue(prefs::kStabilityIncompleteSessionEndCount,
+                           &pref_value))
     stability->set_incomplete_shutdown_count(pref_value);
 
-  if (GetPrefValue(prefs::kStabilityBreakpadRegistrationSuccess, &pref_value))
+  if (GetAndClearPrefValue(prefs::kStabilityBreakpadRegistrationSuccess,
+                           &pref_value))
     stability->set_breakpad_registration_success_count(pref_value);
 
-  if (GetPrefValue(prefs::kStabilityBreakpadRegistrationFail, &pref_value))
+  if (GetAndClearPrefValue(prefs::kStabilityBreakpadRegistrationFail,
+                           &pref_value))
     stability->set_breakpad_registration_failure_count(pref_value);
 
-  if (GetPrefValue(prefs::kStabilityDebuggerPresent, &pref_value))
+  if (GetAndClearPrefValue(prefs::kStabilityDebuggerPresent, &pref_value))
     stability->set_debugger_present_count(pref_value);
 
-  if (GetPrefValue(prefs::kStabilityDebuggerNotPresent, &pref_value))
+  if (GetAndClearPrefValue(prefs::kStabilityDebuggerNotPresent, &pref_value))
     stability->set_debugger_not_present_count(pref_value);
 
   // Note: only logging the following histograms for non-zero values.
-  if (GetPrefValue(prefs::kStabilityDeferredCount, &pref_value)) {
+  if (GetAndClearPrefValue(prefs::kStabilityDeferredCount, &pref_value)) {
     UMA_STABILITY_HISTOGRAM_COUNTS_100(
         "Stability.Internals.InitialStabilityLogDeferredCount", pref_value);
   }
 
   // Note: only logging the following histograms for non-zero values.
-  if (GetPrefValue(prefs::kStabilityDiscardCount, &pref_value)) {
+  if (GetAndClearPrefValue(prefs::kStabilityDiscardCount, &pref_value)) {
     UMA_STABILITY_HISTOGRAM_COUNTS_100("Stability.Internals.DataDiscardCount",
                                        pref_value);
   }
 
   // Note: only logging the following histograms for non-zero values.
-  if (GetPrefValue(prefs::kStabilityVersionMismatchCount, &pref_value)) {
+  if (GetAndClearPrefValue(prefs::kStabilityVersionMismatchCount,
+                           &pref_value)) {
     UMA_STABILITY_HISTOGRAM_COUNTS_100(
         "Stability.Internals.VersionMismatchCount", pref_value);
   }
 
 #if defined(OS_WIN)
-  if (GetPrefValue(prefs::kStabilitySystemCrashCount, &pref_value)) {
+  if (GetAndClearPrefValue(prefs::kStabilitySystemCrashCount, &pref_value)) {
     UMA_STABILITY_HISTOGRAM_COUNTS_100("Stability.Internals.SystemCrashCount",
                                        pref_value);
   }
@@ -198,12 +205,12 @@
   // specific bucket for crashes caused by GMS Core updates.
   if (HasGmsCoreVersionChanged(local_state_)) {
     IncrementPrefValue(prefs::kStabilityCrashCountDueToGmsCoreUpdate);
-  } else {
-    IncrementPrefValue(prefs::kStabilityCrashCount);
+    return;
   }
-#else
-  IncrementPrefValue(prefs::kStabilityCrashCount);
 #endif
+  IncrementPrefValue(prefs::kStabilityCrashCount);
+  StabilityMetricsHelper::RecordStabilityEvent(
+      StabilityEventType::kBrowserCrash);
 
 #if defined(OS_WIN)
   MaybeLogSystemCrash(last_live_timestamp);
@@ -259,7 +266,8 @@
   local_state_->SetInteger(path, value + 1);
 }
 
-int StabilityMetricsProvider::GetPrefValue(const char* path, int* value) {
+int StabilityMetricsProvider::GetAndClearPrefValue(const char* path,
+                                                   int* value) {
   *value = local_state_->GetInteger(path);
   if (*value != 0)
     local_state_->SetInteger(path, 0);
diff --git a/components/metrics/stability_metrics_provider.h b/components/metrics/stability_metrics_provider.h
index 3aeff631..65cde34 100644
--- a/components/metrics/stability_metrics_provider.h
+++ b/components/metrics/stability_metrics_provider.h
@@ -19,7 +19,7 @@
 // Stores and loads system information to prefs for stability logs.
 class StabilityMetricsProvider : public MetricsProvider {
  public:
-  StabilityMetricsProvider(PrefService* local_state);
+  explicit StabilityMetricsProvider(PrefService* local_state);
   ~StabilityMetricsProvider() override;
 
   static void RegisterPrefs(PrefRegistrySimple* registry);
@@ -49,7 +49,7 @@
   void IncrementPrefValue(const char* path);
 
   // Gets pref value specified by |path| and resets it to 0 after retrieving.
-  int GetPrefValue(const char* path, int* value);
+  int GetAndClearPrefValue(const char* path, int* value);
 
   // MetricsProvider:
   void Init() override;
diff --git a/components/optimization_guide/optimization_guide_decider.h b/components/optimization_guide/optimization_guide_decider.h
index a38abba..943362df 100644
--- a/components/optimization_guide/optimization_guide_decider.h
+++ b/components/optimization_guide/optimization_guide_decider.h
@@ -46,10 +46,23 @@
       const std::vector<proto::OptimizationType>& optimization_types,
       const std::vector<proto::OptimizationTarget>& optimization_targets) = 0;
 
+  // Returns whether the current conditions match |optimization_target|.
+  virtual OptimizationGuideDecision ShouldTargetNavigation(
+      content::NavigationHandle* navigation_handle,
+      proto::OptimizationTarget optimization_target) = 0;
+
+  // Returns whether |optimization_type| can be applied for the URL associated
+  // with |navigation_handle|.
+  virtual OptimizationGuideDecision CanApplyOptimization(
+      content::NavigationHandle* navigation_handle,
+      proto::OptimizationType optimization_type,
+      OptimizationMetadata* optimization_metadata) = 0;
+
   // Returns whether the current conditions match |optimization_target| and
   // |optimization_type| can be applied for the URL associated with
   // |navigation_handle|.
-  virtual OptimizationGuideDecision CanApplyOptimization(
+  virtual OptimizationGuideDecision
+  ShouldTargetNavigationAndCanApplyOptimization(
       content::NavigationHandle* navigation_handle,
       proto::OptimizationTarget optimization_target,
       proto::OptimizationType optimization_type,
diff --git a/components/paint_preview/browser/BUILD.gn b/components/paint_preview/browser/BUILD.gn
index 3b72df9..19b85e2 100644
--- a/components/paint_preview/browser/BUILD.gn
+++ b/components/paint_preview/browser/BUILD.gn
@@ -16,6 +16,7 @@
     deps = [
       "//base",
       "//cc/base",
+      "//third_party/zlib/google:zip",
       "//ui/gfx/geometry",
       "//url",
     ]
diff --git a/components/paint_preview/browser/DEPS b/components/paint_preview/browser/DEPS
index 32302be..eca036b 100644
--- a/components/paint_preview/browser/DEPS
+++ b/components/paint_preview/browser/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
   "+cc/base",
+  "+third_party/zlib/google",
 ]
diff --git a/components/paint_preview/browser/file_manager.cc b/components/paint_preview/browser/file_manager.cc
index 272cc601..f209f89 100644
--- a/components/paint_preview/browser/file_manager.cc
+++ b/components/paint_preview/browser/file_manager.cc
@@ -9,12 +9,13 @@
 #include "base/hash/hash.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
+#include "third_party/zlib/google/zip.h"
 
 namespace paint_preview {
 
 namespace {
 
-constexpr char kPaintPreviewDirname[] = "paint_preview";
+constexpr char kZipExt[] = ".zip";
 
 std::string HashToHex(const GURL& url) {
   uint32_t hash = base::PersistentHash(url.spec());
@@ -24,73 +25,145 @@
 }  // namespace
 
 FileManager::FileManager(const base::FilePath& root_directory)
-    : root_directory_(root_directory.AppendASCII(kPaintPreviewDirname)) {}
+    : root_directory_(root_directory) {}
 FileManager::~FileManager() = default;
 
 size_t FileManager::GetSizeOfArtifactsFor(const GURL& url) {
-  return base::ComputeDirectorySize(
-      root_directory_.AppendASCII(HashToHex(url)));
+  base::FilePath path;
+  StorageType storage_type = GetPathForUrl(url, &path);
+  switch (storage_type) {
+    case kDirectory: {
+      return base::ComputeDirectorySize(
+          root_directory_.AppendASCII(HashToHex(url)));
+    }
+    case kZip: {
+      int64_t file_size = 0;
+      if (!base::GetFileSize(path, &file_size) || file_size < 0)
+        return 0;
+      return file_size;
+    }
+    case kNone:  // fallthrough
+    default:
+      return 0;
+  }
 }
 
 bool FileManager::GetCreatedTime(const GURL& url, base::Time* created_time) {
+  base::FilePath path;
+  StorageType storage_type = GetPathForUrl(url, &path);
+  if (storage_type == FileManager::StorageType::kNone)
+    return false;
   base::File::Info info;
-  if (!base::GetFileInfo(root_directory_.AppendASCII(HashToHex(url)), &info))
+  if (!base::GetFileInfo(path, &info))
     return false;
   *created_time = info.creation_time;
   return true;
 }
 
-bool FileManager::GetLastAccessedTime(const GURL& url,
-                                      base::Time* last_accessed_time) {
-  return LastAccessedTimeInternal(root_directory_.AppendASCII(HashToHex(url)),
-                                  last_accessed_time);
+bool FileManager::GetLastModifiedTime(const GURL& url,
+                                      base::Time* last_modified_time) {
+  base::FilePath path;
+  StorageType storage_type = GetPathForUrl(url, &path);
+  if (storage_type == FileManager::StorageType::kNone)
+    return false;
+  base::File::Info info;
+  if (!base::GetFileInfo(path, &info))
+    return false;
+  *last_modified_time = info.last_modified;
+  return true;
 }
 
 bool FileManager::CreateOrGetDirectoryFor(const GURL& url,
                                           base::FilePath* directory) {
-  base::FilePath path = root_directory_.AppendASCII(HashToHex(url));
-  base::File::Error error = base::File::FILE_OK;
-  if (base::CreateDirectoryAndGetError(path, &error)) {
-    *directory = path;
-    return true;
+  base::FilePath path;
+  StorageType storage_type = GetPathForUrl(url, &path);
+  switch (storage_type) {
+    case kNone: {
+      base::FilePath new_path = root_directory_.AppendASCII(HashToHex(url));
+      base::File::Error error = base::File::FILE_OK;
+      if (base::CreateDirectoryAndGetError(new_path, &error)) {
+        *directory = new_path;
+        return true;
+      }
+      DVLOG(1) << "ERROR: failed to create directory: " << path
+               << " with error code " << error;
+      return false;
+    }
+    case kDirectory: {
+      *directory = path;
+      return true;
+    }
+    case kZip: {
+      base::FilePath dst_path = root_directory_.AppendASCII(HashToHex(url));
+      base::File::Error error = base::File::FILE_OK;
+      if (!base::CreateDirectoryAndGetError(dst_path, &error)) {
+        DVLOG(1) << "ERROR: failed to create directory: " << path
+                 << " with error code " << error;
+        return false;
+      }
+      if (!zip::Unzip(path, dst_path)) {
+        DVLOG(1) << "ERROR: failed to unzip: " << path << " to " << dst_path;
+        return false;
+      }
+      base::DeleteFile(path, true);
+      *directory = dst_path;
+      return true;
+    }
+    default:
+      return false;
   }
-  DLOG(ERROR) << "Error failed to create directory: " << path
-              << " with error code " << error;
-  return false;
+}
+
+bool FileManager::CompressDirectoryFor(const GURL& url) {
+  base::FilePath path;
+  StorageType storage_type = GetPathForUrl(url, &path);
+  switch (storage_type) {
+    case kDirectory: {
+      // If there are no files in the directory, zip will succeed, but unzip
+      // will not. Thus don't compress since there is no point.
+      if (!base::ComputeDirectorySize(path))
+        return false;
+      base::FilePath dst_path = path.AddExtensionASCII(kZipExt);
+      if (!zip::Zip(path, dst_path, /* hidden files */ true))
+        return false;
+      base::DeleteFile(path, true);
+      return true;
+    }
+    case kZip:
+      return true;
+    case kNone:  // fallthrough
+    default:
+      return false;
+  }
 }
 
 void FileManager::DeleteArtifactsFor(const std::vector<GURL>& urls) {
-  for (const auto& url : urls)
-    base::DeleteFileRecursively(root_directory_.AppendASCII(HashToHex(url)));
+  for (const auto& url : urls) {
+    base::FilePath path;
+    StorageType storage_type = GetPathForUrl(url, &path);
+    if (storage_type == FileManager::StorageType::kNone)
+      continue;
+    base::DeleteFile(path, true);
+  }
 }
 
 void FileManager::DeleteAll() {
   base::DeleteFileRecursively(root_directory_);
 }
 
-void FileManager::DeleteAllOlderThan(base::Time deletion_time) {
-  std::vector<base::FilePath> dirs_to_delete;
-  base::FileEnumerator enumerator(root_directory_, false,
-                                  base::FileEnumerator::DIRECTORIES);
-  base::Time last_accessed_time;
-  for (base::FilePath dir = enumerator.Next(); !dir.empty();
-       dir = enumerator.Next()) {
-    if (!LastAccessedTimeInternal(dir, &last_accessed_time))
-      continue;
-    if (last_accessed_time < deletion_time)
-      dirs_to_delete.push_back(dir);
+FileManager::StorageType FileManager::GetPathForUrl(const GURL& url,
+                                                    base::FilePath* path) {
+  base::FilePath directory_path = root_directory_.AppendASCII(HashToHex(url));
+  if (base::PathExists(directory_path)) {
+    *path = directory_path;
+    return kDirectory;
   }
-  for (const auto& dir : dirs_to_delete)
-    base::DeleteFileRecursively(dir);
-}
-
-bool FileManager::LastAccessedTimeInternal(const base::FilePath& path,
-                                           base::Time* last_accessed_time) {
-  base::File::Info info;
-  if (!base::GetFileInfo(path, &info))
-    return false;
-  *last_accessed_time = info.last_accessed;
-  return true;
+  base::FilePath zip_path = directory_path.AddExtensionASCII(kZipExt);
+  if (base::PathExists(zip_path)) {
+    *path = zip_path;
+    return kZip;
+  }
+  return kNone;
 }
 
 }  // namespace paint_preview
diff --git a/components/paint_preview/browser/file_manager.h b/components/paint_preview/browser/file_manager.h
index c0e4d395..81b42b0e 100644
--- a/components/paint_preview/browser/file_manager.h
+++ b/components/paint_preview/browser/file_manager.h
@@ -16,33 +16,42 @@
 // user profile).
 class FileManager {
  public:
-  // Create a file manager for |root_directory|/paint_previews
+  // Create a file manager for |root_directory|. Top level items in
+  // |root_directoy| should be exclusively managed by this class. Items within
+  // the subdirectories it creates can be freely modified.
   explicit FileManager(const base::FilePath& root_directory);
   ~FileManager();
 
   // Get statistics about the time of creation and size of artifacts.
   size_t GetSizeOfArtifactsFor(const GURL& url);
   bool GetCreatedTime(const GURL& url, base::Time* created_time);
-  bool GetLastAccessedTime(const GURL& url, base::Time* last_accessed_time);
+  bool GetLastModifiedTime(const GURL& url, base::Time* last_modified_time);
 
-  // Creates or gets a subdirectory under |root_directory|/paint_previews/
-  // for |url| and assigns it to |directory|. Returns true and modifies
-  // |directory| on success.
+  // Creates or gets a subdirectory under |root_directory|/ for |url| and
+  // assigns it to |directory|. Returns true on success. If the directory was
+  // compressed then it is uncompressed automatically.
   bool CreateOrGetDirectoryFor(const GURL& url, base::FilePath* directory);
 
+  // Compresses the directory associated with |url|. Returns true on success or
+  // if the directory was already compressed.
+  // NOTE: an empty directory or a directory containing only empty
+  // files/directories will not compress.
+  bool CompressDirectoryFor(const GURL& url);
+
   // Deletes artifacts associated with |urls|.
   void DeleteArtifactsFor(const std::vector<GURL>& urls);
 
   // Deletes all stored paint previews stored in the |profile_directory_|.
   void DeleteAll();
 
-  // Deletes all captures with access times older than |deletion_time|. Slow and
-  // blocking as it relies on base::FileEnumerator.
-  void DeleteAllOlderThan(base::Time deletion_time);
-
  private:
-  bool LastAccessedTimeInternal(const base::FilePath& path,
-                                base::Time* last_accessed_time);
+  enum StorageType {
+    kNone = 0,
+    kDirectory = 1,
+    kZip = 2,
+  };
+
+  StorageType GetPathForUrl(const GURL& url, base::FilePath* path);
 
   base::FilePath root_directory_;
 
diff --git a/components/paint_preview/browser/file_manager_unittest.cc b/components/paint_preview/browser/file_manager_unittest.cc
index 31f0b01..d90b9e2 100644
--- a/components/paint_preview/browser/file_manager_unittest.cc
+++ b/components/paint_preview/browser/file_manager_unittest.cc
@@ -18,17 +18,19 @@
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   FileManager manager(temp_dir.GetPath());
   GURL url("https://www.chromium.org");
+  GURL missing_url("https://www.muimorhc.org");
   base::FilePath directory;
   EXPECT_TRUE(manager.CreateOrGetDirectoryFor(url, &directory));
   EXPECT_FALSE(directory.empty());
 
   base::Time created_time;
+  EXPECT_FALSE(manager.GetCreatedTime(missing_url, &created_time));
   EXPECT_TRUE(manager.GetCreatedTime(url, &created_time));
 
   base::TouchFile(directory, now - base::TimeDelta::FromSeconds(1),
                   now - base::TimeDelta::FromSeconds(1));
   base::Time accessed_time;
-  EXPECT_TRUE(manager.GetLastAccessedTime(url, &accessed_time));
+  EXPECT_TRUE(manager.GetLastModifiedTime(url, &accessed_time));
   base::FilePath proto_path = directory.AppendASCII("paint_preview.pb");
   base::File file(proto_path,
                   base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
@@ -39,7 +41,8 @@
   base::TouchFile(directory, now + base::TimeDelta::FromSeconds(1),
                   now + base::TimeDelta::FromSeconds(1));
   base::Time later_accessed_time;
-  EXPECT_TRUE(manager.GetLastAccessedTime(url, &later_accessed_time));
+  EXPECT_FALSE(manager.GetLastModifiedTime(missing_url, &created_time));
+  EXPECT_TRUE(manager.GetLastModifiedTime(url, &later_accessed_time));
   EXPECT_GT(later_accessed_time, accessed_time);
 
   EXPECT_GE(manager.GetSizeOfArtifactsFor(url), kSize);
@@ -50,39 +53,113 @@
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   FileManager manager(temp_dir.GetPath());
   GURL url("https://www.chromium.org");
+
+  // Create a new directory.
   base::FilePath new_directory;
   EXPECT_TRUE(manager.CreateOrGetDirectoryFor(url, &new_directory));
   EXPECT_FALSE(new_directory.empty());
   EXPECT_TRUE(base::PathExists(new_directory));
-  base::FilePath old_directory;
-  EXPECT_TRUE(manager.CreateOrGetDirectoryFor(url, &old_directory));
-  EXPECT_FALSE(old_directory.empty());
-  EXPECT_EQ(old_directory, new_directory);
-  EXPECT_TRUE(base::PathExists(old_directory));
+
+  // Open an existing directory.
+  base::FilePath existing_directory;
+  EXPECT_TRUE(manager.CreateOrGetDirectoryFor(url, &existing_directory));
+  EXPECT_FALSE(existing_directory.empty());
+  EXPECT_EQ(existing_directory, new_directory);
+  EXPECT_TRUE(base::PathExists(existing_directory));
+
+  // A file needs to exist for compression to work.
+  base::FilePath test_file_path = existing_directory.AppendASCII("foo.txt");
+  {
+    base::File file(test_file_path,
+                    base::File::FLAG_CREATE | base::File::FLAG_WRITE);
+    const std::string data = "foobarbaz";
+    file.WriteAtCurrentPos(data.data(), data.size());
+  }
+  EXPECT_TRUE(base::PathExists(test_file_path));
+  base::FilePath test_file_path_empty =
+      existing_directory.AppendASCII("bar.txt");
+  {
+    base::File file(test_file_path_empty,
+                    base::File::FLAG_CREATE | base::File::FLAG_WRITE);
+  }
+  EXPECT_TRUE(base::PathExists(test_file_path_empty));
+
+  // Compress.
+  base::FilePath zip_path = existing_directory.AddExtensionASCII(".zip");
+  EXPECT_TRUE(manager.CompressDirectoryFor(url));
+  EXPECT_FALSE(base::PathExists(existing_directory));
+  EXPECT_FALSE(base::PathExists(test_file_path));
+  EXPECT_FALSE(base::PathExists(test_file_path_empty));
+  EXPECT_TRUE(base::PathExists(zip_path));
+  EXPECT_GT(manager.GetSizeOfArtifactsFor(url), 0U);
+  existing_directory.clear();
+
+  // Open a compressed file.
+  EXPECT_TRUE(manager.CreateOrGetDirectoryFor(url, &existing_directory));
+  EXPECT_EQ(existing_directory, new_directory);
+  EXPECT_TRUE(base::PathExists(existing_directory));
+  EXPECT_TRUE(base::PathExists(test_file_path));
+  EXPECT_TRUE(base::PathExists(test_file_path_empty));
+  EXPECT_FALSE(base::PathExists(zip_path));
+}
+
+TEST(FileManagerTest, TestCompressDirectory) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  FileManager manager(temp_dir.GetPath());
+  GURL url("https://www.chromium.org");
+
+  base::FilePath new_directory;
+  EXPECT_TRUE(manager.CreateOrGetDirectoryFor(url, &new_directory));
+  EXPECT_FALSE(new_directory.empty());
+  EXPECT_TRUE(base::PathExists(new_directory));
+
+  // Compression fails without valid contents.
+  base::FilePath zip_path = new_directory.AddExtensionASCII(".zip");
+  EXPECT_FALSE(manager.CompressDirectoryFor(url));
+  EXPECT_TRUE(base::PathExists(new_directory));
+  EXPECT_FALSE(base::PathExists(zip_path));
+
+  // Create a file with contents for compression to work.
+  {
+    base::File file(new_directory.AppendASCII("foo.txt"),
+                    base::File::FLAG_CREATE | base::File::FLAG_WRITE);
+    const std::string data = "foobarbaz";
+    file.WriteAtCurrentPos(data.data(), data.size());
+  }
+
+  EXPECT_TRUE(manager.CompressDirectoryFor(url));
+  EXPECT_FALSE(base::PathExists(new_directory));
+  EXPECT_TRUE(base::PathExists(zip_path));
 }
 
 TEST(FileManagerTest, TestDeleteArtifactsFor) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   FileManager manager(temp_dir.GetPath());
+
   GURL cr_url("https://www.chromium.org");
   base::FilePath cr_directory;
   EXPECT_TRUE(manager.CreateOrGetDirectoryFor(cr_url, &cr_directory));
   EXPECT_FALSE(cr_directory.empty());
   EXPECT_TRUE(base::PathExists(cr_directory));
+
   GURL w3_url("https://www.w3.org");
   base::FilePath w3_directory;
   EXPECT_TRUE(manager.CreateOrGetDirectoryFor(w3_url, &w3_directory));
   EXPECT_FALSE(w3_directory.empty());
   EXPECT_TRUE(base::PathExists(w3_directory));
+
   manager.DeleteArtifactsFor(std::vector<GURL>({cr_url}));
   EXPECT_FALSE(base::PathExists(cr_directory));
   EXPECT_TRUE(base::PathExists(w3_directory));
+
   base::FilePath new_cr_directory;
   EXPECT_TRUE(manager.CreateOrGetDirectoryFor(cr_url, &new_cr_directory));
   EXPECT_FALSE(new_cr_directory.empty());
   EXPECT_TRUE(base::PathExists(new_cr_directory));
   EXPECT_EQ(cr_directory, new_cr_directory);
+
   manager.DeleteArtifactsFor(std::vector<GURL>({cr_url, w3_url}));
   EXPECT_FALSE(base::PathExists(new_cr_directory));
   EXPECT_FALSE(base::PathExists(w3_directory));
@@ -107,29 +184,4 @@
   EXPECT_FALSE(base::PathExists(w3_directory));
 }
 
-TEST(FileManagerTest, TestDeleteAllOlderThan) {
-  base::Time now = base::Time::Now();
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  FileManager manager(temp_dir.GetPath());
-  GURL cr_url("https://www.chromium.org");
-  base::FilePath cr_directory;
-  EXPECT_TRUE(manager.CreateOrGetDirectoryFor(cr_url, &cr_directory));
-  EXPECT_FALSE(cr_directory.empty());
-  EXPECT_TRUE(base::PathExists(cr_directory));
-  base::TouchFile(cr_directory, now - base::TimeDelta::FromSeconds(1),
-                  now - base::TimeDelta::FromSeconds(1));
-
-  GURL w3_url("https://www.w3.org");
-  base::FilePath w3_directory;
-  EXPECT_TRUE(manager.CreateOrGetDirectoryFor(w3_url, &w3_directory));
-  EXPECT_FALSE(w3_directory.empty());
-  EXPECT_TRUE(base::PathExists(w3_directory));
-  base::TouchFile(w3_directory, now + base::TimeDelta::FromSeconds(1),
-                  now + base::TimeDelta::FromSeconds(1));
-  manager.DeleteAllOlderThan(now);
-  EXPECT_FALSE(base::PathExists(cr_directory));
-  EXPECT_TRUE(base::PathExists(w3_directory));
-}
-
 }  // namespace paint_preview
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc
index 2adb1541..172849f 100644
--- a/components/plugins/renderer/webview_plugin.cc
+++ b/components/plugins/renderer/webview_plugin.cc
@@ -21,7 +21,6 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/blink/public/common/page/page_zoom.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/web_coalesced_input_event.h"
 #include "third_party/blink/public/platform/web_url.h"
@@ -267,12 +266,8 @@
   // ApplyWebPreferences before making a WebLocalFrame so that the frame sees a
   // consistent view of our preferences.
   content::RenderView::ApplyWebPreferences(preferences, web_view_);
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker;
-  WebLocalFrame* web_frame = WebLocalFrame::CreateMainFrame(
-      web_view_, this, nullptr,
-      document_interface_broker.InitWithNewPipeAndPassReceiver().PassPipe(),
-      nullptr);
+  WebLocalFrame* web_frame =
+      WebLocalFrame::CreateMainFrame(web_view_, this, nullptr, nullptr);
   // The created WebFrameWidget is owned by the |web_frame|.
   WebFrameWidget::CreateForMainFrame(this, web_frame);
 
diff --git a/components/previews/content/previews_optimization_guide_decider.cc b/components/previews/content/previews_optimization_guide_decider.cc
index e39bc18..0b04c61 100644
--- a/components/previews/content/previews_optimization_guide_decider.cc
+++ b/components/previews/content/previews_optimization_guide_decider.cc
@@ -125,10 +125,11 @@
   // conditions match a painful page load as a prerequisite for returning true.
   optimization_guide::OptimizationMetadata optimization_metadata;
   optimization_guide::OptimizationGuideDecision decision =
-      optimization_guide_decider_->CanApplyOptimization(
-          navigation_handle,
-          optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
-          *optimization_type, &optimization_metadata);
+      optimization_guide_decider_
+          ->ShouldTargetNavigationAndCanApplyOptimization(
+              navigation_handle,
+              optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
+              *optimization_type, &optimization_metadata);
 
   // Return false if we are even unsure if we can apply the optimization (i.e.
   // hint not loaded yet or just not applicable).
@@ -174,7 +175,6 @@
 
     if (optimization_guide_decider_->CanApplyOptimization(
             navigation_handle,
-            optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
             optimization_type,
             /*optimization_metadata=*/nullptr) !=
         optimization_guide::OptimizationGuideDecision::kFalse) {
diff --git a/components/previews/content/previews_optimization_guide_decider_unittest.cc b/components/previews/content/previews_optimization_guide_decider_unittest.cc
index f43fab1..5897f96 100644
--- a/components/previews/content/previews_optimization_guide_decider_unittest.cc
+++ b/components/previews/content/previews_optimization_guide_decider_unittest.cc
@@ -57,8 +57,30 @@
     return registered_optimization_targets_;
   }
 
+  optimization_guide::OptimizationGuideDecision ShouldTargetNavigation(
+      content::NavigationHandle* navigation_handle,
+      optimization_guide::proto::OptimizationTarget optimization_target)
+      override {
+    // Should not be called.
+    EXPECT_TRUE(false);
+    return optimization_guide::OptimizationGuideDecision::kFalse;
+  }
+
   optimization_guide::OptimizationGuideDecision CanApplyOptimization(
       content::NavigationHandle* navigation_handle,
+      optimization_guide::proto::OptimizationType optimization_type,
+      optimization_guide::OptimizationMetadata* optimization_metadata)
+      override {
+    auto response_iter = responses_.find(
+        std::make_tuple(navigation_handle->GetURL(), optimization_type));
+    if (response_iter == responses_.end())
+      return optimization_guide::OptimizationGuideDecision::kFalse;
+    return std::get<0>(response_iter->second);
+  }
+
+  optimization_guide::OptimizationGuideDecision
+  ShouldTargetNavigationAndCanApplyOptimization(
+      content::NavigationHandle* navigation_handle,
       optimization_guide::proto::OptimizationTarget optimization_target,
       optimization_guide::proto::OptimizationType optimization_type,
       optimization_guide::OptimizationMetadata* optimization_metadata)
diff --git a/components/printing/browser/printer_capabilities.cc b/components/printing/browser/printer_capabilities.cc
index 7f7f48a..b6be716 100644
--- a/components/printing/browser/printer_capabilities.cc
+++ b/components/printing/browser/printer_capabilities.cc
@@ -90,7 +90,7 @@
 
 // Returns a dictionary representing printer capabilities as CDD.  Returns
 // an empty dictionary if a dictionary could not be generated.
-base::Value GetPrinterCapabilitiesOnBlockingPoolThread(
+base::Value GetPrinterCapabilitiesOnBlockingTaskRunner(
     const std::string& device_name,
     const PrinterSemanticCapsAndDefaults::Papers& additional_papers,
     bool has_secure_protocol,
@@ -151,7 +151,7 @@
 }
 #endif
 
-base::Value GetSettingsOnBlockingPool(
+base::Value GetSettingsOnBlockingTaskRunner(
     const std::string& device_name,
     const PrinterBasicInfo& basic_info,
     const PrinterSemanticCapsAndDefaults::Papers& additional_papers,
@@ -176,7 +176,7 @@
   printer_info_capabilities.SetKey(kPrinter, std::move(printer_info));
   printer_info_capabilities.SetKey(
       kSettingCapabilities,
-      GetPrinterCapabilitiesOnBlockingPoolThread(
+      GetPrinterCapabilitiesOnBlockingTaskRunner(
           device_name, additional_papers, has_secure_protocol, print_backend));
   return printer_info_capabilities;
 }
diff --git a/components/printing/browser/printer_capabilities.h b/components/printing/browser/printer_capabilities.h
index e1dab43..182c7aed 100644
--- a/components/printing/browser/printer_capabilities.h
+++ b/components/printing/browser/printer_capabilities.h
@@ -36,7 +36,7 @@
 // with default settings.
 // Data from |basic_info|, |additional_papers| and |has_secure_protocol| are
 // incorporated into the returned dictionary.
-base::Value GetSettingsOnBlockingPool(
+base::Value GetSettingsOnBlockingTaskRunner(
     const std::string& device_name,
     const PrinterBasicInfo& basic_info,
     const PrinterSemanticCapsAndDefaults::Papers& additional_papers,
diff --git a/components/printing/browser/printer_capabilities_unittest.cc b/components/printing/browser/printer_capabilities_unittest.cc
index 64cf25f..7b74d12 100644
--- a/components/printing/browser/printer_capabilities_unittest.cc
+++ b/components/printing/browser/printer_capabilities_unittest.cc
@@ -9,6 +9,9 @@
 #include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/stl_util.h"
+#include "base/task/post_task.h"
+#include "base/task_runner_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "content/public/test/browser_task_environment.h"
 #include "printing/backend/test_print_backend.h"
@@ -23,26 +26,60 @@
 
 const char kDpi[] = "dpi";
 
+void GetSettingsDone(base::OnceClosure done_closure,
+                     base::Value* out_settings,
+                     base::Value settings) {
+  *out_settings = std::move(settings);
+  std::move(done_closure).Run();
+}
+
 }  // namespace
 
 class PrinterCapabilitiesTest : public testing::Test {
  public:
-  PrinterCapabilitiesTest() {}
-  ~PrinterCapabilitiesTest() override {}
+  PrinterCapabilitiesTest() = default;
+  ~PrinterCapabilitiesTest() override = default;
 
  protected:
   void SetUp() override {
     test_backend_ = base::MakeRefCounted<TestPrintBackend>();
     PrintBackend::SetPrintBackendForTesting(test_backend_.get());
+    blocking_task_runner_ = base::CreateSingleThreadTaskRunner(
+        {base::ThreadPool(), base::MayBlock()});
+    disallow_blocking_ = std::make_unique<base::ScopedDisallowBlocking>();
   }
 
-  void TearDown() override { test_backend_ = nullptr; }
+  void TearDown() override {
+    disallow_blocking_.reset();
+    test_backend_.reset();
+  }
+
+  base::Value GetSettingsOnBlockingTaskRunnerAndWaitForResults(
+      const std::string& printer_name,
+      const PrinterBasicInfo& basic_info,
+      const PrinterSemanticCapsAndDefaults::Papers& papers,
+      scoped_refptr<PrintBackend> backend) {
+    base::RunLoop run_loop;
+    base::Value settings;
+
+    base::PostTaskAndReplyWithResult(
+        blocking_task_runner_.get(), FROM_HERE,
+        base::BindOnce(&GetSettingsOnBlockingTaskRunner, printer_name,
+                       basic_info, papers, /*has_secure_protocol=*/false,
+                       backend),
+        base::BindOnce(&GetSettingsDone, run_loop.QuitClosure(), &settings));
+
+    run_loop.Run();
+    return settings;
+  }
 
   TestPrintBackend* print_backend() { return test_backend_.get(); }
 
  private:
   content::BrowserTaskEnvironment task_environment_;
   scoped_refptr<TestPrintBackend> test_backend_;
+  scoped_refptr<base::TaskRunner> blocking_task_runner_;
+  std::unique_ptr<base::ScopedDisallowBlocking> disallow_blocking_;
 };
 
 // Verify that we don't crash for a missing printer and a nullptr is never
@@ -53,8 +90,8 @@
   PrinterSemanticCapsAndDefaults::Papers no_additional_papers;
 
   base::Value settings_dictionary =
-      GetSettingsOnBlockingPool(printer_name, basic_info, no_additional_papers,
-                                /* has_secure_protocol */ false, nullptr);
+      GetSettingsOnBlockingTaskRunnerAndWaitForResults(
+          printer_name, basic_info, no_additional_papers, nullptr);
 
   ASSERT_FALSE(settings_dictionary.DictEmpty());
 }
@@ -69,9 +106,9 @@
   caps->dpis = {{600, 600}};
   print_backend()->AddValidPrinter(printer_name, std::move(caps));
 
-  base::Value settings_dictionary = GetSettingsOnBlockingPool(
-      printer_name, basic_info, no_additional_papers,
-      /* has_secure_protocol */ false, print_backend());
+  base::Value settings_dictionary =
+      GetSettingsOnBlockingTaskRunnerAndWaitForResults(
+          printer_name, basic_info, no_additional_papers, print_backend());
 
   // Verify settings were created.
   ASSERT_FALSE(settings_dictionary.DictEmpty());
@@ -99,9 +136,9 @@
   // Return false when attempting to retrieve capabilities.
   print_backend()->AddValidPrinter(printer_name, nullptr);
 
-  base::Value settings_dictionary = GetSettingsOnBlockingPool(
-      printer_name, basic_info, no_additional_papers,
-      /* has_secure_protocol */ false, print_backend());
+  base::Value settings_dictionary =
+      GetSettingsOnBlockingTaskRunnerAndWaitForResults(
+          printer_name, basic_info, no_additional_papers, print_backend());
 
   // Verify settings were created.
   ASSERT_FALSE(settings_dictionary.DictEmpty());
@@ -127,9 +164,9 @@
   additional_papers.push_back({"foo", "vendor", {200, 300}});
   additional_papers.push_back({"bar", "vendor", {600, 600}});
 
-  base::Value settings_dictionary = GetSettingsOnBlockingPool(
-      printer_name, basic_info, additional_papers,
-      /* has_secure_protocol */ false, print_backend());
+  base::Value settings_dictionary =
+      GetSettingsOnBlockingTaskRunnerAndWaitForResults(
+          printer_name, basic_info, additional_papers, print_backend());
 
   // Verify settings were created.
   ASSERT_FALSE(settings_dictionary.DictEmpty());
@@ -191,7 +228,6 @@
   std::string printer_name = "test_printer";
   PrinterBasicInfo basic_info;
   PrinterSemanticCapsAndDefaults::Papers no_additional_papers;
-  bool has_secure_protocol = false;
 
   // Set a capability and add a valid printer.
   auto caps = std::make_unique<PrinterSemanticCapsAndDefaults>();
@@ -199,8 +235,8 @@
   print_backend()->AddValidPrinter(printer_name, std::move(caps));
 
   base::Value settings_dictionary =
-      GetSettingsOnBlockingPool(printer_name, basic_info, no_additional_papers,
-                                has_secure_protocol, print_backend());
+      GetSettingsOnBlockingTaskRunnerAndWaitForResults(
+          printer_name, basic_info, no_additional_papers, print_backend());
 
   // Verify settings were created.
   ASSERT_FALSE(settings_dictionary.DictEmpty());
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index ca398efa..4d158128 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -43,7 +43,6 @@
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 #include "third_party/blink/public/common/frame/frame_owner_element_type.h"
 #include "third_party/blink/public/common/frame/sandbox_flags.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_data.h"
 #include "third_party/blink/public/platform/web_double_size.h"
@@ -726,12 +725,8 @@
   };
 
   HeaderAndFooterClient frame_client;
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker;
   blink::WebLocalFrame* frame = blink::WebLocalFrame::CreateMainFrame(
-      web_view, &frame_client, nullptr,
-      document_interface_broker.InitWithNewPipeAndPassReceiver().PassPipe(),
-      nullptr);
+      web_view, &frame_client, nullptr, nullptr);
 
   blink::WebWidgetClient web_widget_client;
   blink::WebFrameWidget::CreateForMainFrame(&web_widget_client, frame);
@@ -966,12 +961,8 @@
       /*compositing_enabled=*/false,
       /*opener=*/nullptr);
   content::RenderView::ApplyWebPreferences(prefs, web_view);
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker;
-  blink::WebLocalFrame* main_frame = blink::WebLocalFrame::CreateMainFrame(
-      web_view, this, nullptr,
-      document_interface_broker.InitWithNewPipeAndPassReceiver().PassPipe(),
-      nullptr);
+  blink::WebLocalFrame* main_frame =
+      blink::WebLocalFrame::CreateMainFrame(web_view, this, nullptr, nullptr);
   frame_.Reset(main_frame);
   blink::WebFrameWidget::CreateForMainFrame(this, main_frame);
   node_to_print_.Reset();
diff --git a/components/sync/protocol/sharing_sms_fetch_message.proto b/components/sync/protocol/sharing_sms_fetch_message.proto
index 7c06be3..94fddf679 100644
--- a/components/sync/protocol/sharing_sms_fetch_message.proto
+++ b/components/sync/protocol/sharing_sms_fetch_message.proto
@@ -10,7 +10,19 @@
 option optimize_for = LITE_RUNTIME;
 
 // Request message to fetch a SMS from a remote device.
-message SmsFetchRequest {}
+message SmsFetchRequest {
+  // The origin that is requesting the SMS. Remote devices use it to match
+  // against the metadata contained in the received SMS.
+  // required
+  string origin = 1;
+}
 
 // Response message to fetch a SMS from a remote device.
-message SmsFetchResponse {}
+message SmsFetchResponse {
+  // The full contents of the received SMS.
+  // required
+  string sms = 1;
+  // The parsed one time code of the received SMS.
+  // required
+  string one_time_code = 2;
+}
diff --git a/components/system_media_controls/mac/now_playing_info_center_delegate.h b/components/system_media_controls/mac/now_playing_info_center_delegate.h
index f35390ba..7330991 100644
--- a/components/system_media_controls/mac/now_playing_info_center_delegate.h
+++ b/components/system_media_controls/mac/now_playing_info_center_delegate.h
@@ -24,6 +24,10 @@
 
   // Part of the implementation of SystemMediaControls.
   void SetPlaybackStatus(SystemMediaControls::PlaybackStatus status);
+  void SetTitle(const base::string16& title);
+  void SetArtist(const base::string16& artist);
+  void SetAlbum(const base::string16& album);
+  void ClearMetadata();
 
  private:
   base::scoped_nsobject<NowPlayingInfoCenterDelegateCocoa>
diff --git a/components/system_media_controls/mac/now_playing_info_center_delegate.mm b/components/system_media_controls/mac/now_playing_info_center_delegate.mm
index 5c2fc25..13b1cbd 100644
--- a/components/system_media_controls/mac/now_playing_info_center_delegate.mm
+++ b/components/system_media_controls/mac/now_playing_info_center_delegate.mm
@@ -6,6 +6,7 @@
 
 #import <MediaPlayer/MediaPlayer.h>
 
+#include "base/strings/sys_string_conversions.h"
 #include "components/system_media_controls/mac/now_playing_info_center_delegate_cocoa.h"
 
 namespace system_media_controls {
@@ -47,5 +48,24 @@
   [now_playing_info_center_delegate_cocoa_ setPlaybackState:state];
 }
 
+void NowPlayingInfoCenterDelegate::SetTitle(const base::string16& title) {
+  [now_playing_info_center_delegate_cocoa_
+      setTitle:base::SysUTF16ToNSString(title)];
+}
+
+void NowPlayingInfoCenterDelegate::SetArtist(const base::string16& artist) {
+  [now_playing_info_center_delegate_cocoa_
+      setArtist:base::SysUTF16ToNSString(artist)];
+}
+
+void NowPlayingInfoCenterDelegate::SetAlbum(const base::string16& album) {
+  [now_playing_info_center_delegate_cocoa_
+      setAlbum:base::SysUTF16ToNSString(album)];
+}
+
+void NowPlayingInfoCenterDelegate::ClearMetadata() {
+  [now_playing_info_center_delegate_cocoa_ clearMetadata];
+}
+
 }  // namespace internal
 }  // namespace system_media_controls
diff --git a/components/system_media_controls/mac/now_playing_info_center_delegate_cocoa.h b/components/system_media_controls/mac/now_playing_info_center_delegate_cocoa.h
index 2205fbfe..471eb900 100644
--- a/components/system_media_controls/mac/now_playing_info_center_delegate_cocoa.h
+++ b/components/system_media_controls/mac/now_playing_info_center_delegate_cocoa.h
@@ -18,6 +18,12 @@
 
 // Called by the NowPlayingInfoCenterDelegateImpl to set metadata.
 - (void)setPlaybackState:(MPNowPlayingPlaybackState)state;
+- (void)setTitle:(NSString*)title;
+- (void)setArtist:(NSString*)artist;
+- (void)setAlbum:(NSString*)album;
+
+// Sets all metadata to default values.
+- (void)clearMetadata;
 
 @end
 
diff --git a/components/system_media_controls/mac/now_playing_info_center_delegate_cocoa.mm b/components/system_media_controls/mac/now_playing_info_center_delegate_cocoa.mm
index 3e7e365..bd1879b 100644
--- a/components/system_media_controls/mac/now_playing_info_center_delegate_cocoa.mm
+++ b/components/system_media_controls/mac/now_playing_info_center_delegate_cocoa.mm
@@ -43,6 +43,26 @@
   [self updateNowPlayingInfo];
 }
 
+- (void)setTitle:(NSString*)title {
+  [nowPlayingInfo_ setObject:title forKey:MPMediaItemPropertyTitle];
+  [self updateNowPlayingInfo];
+}
+
+- (void)setArtist:(NSString*)artist {
+  [nowPlayingInfo_ setObject:artist forKey:MPMediaItemPropertyArtist];
+  [self updateNowPlayingInfo];
+}
+
+- (void)setAlbum:(NSString*)album {
+  [nowPlayingInfo_ setObject:album forKey:MPMediaItemPropertyAlbumTitle];
+  [self updateNowPlayingInfo];
+}
+
+- (void)clearMetadata {
+  [self initializeNowPlayingInfoValues];
+  [self updateNowPlayingInfo];
+}
+
 - (void)initializeNowPlayingInfoValues {
   [nowPlayingInfo_ setObject:[NSNumber numberWithDouble:0]
                       forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
@@ -56,6 +76,7 @@
   [nowPlayingInfo_ setObject:@"Chromium" forKey:MPMediaItemPropertyTitle];
 #endif
   [nowPlayingInfo_ setObject:@"" forKey:MPMediaItemPropertyArtist];
+  [nowPlayingInfo_ setObject:@"" forKey:MPMediaItemPropertyAlbumTitle];
 }
 
 - (void)updateNowPlayingInfo {
diff --git a/components/system_media_controls/mac/system_media_controls_mac.h b/components/system_media_controls/mac/system_media_controls_mac.h
index d8c59938..58ffb7a 100644
--- a/components/system_media_controls/mac/system_media_controls_mac.h
+++ b/components/system_media_controls/mac/system_media_controls_mac.h
@@ -38,12 +38,12 @@
   void SetIsPlayPauseEnabled(bool value) override;
   void SetIsStopEnabled(bool value) override;
   void SetPlaybackStatus(PlaybackStatus status) override;
-  void SetTitle(const base::string16& title) override {}
-  void SetArtist(const base::string16& artist) override {}
-  void SetAlbum(const base::string16& album) override {}
+  void SetTitle(const base::string16& title) override;
+  void SetArtist(const base::string16& artist) override;
+  void SetAlbum(const base::string16& album) override;
   void SetThumbnail(const SkBitmap& bitmap) override {}
   void ClearThumbnail() override {}
-  void ClearMetadata() override {}
+  void ClearMetadata() override;
   void UpdateDisplay() override {}
 
  private:
diff --git a/components/system_media_controls/mac/system_media_controls_mac.mm b/components/system_media_controls/mac/system_media_controls_mac.mm
index 6f58387..db92bfff 100644
--- a/components/system_media_controls/mac/system_media_controls_mac.mm
+++ b/components/system_media_controls/mac/system_media_controls_mac.mm
@@ -58,5 +58,21 @@
   now_playing_info_center_delegate_.SetPlaybackStatus(status);
 }
 
+void SystemMediaControlsMac::SetTitle(const base::string16& title) {
+  now_playing_info_center_delegate_.SetTitle(title);
+}
+
+void SystemMediaControlsMac::SetArtist(const base::string16& artist) {
+  now_playing_info_center_delegate_.SetArtist(artist);
+}
+
+void SystemMediaControlsMac::SetAlbum(const base::string16& album) {
+  now_playing_info_center_delegate_.SetAlbum(album);
+}
+
+void SystemMediaControlsMac::ClearMetadata() {
+  now_playing_info_center_delegate_.ClearMetadata();
+}
+
 }  // namespace internal
 }  // namespace system_media_controls
diff --git a/components/visitedlink/browser/visitedlink_master.cc b/components/visitedlink/browser/visitedlink_master.cc
index 2202593..3c6ea4b 100644
--- a/components/visitedlink/browser/visitedlink_master.cc
+++ b/components/visitedlink/browser/visitedlink_master.cc
@@ -21,6 +21,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 #include "components/visitedlink/browser/visitedlink_delegate.h"
 #include "components/visitedlink/browser/visitedlink_event_listener.h"
@@ -339,6 +340,7 @@
 }
 
 void VisitedLinkMaster::AddURL(const GURL& url) {
+  TRACE_EVENT0("browser", "VisitedLinkMaster::AddURL");
   Hash index = TryToAddURL(url);
   if (!table_builder_ && !table_is_loading_from_file_ && index != null_hash_) {
     // Not rebuilding, so we want to keep the file on disk up to date.
@@ -351,6 +353,7 @@
 }
 
 void VisitedLinkMaster::AddURLs(const std::vector<GURL>& urls) {
+  TRACE_EVENT0("browser", "VisitedLinkMaster::AddURLs");
   for (const GURL& url : urls) {
     Hash index = TryToAddURL(url);
     if (!table_builder_ && !table_is_loading_from_file_ && index != null_hash_)
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 7c6a425..7fe0b75a 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -264,6 +264,7 @@
     "switches.h",
     "traced_value.cc",
     "traced_value.h",
+    "vertical_scroll_direction.h",
     "viz_common_export.h",
     "viz_utils.cc",
     "viz_utils.h",
diff --git a/components/viz/common/vertical_scroll_direction.h b/components/viz/common/vertical_scroll_direction.h
new file mode 100644
index 0000000..bf2e7f7d
--- /dev/null
+++ b/components/viz/common/vertical_scroll_direction.h
@@ -0,0 +1,17 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_COMMON_VERTICAL_SCROLL_DIRECTION_H_
+#define COMPONENTS_VIZ_COMMON_VERTICAL_SCROLL_DIRECTION_H_
+
+namespace viz {
+
+// Used to indicate the vertical scroll direction of the root layer. Note that
+// |kNull| is only used to represent the absence of a vertical scroll direction.
+// See services/viz/public/mojom/vertical_scroll_position.mojom.
+enum class VerticalScrollDirection { kNull, kDown, kUp };
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_COMMON_VERTICAL_SCROLL_DIRECTION_H_
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index 2edbf32..f87e44f 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -16,7 +16,6 @@
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/site_isolation_policy.h"
 #include "content/public/browser/web_contents.h"
@@ -3598,81 +3597,6 @@
   EXPECT_EQ(rfh_a, current_frame_host());
 }
 
-// Make sure we are exposing the duration between back navigation's
-// navigationStart and the page's original navigationStart through pageshow
-// event's timeStamp, and that we aren't modifying
-// performance.timing.navigationStart.
-IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, NavigationStart) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  GURL url_a(embedded_test_server()->GetURL(
-      "a.com", "/back_forward_cache/record_navigation_start_time_stamp.html"));
-  GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
-
-  // 1) Navigate to A.
-  EXPECT_TRUE(NavigateToURL(shell(), url_a));
-  RenderFrameHostImpl* rfh_a = current_frame_host();
-  RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a);
-
-  double initial_page_show_time_stamp =
-      EvalJs(shell(), "window.initialPageShowTimeStamp").ExtractDouble();
-  EXPECT_EQ(initial_page_show_time_stamp,
-            EvalJs(shell(), "window.latestPageShowTimeStamp"));
-  double initial_navigation_start =
-      EvalJs(shell(), "window.initialNavigationStart").ExtractDouble();
-
-  // 2) Navigate to B. A should be in the back forward cache.
-  EXPECT_TRUE(NavigateToURL(shell(), url_b));
-  EXPECT_FALSE(delete_observer_rfh_a.deleted());
-  EXPECT_TRUE(rfh_a->is_in_back_forward_cache());
-
-  // 3) Navigate back and expect everything to be restored.
-  NavigationHandleObserver observer(web_contents(), url_a);
-  base::TimeTicks time_before_navigation = base::TimeTicks::Now();
-  double js_time_before_navigation =
-      EvalJs(shell(), "performance.now()").ExtractDouble();
-  web_contents()->GetController().GoBack();
-  EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
-  base::TimeTicks time_after_navigation = base::TimeTicks::Now();
-  double js_time_after_navigation =
-      EvalJs(shell(), "performance.now()").ExtractDouble();
-
-  // The navigation start time should be between the time we saved just before
-  // calling GoBack() and the time we saved just after calling GoBack().
-  base::TimeTicks back_navigation_start = observer.navigation_start();
-  EXPECT_LT(time_before_navigation, back_navigation_start);
-  EXPECT_GT(time_after_navigation, back_navigation_start);
-
-  // Check JS values. window.initialNavigationStart should not change.
-  EXPECT_EQ(initial_navigation_start,
-            EvalJs(shell(), "window.initialNavigationStart"));
-  // performance.timing.navigationStart should not change.
-  EXPECT_EQ(initial_navigation_start,
-            EvalJs(shell(), "performance.timing.navigationStart"));
-  // window.initialPageShowTimeStamp should not change.
-  EXPECT_EQ(initial_page_show_time_stamp,
-            EvalJs(shell(), "window.initialPageShowTimeStamp"));
-  // window.latestPageShowTimeStamp should be updated with the timestamp of the
-  // last pageshow event, which occurs after the page is restored. This should
-  // be greater than the initial pageshow event's timestamp.
-  double latest_page_show_time_stamp =
-      EvalJs(shell(), "window.latestPageShowTimeStamp").ExtractDouble();
-  EXPECT_LT(initial_page_show_time_stamp, latest_page_show_time_stamp);
-
-  // |latest_page_show_time_stamp| should be the duration between initial
-  // navigation start and |back_navigation_start|. Note that since
-  // performance.timing.navigationStart returns a 64-bit integer instead of
-  // double, we might be losing somewhere between 0 to 1 milliseconds of
-  // precision, hence the usage of EXPECT_NEAR.
-  EXPECT_NEAR(
-      (back_navigation_start - base::TimeTicks::UnixEpoch()).InMillisecondsF(),
-      latest_page_show_time_stamp + initial_navigation_start, 1.0);
-  // Expect that the back navigation start value calculated from the JS results
-  // are between time taken before & after navigation, just like
-  // |before_navigation_start|.
-  EXPECT_LT(js_time_before_navigation, latest_page_show_time_stamp);
-  EXPECT_GT(js_time_after_navigation, latest_page_show_time_stamp);
-}
-
 // Do a same document navigation and make sure we do not fire the
 // DidFirstVisuallyNonEmptyPaint again
 IN_PROC_BROWSER_TEST_F(
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index 131b6f6..d29ce2e 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -236,7 +236,7 @@
   RFH_CHILD_FRAME_NEEDS_OWNER_ELEMENT_TYPE = 208,
   OBSOLETE_RFH_INVALID_WEB_REPORTING_CRASH_ID = 209,
   RFH_DETACH_MAIN_FRAME = 210,
-  RFH_DOCUMENT_INTERFACE_BROKER_MISSING = 211,
+  RFH_BROWSER_INTERFACE_BROKER_MISSING = 211,
   RFPH_POST_MESSAGE_INVALID_SOURCE_ORIGIN = 212,
   INVALID_INITIATOR_ORIGIN = 213,
   RFHI_BEGIN_NAVIGATION_MISSING_INITIATOR_ORIGIN = 214,
diff --git a/content/browser/cache_storage/cache_storage_cache_entry_handler.cc b/content/browser/cache_storage/cache_storage_cache_entry_handler.cc
index 35beac4..537b5332 100644
--- a/content/browser/cache_storage/cache_storage_cache_entry_handler.cc
+++ b/content/browser/cache_storage/cache_storage_cache_entry_handler.cc
@@ -37,14 +37,12 @@
         blob_entry_(blob_entry),
         cache_index_(cache_index),
         orig_offset_(offset),
-        orig_length_(length) {
-    DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  }
+        orig_length_(length) {}
 
   int Read(net::IOBuffer* dst_buffer,
            int buffer_size,
            net::CompletionOnceCallback callback) override {
-    DCHECK_CURRENTLY_ON(BrowserThread::IO);
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
     uint64_t offset = orig_offset_ + bytes_read_;
 
@@ -77,7 +75,10 @@
 
   std::string Description() const override { return "DiskCacheStream"; }
 
-  bool MayHaveMoreBytes() const override { return bytes_read_ < orig_length_; }
+  bool MayHaveMoreBytes() const override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    return bytes_read_ < orig_length_;
+  }
 
  private:
   const scoped_refptr<CacheStorageCacheEntryHandler::DiskCacheBlobEntry>
@@ -86,6 +87,7 @@
   const uint64_t orig_offset_;
   const uint64_t orig_length_;
   uint64_t bytes_read_ = 0;
+  SEQUENCE_CHECKER(sequence_checker_);
 };
 
 // A |storage::mojom::BlobDataItemReader| implementation that
@@ -100,17 +102,13 @@
       CacheStorageCache::EntryIndex side_data_disk_cache_index)
       : blob_entry_(std::move(blob_entry)),
         disk_cache_index_(disk_cache_index),
-        side_data_disk_cache_index_(side_data_disk_cache_index) {
-    DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  }
-  ~EntryReaderImpl() override { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
+        side_data_disk_cache_index_(side_data_disk_cache_index) {}
 
   void Read(uint64_t offset,
             uint64_t length,
             mojo::ScopedDataPipeProducerHandle pipe,
             ReadCallback callback) override {
-    DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     uint64_t size = blob_entry_->GetSize(disk_cache_index_);
     if (offset > size) {
       std::move(callback).Run(net::ERR_INVALID_ARGUMENT);
@@ -134,8 +132,7 @@
   }
 
   void ReadSideData(ReadSideDataCallback callback) override {
-    DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     // Use a WrappedIOBuffer so that the DiskCacheBlobEntry writes directly
     // to the BigBuffer without a copy.
     int length = blob_entry_->GetSize(side_data_disk_cache_index_);
@@ -170,31 +167,16 @@
   const CacheStorageCache::EntryIndex disk_cache_index_;
   const CacheStorageCache::EntryIndex side_data_disk_cache_index_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
   DISALLOW_COPY_AND_ASSIGN(EntryReaderImpl);
 };
 
 void FinalizeBlobOnIOThread(
     scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
-    scoped_refptr<CacheStorageCacheEntryHandler::DiskCacheBlobEntry> blob_entry,
-    CacheStorageCache::EntryIndex disk_cache_index,
-    CacheStorageCache::EntryIndex side_data_disk_cache_index,
-    std::string uuid,
+    storage::mojom::BlobDataItemPtr element,
+    const std::string& uuid,
     mojo::PendingReceiver<blink::mojom::Blob> receiver) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  auto element = storage::mojom::BlobDataItem::New();
-  element->size = blob_entry->GetSize(disk_cache_index);
-  element->side_data_size =
-      side_data_disk_cache_index == CacheStorageCache::INDEX_INVALID
-          ? 0
-          : blob_entry->GetSize(side_data_disk_cache_index);
-  element->type = storage::mojom::BlobDataItemType::kCacheStorage;
-
-  auto handle = std::make_unique<EntryReaderImpl>(
-      std::move(blob_entry), disk_cache_index, side_data_disk_cache_index);
-  mojo::MakeSelfOwnedReceiver(std::move(handle),
-                              element->reader.InitWithNewPipeAndPassReceiver());
-
   blob_storage_context->context()->RegisterFromDataItem(
       std::move(receiver), uuid, std::move(element));
 }
@@ -206,20 +188,9 @@
     base::WeakPtr<CacheStorageCacheEntryHandler> entry_handler,
     CacheStorageCacheHandle cache_handle,
     disk_cache::ScopedEntryPtr disk_cache_entry)
-    : base::RefCountedDeleteOnSequence<DiskCacheBlobEntry>(
-          base::SequencedTaskRunnerHandle::Get()),
-      task_runner_(base::SequencedTaskRunnerHandle::Get()),
-      entry_handler_(std::move(entry_handler)),
+    : entry_handler_(std::move(entry_handler)),
       cache_handle_(std::move(cache_handle)),
-      disk_cache_entry_(std::move(disk_cache_entry)),
-      valid_(true),
-      key_(disk_cache_entry_->GetKey()),
-      index_headers_size_(
-          disk_cache_entry_->GetDataSize(CacheStorageCache::INDEX_HEADERS)),
-      index_response_body_size_(disk_cache_entry_->GetDataSize(
-          CacheStorageCache::INDEX_RESPONSE_BODY)),
-      index_side_data_size_(
-          disk_cache_entry_->GetDataSize(CacheStorageCache::INDEX_SIDE_DATA)) {}
+      disk_cache_entry_(std::move(disk_cache_entry)) {}
 
 int CacheStorageCacheEntryHandler::DiskCacheBlobEntry::Read(
     scoped_refptr<net::IOBuffer> dst_buffer,
@@ -227,52 +198,36 @@
     uint64_t offset,
     int bytes_to_read,
     base::OnceCallback<void(int)> callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!valid_)
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!disk_cache_entry_)
     return net::ERR_CACHE_READ_FAILURE;
 
-  if (task_runner_->RunsTasksInCurrentSequence()) {
-    return ReadOnSequenceInternal(std::move(dst_buffer), disk_cache_index,
-                                  offset, bytes_to_read, std::move(callback));
-  }
-
-  task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&DiskCacheBlobEntry::ReadOnSequence, this,
-                                std::move(dst_buffer), disk_cache_index, offset,
-                                bytes_to_read, std::move(callback)));
-  return net::ERR_IO_PENDING;
+  return disk_cache_entry_->ReadData(disk_cache_index, offset, dst_buffer.get(),
+                                     bytes_to_read, std::move(callback));
 }
 
 int CacheStorageCacheEntryHandler::DiskCacheBlobEntry::GetSize(
     CacheStorageCache::EntryIndex disk_cache_index) const {
-  // Callable on any thread.
-  if (!valid_)
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!disk_cache_entry_)
     return 0;
   switch (disk_cache_index) {
     case CacheStorageCache::INDEX_INVALID:
       return 0;
     case CacheStorageCache::INDEX_HEADERS:
-      return index_headers_size_;
+      return disk_cache_entry_->GetDataSize(CacheStorageCache::INDEX_HEADERS);
     case CacheStorageCache::INDEX_RESPONSE_BODY:
-      return index_response_body_size_;
+      return disk_cache_entry_->GetDataSize(
+          CacheStorageCache::INDEX_RESPONSE_BODY);
     case CacheStorageCache::INDEX_SIDE_DATA:
-      return index_side_data_size_;
+      return disk_cache_entry_->GetDataSize(CacheStorageCache::INDEX_SIDE_DATA);
   }
   NOTREACHED();
 }
 
-void CacheStorageCacheEntryHandler::DiskCacheBlobEntry::PrintTo(
-    ::std::ostream* os) const {
-  // Callable on any thread.
-  if (valid_)
-    *os << "disk_cache_key:" << key_;
-  else
-    *os << "<invalidated>";
-}
-
 void CacheStorageCacheEntryHandler::DiskCacheBlobEntry::Invalidate() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  valid_ = false;
   cache_handle_ = base::nullopt;
   entry_handler_ = nullptr;
   disk_cache_entry_ = nullptr;
@@ -284,58 +239,6 @@
   return disk_cache_entry_;
 }
 
-void CacheStorageCacheEntryHandler::DiskCacheBlobEntry::ReadOnSequence(
-    scoped_refptr<net::IOBuffer> dst_buffer,
-    int disk_cache_index,
-    uint64_t offset,
-    int bytes_to_read,
-    base::OnceCallback<void(int)> callback) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  // The disk_cache behavior of sometimes returning the result synchronously
-  // and sometimes invoking the callback requires us to adapt our callback
-  // to repeating here.  Ideally disk_cache should be refactored to always
-  // report the result through the callback.
-  auto adapted_callback = base::AdaptCallbackForRepeating(std::move(callback));
-
-  int result = ReadOnSequenceInternal(std::move(dst_buffer), disk_cache_index,
-                                      offset, bytes_to_read, adapted_callback);
-
-  if (result == net::ERR_IO_PENDING)
-    return;
-
-  DidReadOnSequence(std::move(adapted_callback), result);
-}
-
-int CacheStorageCacheEntryHandler::DiskCacheBlobEntry::ReadOnSequenceInternal(
-    scoped_refptr<net::IOBuffer> dst_buffer,
-    int disk_cache_index,
-    uint64_t offset,
-    int bytes_to_read,
-    base::OnceCallback<void(int)> callback) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  if (!disk_cache_entry_) {
-    return net::ERR_CACHE_READ_FAILURE;
-  }
-
-  return disk_cache_entry_->ReadData(
-      disk_cache_index, offset, dst_buffer.get(), bytes_to_read,
-      base::BindOnce(&DiskCacheBlobEntry::DidReadOnSequence, this,
-                     std::move(callback)));
-}
-
-void CacheStorageCacheEntryHandler::DiskCacheBlobEntry::DidReadOnSequence(
-    base::OnceCallback<void(int)> callback,
-    int result) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
-    std::move(callback).Run(result);
-  } else {
-    base::PostTask(FROM_HERE, {BrowserThread::IO},
-                   base::BindOnce(std::move(callback), result));
-  }
-}
-
 CacheStorageCacheEntryHandler::DiskCacheBlobEntry::~DiskCacheBlobEntry() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (entry_handler_)
@@ -492,17 +395,35 @@
   blob->size = blob_entry->GetSize(disk_cache_index);
   blob->uuid = base::GenerateGUID();
 
+  auto element = storage::mojom::BlobDataItem::New();
+  element->size = blob_entry->GetSize(disk_cache_index);
+  element->side_data_size =
+      side_data_disk_cache_index == CacheStorageCache::INDEX_INVALID
+          ? 0
+          : blob_entry->GetSize(side_data_disk_cache_index);
+  element->type = storage::mojom::BlobDataItemType::kCacheStorage;
+
+  // Bind the blob data item on the current sequence.  This ensures
+  // that the mojo messages are delivered directly to the correct
+  // cache_storage sequence.  This works even if the cache_storage is
+  // running off the IO thread.
+  auto handle = std::make_unique<EntryReaderImpl>(
+      std::move(blob_entry), disk_cache_index, side_data_disk_cache_index);
+  mojo::MakeSelfOwnedReceiver(std::move(handle),
+                              element->reader.InitWithNewPipeAndPassReceiver());
+
+  // We can only register the blob in the storage context on the IO thread.
+  // TODO(crbug/1022104): Once the blob context is not locked to the IO thread
+  //                      we can finalize the blob directly on the sequence.
   if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
-    FinalizeBlobOnIOThread(blob_storage_context_, std::move(blob_entry),
-                           disk_cache_index, side_data_disk_cache_index,
+    FinalizeBlobOnIOThread(blob_storage_context_, std::move(element),
                            blob->uuid,
                            blob->blob.InitWithNewPipeAndPassReceiver());
   } else {
     base::PostTask(
         FROM_HERE, {BrowserThread::IO},
         base::BindOnce(&FinalizeBlobOnIOThread, blob_storage_context_,
-                       std::move(blob_entry), disk_cache_index,
-                       side_data_disk_cache_index, blob->uuid,
+                       std::move(element), blob->uuid,
                        blob->blob.InitWithNewPipeAndPassReceiver()));
   }
 
diff --git a/content/browser/cache_storage/cache_storage_cache_entry_handler.h b/content/browser/cache_storage/cache_storage_cache_entry_handler.h
index 1f2de39..f59caff 100644
--- a/content/browser/cache_storage/cache_storage_cache_entry_handler.h
+++ b/content/browser/cache_storage/cache_storage_cache_entry_handler.h
@@ -9,7 +9,7 @@
 #include <set>
 
 #include "base/macros.h"
-#include "base/memory/ref_counted_delete_on_sequence.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/util/type_safety/pass_key.h"
@@ -68,13 +68,7 @@
   // The DiskCacheBlobEntry is a ref-counted object containing both
   // a disk_cache Entry and a Handle to the cache in which it lives.  This
   // blob entry can then be used to create an |EntryReaderImpl|.
-  //
-  // |EntryReaderImpl| always lives on the IO thread.  The DiskCacheBlobEntry
-  // is held cross-sequence, but is always created and destroyed on the
-  // cache_storage scheduler sequence. This ensure both the cache and the
-  // disk_cache entry live as long as the blob.
-  class DiskCacheBlobEntry
-      : public base::RefCountedDeleteOnSequence<DiskCacheBlobEntry> {
+  class DiskCacheBlobEntry : public base::RefCounted<DiskCacheBlobEntry> {
    public:
     // Use |CacheStorageCacheEntryHandler::CreateDiskCacheBlobEntry|.
     DiskCacheBlobEntry(
@@ -83,70 +77,28 @@
         CacheStorageCacheHandle cache_handle,
         disk_cache::ScopedEntryPtr disk_cache_entry);
 
-    // Only callable on IO thread.
     int Read(scoped_refptr<net::IOBuffer> dst_buffer,
              CacheStorageCache::EntryIndex disk_cache_index,
              uint64_t offset,
              int bytes_to_read,
              base::OnceCallback<void(int)> callback);
 
-    // Callable on any thread.
     int GetSize(CacheStorageCache::EntryIndex disk_cache_index) const;
 
-    // Callable on any thread.
-    void PrintTo(::std::ostream* os) const;
-
-    // Only callable on the creation sequence.
     void Invalidate();
 
-    // Only callable on the creation sequence.
     disk_cache::ScopedEntryPtr& disk_cache_entry();
 
    private:
-    friend class base::DeleteHelper<DiskCacheBlobEntry>;
-    friend class base::RefCountedDeleteOnSequence<DiskCacheBlobEntry>;
+    friend class base::RefCounted<DiskCacheBlobEntry>;
     ~DiskCacheBlobEntry();
 
-    // Only callable on the creation sequence.
-    void ReadOnSequence(scoped_refptr<net::IOBuffer> dst_buffer,
-                        int disk_cache_index,
-                        uint64_t offset,
-                        int bytes_to_read,
-                        base::OnceCallback<void(int)> callback);
-
-    // Only callable on the creation sequence.
-    int ReadOnSequenceInternal(scoped_refptr<net::IOBuffer> dst_buffer,
-                               int disk_cache_index,
-                               uint64_t offset,
-                               int bytes_to_read,
-                               base::OnceCallback<void(int)> callback);
-
-    void DidReadOnSequence(base::OnceCallback<void(int)> callback, int result);
-
-    // Accessed on any thread
-    const scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
-    // Only accessed on the creation sequence.
     base::WeakPtr<CacheStorageCacheEntryHandler> entry_handler_;
     base::Optional<CacheStorageCacheHandle> cache_handle_;
     disk_cache::ScopedEntryPtr disk_cache_entry_;
 
-    // Accessed on any thread.
-    std::atomic<bool> valid_;
-
-    // Cached on the creation sequence so that they can be synchronously
-    // read on the IO thread.
-    const std::string key_;
-    const int index_headers_size_;
-    const int index_response_body_size_;
-    const int index_side_data_size_;
-
-    // For methods that should only be executed on the creation sequence.
     SEQUENCE_CHECKER(sequence_checker_);
 
-    // Do not add a WeakPtrFactory since this class uses a cross-sequence
-    // delete helper.
-
     DISALLOW_COPY_AND_ASSIGN(DiskCacheBlobEntry);
   };
 
diff --git a/content/browser/frame_host/back_forward_cache_impl.cc b/content/browser/frame_host/back_forward_cache_impl.cc
index b19d2ba..10d01a9 100644
--- a/content/browser/frame_host/back_forward_cache_impl.cc
+++ b/content/browser/frame_host/back_forward_cache_impl.cc
@@ -39,18 +39,11 @@
 // The default time to live in seconds for documents in BackForwardCache.
 static constexpr int kDefaultTimeToLiveInBackForwardCacheInSeconds = 15;
 
-// Invalid |navigation_start| value, for calls to SetPageFrozenImpl where we
-// don't need |navigation_start|.
-constexpr base::TimeTicks kInvalidNavigationStart = base::TimeTicks();
-
 void SetPageFrozenImpl(
     RenderFrameHostImpl* render_frame_host,
     bool frozen,
-    std::unordered_set<RenderViewHostImpl*>* render_view_hosts,
-    base::TimeTicks navigation_start) {
+    std::unordered_set<RenderViewHostImpl*>* render_view_hosts) {
   RenderViewHostImpl* render_view_host = render_frame_host->render_view_host();
-  // |navigation_start| should only be valid if we're restoring a page.
-  DCHECK_EQ(frozen, navigation_start == kInvalidNavigationStart);
   // (Un)Freeze the frame's page if it is not (un)frozen yet.
   if (render_view_hosts->find(render_view_host) == render_view_hosts->end()) {
     // The state change for bfcache is:
@@ -65,8 +58,8 @@
       render_view_host->Send(
           new PageMsg_PutPageIntoBackForwardCache(rvh_routing_id));
     } else {
-      render_view_host->Send(new PageMsg_RestorePageFromBackForwardCache(
-          rvh_routing_id, navigation_start));
+      render_view_host->Send(
+          new PageMsg_RestorePageFromBackForwardCache(rvh_routing_id));
     }
     render_view_hosts->insert(render_view_host);
   }
@@ -74,8 +67,7 @@
   for (size_t index = 0; index < render_frame_host->child_count(); ++index) {
     RenderFrameHostImpl* child_frame_host =
         render_frame_host->child_at(index)->current_frame_host();
-    SetPageFrozenImpl(child_frame_host, frozen, render_view_hosts,
-                      navigation_start);
+    SetPageFrozenImpl(child_frame_host, frozen, render_view_hosts);
   }
 }
 
@@ -337,20 +329,14 @@
   // |frozen_render_view_hosts| keeps track of the ones that freezing has been
   // applied to.
   std::unordered_set<RenderViewHostImpl*> frozen_render_view_hosts;
-  // |navigation_start| is used only when resuming a page, hence an invalid
-  // value is passed here.
-
-  SetPageFrozenImpl(main_rfh, /*frozen = */ true, &frozen_render_view_hosts,
-                    kInvalidNavigationStart);
+  SetPageFrozenImpl(main_rfh, /*frozen = */ true, &frozen_render_view_hosts);
 }
 
-void BackForwardCacheImpl::Resume(RenderFrameHostImpl* main_rfh,
-                                  base::TimeTicks navigation_start) {
+void BackForwardCacheImpl::Resume(RenderFrameHostImpl* main_rfh) {
   // |unfrozen_render_view_hosts| keeps track of the ones that resuming has
   // been applied to.
   std::unordered_set<RenderViewHostImpl*> unfrozen_render_view_hosts;
-  SetPageFrozenImpl(main_rfh, /*frozen = */ false, &unfrozen_render_view_hosts,
-                    navigation_start);
+  SetPageFrozenImpl(main_rfh, /*frozen = */ false, &unfrozen_render_view_hosts);
 }
 
 std::unique_ptr<BackForwardCacheImpl::Entry> BackForwardCacheImpl::RestoreEntry(
diff --git a/content/browser/frame_host/back_forward_cache_impl.h b/content/browser/frame_host/back_forward_cache_impl.h
index 2dbb33f8..ee14c0e 100644
--- a/content/browser/frame_host/back_forward_cache_impl.h
+++ b/content/browser/frame_host/back_forward_cache_impl.h
@@ -88,8 +88,7 @@
   // Iterates over all the RenderViewHost inside |main_rfh| and freeze or
   // resume them.
   static void Freeze(RenderFrameHostImpl* main_rfh);
-  static void Resume(RenderFrameHostImpl* main_rfh,
-                     base::TimeTicks navigation_start);
+  static void Resume(RenderFrameHostImpl* main_rfh);
 
   // Returns a pointer to a cached BackForwardCache entry matching
   // |navigation_entry_id| if it exists in the BackForwardCache. Returns nullptr
diff --git a/content/browser/frame_host/frame_tree.cc b/content/browser/frame_host/frame_tree.cc
index fd588f51..579d5d4 100644
--- a/content/browser/frame_host/frame_tree.cc
+++ b/content/browser/frame_host/frame_tree.cc
@@ -178,10 +178,6 @@
     int process_id,
     int new_routing_id,
     service_manager::mojom::InterfaceProviderRequest interface_provider_request,
-    mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_content_receiver,
-    mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_blink_receiver,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker_receiver,
     blink::WebTreeScopeType scope,
@@ -226,12 +222,6 @@
   added_node->current_frame_host()->BindInterfaceProviderRequest(
       std::move(interface_provider_request));
 
-  DCHECK(document_interface_broker_content_receiver.is_valid());
-  DCHECK(document_interface_broker_blink_receiver.is_valid());
-  added_node->current_frame_host()->BindDocumentInterfaceBrokerReceiver(
-      std::move(document_interface_broker_content_receiver),
-      std::move(document_interface_broker_blink_receiver));
-
   DCHECK(browser_interface_broker_receiver.is_valid());
   added_node->current_frame_host()->BindBrowserInterfaceBrokerReceiver(
       std::move(browser_interface_broker_receiver));
diff --git a/content/browser/frame_host/frame_tree.h b/content/browser/frame_host/frame_tree.h
index 092e9cf2..2f47581 100644
--- a/content/browser/frame_host/frame_tree.h
+++ b/content/browser/frame_host/frame_tree.h
@@ -156,10 +156,6 @@
       int new_routing_id,
       service_manager::mojom::InterfaceProviderRequest
           interface_provider_request,
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-          document_interface_broker_content_receiver,
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-          document_interface_broker_blink_receiver,
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker_receiver,
       blink::WebTreeScopeType scope,
diff --git a/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc b/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
index a3a425d..666628c 100644
--- a/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
+++ b/content/browser/frame_host/frame_tree_node_blame_context_unittest.cc
@@ -100,8 +100,6 @@
       tree()->AddFrame(
           node, process_id(), child_id,
           TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-          TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-          TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
           TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
           blink::WebTreeScopeType::kDocument, std::string(),
           base::StringPrintf("uniqueName%d", child_id), false,
diff --git a/content/browser/frame_host/frame_tree_unittest.cc b/content/browser/frame_host/frame_tree_unittest.cc
index 1ffe334..071cc7d 100644
--- a/content/browser/frame_host/frame_tree_unittest.cc
+++ b/content/browser/frame_host/frame_tree_unittest.cc
@@ -57,11 +57,6 @@
   return TestRenderFrameHost::CreateStubInterfaceProviderRequest();
 }
 
-mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-CreateStubDocumentInterfaceBrokerReceiver() {
-  return TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver();
-}
-
 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
 CreateStubBrowserInterfaceBrokerReceiver() {
   return TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver();
@@ -176,48 +171,36 @@
   // Simulate attaching a series of frames to build the frame tree.
   frame_tree->AddFrame(
       root, process_id, 14, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       root, process_id, 15, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       root, process_id, 16, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName2", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       root->child_at(0), process_id, 244, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName3", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       root->child_at(1), process_id, 255, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, no_children_node, "uniqueName4",
       false, base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       root->child_at(0), process_id, 245, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName5", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -232,40 +215,30 @@
   FrameTreeNode* child_16 = root->child_at(2);
   frame_tree->AddFrame(
       child_16, process_id, 264, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName6", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       child_16, process_id, 265, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName7", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       child_16, process_id, 266, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName8", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       child_16, process_id, 267, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, deep_subtree, "uniqueName9", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(
       child_16, process_id, 268, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName10", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -274,16 +247,12 @@
   FrameTreeNode* child_267 = child_16->child_at(3);
   frame_tree->AddFrame(
       child_267, process_id, 365, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName11", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), false, kOwnerType);
   frame_tree->AddFrame(child_267->child_at(0), process_id, 455,
                        CreateStubInterfaceProviderRequest(),
-                       CreateStubDocumentInterfaceBrokerReceiver(),
-                       CreateStubDocumentInterfaceBrokerReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        blink::WebTreeScopeType::kDocument, std::string(),
                        "uniqueName12", false, base::UnguessableToken::Create(),
@@ -291,8 +260,6 @@
                        kOwnerType);
   frame_tree->AddFrame(child_267->child_at(0)->child_at(0), process_id, 555,
                        CreateStubInterfaceProviderRequest(),
-                       CreateStubDocumentInterfaceBrokerReceiver(),
-                       CreateStubDocumentInterfaceBrokerReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        blink::WebTreeScopeType::kDocument, std::string(),
                        "uniqueName13", false, base::UnguessableToken::Create(),
@@ -300,8 +267,6 @@
                        kOwnerType);
   frame_tree->AddFrame(child_267->child_at(0)->child_at(0)->child_at(0),
                        process_id, 655, CreateStubInterfaceProviderRequest(),
-                       CreateStubDocumentInterfaceBrokerReceiver(),
-                       CreateStubDocumentInterfaceBrokerReceiver(),
                        CreateStubBrowserInterfaceBrokerReceiver(),
                        blink::WebTreeScopeType::kDocument, std::string(),
                        "uniqueName14", false, base::UnguessableToken::Create(),
@@ -380,24 +345,18 @@
   constexpr auto kOwnerType = blink::FrameOwnerElementType::kIframe;
   main_test_rfh()->OnCreateChildFrame(
       22, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "child0", "uniqueName0", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
       23, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "child1", "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
       24, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName2", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -409,8 +368,6 @@
   // Add one grandchild frame.
   child1->current_frame_host()->OnCreateChildFrame(
       33, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "grandchild", "uniqueName3", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -453,24 +410,18 @@
   FrameTreeNode* root = frame_tree->root();
   main_test_rfh()->OnCreateChildFrame(
       22, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "child0", "uniqueName0", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
       23, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "child1", "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
       24, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "child2", "uniqueName2", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -482,8 +433,6 @@
   // Add one grandchild frame.
   child1->current_frame_host()->OnCreateChildFrame(
       33, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "grandchild", "uniqueName3", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -519,8 +468,6 @@
   // Simulate attaching a series of frames to build the frame tree.
   main_test_rfh()->OnCreateChildFrame(
       14, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -531,8 +478,6 @@
       activity.GetLog());
   main_test_rfh()->OnCreateChildFrame(
       18, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -557,8 +502,6 @@
   constexpr auto kOwnerType = blink::FrameOwnerElementType::kIframe;
   main_test_rfh()->OnCreateChildFrame(
       22, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -569,8 +512,6 @@
       activity.GetLog());
   main_test_rfh()->OnCreateChildFrame(
       23, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -603,8 +544,6 @@
   // Simulate attaching a frame from mismatched process id.
   ASSERT_FALSE(frame_tree->AddFrame(
       root, process_id + 1, 1, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -623,16 +562,12 @@
   constexpr auto kOwnerType = blink::FrameOwnerElementType::kIframe;
   main_test_rfh()->OnCreateChildFrame(
       22, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
       FrameOwnerProperties(), kOwnerType);
   main_test_rfh()->OnCreateChildFrame(
       23, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -642,8 +577,6 @@
   RenderFrameHostImpl* child1_rfh = root->child_at(0)->current_frame_host();
   child1_rfh->OnCreateChildFrame(
       33, CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName2", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 5b34d44..88441c5 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -1971,8 +1971,6 @@
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), unique_name0, false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2011,8 +2009,6 @@
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), unique_name1, false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2051,8 +2047,6 @@
   subframe->OnCreateChildFrame(
       process()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), unique_name2, false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2109,8 +2103,6 @@
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), unique_name, false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -3345,8 +3337,6 @@
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), unique_name, false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -3514,8 +3504,6 @@
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), unique_name, false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -4776,8 +4764,6 @@
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), unique_name, false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index f71489c4..06f1878 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -202,7 +202,6 @@
 #include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
 #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
 #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
-#include "third_party/blink/public/mojom/frame/frame_host_test_interface.mojom.h"
 #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
 #include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom.h"
 #include "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom.h"
@@ -1816,8 +1815,6 @@
   SetRenderFrameCreated(false);
   InvalidateMojoConnection();
   document_scoped_interface_provider_binding_.Close();
-  document_interface_broker_content_receiver_.reset();
-  document_interface_broker_blink_receiver_.reset();
   broker_receiver_.reset();
   SetLastCommittedUrl(GURL());
   bundled_exchanges_handle_.reset();
@@ -1992,14 +1989,6 @@
   service_manager::mojom::InterfaceProviderPtr interface_provider;
   BindInterfaceProviderRequest(mojo::MakeRequest(&interface_provider));
 
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_content;
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_blink;
-  BindDocumentInterfaceBrokerReceiver(
-      document_interface_broker_content.InitWithNewPipeAndPassReceiver(),
-      document_interface_broker_blink.InitWithNewPipeAndPassReceiver());
-
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
   BindBrowserInterfaceBrokerReceiver(
@@ -2008,8 +1997,6 @@
   mojom::CreateFrameParamsPtr params = mojom::CreateFrameParams::New();
   params->interface_bundle = mojom::DocumentScopedInterfaceBundle::New(
       interface_provider.PassInterface(),
-      std::move(document_interface_broker_content),
-      std::move(document_interface_broker_blink),
       std::move(browser_interface_broker));
 
   params->routing_id = routing_id_;
@@ -2211,10 +2198,6 @@
     int new_routing_id,
     service_manager::mojom::InterfaceProviderRequest
         new_interface_provider_provider_request,
-    mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_content_receiver,
-    mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_blink_receiver,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker_receiver,
     blink::WebTreeScopeType scope,
@@ -2228,8 +2211,6 @@
   // TODO(lukasza): Call ReceivedBadMessage when |frame_unique_name| is empty.
   DCHECK(!frame_unique_name.empty());
   DCHECK(new_interface_provider_provider_request.is_pending());
-  DCHECK(document_interface_broker_content_receiver.is_valid());
-  DCHECK(document_interface_broker_blink_receiver.is_valid());
   DCHECK(browser_interface_broker_receiver.is_valid());
   if (owner_type == blink::FrameOwnerElementType::kNone) {
     // Any child frame must have a HTMLFrameOwnerElement in its parent document
@@ -2247,15 +2228,11 @@
     return;
 
   // |new_routing_id|, |new_interface_provider_provider_request|,
-  // |document_interface_broker_content_receiver|,
-  // |document_interface_broker_blink_receiver|,
   // |browser_interface_broker_receiver| and |devtools_frame_token| were
   // generated on the browser's IO thread and not taken from the renderer
   // process.
   frame_tree_->AddFrame(frame_tree_node_, GetProcess()->GetID(), new_routing_id,
                         std::move(new_interface_provider_provider_request),
-                        std::move(document_interface_broker_content_receiver),
-                        std::move(document_interface_broker_blink_receiver),
                         std::move(browser_interface_broker_receiver), scope,
                         frame_name, frame_unique_name, is_created_by_script,
                         devtools_frame_token, frame_policy,
@@ -2607,7 +2584,6 @@
   CHECK(request != navigation_requests_.end());
 
   std::unique_ptr<NavigationRequest> owned_request = std::move(request->second);
-  base::TimeTicks navigation_start = owned_request->NavigationStart();
   navigation_requests_.erase(committing_navigation_request);
 
   // During a normal (uncached) navigation, is_loading_ is set to true in
@@ -2625,8 +2601,7 @@
                               /*is_same_document_navigation=*/false);
 
   // Now that the restored frame has been committed, unfreeze it.
-  frame_tree_node()->render_manager()->UnfreezeCurrentFrameHost(
-      navigation_start);
+  frame_tree_node()->render_manager()->UnfreezeCurrentFrameHost();
 
   // The page is already loaded since it came from the cache, so fire the stop
   // loading event.
@@ -3231,6 +3206,18 @@
   return enabled_bindings_;
 }
 
+void RenderFrameHostImpl::SetWebUIProperty(const std::string& name,
+                                           const std::string& value) {
+  // This is a sanity check before telling the renderer to enable the property.
+  // It could lie and send the corresponding IPC messages anyway, but we will
+  // not act on them if enabled_bindings_ doesn't agree. If we get here without
+  // WebUI bindings, terminate the renderer process.
+  if (enabled_bindings_ & BINDINGS_POLICY_WEB_UI)
+    Send(new FrameMsg_SetWebUIProperty(routing_id_, name, value));
+  else
+    ReceivedBadMessage(GetProcess(), bad_message::RVH_WEB_UI_BINDINGS_MISMATCH);
+}
+
 void RenderFrameHostImpl::DisableBeforeUnloadHangMonitorForTesting() {
   beforeunload_timeout_.reset();
 }
@@ -4226,23 +4213,6 @@
       std::make_unique<ActiveURLMessageFilter>(this));
 }
 
-void RenderFrameHostImpl::BindDocumentInterfaceBrokerReceiver(
-    mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-        content_receiver,
-    mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-        blink_receiver) {
-  DCHECK(!document_interface_broker_content_receiver_.is_bound());
-  DCHECK(content_receiver.is_valid());
-  document_interface_broker_content_receiver_.Bind(std::move(content_receiver));
-  document_interface_broker_content_receiver_.SetFilter(
-      std::make_unique<ActiveURLMessageFilter>(this));
-  DCHECK(!document_interface_broker_blink_receiver_.is_bound());
-  DCHECK(blink_receiver.is_valid());
-  document_interface_broker_blink_receiver_.Bind(std::move(blink_receiver));
-  document_interface_broker_blink_receiver_.SetFilter(
-      std::make_unique<ActiveURLMessageFilter>(this));
-}
-
 void RenderFrameHostImpl::BindBrowserInterfaceBrokerReceiver(
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> receiver) {
   DCHECK(receiver.is_valid());
@@ -4420,15 +4390,6 @@
   main_frame->BindInterfaceProviderRequest(
       mojo::MakeRequest(&main_frame_interface_provider_info));
 
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_content;
-
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_blink;
-  main_frame->BindDocumentInterfaceBrokerReceiver(
-      document_interface_broker_content.InitWithNewPipeAndPassReceiver(),
-      document_interface_broker_blink.InitWithNewPipeAndPassReceiver());
-
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
   main_frame->BindBrowserInterfaceBrokerReceiver(
@@ -4449,8 +4410,6 @@
       main_frame->GetLocalRenderWidgetHost()->GetRoutingID(), visual_properties,
       mojom::DocumentScopedInterfaceBundle::New(
           std::move(main_frame_interface_provider_info),
-          std::move(document_interface_broker_content),
-          std::move(document_interface_broker_blink),
           std::move(browser_interface_broker)),
       cloned_namespace->id(), main_frame->GetDevToolsFrameToken());
 
@@ -6639,22 +6598,6 @@
   }
 }
 
-// This is a test-only interface, not exposed in production.
-void RenderFrameHostImpl::GetFrameHostTestInterface(
-    mojo::PendingReceiver<blink::mojom::FrameHostTestInterface> receiver) {
-  class FrameHostTestInterfaceImpl
-      : public blink::mojom::FrameHostTestInterface {
-   public:
-    void Ping(const GURL& url, const std::string& event) override {}
-    void GetName(GetNameCallback callback) override {
-      std::move(callback).Run("RenderFrameHostImpl");
-    }
-  };
-
-  mojo::MakeSelfOwnedReceiver(std::make_unique<FrameHostTestInterfaceImpl>(),
-                              std::move(receiver));
-}
-
 void RenderFrameHostImpl::CreateAppCacheBackend(
     mojo::PendingReceiver<blink::mojom::AppCacheBackend> receiver) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -7477,13 +7420,7 @@
             std::move(interface_provider_request_of_previous_document));
     BindInterfaceProviderRequest(
         std::move(interface_params->interface_provider_request));
-
-    document_interface_broker_content_receiver_.reset();
-    document_interface_broker_blink_receiver_.reset();
     broker_receiver_.reset();
-    BindDocumentInterfaceBrokerReceiver(
-        std::move(interface_params->document_interface_broker_content_receiver),
-        std::move(interface_params->document_interface_broker_blink_receiver));
     BindBrowserInterfaceBrokerReceiver(
         std::move(interface_params->browser_interface_broker_receiver));
   } else {
@@ -7496,8 +7433,6 @@
     // possibly from a different security origin, will no longer be dispatched.
     if (frame_tree_node_->has_committed_real_load()) {
       document_scoped_interface_provider_binding_.Close();
-      document_interface_broker_content_receiver_.reset();
-      document_interface_broker_blink_receiver_.reset();
       broker_receiver_.reset();
       bad_message::ReceivedBadMessage(
           process, bad_message::RFH_INTERFACE_PROVIDER_MISSING);
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 135fe5b6..a9b02bd7 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -85,7 +85,6 @@
 #include "third_party/blink/public/mojom/commit_result/commit_result.mojom.h"
 #include "third_party/blink/public/mojom/contacts/contacts_manager.mojom.h"
 #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
 #include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
 #include "third_party/blink/public/mojom/frame/frame.mojom.h"
 #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom.h"
@@ -204,7 +203,6 @@
       public RenderProcessHostObserver,
       public SiteInstanceImpl::Observer,
       public service_manager::mojom::InterfaceProvider,
-      public blink::mojom::DocumentInterfaceBroker,
       public blink::mojom::LocalFrameHost,
       public CSPContext,
       public ui::AXActionHandler {
@@ -292,6 +290,8 @@
                               const std::string& message) override;
   void AllowBindings(int binding_flags) override;
   int GetEnabledBindings() override;
+  void SetWebUIProperty(const std::string& name,
+                        const std::string& value) override;
   void DisableBeforeUnloadHangMonitorForTesting() override;
   bool IsBeforeUnloadHangMonitorDisabledForTesting() override;
   bool GetSuddenTerminationDisablerState(
@@ -415,12 +415,6 @@
   // interface that the RenderFrameHost corresponding to the child frame should
   // bind to expose services to the renderer process. The caller takes care of
   // sending down the client end of the pipe to the child RenderFrame to use.
-  // |document_interface_broker_content_handle| and
-  // |document_interface_broker_blink_handle| are the pipe handles bound by
-  // to request ends of DocumentInterfaceProviderInterface in content and blink
-  // parts of the child frame. RenderFrameHost should bind these handles to
-  // expose services to the renderer process. The caller takes care of sending
-  // down the client end of the pipe to the child RenderFrame to use.
   // |browser_interface_broker_receiver| is the receiver end of
   // BrowserInterfaceBroker interface in the child frame. RenderFrameHost should
   // bind this receiver to expose services to the renderer process. The caller
@@ -430,10 +424,6 @@
       int new_routing_id,
       service_manager::mojom::InterfaceProviderRequest
           interface_provider_request,
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-          document_interface_broker_content_receiver,
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-          document_interface_broker_blink_receiver,
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker_receiver,
       blink::WebTreeScopeType scope,
@@ -884,16 +874,6 @@
       service_manager::mojom::InterfaceProviderRequest
           interface_provider_request);
 
-  // Binds content and blink receiver ends of the DocumentInterfaceProvider
-  // interface through which services provided by this RenderFrameHost are
-  // exposed to the corresponding RenderFrame. The caller is responsible for
-  // plumbing the client ends to the the renderer process.
-  void BindDocumentInterfaceBrokerReceiver(
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-          content_receiver,
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-          blink_receiver);
-
   // Binds the receiver end of the BrowserInterfaceBroker interface through
   // which services provided by this RenderFrameHost are exposed to the
   // corresponding RenderFrame. The caller is responsible for plumbing the
@@ -1669,11 +1649,6 @@
   void GetInterface(const std::string& interface_name,
                     mojo::ScopedMessagePipeHandle interface_pipe) override;
 
-  // blink::mojom::DocumentInterfaceBroker:
-  void GetFrameHostTestInterface(
-      mojo::PendingReceiver<blink::mojom::FrameHostTestInterface> receiver)
-      override;
-
   // Allows tests to disable the swapout event timer to simulate bugs that
   // happen before it fires (to avoid flakiness).
   void DisableSwapOutTimerForTesting();
@@ -2355,15 +2330,6 @@
   mojo::Binding<service_manager::mojom::InterfaceProvider>
       document_scoped_interface_provider_binding_;
 
-  // Receivers for the DocumentInterfaceBroker through which this
-  // RenderFrameHostImpl exposes document-scoped Mojo services to the currently
-  // active document in the corresponding RenderFrame. Because of the type
-  // difference between content and blink, two separate pipes are used.
-  mojo::Receiver<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_content_receiver_{this};
-  mojo::Receiver<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_blink_receiver_{this};
-
   // BrowserInterfaceBroker implementation through which this
   // RenderFrameHostImpl exposes document-scoped Mojo services to the currently
   // active document in the corresponding RenderFrame.
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index e2d9da65..40bea88a 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -624,10 +624,9 @@
   bfcache_entry_to_restore_ = std::move(entry);
 }
 
-void RenderFrameHostManager::UnfreezeCurrentFrameHost(
-    base::TimeTicks navigation_start) {
+void RenderFrameHostManager::UnfreezeCurrentFrameHost() {
   delegate_->GetControllerForRenderManager().GetBackForwardCache().Resume(
-      current_frame_host(), navigation_start);
+      current_frame_host());
 }
 
 void RenderFrameHostManager::ResetProxyHosts() {
diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h
index 1dfba39..08f5e5a 100644
--- a/content/browser/frame_host/render_frame_host_manager.h
+++ b/content/browser/frame_host/render_frame_host_manager.h
@@ -301,7 +301,7 @@
   // BackForwardCache:
   // Unfreezes the current frame host. This is called after committing a
   // navigation to a frame that was restored from the back-forward cache.
-  void UnfreezeCurrentFrameHost(base::TimeTicks navigation_start);
+  void UnfreezeCurrentFrameHost();
 
   // Deletes any proxy hosts associated with this node. Used during destruction
   // of WebContentsImpl.
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc
index b872410..4eff37f7 100644
--- a/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -1781,8 +1781,6 @@
   contents()->GetMainFrame()->OnCreateChildFrame(
       contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "frame_name", "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -1790,8 +1788,6 @@
   contents()->GetMainFrame()->OnCreateChildFrame(
       contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "frame_name", "uniqueName2", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -1934,8 +1930,6 @@
   contents1->GetMainFrame()->OnCreateChildFrame(
       contents1->GetMainFrame()->GetProcess()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "frame_name", "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -1987,8 +1981,6 @@
   main_rfh->OnCreateChildFrame(
       main_rfh->GetProcess()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2157,8 +2149,6 @@
   tree1->AddFrame(
       root1, process_id, 12,
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName0", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2166,8 +2156,6 @@
   tree1->AddFrame(
       root1, process_id, 13,
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2182,8 +2170,6 @@
   tree2->AddFrame(
       root2, process_id, 22,
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName2", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2191,8 +2177,6 @@
   tree2->AddFrame(
       root2, process_id, 23,
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName3", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2212,8 +2196,6 @@
   tree4->AddFrame(
       root4, process_id, 42,
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), "uniqueName4", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2267,8 +2249,6 @@
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "frame1", "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2276,8 +2256,6 @@
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "frame2", "uniqueName2", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2285,8 +2263,6 @@
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "frame3", "uniqueName3", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2385,8 +2361,6 @@
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "frame1", "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -2883,8 +2857,6 @@
   main_test_rfh()->OnCreateChildFrame(
       main_test_rfh()->GetProcess()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, "frame1", "uniqueName1", false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
diff --git a/content/browser/frame_host/render_frame_message_filter.cc b/content/browser/frame_host/render_frame_message_filter.cc
index e4972dba..3ce08e3 100644
--- a/content/browser/frame_host/render_frame_message_filter.cc
+++ b/content/browser/frame_host/render_frame_message_filter.cc
@@ -81,8 +81,6 @@
     blink::FrameOwnerElementType owner_type,
     int new_routing_id,
     mojo::ScopedMessagePipeHandle interface_provider_request_handle,
-    mojo::ScopedMessagePipeHandle document_interface_broker_content_handle,
-    mojo::ScopedMessagePipeHandle document_interface_broker_blink_handle,
     mojo::ScopedMessagePipeHandle browser_interface_broker_handle) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   RenderFrameHostImpl* render_frame_host =
@@ -94,10 +92,6 @@
         new_routing_id,
         service_manager::mojom::InterfaceProviderRequest(
             std::move(interface_provider_request_handle)),
-        mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>(
-            std::move(document_interface_broker_content_handle)),
-        mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>(
-            std::move(document_interface_broker_blink_handle)),
         mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>(
             std::move(browser_interface_broker_handle)),
         scope, frame_name, frame_unique_name, is_created_by_script,
@@ -278,20 +272,6 @@
   params_reply->new_interface_provider =
       interface_provider.PassInterface().PassHandle().release();
 
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_content;
-  auto document_interface_broker_receiver_content =
-      document_interface_broker_content.InitWithNewPipeAndPassReceiver();
-  params_reply->document_interface_broker_content_handle =
-      document_interface_broker_content.PassPipe().release();
-
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_blink;
-  auto document_interface_broker_receiver_blink =
-      document_interface_broker_blink.InitWithNewPipeAndPassReceiver();
-  params_reply->document_interface_broker_blink_handle =
-      document_interface_broker_blink.PassPipe().release();
-
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
   auto browser_interface_broker_receiver =
@@ -310,8 +290,6 @@
           params.frame_policy, params.frame_owner_properties,
           params.frame_owner_element_type, params_reply->child_routing_id,
           interface_provider_request.PassMessagePipe(),
-          document_interface_broker_receiver_content.PassPipe(),
-          document_interface_broker_receiver_blink.PassPipe(),
           browser_interface_broker_receiver.PassPipe()));
 }
 
diff --git a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
index c7d01bf..304ee554 100644
--- a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -19,6 +19,7 @@
 #include "content/browser/browser_plugin/browser_plugin_guest.h"
 #include "content/browser/compositor/test/test_image_transport_factory.h"
 #include "content/browser/gpu/compositor_util.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -58,7 +59,8 @@
         widget.InitWithNewPipeAndPassReceiver());
 
     widget_host_ = new RenderWidgetHostImpl(
-        &delegate_, process_host, routing_id, std::move(widget), false);
+        &delegate_, process_host, routing_id, std::move(widget),
+        /*hidden=*/false, std::make_unique<FrameTokenMessageQueue>());
     view_ = RenderWidgetHostViewGuest::Create(
         widget_host_, nullptr,
         (new TestRenderWidgetHostView(widget_host_))->GetWeakPtr());
@@ -144,7 +146,8 @@
         widget.InitWithNewPipeAndPassReceiver());
 
     widget_host_ = new RenderWidgetHostImpl(
-        &delegate_, process_host, routing_id, std::move(widget), false);
+        &delegate_, process_host, routing_id, std::move(widget),
+        /*hidden=*/false, std::make_unique<FrameTokenMessageQueue>());
     view_ = RenderWidgetHostViewGuest::Create(
         widget_host_, browser_plugin_guest_,
         (new TestRenderWidgetHostView(widget_host_))->GetWeakPtr());
diff --git a/content/browser/media/encrypted_media_browsertest.cc b/content/browser/media/encrypted_media_browsertest.cc
index 088f45e..795cd28 100644
--- a/content/browser/media/encrypted_media_browsertest.cc
+++ b/content/browser/media/encrypted_media_browsertest.cc
@@ -270,6 +270,14 @@
   RunMultipleFileTest(std::string(), "bear-flac-cenc.mp4", media::kEnded);
 }
 
+IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_MP4_OPUS) {
+#if defined(OS_ANDROID)
+  if (!media::MediaCodecUtil::IsOpusDecoderAvailable())
+    return;
+#endif
+  RunMultipleFileTest(std::string(), "bear-opus-cenc.mp4", media::kEnded);
+}
+
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_MP4_VP9) {
   // MP4 without MSE is not support yet, http://crbug.com/170793.
   if (CurrentSourceType() != SrcType::MSE) {
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc
index 8d87f50..d822691d 100644
--- a/content/browser/navigation_browsertest.cc
+++ b/content/browser/navigation_browsertest.cc
@@ -100,16 +100,6 @@
     return intercepted_requests_;
   }
 
-  std::vector<mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>>&
-  intercepted_broker_content_receivers() {
-    return intercepted_broker_content_receivers_;
-  }
-
-  std::vector<mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>>&
-  intercepted_broker_blink_receivers() {
-    return intercepted_broker_blink_receivers_;
-  }
-
  protected:
   bool WillProcessDidCommitNavigation(
       RenderFrameHost* render_frame_host,
@@ -123,16 +113,6 @@
         *interface_params
             ? std::move((*interface_params)->interface_provider_request)
             : nullptr);
-    intercepted_broker_content_receivers_.push_back(
-        *interface_params
-            ? std::move((*interface_params)
-                            ->document_interface_broker_content_receiver)
-            : mojo::NullReceiver());
-    intercepted_broker_blink_receivers_.push_back(
-        *interface_params
-            ? std::move(
-                  (*interface_params)->document_interface_broker_blink_receiver)
-            : mojo::NullReceiver());
     if (loop_)
       loop_->Quit();
     // Do not send the message to the RenderFrameHostImpl.
@@ -146,10 +126,6 @@
       intercepted_messages_;
   std::vector<::service_manager::mojom::InterfaceProviderRequest>
       intercepted_requests_;
-  std::vector<mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>>
-      intercepted_broker_content_receivers_;
-  std::vector<mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>>
-      intercepted_broker_blink_receivers_;
   std::unique_ptr<base::RunLoop> loop_;
 };
 
diff --git a/content/browser/portal/portal.cc b/content/browser/portal/portal.cc
index bbc4261..edd87424 100644
--- a/content/browser/portal/portal.cc
+++ b/content/browser/portal/portal.cc
@@ -148,10 +148,6 @@
       owner_render_frame_host_->GetProcess()->GetID(),
       owner_render_frame_host_->GetProcess()->GetNextRoutingID(),
       std::move(interface_provider_request),
-      mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver(),
-      mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver(),
       mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
           .InitWithNewPipeAndPassReceiver(),
       blink::WebTreeScopeType::kDocument, "", "", true,
diff --git a/content/browser/renderer_host/cursor_manager_unittest.cc b/content/browser/renderer_host/cursor_manager_unittest.cc
index e65b24a..d11672f8 100644
--- a/content/browser/renderer_host/cursor_manager_unittest.cc
+++ b/content/browser/renderer_host/cursor_manager_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/browser/renderer_host/cursor_manager.h"
 
 #include "build/build_config.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -71,7 +72,8 @@
                              process,
                              routing_id,
                              std::move(widget),
-                             false),
+                             /*hidden=*/false,
+                             std::make_unique<FrameTokenMessageQueue>()),
         widget_impl_(std::move(widget_impl)) {}
 
   std::unique_ptr<MockWidgetImpl> widget_impl_;
diff --git a/content/browser/renderer_host/frame_token_message_queue.cc b/content/browser/renderer_host/frame_token_message_queue.cc
index b49bd51..ba69284b 100644
--- a/content/browser/renderer_host/frame_token_message_queue.cc
+++ b/content/browser/renderer_host/frame_token_message_queue.cc
@@ -9,10 +9,13 @@
 
 namespace content {
 
-FrameTokenMessageQueue::FrameTokenMessageQueue(Client* client)
-    : client_(client) {}
+FrameTokenMessageQueue::FrameTokenMessageQueue() = default;
 
-FrameTokenMessageQueue::~FrameTokenMessageQueue() {}
+FrameTokenMessageQueue::~FrameTokenMessageQueue() = default;
+
+void FrameTokenMessageQueue::Init(Client* client) {
+  client_ = client;
+}
 
 void FrameTokenMessageQueue::DidProcessFrame(uint32_t frame_token) {
   // Frame tokens always increase.
diff --git a/content/browser/renderer_host/frame_token_message_queue.h b/content/browser/renderer_host/frame_token_message_queue.h
index 067e0e87..8e5c480 100644
--- a/content/browser/renderer_host/frame_token_message_queue.h
+++ b/content/browser/renderer_host/frame_token_message_queue.h
@@ -49,9 +49,13 @@
     // Process the enqueued message.
     virtual void OnProcessSwapMessage(const IPC::Message& message) = 0;
   };
-  explicit FrameTokenMessageQueue(Client* client);
+  FrameTokenMessageQueue();
   virtual ~FrameTokenMessageQueue();
 
+  // Initializes this instance. This should always be the first method called
+  // to initialize state.
+  void Init(Client* client);
+
   // Signals that a frame with token |frame_token| was finished processing. If
   // there are any queued messages belonging to it, they will be processed.
   void DidProcessFrame(uint32_t frame_token);
@@ -79,7 +83,7 @@
 
  private:
   // Not owned.
-  Client* const client_;
+  Client* client_ = nullptr;
 
   // Last non-zero frame token received from the renderer. Any swap messsages
   // having a token less than or equal to this value will be processed.
diff --git a/content/browser/renderer_host/frame_token_message_queue_unittest.cc b/content/browser/renderer_host/frame_token_message_queue_unittest.cc
index 57f60c8..6a3cd5e 100644
--- a/content/browser/renderer_host/frame_token_message_queue_unittest.cc
+++ b/content/browser/renderer_host/frame_token_message_queue_unittest.cc
@@ -129,8 +129,9 @@
   DISALLOW_COPY_AND_ASSIGN(FrameTokenMessageQueueTest);
 };
 
-FrameTokenMessageQueueTest::FrameTokenMessageQueueTest()
-    : frame_token_message_queue_(&test_client_) {}
+FrameTokenMessageQueueTest::FrameTokenMessageQueueTest() {
+  frame_token_message_queue_.Init(&test_client_);
+}
 
 // Tests that if a valid IPC::Message is enqueued, that it is processed when its
 // matching frame token arrives.
diff --git a/content/browser/renderer_host/input/mouse_latency_browsertest.cc b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
index df5613a..aa68aff 100644
--- a/content/browser/renderer_host/input/mouse_latency_browsertest.cc
+++ b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
@@ -83,7 +83,8 @@
                              process,
                              routing_id,
                              std::move(widget),
-                             hidden) {
+                             hidden,
+                             std::make_unique<FrameTokenMessageQueue>()) {
     ui::LatencyTracker::SetLatencyInfoProcessorForTesting(base::BindRepeating(
         &TracingRenderWidgetHost::HandleLatencyInfoAfterGpuSwap,
         base::Unretained(this)));
diff --git a/content/browser/renderer_host/mock_render_widget_host.cc b/content/browser/renderer_host/mock_render_widget_host.cc
index 0b65bc7..01db35eb 100644
--- a/content/browser/renderer_host/mock_render_widget_host.cc
+++ b/content/browser/renderer_host/mock_render_widget_host.cc
@@ -10,9 +10,8 @@
 namespace {
 class TestFrameTokenMessageQueue : public content::FrameTokenMessageQueue {
  public:
-  explicit TestFrameTokenMessageQueue(FrameTokenMessageQueue::Client* client)
-      : FrameTokenMessageQueue(client) {}
-  ~TestFrameTokenMessageQueue() override {}
+  TestFrameTokenMessageQueue() = default;
+  ~TestFrameTokenMessageQueue() override = default;
 
   uint32_t processed_frame_messages_count() {
     return processed_frame_messages_count_;
@@ -108,12 +107,12 @@
                            process,
                            routing_id,
                            std::move(widget),
-                           false),
+                           /*hidden=*/false,
+                           std::make_unique<TestFrameTokenMessageQueue>()),
       new_content_rendering_timeout_fired_(false),
       widget_impl_(std::move(widget_impl)),
       fling_scheduler_(std::make_unique<FlingScheduler>(this)) {
   acked_touch_event_type_ = blink::WebInputEvent::kUndefined;
-  frame_token_message_queue_.reset(new TestFrameTokenMessageQueue(this));
 }
 
 }  // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 292e9dc..66ec7a1 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1501,7 +1501,7 @@
 
   // This instance of PushMessagingManager is only used from clients
   // bound to service workers (i.e. PushProvider), since frame-bound
-  // clients will rely on DocumentInterfaceBroker instead. Therefore,
+  // clients will rely on BrowserInterfaceBroker instead. Therefore,
   // pass an invalid frame ID here.
   //
   // Constructing the manager must occur after RegisterHost(), since
diff --git a/content/browser/renderer_host/render_process_host_unittest.cc b/content/browser/renderer_host/render_process_host_unittest.cc
index 6e4d0c4..05b0d08 100644
--- a/content/browser/renderer_host/render_process_host_unittest.cc
+++ b/content/browser/renderer_host/render_process_host_unittest.cc
@@ -134,8 +134,6 @@
   main_test_rfh()->OnCreateChildFrame(
       process()->GetNextRoutingID(),
       TestRenderFrameHost::CreateStubInterfaceProviderRequest(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
-      TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver(),
       TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, std::string(), unique_name, false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 676c058..b34aa688 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -349,11 +349,6 @@
         mojom::DocumentScopedInterfaceBundle::New();
     main_rfh->BindInterfaceProviderRequest(mojo::MakeRequest(
         &params->main_frame_interface_bundle->interface_provider));
-    main_rfh->BindDocumentInterfaceBrokerReceiver(
-        params->main_frame_interface_bundle->document_interface_broker_content
-            .InitWithNewPipeAndPassReceiver(),
-        params->main_frame_interface_bundle->document_interface_broker_blink
-            .InitWithNewPipeAndPassReceiver());
     main_rfh->BindBrowserInterfaceBrokerReceiver(
         params->main_frame_interface_bundle->browser_interface_broker
             .InitWithNewPipeAndPassReceiver());
@@ -764,18 +759,6 @@
   return delegate_->GetPendingMainFrame();
 }
 
-void RenderViewHostImpl::SetWebUIProperty(const std::string& name,
-                                          const std::string& value) {
-  // This is a sanity check before telling the renderer to enable the property.
-  // It could lie and send the corresponding IPC messages anyway, but we will
-  // not act on them if enabled_bindings_ doesn't agree. If we get here without
-  // WebUI bindings, kill the renderer process.
-  if (GetMainFrame()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI)
-    Send(new ViewMsg_SetWebUIProperty(GetRoutingID(), name, value));
-  else
-    ReceivedBadMessage(GetProcess(), bad_message::RVH_WEB_UI_BINDINGS_MISMATCH);
-}
-
 void RenderViewHostImpl::RenderWidgetGotFocus() {
   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
   if (view)
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 80ef5c5b..994b6142 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -102,8 +102,6 @@
   SiteInstanceImpl* GetSiteInstance() override;
   bool IsRenderViewLive() override;
   void NotifyMoveOrResizeStarted() override;
-  void SetWebUIProperty(const std::string& name,
-                        const std::string& value) override;
   WebPreferences GetWebkitPreferences() override;
   void UpdateWebkitPreferences(const WebPreferences& prefs) override;
   void OnWebkitPreferencesChanged() override;
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index 40ee2c5..bf10c09 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -12,6 +12,7 @@
 
 #include "base/callback.h"
 #include "build/build_config.h"
+#include "components/viz/common/vertical_scroll_direction.h"
 #include "content/browser/renderer_host/input_event_shim.h"
 #include "content/common/content_export.h"
 #include "content/common/drag_event_source_info.h"
@@ -306,11 +307,6 @@
   // Note: This is also exposed by the RenderFrameHostDelegate.
   virtual ukm::SourceId GetUkmSourceIdForLastCommittedSource() const;
 
-  // Notifies the delegate that a focused editable element has been touched
-  // inside this RenderWidgetHost. If |editable| is true then the focused
-  // element accepts text input.
-  virtual void FocusedNodeTouched(bool editable) {}
-
   // Return this object cast to a WebContents, if it is one. If the object is
   // not a WebContents, returns nullptr.
   virtual WebContents* GetAsWebContents();
@@ -331,6 +327,15 @@
   // Returns the focused frame across all delegates, or nullptr if none.
   virtual RenderFrameHostImpl* GetFocusedFrameFromFocusedDelegate();
 
+  // Invoked when the vertical scroll direction of the root layer changes. Note
+  // that if a scroll in a given direction occurs, the scroll is completed, and
+  // then another scroll in the *same* direction occurs, we will not consider
+  // the second scroll event to have caused a change in direction. Also note
+  // note that this API will *never* be called with |kNull| which only exists to
+  // indicate the absence of a vertical scroll direction.
+  virtual void OnVerticalScrollDirectionChanged(
+      viz::VerticalScrollDirection scroll_direction) {}
+
  protected:
   virtual ~RenderWidgetHostDelegate() {}
 };
diff --git a/content/browser/renderer_host/render_widget_host_factory.cc b/content/browser/renderer_host/render_widget_host_factory.cc
index db3617c..d13c1a7 100644
--- a/content/browser/renderer_host/render_widget_host_factory.cc
+++ b/content/browser/renderer_host/render_widget_host_factory.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/renderer_host/render_widget_host_factory.h"
 
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 
 namespace content {
@@ -23,7 +24,8 @@
         delegate, process, routing_id, std::move(widget_interface), hidden);
   }
   return std::make_unique<RenderWidgetHostImpl>(
-      delegate, process, routing_id, std::move(widget_interface), hidden);
+      delegate, process, routing_id, std::move(widget_interface), hidden,
+      std::make_unique<FrameTokenMessageQueue>());
 }
 
 // static
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index a66279d6..c988820 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -345,7 +345,8 @@
     RenderProcessHost* process,
     int32_t routing_id,
     mojo::PendingRemote<mojom::Widget> widget,
-    bool hidden)
+    bool hidden,
+    std::unique_ptr<FrameTokenMessageQueue> frame_token_message_queue)
     : delegate_(delegate),
       process_(process),
       routing_id_(routing_id),
@@ -356,8 +357,7 @@
       new_content_rendering_delay_(
           TimeDelta::FromMilliseconds(kNewContentRenderingDelayMs)),
       compositor_frame_sink_receiver_(this),
-      frame_token_message_queue_(
-          std::make_unique<FrameTokenMessageQueue>(this)),
+      frame_token_message_queue_(std::move(frame_token_message_queue)),
       render_frame_metadata_provider_(
 #if defined(OS_MACOSX)
           ui::WindowResizeHelperMac::Get()->task_runner(),
@@ -367,6 +367,9 @@
           frame_token_message_queue_.get()),
       frame_sink_id_(base::checked_cast<uint32_t>(process_->GetID()),
                      base::checked_cast<uint32_t>(routing_id_)) {
+  DCHECK(frame_token_message_queue_);
+  frame_token_message_queue_->Init(this);
+
 #if defined(OS_MACOSX)
   fling_scheduler_ = std::make_unique<FlingSchedulerMac>(this);
 #elif defined(OS_ANDROID)
@@ -637,7 +640,6 @@
     IPC_MESSAGE_HANDLER(WidgetHostMsg_UnlockMouse, OnUnlockMouse)
     IPC_MESSAGE_HANDLER(WidgetHostMsg_SelectionBoundsChanged,
                         OnSelectionBoundsChanged)
-    IPC_MESSAGE_HANDLER(WidgetHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
     IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
     IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
     IPC_MESSAGE_HANDLER(WidgetHostMsg_FrameSwapMessages,
@@ -1797,11 +1799,6 @@
     view_->SelectionBoundsChanged(params);
 }
 
-void RenderWidgetHostImpl::OnFocusedNodeTouched(bool editable) {
-  if (delegate_)
-    delegate_->FocusedNodeTouched(editable);
-}
-
 void RenderWidgetHostImpl::OnStartDragging(
     const DropData& drop_data,
     blink::WebDragOperationsMask drag_operations_mask,
@@ -3234,12 +3231,31 @@
     const cc::RenderFrameMetadata& metadata) {}
 
 void RenderWidgetHostImpl::OnRenderFrameMetadataChangedAfterActivation() {
-  bool is_mobile_optimized =
-      render_frame_metadata_provider_.LastRenderFrameMetadata()
-          .is_mobile_optimized;
+  const auto& metadata =
+      render_frame_metadata_provider_.LastRenderFrameMetadata();
+
+  bool is_mobile_optimized = metadata.is_mobile_optimized;
   input_router_->NotifySiteIsMobileOptimized(is_mobile_optimized);
   if (auto* touch_emulator = GetExistingTouchEmulator())
     touch_emulator->SetDoubleTapSupportForPageEnabled(!is_mobile_optimized);
+
+  // The value |kNull| is only used to indicate an absence of vertical scroll
+  // direction and should therefore be ignored.
+  if (metadata.new_vertical_scroll_direction ==
+      viz::VerticalScrollDirection::kNull) {
+    return;
+  }
+
+  // Changes in vertical scroll direction are only propagated for main frames.
+  // If there is no |owner_delegate|, this is not a main frame.
+  if (!owner_delegate())
+    return;
+
+  if (!delegate())
+    return;
+
+  delegate()->OnVerticalScrollDirectionChanged(
+      metadata.new_vertical_scroll_direction);
 }
 
 void RenderWidgetHostImpl::OnLocalSurfaceIdChanged(
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index dd76a0ef..85ae36e 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -166,11 +166,13 @@
   // |routing_id| must not be MSG_ROUTING_NONE.
   // If this object outlives |delegate|, DetachDelegate() must be called when
   // |delegate| goes away.
-  RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
-                       RenderProcessHost* process,
-                       int32_t routing_id,
-                       mojo::PendingRemote<mojom::Widget> widget_interface,
-                       bool hidden);
+  RenderWidgetHostImpl(
+      RenderWidgetHostDelegate* delegate,
+      RenderProcessHost* process,
+      int32_t routing_id,
+      mojo::PendingRemote<mojom::Widget> widget_interface,
+      bool hidden,
+      std::unique_ptr<FrameTokenMessageQueue> frame_token_message_queue);
 
   ~RenderWidgetHostImpl() override;
 
@@ -898,7 +900,6 @@
   void OnSelectionBoundsChanged(
       const WidgetHostMsg_SelectionBounds_Params& params);
   void OnSetNeedsBeginFrames(bool needs_begin_frames);
-  void OnFocusedNodeTouched(bool editable);
   void OnStartDragging(const DropData& drop_data,
                        blink::WebDragOperationsMask operations_allowed,
                        const SkBitmap& bitmap,
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
index 6b8be4da..be6d8b0 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -13,6 +13,7 @@
 #include "content/browser/compositor/surface_utils.h"
 #include "content/browser/compositor/test/test_image_transport_factory.h"
 #include "content/browser/renderer_host/frame_connector_delegate.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
 #include "content/browser/renderer_host/render_widget_targeter.h"
@@ -206,7 +207,8 @@
         widget_root.InitWithNewPipeAndPassReceiver());
     widget_host_root_ = std::make_unique<RenderWidgetHostImpl>(
         &delegate_, process_host_root_.get(),
-        process_host_root_->GetNextRoutingID(), std::move(widget_root), false);
+        process_host_root_->GetNextRoutingID(), std::move(widget_root),
+        /*hidden=*/false, std::make_unique<FrameTokenMessageQueue>());
     view_root_ =
         std::make_unique<MockRootRenderWidgetHostView>(widget_host_root_.get());
 
@@ -241,7 +243,8 @@
         widget_child.InitWithNewPipeAndPassReceiver());
     child.widget_host = std::make_unique<RenderWidgetHostImpl>(
         &delegate_, child.process_host.get(),
-        child.process_host->GetNextRoutingID(), std::move(widget_child), false);
+        child.process_host->GetNextRoutingID(), std::move(widget_child),
+        /*hidden=*/false, std::make_unique<FrameTokenMessageQueue>());
     child.view = std::make_unique<TestRenderWidgetHostViewChildFrame>(
         child.widget_host.get());
     child.frame_connector = std::make_unique<MockFrameConnectorDelegate>(
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 9626750..fa484126 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -378,6 +378,20 @@
     return focus_owning_web_contents_call_count;
   }
 
+  void OnVerticalScrollDirectionChanged(
+      viz::VerticalScrollDirection scroll_direction) override {
+    ++on_vertical_scroll_direction_changed_call_count_;
+    last_vertical_scroll_direction_ = scroll_direction;
+  }
+
+  int GetOnVerticalScrollDirectionChangedCallCount() const {
+    return on_vertical_scroll_direction_changed_call_count_;
+  }
+
+  viz::VerticalScrollDirection GetLastVerticalScrollDirection() const {
+    return last_vertical_scroll_direction_;
+  }
+
   RenderViewHostDelegateView* GetDelegateView() override {
     return mock_delegate_view();
   }
@@ -448,6 +462,10 @@
   double zoom_level_ = 0;
 
   int focus_owning_web_contents_call_count = 0;
+
+  int on_vertical_scroll_direction_changed_call_count_ = 0;
+  viz::VerticalScrollDirection last_vertical_scroll_direction_ =
+      viz::VerticalScrollDirection::kNull;
 };
 
 class MockRenderWidgetHostOwnerDelegate
@@ -2180,4 +2198,43 @@
 }
 #endif
 
+// Tests that vertical scroll direction changes are propagated to the delegate.
+TEST_F(RenderWidgetHostTest, OnVerticalScrollDirectionChanged) {
+  const auto NotifyVerticalScrollDirectionChanged =
+      [this](viz::VerticalScrollDirection scroll_direction) {
+        static uint32_t frame_token = 1u;
+        host_->frame_token_message_queue_->DidProcessFrame(frame_token);
+
+        cc::RenderFrameMetadata metadata;
+        metadata.new_vertical_scroll_direction = scroll_direction;
+        static_cast<mojom::RenderFrameMetadataObserverClient*>(
+            host_->render_frame_metadata_provider())
+            ->OnRenderFrameMetadataChanged(frame_token++, metadata);
+      };
+
+  // Verify initial state.
+  EXPECT_EQ(0, delegate_->GetOnVerticalScrollDirectionChangedCallCount());
+  EXPECT_EQ(viz::VerticalScrollDirection::kNull,
+            delegate_->GetLastVerticalScrollDirection());
+
+  // Verify that we will *not* propagate a vertical scroll of |kNull| which is
+  // only used to indicate the absence of a change in vertical scroll direction.
+  NotifyVerticalScrollDirectionChanged(viz::VerticalScrollDirection::kNull);
+  EXPECT_EQ(0, delegate_->GetOnVerticalScrollDirectionChangedCallCount());
+  EXPECT_EQ(viz::VerticalScrollDirection::kNull,
+            delegate_->GetLastVerticalScrollDirection());
+
+  // Verify that we will propagate a vertical scroll |kUp|.
+  NotifyVerticalScrollDirectionChanged(viz::VerticalScrollDirection::kUp);
+  EXPECT_EQ(1, delegate_->GetOnVerticalScrollDirectionChangedCallCount());
+  EXPECT_EQ(viz::VerticalScrollDirection::kUp,
+            delegate_->GetLastVerticalScrollDirection());
+
+  // Verify that we will propagate a vertical scroll |kDown|.
+  NotifyVerticalScrollDirectionChanged(viz::VerticalScrollDirection::kDown);
+  EXPECT_EQ(2, delegate_->GetOnVerticalScrollDirectionChangedCallCount());
+  EXPECT_EQ(viz::VerticalScrollDirection::kDown,
+            delegate_->GetLastVerticalScrollDirection());
+}
+
 }  // namespace content
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 e346d20..1e4ffbe 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -360,7 +360,6 @@
 #if defined(OS_WIN)
       legacy_render_widget_host_HWND_(nullptr),
       legacy_window_destroyed_(false),
-      virtual_keyboard_requested_(false),
 #endif
       is_guest_view_hack_(is_guest_view_hack),
       device_scale_factor_(0.0f),
@@ -763,28 +762,6 @@
   }
 }
 
-void RenderWidgetHostViewAura::FocusedNodeTouched(bool editable) {
-#if defined(OS_WIN)
-  auto* input_method = GetInputMethod();
-  if (!input_method || !input_method->GetInputMethodKeyboardController())
-    return;
-  auto* controller = input_method->GetInputMethodKeyboardController();
-  if (editable && host()->GetView() && host()->delegate()) {
-    if (last_pointer_type_ == ui::EventPointerType::POINTER_TYPE_TOUCH) {
-      keyboard_observer_.reset(new WinScreenKeyboardObserver(this));
-      if (!controller->DisplayVirtualKeyboard())
-        keyboard_observer_.reset(nullptr);
-    } else {
-      keyboard_observer_.reset(nullptr);
-    }
-    virtual_keyboard_requested_ = keyboard_observer_.get();
-  } else {
-    virtual_keyboard_requested_ = false;
-    controller->DismissVirtualKeyboard();
-  }
-#endif
-}
-
 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
   GetCursorManager()->UpdateCursor(this, cursor);
 }
@@ -1799,16 +1776,7 @@
     input_method->CancelComposition(this);
   has_composition_text_ = false;
 
-#if defined(OS_WIN)
-  if (!editable && virtual_keyboard_requested_ && window_) {
-    virtual_keyboard_requested_ = false;
-
-    if (input_method && input_method->GetInputMethodKeyboardController()) {
-      input_method->GetInputMethodKeyboardController()
-          ->DismissVirtualKeyboard();
-    }
-  }
-#elif defined(OS_FUCHSIA)
+#if defined(OS_FUCHSIA)
   if (!editable && window_) {
     if (input_method) {
       input_method->GetInputMethodKeyboardController()
@@ -2460,6 +2428,22 @@
     // Ensure that accessibility events are fired when the selection location
     // moves from UI back to content.
     text_input_manager->NotifySelectionBoundsChanged(updated_view);
+    // Register for input pane visibility change.
+#if defined(OS_WIN)
+    auto* controller = GetInputMethod()->GetInputMethodKeyboardController();
+    if (controller && state->show_ime_if_needed && host()->GetView() &&
+        host()->delegate()) {
+      if (show_virtual_keyboard) {
+        keyboard_observer_.reset(new WinScreenKeyboardObserver(this));
+        if (!controller->DisplayVirtualKeyboard())
+          keyboard_observer_.reset(nullptr);
+      } else {
+        keyboard_observer_.reset(nullptr);
+      }
+    } else {
+      keyboard_observer_.reset(nullptr);
+    }
+#endif
   }
 
   if (auto* render_widget_host = updated_view->host()) {
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 ca28672..8e874e2 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -113,7 +113,6 @@
   bool IsMouseLocked() override;
   gfx::Size GetVisibleViewportSize() override;
   void SetInsets(const gfx::Insets& insets) override;
-  void FocusedNodeTouched(bool editable) override;
   void SetNeedsBeginFrames(bool needs_begin_frames) override;
   void SetWantsAnimateOnlyBeginFrames() override;
   TouchSelectionControllerClientManager*
@@ -651,9 +650,6 @@
   // we receive a request to show the context menu on a long press.
   std::unique_ptr<ContextMenuParams> last_context_menu_params_;
 
-  // Set to true if we requested the on screen keyboard to be displayed.
-  bool virtual_keyboard_requested_;
-
   friend class WinScreenKeyboardObserver;
   std::unique_ptr<WinScreenKeyboardObserver> keyboard_observer_;
 
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 a463463..e3de2e7 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
@@ -49,6 +49,7 @@
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/renderer_host/delegated_frame_host.h"
 #include "content/browser/renderer_host/delegated_frame_host_client_aura.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/input/input_router.h"
 #include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
 #include "content/browser/renderer_host/overscroll_controller.h"
@@ -430,7 +431,8 @@
                              process,
                              routing_id,
                              std::move(widget),
-                             false),
+                             /*hidden=*/false,
+                             std::make_unique<FrameTokenMessageQueue>()),
         widget_impl_(std::move(widget_impl)) {
     lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo();
   }
@@ -662,6 +664,7 @@
 
     TextInputState state_with_type_text;
     state_with_type_text.type = type;
+    state_with_type_text.show_ime_if_needed = true;
     view->TextInputStateChanged(state_with_type_text);
   }
 
@@ -6757,7 +6760,7 @@
 
 TEST_F(RenderWidgetHostViewAuraKeyboardTest, KeyboardObserverDestroyed) {
   parent_view_->SetLastPointerType(ui::EventPointerType::POINTER_TYPE_TOUCH);
-  parent_view_->FocusedNodeTouched(true);
+  ActivateViewForTextInputManager(parent_view_, ui::TEXT_INPUT_TYPE_TEXT);
   EXPECT_NE(parent_view_->keyboard_observer_.get(), nullptr);
   EXPECT_EQ(keyboard_controller_observer_count(), 1u);
   // Detach the RenderWidgetHostViewAura from the IME.
@@ -6770,12 +6773,12 @@
        KeyboardObserverForOnlyTouchInput) {
   // Show virtual keyboard for touch inputs.
   parent_view_->SetLastPointerType(ui::EventPointerType::POINTER_TYPE_TOUCH);
-  parent_view_->FocusedNodeTouched(true);
+  ActivateViewForTextInputManager(parent_view_, ui::TEXT_INPUT_TYPE_TEXT);
   EXPECT_NE(parent_view_->keyboard_observer_.get(), nullptr);
   EXPECT_EQ(keyboard_controller_observer_count(), 1u);
   // Do not show virtual keyboard for mouse inputs.
   parent_view_->SetLastPointerType(ui::EventPointerType::POINTER_TYPE_MOUSE);
-  parent_view_->FocusedNodeTouched(true);
+  ActivateViewForTextInputManager(parent_view_, ui::TEXT_INPUT_TYPE_TEXT);
   EXPECT_EQ(parent_view_->keyboard_observer_.get(), nullptr);
   EXPECT_EQ(keyboard_controller_observer_count(), 0u);
 }
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 50aad3c..ce5ca1a 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -566,11 +566,6 @@
   return weak_factory_.GetWeakPtr();
 }
 
-void RenderWidgetHostViewBase::FocusedNodeTouched(
-    bool editable) {
-  DVLOG(1) << "FocusedNodeTouched: " << editable;
-}
-
 void RenderWidgetHostViewBase::GetScreenInfo(ScreenInfo* screen_info) {
   DisplayUtil::GetNativeViewScreenInfo(screen_info, GetNativeView());
 }
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 add7df1..f299bb0 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -120,7 +120,6 @@
       base::OnceCallback<void(const SkBitmap&)> callback) override;
   std::unique_ptr<viz::ClientFrameSinkVideoCapturer> CreateVideoCapturer()
       override;
-  void FocusedNodeTouched(bool editable) override;
   void GetScreenInfo(ScreenInfo* screen_info) override;
   void EnableAutoResize(const gfx::Size& min_size,
                         const gfx::Size& max_size) override;
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index 0e065bae..bf935c52 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -26,6 +26,7 @@
 #include "content/browser/compositor/test/test_image_transport_factory.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/renderer_host/frame_connector_delegate.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/common/frame_visual_properties.h"
@@ -126,7 +127,8 @@
     widget_impl_ = std::make_unique<MockWidgetImpl>(
         widget.InitWithNewPipeAndPassReceiver());
     widget_host_ = new RenderWidgetHostImpl(
-        &delegate_, process_host, routing_id, std::move(widget), false);
+        &delegate_, process_host, routing_id, std::move(widget),
+        /*hidden=*/false, std::make_unique<FrameTokenMessageQueue>());
     view_ = RenderWidgetHostViewChildFrame::Create(widget_host_);
 
     test_frame_connector_ =
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
index 4bdbb690..67e7b0a3 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -13,6 +13,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/compositor/test/test_image_transport_factory.h"
 #include "content/browser/gpu/compositor_util.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/common/input_messages.h"
@@ -149,7 +150,8 @@
             widget.InitWithNewPipeAndPassReceiver());
 
     RenderWidgetHostImpl* render_widget = new RenderWidgetHostImpl(
-        &delegate, process_host, routing_id, std::move(widget), false);
+        &delegate, process_host, routing_id, std::move(widget),
+        /*hidden=*/false, std::make_unique<FrameTokenMessageQueue>());
 
     ui::WindowResizeHelperMac::Get()->Init(base::ThreadTaskRunnerHandle::Get());
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index f4ac9aa..cee79138 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -28,6 +28,7 @@
 #include "content/browser/compositor/image_transport_factory.h"
 #include "content/browser/frame_host/render_widget_host_view_guest.h"
 #include "content/browser/gpu/compositor_util.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/text_input_manager.h"
 #include "content/common/input_messages.h"
@@ -368,7 +369,8 @@
                              process,
                              routing_id,
                              std::move(widget),
-                             false),
+                             /*hidden=*/false,
+                             std::make_unique<FrameTokenMessageQueue>()),
         widget_impl_(std::move(widget_impl)) {
     set_renderer_initialized(true);
     lastWheelEventLatencyInfo = ui::LatencyInfo();
diff --git a/content/browser/renderer_host/text_input_client_mac_unittest.mm b/content/browser/renderer_host/text_input_client_mac_unittest.mm
index 28d2c58..538618f 100644
--- a/content/browser/renderer_host/text_input_client_mac_unittest.mm
+++ b/content/browser/renderer_host/text_input_client_mac_unittest.mm
@@ -11,6 +11,7 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -62,8 +63,9 @@
     mock_widget_impl_ = std::make_unique<MockWidgetImpl>(
         widget.InitWithNewPipeAndPassReceiver());
 
-    widget_.reset(new RenderWidgetHostImpl(&delegate_, rph, routing_id,
-                                           std::move(widget), false));
+    widget_.reset(new RenderWidgetHostImpl(
+        &delegate_, rph, routing_id, std::move(widget), /*hidden=*/false,
+        std::make_unique<FrameTokenMessageQueue>()));
   }
 
   void TearDown() override {
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index ef01149..d303c1b5 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -408,8 +408,8 @@
   EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());
   EXPECT_EQ(0, shell()->web_contents()->GetMainFrame()->GetEnabledBindings());
 
-  RenderViewHost* compromised_renderer =
-      shell()->web_contents()->GetRenderViewHost();
+  RenderFrameHost* compromised_renderer =
+      shell()->web_contents()->GetMainFrame();
   RenderProcessHostKillWaiter kill_waiter(compromised_renderer->GetProcess());
   compromised_renderer->SetWebUIProperty("toolkit", "views");
   EXPECT_EQ(bad_message::RVH_WEB_UI_BINDINGS_MISMATCH, kill_waiter.Wait());
@@ -749,7 +749,7 @@
 // rule, see: RenderFrameHostImplBrowserTest.
 // InterfaceProviderRequestIsOptionalForFirstCommit.
 // TODO(crbug.com/718652): when all clients are converted to use
-// DocumentInterfaceBroker, InterfaceProviderRequest-related code will be
+// BrowserInterfaceBroker, InterfaceProviderRequest-related code will be
 // removed.
 IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                        MissingInterfaceProviderOnNonSameDocumentCommit) {
@@ -883,10 +883,6 @@
           std::move(params),
           mojom::DidCommitProvisionalLoadInterfaceParams::New(
               mojo::MakeRequest(&isolated_interface_provider),
-              mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-                  .InitWithNewPipeAndPassReceiver(),
-              mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-                  .InitWithNewPipeAndPassReceiver(),
               mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
                   .InitWithNewPipeAndPassReceiver()));
 
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 26f26d2..17147204 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -6200,10 +6200,6 @@
     params->routing_id = frame_routing_id;
     params->interface_bundle = mojom::DocumentScopedInterfaceBundle::New();
     mojo::MakeRequest(&params->interface_bundle->interface_provider);
-    ignore_result(params->interface_bundle->document_interface_broker_content
-                      .InitWithNewPipeAndPassReceiver());
-    ignore_result(params->interface_bundle->document_interface_broker_blink
-                      .InitWithNewPipeAndPassReceiver());
     ignore_result(params->interface_bundle->browser_interface_broker
                       .InitWithNewPipeAndPassReceiver());
     params->previous_routing_id = previous_routing_id;
@@ -6270,10 +6266,6 @@
     params->routing_id = frame_routing_id;
     params->interface_bundle = mojom::DocumentScopedInterfaceBundle::New();
     mojo::MakeRequest(&params->interface_bundle->interface_provider);
-    ignore_result(params->interface_bundle->document_interface_broker_content
-                      .InitWithNewPipeAndPassReceiver());
-    ignore_result(params->interface_bundle->document_interface_broker_blink
-                      .InitWithNewPipeAndPassReceiver());
     ignore_result(params->interface_bundle->browser_interface_broker
                       .InitWithNewPipeAndPassReceiver());
     params->previous_routing_id = IPC::mojom::kRoutingIdNone;
@@ -14435,10 +14427,6 @@
           std::move(params),
           mojom::DidCommitProvisionalLoadInterfaceParams::New(
               mojo::MakeRequest(&interface_provider),
-              mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-                  .InitWithNewPipeAndPassReceiver(),
-              mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-                  .InitWithNewPipeAndPassReceiver(),
               mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
                   .InitWithNewPipeAndPassReceiver()));
 
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index afd538a3..24f6c1c 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -2466,7 +2466,6 @@
   const int inset_height = 200;
   parent_render_widget_host_aura->SetLastPointerType(
       ui::EventPointerType::POINTER_TYPE_TOUCH);
-  parent_render_widget_host_aura->FocusedNodeTouched(true);
   parent_render_widget_host_aura->SetInsets(gfx::Insets(0, 0, inset_height, 0));
 
   // After focus on editable element, we expect element to be scrolled
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 24667e2..9a9b78eb 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -73,6 +73,7 @@
 #include "content/browser/media/media_web_contents_observer.h"
 #include "content/browser/media/session/media_session_impl.h"
 #include "content/browser/plugin_content_origin_whitelist.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
@@ -1645,6 +1646,12 @@
   return focused_node ? focused_node->current_frame_host() : nullptr;
 }
 
+void WebContentsImpl::OnVerticalScrollDirectionChanged(
+    viz::VerticalScrollDirection scroll_direction) {
+  for (auto& observer : observers_)
+    observer.DidChangeVerticalScrollDirection(scroll_direction);
+}
+
 void WebContentsImpl::OnAudioStateChanged() {
   // This notification can come from any embedded contents or from this
   // WebContents' stream monitor. Aggregate these signals to get the actual
@@ -2993,7 +3000,8 @@
   }
 
   RenderWidgetHostImpl* widget_host = new RenderWidgetHostImpl(
-      this, process, route_id, std::move(widget), IsHidden());
+      this, process, route_id, std::move(widget), IsHidden(),
+      std::make_unique<FrameTokenMessageQueue>());
   RenderWidgetHostViewBase* widget_view =
       static_cast<RenderWidgetHostViewBase*>(
           view_->CreateViewForChildWidget(widget_host));
@@ -4394,13 +4402,6 @@
     NavigationHandle* navigation_handle) {
   TRACE_EVENT1("navigation", "WebContentsImpl::ReadyToCommitNavigation",
                "navigation_handle", navigation_handle);
-
-  if (!navigation_handle->GetParentFrame() &&
-      record_max_frame_count_when_leaving_current_page_) {
-    RecordMaxFrameCountUMA(max_frame_count_);
-    record_max_frame_count_when_leaving_current_page_ = false;
-  }
-
   for (auto& observer : observers_)
     observer.ReadyToCommitNavigation(navigation_handle);
 
@@ -4493,15 +4494,20 @@
     should_focus_location_bar_by_default_ = false;
   }
 
-  // If navigation has successfully finished in the main page, set
-  // |record_max_frame_count_when_leaving_current_page_| to true so that when
-  // the main frame navigates away from this page we know to record this page's
-  // max frame count.
-  if (navigation_handle->IsInMainFrame() && !navigation_handle->IsErrorPage()) {
-    record_max_frame_count_when_leaving_current_page_ = true;
+  if (navigation_handle->IsInMainFrame() && first_navigation_completed_)
+    RecordMaxFrameCountUMA(max_loaded_frame_count_);
 
-    // Navigation has completed in main frame. Reset |max_frame_count_| to 1.
-    max_frame_count_ = 1;
+  // If navigation has successfully finished in the main frame, set
+  // |first_navigation_completed_| to true so that we will record
+  // |max_loaded_frame_count_| above when future main frame navigations finish.
+  if (navigation_handle->IsInMainFrame() && !navigation_handle->IsErrorPage()) {
+    first_navigation_completed_ = true;
+
+    // Navigation has completed in main frame. Reset |max_loaded_frame_count_|.
+    // |max_loaded_frame_count_| is not necessarily 1 if the navigation was
+    // served from BackForwardCache.
+    max_loaded_frame_count_ =
+        GetMainFrame()->frame_tree_node()->GetFrameTreeSize();
   }
 }
 
@@ -4858,13 +4864,15 @@
   GURL validated_url(url);
   source->GetProcess()->FilterURL(false, &validated_url);
 
-  if (!source->GetParent()) {
-    size_t frame_count = source->frame_tree_node()->GetFrameTreeSize();
-    UMA_HISTOGRAM_COUNTS_1000("Navigation.MainFrame.FrameCount", frame_count);
-  }
-
   for (auto& observer : observers_)
     observer.DidFinishLoad(source, validated_url);
+
+  size_t tree_size = frame_tree_.root()->GetFrameTreeSize();
+  if (max_loaded_frame_count_ < tree_size)
+    max_loaded_frame_count_ = tree_size;
+
+  if (!source->GetParent())
+    UMA_HISTOGRAM_COUNTS_1000("Navigation.MainFrame.FrameCount", tree_size);
 }
 
 void WebContentsImpl::OnGoToEntryAtOffset(RenderFrameHostImpl* source,
@@ -5298,12 +5306,6 @@
 void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost* old_host,
                                          RenderFrameHost* new_host,
                                          bool is_main_frame) {
-  if (!old_host) {
-    frame_count_++;
-    if (max_frame_count_ < frame_count_)
-      max_frame_count_ = frame_count_;
-  }
-
 #if defined(OS_ANDROID)
   // Copy importance from |old_host| if |new_host| is a main frame.
   if (old_host && !new_host->GetParent()) {
@@ -5408,18 +5410,18 @@
 }
 
 void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
-  if (!render_frame_host->GetParent() && IsBeingDestroyed() &&
-      record_max_frame_count_when_leaving_current_page_ &&
+  if (IsBeingDestroyed() && !render_frame_host->GetParent() &&
+      first_navigation_completed_ &&
       !static_cast<RenderFrameHostImpl*>(render_frame_host)
            ->is_in_back_forward_cache()) {
     // Main frame has been deleted because WebContents is being destroyed.
     // Note that we aren't recording this here when the main frame is in the
     // back-forward cache because that means we've actually already navigated
     // away from it (and we got to this point because the WebContents is
-    // deleted), which means |max_frame_count_| is already overwritten.
-    // The |max_frame_count_| value will instead be recorded from within
-    // |WebContentsImpl::ReadyToCommitNavigation()|.
-    RecordMaxFrameCountUMA(max_frame_count_);
+    // deleted), which means |max_loaded_frame_count_| is already overwritten.
+    // The |max_loaded_frame_count_| value will instead be recorded from within
+    // |WebContentsImpl::DidFinishNavigation()|.
+    RecordMaxFrameCountUMA(max_loaded_frame_count_);
   }
 
   is_notifying_observers_ = true;
@@ -6820,8 +6822,6 @@
 }
 
 void WebContentsImpl::OnFrameRemoved(RenderFrameHost* render_frame_host) {
-  frame_count_--;
-
   for (auto& observer : observers_)
     observer.FrameDeleted(render_frame_host);
 }
@@ -7315,15 +7315,6 @@
   return true;
 }
 
-void WebContentsImpl::FocusedNodeTouched(bool editable) {
-#if defined(OS_WIN)
-  RenderWidgetHostView* view = GetRenderWidgetHostView();
-  if (!view)
-    return;
-  view->FocusedNodeTouched(editable);
-#endif
-}
-
 void WebContentsImpl::ShowInsecureLocalhostWarningIfNeeded() {
   bool allow_localhost = base::CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kAllowInsecureLocalhost);
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 9f15d65..d53596abe 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -778,6 +778,8 @@
   void ResetAutoResizeSize() override;
   InputEventShim* GetInputEventShim() const override;
   RenderFrameHostImpl* GetFocusedFrameFromFocusedDelegate() override;
+  void OnVerticalScrollDirectionChanged(
+      viz::VerticalScrollDirection scroll_direction) override;
 
 #if !defined(OS_ANDROID)
   double GetPendingPageZoomLevel() override;
@@ -840,7 +842,6 @@
   bool OnUpdateDragCursor() override;
   bool IsWidgetForMainFrame(RenderWidgetHostImpl* render_widget_host) override;
   bool AddDomainInfoToRapporSample(rappor::Sample* sample) override;
-  void FocusedNodeTouched(bool editable) override;
   bool IsShowingContextMenuOnPage() const override;
 
   // RenderFrameHostManager::Delegate ------------------------------------------
@@ -1929,19 +1930,13 @@
   std::unique_ptr<JavaScriptDialogNavigationDeferrer>
       javascript_dialog_navigation_deferrer_;
 
-  // The number of frames currently in this WebContents.
-  size_t frame_count_ = 0;
+  // The max number of loaded frames that have been seen in this WebContents.
+  // This number is reset with each main frame navigation.
+  size_t max_loaded_frame_count_ = 0;
 
-  // The max number of frames seen in the current page hosted by this
-  // WebContents.
-  size_t max_frame_count_ = 0;
-
-  // This boolean value is used to keep track of whether we should record
-  // |max_frame_count_| when the main frame navigation is ready to commit.
-  // |max_frame_count_| should not be recorded for initial navigation for
-  // example. This is because |max_frame_count_| refers to the page that is
-  // being navigated away from.
-  bool record_max_frame_count_when_leaving_current_page_ = false;
+  // This boolean value is used to keep track of whether we finished the first
+  // successful navigation in this WebContents.
+  bool first_navigation_completed_ = false;
 
   base::WeakPtrFactory<WebContentsImpl> loading_weak_factory_{this};
   base::WeakPtrFactory<WebContentsImpl> weak_factory_{this};
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 07d3838..b50158e 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -4156,12 +4156,12 @@
 
   GURL url = embedded_test_server()->GetURL("a.com", "/title1.html");
   EXPECT_TRUE(NavigateToURL(shell(), url));
-  EXPECT_EQ(web_contents->max_frame_count_, 1u);
+  EXPECT_EQ(web_contents->max_loaded_frame_count_, 1u);
 
   GURL url_with_iframes_out_of_process =
       embedded_test_server()->GetURL("b.com", "/page_with_iframe.html");
   EXPECT_TRUE(NavigateToURL(shell(), url_with_iframes_out_of_process));
-  EXPECT_EQ(web_contents->max_frame_count_, 2u);
+  EXPECT_EQ(web_contents->max_loaded_frame_count_, 2u);
 
   // There should be two samples for kFrameCountUMA.
   histogram_tester.ExpectTotalCount(kFrameCountUMA, 2);
@@ -4180,7 +4180,7 @@
   GURL url_with_multiple_iframes = embedded_test_server()->GetURL(
       "b.com", "/cross_site_iframe_factory.html?b(a,c(b),d,b)");
   EXPECT_TRUE(NavigateToURL(shell(), url_with_multiple_iframes));
-  EXPECT_EQ(web_contents->max_frame_count_, 6u);
+  EXPECT_EQ(web_contents->max_loaded_frame_count_, 6u);
 
   histogram_tester.ExpectTotalCount(kMaxFrameCountUMA, 2);
   histogram_tester.ExpectBucketCount(kMaxFrameCountUMA, 1, 1);
@@ -4208,16 +4208,14 @@
   GURL url_with_iframes =
       embedded_test_server()->GetURL("a.com", "/page_with_iframe.html");
   EXPECT_TRUE(NavigateToURL(shell(), url_with_iframes));
-  EXPECT_EQ(web_contents->max_frame_count_, 2u);
+  EXPECT_EQ(web_contents->max_loaded_frame_count_, 2u);
 
   // |url_with_iframes| contains another iframe inside it. This means that we
   // have 4 iframes inside.
   auto* rfh =
       static_cast<RenderFrameHostImpl*>(CreateSubframe(url_with_iframes));
 
-  EXPECT_EQ(web_contents->max_frame_count_, 4u);
-  EXPECT_EQ(web_contents->frame_count_, 4u);
-
+  EXPECT_EQ(web_contents->max_loaded_frame_count_, 4u);
   ASSERT_NE(rfh, nullptr);
 
   shell()->Close();
@@ -4243,13 +4241,12 @@
   GURL url_with_iframes =
       embedded_test_server()->GetURL("a.com", "/page_with_iframe.html");
   EXPECT_TRUE(NavigateToURL(shell(), url_with_iframes));
-  EXPECT_EQ(web_contents->max_frame_count_, 2u);
+  EXPECT_EQ(web_contents->max_loaded_frame_count_, 2u);
 
   GURL url = embedded_test_server()->GetURL("a.com", "/title1.html");
   auto* rfh = static_cast<RenderFrameHostImpl*>(CreateSubframe(url));
   ASSERT_NE(rfh, nullptr);
-  EXPECT_EQ(web_contents->max_frame_count_, 3u);
-  EXPECT_EQ(web_contents->frame_count_, 3u);
+  EXPECT_EQ(web_contents->max_loaded_frame_count_, 3u);
 
   // Let's remove the first child.
   auto* main_frame = web_contents->GetMainFrame();
@@ -4260,8 +4257,7 @@
                             "iframe').parentNode);"));
   observer.Wait();
 
-  EXPECT_EQ(web_contents->max_frame_count_, 3u);
-  EXPECT_EQ(web_contents->frame_count_, 2u);
+  EXPECT_EQ(web_contents->max_loaded_frame_count_, 3u);
 
   // Let's remove the second child.
   node_to_remove = main_frame->child_at(0);
@@ -4271,8 +4267,7 @@
       "document.body.removeChild(document.querySelector('iframe'));"));
   observer_second.Wait();
 
-  EXPECT_EQ(web_contents->max_frame_count_, 3u);
-  EXPECT_EQ(web_contents->frame_count_, 1u);
+  EXPECT_EQ(web_contents->max_loaded_frame_count_, 3u);
 
   shell()->Close();
 
@@ -4462,4 +4457,197 @@
   EXPECT_EQ(shell()->web_contents()->GetThemeColor(), 0xFFFF0000u);
 }
 
+namespace {
+
+// A WebContentsObserver which caches the total number of calls to
+// DidChangeVerticalScrollDirection as well as the most recently provided value.
+class DidChangeVerticalScrollDirectionObserver : public WebContentsObserver {
+ public:
+  explicit DidChangeVerticalScrollDirectionObserver(WebContents* web_contents)
+      : WebContentsObserver(web_contents) {}
+
+  // WebContentsObserver:
+  void DidChangeVerticalScrollDirection(
+      viz::VerticalScrollDirection scroll_direction) override {
+    ++call_count_;
+    last_value_ = scroll_direction;
+  }
+
+  int call_count() const { return call_count_; }
+  viz::VerticalScrollDirection last_value() const { return last_value_; }
+
+ private:
+  int call_count_ = 0;
+  viz::VerticalScrollDirection last_value_ =
+      viz::VerticalScrollDirection::kNull;
+
+  DISALLOW_COPY_AND_ASSIGN(DidChangeVerticalScrollDirectionObserver);
+};
+
+}  // namespace
+
+// Tests that DidChangeVerticalScrollDirection is called only when the vertical
+// scroll direction has changed and that it includes the correct details.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       DidChangeVerticalScrollDirection) {
+  net::EmbeddedTestServer* server = embedded_test_server();
+  EXPECT_TRUE(server->Start());
+
+  // Set up the DOM.
+  EXPECT_TRUE(NavigateToURL(
+      shell(), GURL(server->GetURL("/scrollable_page_with_content.html"))));
+
+  // Size our view so that we can scroll both horizontally and vertically.
+  ResizeWebContentsView(shell(), gfx::Size(10, 10), /*set_start_page=*/false);
+
+  // Set up observers to watch the web contents and render frame submissions.
+  auto* web_contents = shell()->web_contents();
+  DidChangeVerticalScrollDirectionObserver web_contents_observer(web_contents);
+  RenderFrameSubmissionObserver render_frame_observer(web_contents);
+
+  // Verify that we are starting our test without scroll offset.
+  render_frame_observer.WaitForScrollOffset(gfx::Vector2dF());
+
+  // Assert initial state.
+  EXPECT_EQ(0, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kNull,
+            web_contents_observer.last_value());
+
+  // Scroll offset is dependent upon device pixel ratio which can vary across
+  // devices. To account for this, we extract the |devicePixelRatio| from our
+  // content window and for the remainder of this test use a scaled |Vector2dF|,
+  // which takes pixel ratio into consideration, when waiting for scroll offset.
+  // Note that this is primarily being done to satisfy tests running on Android.
+  const double device_pixel_ratio =
+      EvalJs(web_contents, "window.devicePixelRatio").ExtractDouble();
+  auto ScaledVector2dF = [device_pixel_ratio](float x, float y) {
+    return gfx::Vector2dF(std::floor(x * device_pixel_ratio),
+                          std::floor(y * device_pixel_ratio));
+  };
+
+  // Scroll down.
+  EXPECT_TRUE(ExecJs(web_contents, "window.scrollTo(0, 5)"));
+  render_frame_observer.WaitForScrollOffset(ScaledVector2dF(0.f, 5.f));
+
+  // Assert that we are notified of the scroll down event.
+  EXPECT_EQ(1, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kDown,
+            web_contents_observer.last_value());
+
+  // Scroll down again.
+  EXPECT_TRUE(ExecJs(web_contents, "window.scrollTo(0, 10)"));
+  render_frame_observer.WaitForScrollOffset(ScaledVector2dF(0.f, 10.f));
+
+  // Assert that we are *not* notified of the scroll down event given that no
+  // change in scroll direction occurred (as our previous scroll was also down).
+  EXPECT_EQ(1, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kDown,
+            web_contents_observer.last_value());
+
+  // Scroll right.
+  EXPECT_TRUE(ExecJs(web_contents, "window.scrollTo(10, 10)"));
+  render_frame_observer.WaitForScrollOffset(ScaledVector2dF(10.f, 10.f));
+
+  // Assert that we are *not* notified of the scroll right event given that no
+  // change occurred in the vertical direction.
+  EXPECT_EQ(1, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kDown,
+            web_contents_observer.last_value());
+
+  // Scroll left.
+  EXPECT_TRUE(ExecJs(web_contents, "window.scrollTo(0, 10)"));
+  render_frame_observer.WaitForScrollOffset(ScaledVector2dF(0.f, 10.f));
+
+  // Assert that we are *not* notified of the scroll left event given that no
+  // change occurred in the vertical direction.
+  EXPECT_EQ(1, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kDown,
+            web_contents_observer.last_value());
+
+  // Scroll up.
+  EXPECT_TRUE(ExecJs(web_contents, "window.scrollTo(0, 5)"));
+  render_frame_observer.WaitForScrollOffset(ScaledVector2dF(0.f, 5.f));
+
+  // Assert that we are notified of the scroll up event.
+  EXPECT_EQ(2, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kUp,
+            web_contents_observer.last_value());
+
+  // Scroll up again.
+  EXPECT_TRUE(ExecJs(web_contents, "window.scrollTo(0, 0)"));
+  render_frame_observer.WaitForScrollOffset(ScaledVector2dF(0.f, 0.f));
+
+  // Assert that we are *not* notified of the scroll up event given that no
+  // change in scroll direction occurred (as our previous scroll was also up).
+  EXPECT_EQ(2, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kUp,
+            web_contents_observer.last_value());
+}
+
+// Tests that DidChangeVerticalScrollDirection is *not* called when the vertical
+// scroll direction has changed in a child frame. We expect to only be notified
+// of vertical scroll direction changes to the main frame's root layer.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       DidChangeVerticalScrollDirectionWithIframe) {
+  net::EmbeddedTestServer* server = embedded_test_server();
+  EXPECT_TRUE(server->Start());
+
+  // Set up the DOM.
+  GURL main_url(server->GetURL("a.co", "/scrollable_page_with_iframe.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Set up the iframe.
+  auto* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents());
+  FrameTreeNode* iframe = web_contents->GetFrameTree()->root()->child_at(0);
+  GURL iframe_url(server->GetURL("b.co", "/scrollable_page_with_content.html"));
+  NavigateFrameToURL(iframe, iframe_url);
+
+  // Size our view so that we can scroll both horizontally and vertically.
+  ResizeWebContentsView(shell(), gfx::Size(10, 10), /*set_start_page=*/false);
+
+  // Set up an observer to watch the web contents.
+  DidChangeVerticalScrollDirectionObserver web_contents_observer(web_contents);
+
+  // Assert initial state.
+  EXPECT_EQ(0, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kNull,
+            web_contents_observer.last_value());
+
+  // Scroll down in the iframe.
+  EXPECT_TRUE(ExecJs(iframe->current_frame_host(), "window.scrollTo(0, 10)"));
+
+  // Assert that we are *not* notified of the scroll down event given that the
+  // scroll was not performed on the main frame's root layer.
+  EXPECT_EQ(0, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kNull,
+            web_contents_observer.last_value());
+
+  // Scroll right in the iframe.
+  EXPECT_TRUE(ExecJs(iframe->current_frame_host(), "window.scrollTo(10, 10)"));
+
+  // Assert that we are *not* notified of the scroll right event given that the
+  // scroll was not performed on the main frame's root layer.
+  EXPECT_EQ(0, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kNull,
+            web_contents_observer.last_value());
+
+  // Scroll left in the iframe.
+  EXPECT_TRUE(ExecJs(iframe->current_frame_host(), "window.scrollTo(0, 10)"));
+
+  // Assert that we are *not* notified of the scroll left event given that the
+  // scroll was not performed on the main frame's root layer.
+  EXPECT_EQ(0, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kNull,
+            web_contents_observer.last_value());
+
+  // Scroll up in the iframe.
+  EXPECT_TRUE(ExecJs(iframe->current_frame_host(), "window.scrollTo(0, 0)"));
+
+  // Assert that we are *not* notified of the scroll up event given that the
+  // scroll was not performed on the main frame's root layer.
+  EXPECT_EQ(0, web_contents_observer.call_count());
+  EXPECT_EQ(viz::VerticalScrollDirection::kNull,
+            web_contents_observer.last_value());
+}
+
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index f093feec..afde992 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -325,8 +325,17 @@
     last_theme_color_ = theme_color;
   }
 
+  void DidChangeVerticalScrollDirection(
+      viz::VerticalScrollDirection scroll_direction) override {
+    last_vertical_scroll_direction_ = scroll_direction;
+  }
+
   const GURL& last_url() const { return last_url_; }
   base::Optional<SkColor> last_theme_color() const { return last_theme_color_; }
+  base::Optional<viz::VerticalScrollDirection> last_vertical_scroll_direction()
+      const {
+    return last_vertical_scroll_direction_;
+  }
   bool observed_did_first_visually_non_empty_paint() const {
     return observed_did_first_visually_non_empty_paint_;
   }
@@ -334,6 +343,7 @@
  private:
   GURL last_url_;
   base::Optional<SkColor> last_theme_color_;
+  base::Optional<viz::VerticalScrollDirection> last_vertical_scroll_direction_;
   bool observed_did_first_visually_non_empty_paint_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(TestWebContentsObserver);
@@ -3400,6 +3410,18 @@
   EXPECT_TRUE(observer.observed_did_first_visually_non_empty_paint());
 }
 
+TEST_F(WebContentsImplTest, DidChangeVerticalScrollDirection) {
+  TestWebContentsObserver observer(contents());
+
+  EXPECT_FALSE(observer.last_vertical_scroll_direction().has_value());
+
+  contents()->OnVerticalScrollDirectionChanged(
+      viz::VerticalScrollDirection::kUp);
+
+  EXPECT_EQ(viz::VerticalScrollDirection::kUp,
+            observer.last_vertical_scroll_direction().value());
+}
+
 namespace {
 
 class MockWebContentsDelegate : public WebContentsDelegate {
diff --git a/content/common/document_scoped_interface_bundle.mojom b/content/common/document_scoped_interface_bundle.mojom
index 63f816b9..9c52764 100644
--- a/content/common/document_scoped_interface_bundle.mojom
+++ b/content/common/document_scoped_interface_bundle.mojom
@@ -5,7 +5,6 @@
 module content.mojom;
 
 import "services/service_manager/public/mojom/interface_provider.mojom";
-import "third_party/blink/public/mojom/frame/document_interface_broker.mojom";
 import "third_party/blink/public/mojom/browser_interface_broker.mojom";
 
 struct DocumentScopedInterfaceBundle {
@@ -13,17 +12,10 @@
   // services exposed by its RenderFrameHost.
   service_manager.mojom.InterfaceProvider interface_provider;
 
-  // The DocumentInterfaceBroker through which the RenderFrame can access
-  // interfaces exposed by its RenderFrameHost
-  pending_remote<blink.mojom.DocumentInterfaceBroker>
-      document_interface_broker_content;
-  pending_remote<blink.mojom.DocumentInterfaceBroker>
-      document_interface_broker_blink;
-
   // The BrowserInterfaceBroker through which the RenderFrame can access
-  // interfaces exposed by its RenderFrameHost
-  // It will eventually replace interface_provider and
-  // document_interface_broker* above and become the only way to get
-  // document-scoped interfaces from the browser (see crbug.com/985120)
+  // interfaces exposed by its RenderFrameHost.
+  // It will eventually replace interface_provider above and become the
+  // only way to get document-scoped interfaces from the browser
+  // (see crbug.com/985120).
   pending_remote<blink.mojom.BrowserInterfaceBroker> browser_interface_broker;
 };
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index a4699d3..9df7cb7 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -377,7 +377,7 @@
   // Sent by the renderer when a navigation commits in the frame.
 
   // If |interface_params| is non-empty, the FrameHost implementation
-  // must unbind the old InterfaceProvider and DocumentInterfaceBroker
+  // must unbind the old InterfaceProvider and BrowserInterfaceBroker
   // connections, and drop any interface requests pending on them.
   // Then it should bind the appropriate requests and start servicing
   // GetInterface messages coming in on these new connections
@@ -387,9 +387,8 @@
   // is set for cross-document navigations. This prevents origin confusion by
   // ensuring that interface requests racing with navigation commit will be
   // either ignored, or serviced correctly in the security context of the
-  // document they originated from (based on which InterfaceProvider connection
-  // the GetInterface messages arrive on or DocumentInterfaceBroker
-  // connection the Get<interface> messages arrive on).
+  // document they originated from (based on which InterfaceProvider or
+  // BrowserInterfaceBroker connection the GetInterface messages arrive on).
   DidCommitProvisionalLoad(
       DidCommitProvisionalLoadParams params,
       DidCommitProvisionalLoadInterfaceParams? interface_params);
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 1e7fd1ff..9b506e8 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -568,10 +568,6 @@
 IPC_STRUCT_BEGIN(FrameHostMsg_CreateChildFrame_Params_Reply)
   IPC_STRUCT_MEMBER(int32_t, child_routing_id)
   IPC_STRUCT_MEMBER(mojo::MessagePipeHandle, new_interface_provider)
-  IPC_STRUCT_MEMBER(mojo::MessagePipeHandle,
-                    document_interface_broker_content_handle)
-  IPC_STRUCT_MEMBER(mojo::MessagePipeHandle,
-                    document_interface_broker_blink_handle)
   IPC_STRUCT_MEMBER(mojo::MessagePipeHandle, browser_interface_broker_handle)
   IPC_STRUCT_MEMBER(base::UnguessableToken, devtools_frame_token)
 IPC_STRUCT_END()
@@ -934,6 +930,12 @@
 // fallback contents (i.e., <object>).
 IPC_MESSAGE_ROUTED0(FrameMsg_RenderFallbackContent)
 
+// Tell the renderer to add a property to the WebUI binding object.  This
+// only works if we allowed WebUI bindings.
+IPC_MESSAGE_ROUTED2(FrameMsg_SetWebUIProperty,
+                    std::string /* property_name */,
+                    std::string /* property_value_json */)
+
 // -----------------------------------------------------------------------------
 // Messages sent from the renderer to the browser.
 
diff --git a/content/common/frame_messages.mojom b/content/common/frame_messages.mojom
index 0ad8ece..9607369 100644
--- a/content/common/frame_messages.mojom
+++ b/content/common/frame_messages.mojom
@@ -6,17 +6,12 @@
 
 import "services/service_manager/public/mojom/interface_provider.mojom";
 import "third_party/blink/public/mojom/browser_interface_broker.mojom";
-import "third_party/blink/public/mojom/frame/document_interface_broker.mojom";
 
 [Native]
 struct DidCommitProvisionalLoadParams;
 
 struct DidCommitProvisionalLoadInterfaceParams {
   service_manager.mojom.InterfaceProvider& interface_provider_request;
-  pending_receiver<blink.mojom.DocumentInterfaceBroker>
-      document_interface_broker_content_receiver;
-  pending_receiver<blink.mojom.DocumentInterfaceBroker>
-      document_interface_broker_blink_receiver;
   pending_receiver<blink.mojom.BrowserInterfaceBroker>
       browser_interface_broker_receiver;
 };
diff --git a/content/common/page_messages.h b/content/common/page_messages.h
index 50e77ced..4bcb686 100644
--- a/content/common/page_messages.h
+++ b/content/common/page_messages.h
@@ -43,8 +43,7 @@
 
 // Sent to all renderers to resume all frames and dispatch page visibility
 // events for bfcache.
-IPC_MESSAGE_ROUTED1(PageMsg_RestorePageFromBackForwardCache,
-                    base::TimeTicks /* navigation_start */)
+IPC_MESSAGE_ROUTED0(PageMsg_RestorePageFromBackForwardCache)
 
 // Sent to all renderers when the mainframe state required by
 // blink::TextAutosizer changes in the main frame's renderer.
diff --git a/content/common/render_frame_metadata.mojom b/content/common/render_frame_metadata.mojom
index f36d562..b1d5710 100644
--- a/content/common/render_frame_metadata.mojom
+++ b/content/common/render_frame_metadata.mojom
@@ -7,6 +7,7 @@
 import "mojo/public/mojom/base/time.mojom";
 import "services/viz/public/mojom/compositing/local_surface_id_allocation.mojom";
 import "services/viz/public/mojom/compositing/selection.mojom";
+import "services/viz/public/mojom/compositing/vertical_scroll_direction.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
 
 // See components/viz/service/quads/render_frame_metadata.h
@@ -58,6 +59,8 @@
 
   float top_controls_shown_ratio;
 
+  viz.mojom.VerticalScrollDirection new_vertical_scroll_direction;
+
   // Used to position Android bottom bar, whose position is computed by the
   // renderer compositor.
   [EnableIf=is_android]
diff --git a/content/common/render_frame_metadata_mojom_traits.cc b/content/common/render_frame_metadata_mojom_traits.cc
index f1b7f946..cd87c25 100644
--- a/content/common/render_frame_metadata_mojom_traits.cc
+++ b/content/common/render_frame_metadata_mojom_traits.cc
@@ -7,6 +7,7 @@
 #include "build/build_config.h"
 #include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "services/viz/public/cpp/compositing/selection_mojom_traits.h"
+#include "services/viz/public/cpp/compositing/vertical_scroll_direction_mojom_traits.h"
 #include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
 #include "ui/gfx/mojom/selection_bound_mojom_traits.h"
 
@@ -40,7 +41,9 @@
          data.ReadRootLayerSize(&out->root_layer_size) &&
 #endif
          data.ReadViewportSizeInPixels(&out->viewport_size_in_pixels) &&
-         data.ReadLocalSurfaceIdAllocation(&out->local_surface_id_allocation);
+         data.ReadLocalSurfaceIdAllocation(&out->local_surface_id_allocation) &&
+         data.ReadNewVerticalScrollDirection(
+             &out->new_vertical_scroll_direction);
 }
 
 }  // namespace mojo
diff --git a/content/common/render_frame_metadata_mojom_traits.h b/content/common/render_frame_metadata_mojom_traits.h
index 9140368c..8cd8b6a 100644
--- a/content/common/render_frame_metadata_mojom_traits.h
+++ b/content/common/render_frame_metadata_mojom_traits.h
@@ -72,6 +72,11 @@
     return metadata.top_controls_shown_ratio;
   }
 
+  static viz::VerticalScrollDirection new_vertical_scroll_direction(
+      const cc::RenderFrameMetadata& metadata) {
+    return metadata.new_vertical_scroll_direction;
+  }
+
 #if defined(OS_ANDROID)
   static float bottom_controls_height(const cc::RenderFrameMetadata& metadata) {
     return metadata.bottom_controls_height;
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index ef39610..d567ec81 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -133,12 +133,6 @@
 // Sets the page scale for the current main frame to the given page scale.
 IPC_MESSAGE_ROUTED1(ViewMsg_SetPageScale, float /* page_scale_factor */)
 
-// Tell the renderer to add a property to the WebUI binding object.  This
-// only works if we allowed WebUI bindings.
-IPC_MESSAGE_ROUTED2(ViewMsg_SetWebUIProperty,
-                    std::string /* property_name */,
-                    std::string /* property_value_json */)
-
 // Used to notify the render-view that we have received a target URL. Used
 // to prevent target URLs spamming the browser.
 IPC_MESSAGE_ROUTED0(ViewMsg_UpdateTargetURL_ACK)
diff --git a/content/common/widget_messages.h b/content/common/widget_messages.h
index 004775f..dbd1115f 100644
--- a/content/common/widget_messages.h
+++ b/content/common/widget_messages.h
@@ -268,11 +268,6 @@
 // WidgetHostMsg_UnlockMouse).
 IPC_MESSAGE_ROUTED0(WidgetHostMsg_UnlockMouse)
 
-// Message sent from renderer to the browser when the element that is focused
-// has been touched. A bool is passed in this message which indicates if the
-// node is editable.
-IPC_MESSAGE_ROUTED1(WidgetHostMsg_FocusedNodeTouched, bool /* editable */)
-
 // Sent by the renderer process in response to an earlier WidgetMsg_ForceRedraw
 // message. The reply includes the snapshot-id from the request.
 IPC_MESSAGE_ROUTED1(WidgetHostMsg_ForceRedrawComplete, int /* snapshot_id */)
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index b8bf9f0b..7354a45 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -311,6 +311,11 @@
   // RenderFrame. See BindingsPolicy for details.
   virtual int GetEnabledBindings() = 0;
 
+  // Sets a property with the given name and value on the WebUI object
+  // associated with this RenderFrameHost, if one exists.
+  virtual void SetWebUIProperty(const std::string& name,
+                                const std::string& value) = 0;
+
 #if defined(OS_ANDROID)
   // Returns an InterfaceProvider for Java-implemented interfaces that are
   // scoped to this RenderFrameHost. This provides access to interfaces
diff --git a/content/public/browser/render_view_host.h b/content/public/browser/render_view_host.h
index a0c210b..95679ab 100644
--- a/content/public/browser/render_view_host.h
+++ b/content/public/browser/render_view_host.h
@@ -99,11 +99,6 @@
   // started.
   virtual void NotifyMoveOrResizeStarted() = 0;
 
-  // Sets a property with the given name and value on the Web UI binding object.
-  // Must call AllowWebUIBindings() on this renderer first.
-  virtual void SetWebUIProperty(const std::string& name,
-                                const std::string& value) = 0;
-
   // TODO(mustaq): Replace "Webkit" from the following three method names.
   //
   // Returns the current WebKit preferences. Note: WebPreferences is cached, so
diff --git a/content/public/browser/render_widget_host_view.h b/content/public/browser/render_widget_host_view.h
index 78e05582..a820a19 100644
--- a/content/public/browser/render_widget_host_view.h
+++ b/content/public/browser/render_widget_host_view.h
@@ -227,11 +227,6 @@
   virtual std::unique_ptr<viz::ClientFrameSinkVideoCapturer>
   CreateVideoCapturer() = 0;
 
-  // Notification that a node was touched.
-  // The |editable| parameter indicates if the node is editable, for e.g.
-  // an input field, etc.
-  virtual void FocusedNodeTouched(bool editable) = 0;
-
   // Informs the view that its associated render widget has frames to draw and
   // wants to have BeginFrame messages sent to it.  This should only be called
   // when the value has changed.  Views must initially default to false.
diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h
index d40b985e..b3c757d5 100644
--- a/content/public/browser/web_contents_observer.h
+++ b/content/public/browser/web_contents_observer.h
@@ -11,6 +11,7 @@
 #include "base/optional.h"
 #include "base/process/kill.h"
 #include "base/process/process_handle.h"
+#include "components/viz/common/vertical_scroll_direction.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/reload_type.h"
@@ -471,6 +472,15 @@
   virtual void DidAttachInterstitialPage() {}
   virtual void DidDetachInterstitialPage() {}
 
+  // Invoked when the vertical scroll direction of the root layer is changed.
+  // Note that if a scroll in a given direction occurs, the scroll is completed,
+  // and then another scroll in the *same* direction occurs, we will not
+  // consider the second scroll event to have caused a change in direction. Also
+  // note that this API will *never* be called with |kNull| which only exists to
+  // indicate the absence of a vertical scroll direction.
+  virtual void DidChangeVerticalScrollDirection(
+      viz::VerticalScrollDirection scroll_direction) {}
+
   // Invoked before a form repost warning is shown.
   virtual void BeforeFormRepostWarningShow() {}
 
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 9529fd4..df914d3 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -786,13 +786,6 @@
                                              base::FEATURE_ENABLED_BY_DEFAULT};
 #endif  // defined(OS_CHROMEOS)
 
-#if defined(OS_WIN)
-// Enables the use of a touch fling curve that is based on the behavior of
-// native apps on Windows.
-const base::Feature kExperimentalFlingAnimation{
-    "ExperimentalFlingAnimation", base::FEATURE_DISABLED_BY_DEFAULT};
-#endif  // defined(OS_WIN)
-
 #if defined(OS_MACOSX)
 // Enables caching of media devices for the purpose of enumerating them.
 const base::Feature kDeviceMonitorMac{"DeviceMonitorMac",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index c23353e..de3d354 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -170,10 +170,6 @@
 CONTENT_EXPORT extern const base::Feature kWebUIPolymer2Exceptions;
 #endif
 
-#if defined(OS_WIN)
-CONTENT_EXPORT extern const base::Feature kExperimentalFlingAnimation;
-#endif  // defined(OS_WIN)
-
 #if defined(OS_MACOSX)
 CONTENT_EXPORT extern const base::Feature kDeviceMonitorMac;
 CONTENT_EXPORT extern const base::Feature kIOSurfaceCapturer;
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h
index 4c36a22..d60699b 100644
--- a/content/public/renderer/render_frame.h
+++ b/content/public/renderer/render_frame.h
@@ -22,7 +22,6 @@
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "third_party/blink/public/common/navigation/triggering_event_info.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/web/web_navigation_policy.h"
 #include "ui/accessibility/ax_mode.h"
@@ -173,11 +172,6 @@
   // interfaces exposed to it by the application running in this frame.
   virtual service_manager::InterfaceProvider* GetRemoteInterfaces() = 0;
 
-  // Returns the DocumentInterfaceBroker that this process can use to bind
-  // interfaces exposed to it by the application running in this frame.
-  virtual blink::mojom::DocumentInterfaceBroker*
-  GetDocumentInterfaceBroker() = 0;
-
   // Returns the BrowserInterfaceBrokerProxy that this process can use to bind
   // interfaces exposed to it by the application running in this frame.
   virtual blink::BrowserInterfaceBrokerProxy* GetBrowserInterfaceBroker() = 0;
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc
index 491681e..46ddf4d9 100644
--- a/content/public/test/mock_render_thread.cc
+++ b/content/public/test/mock_render_thread.cc
@@ -277,18 +277,6 @@
   return interface_provider_request;
 }
 
-mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-MockRenderThread::TakeInitialDocumentInterfaceBrokerReceiverForFrame(
-    int32_t routing_id) {
-  auto it =
-      frame_routing_id_to_initial_document_broker_receivers_.find(routing_id);
-  if (it == frame_routing_id_to_initial_document_broker_receivers_.end())
-    return mojo::NullReceiver();
-  auto document_broker_receiver = std::move(it->second);
-  frame_routing_id_to_initial_document_broker_receivers_.erase(it);
-  return document_broker_receiver;
-}
-
 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
 MockRenderThread::TakeInitialBrowserInterfaceBrokerReceiverForFrame(
     int32_t routing_id) {
@@ -323,21 +311,6 @@
   params_reply->new_interface_provider =
       interface_provider.PassInterface().PassHandle().release();
 
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker;
-  frame_routing_id_to_initial_document_broker_receivers_.emplace(
-      params_reply->child_routing_id,
-      document_interface_broker.InitWithNewPipeAndPassReceiver());
-  params_reply->document_interface_broker_content_handle =
-      document_interface_broker.PassPipe().release();
-
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_blink;
-  ignore_result(
-      document_interface_broker_blink.InitWithNewPipeAndPassReceiver());
-  params_reply->document_interface_broker_blink_handle =
-      document_interface_broker_blink.PassPipe().release();
-
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
   frame_routing_id_to_initial_browser_broker_receivers_.emplace(
@@ -391,25 +364,11 @@
       reply->main_frame_route_id,
       mojo::MakeRequest(
           &reply->main_frame_interface_bundle->interface_provider));
-
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker;
-  frame_routing_id_to_initial_document_broker_receivers_.emplace(
-      reply->main_frame_route_id,
-      document_interface_broker.InitWithNewPipeAndPassReceiver());
-
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
   frame_routing_id_to_initial_browser_broker_receivers_.emplace(
       reply->main_frame_route_id,
       browser_interface_broker.InitWithNewPipeAndPassReceiver());
-  reply->main_frame_interface_bundle->document_interface_broker_content =
-      std::move(document_interface_broker);
-
-  ignore_result(document_interface_broker.InitWithNewPipeAndPassReceiver());
-  reply->main_frame_interface_bundle->document_interface_broker_blink =
-      std::move(document_interface_broker);
-
   reply->main_frame_interface_bundle->browser_interface_broker =
       std::move(browser_interface_broker);
 
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h
index d9af68f..38ef2fa 100644
--- a/content/public/test/mock_render_thread.h
+++ b/content/public/test/mock_render_thread.h
@@ -20,7 +20,6 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "services/service_manager/public/mojom/interface_provider.mojom.h"
 #include "third_party/blink/public/mojom/browser_interface_broker.mojom.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
 
 struct FrameHostMsg_CreateChildFrame_Params;
 struct FrameHostMsg_CreateChildFrame_Params_Reply;
@@ -120,13 +119,6 @@
   service_manager::mojom::InterfaceProviderRequest
   TakeInitialInterfaceProviderRequestForFrame(int32_t routing_id);
 
-  // Returns the receiver end of the DocumentInterfaceBroker interface whose
-  // client end was passed in to construct RenderFrame with |routing_id|; if
-  // any. The client end will be used by the RenderFrame to service interface
-  // requests originating from the initial empty document.
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-  TakeInitialDocumentInterfaceBrokerReceiverForFrame(int32_t routing_id);
-
   // Returns the receiver end of the BrowserInterfaceBroker interface whose
   // client end was passed in to construct RenderFrame with |routing_id|; if
   // any. The client end will be used by the RenderFrame to service interface
@@ -165,10 +157,6 @@
   std::map<int32_t, service_manager::mojom::InterfaceProviderRequest>
       frame_routing_id_to_initial_interface_provider_requests_;
 
-  std::map<int32_t,
-           mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>>
-      frame_routing_id_to_initial_document_broker_receivers_;
-
   std::map<int32_t, mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>>
       frame_routing_id_to_initial_browser_broker_receivers_;
 
diff --git a/content/public/test/navigation_handle_observer.cc b/content/public/test/navigation_handle_observer.cc
index 6e0565d..5684512 100644
--- a/content/public/test/navigation_handle_observer.cc
+++ b/content/public/test/navigation_handle_observer.cc
@@ -35,7 +35,6 @@
   was_redirected_ = navigation_handle->WasServerRedirect();
   frame_tree_node_id_ = navigation_handle->GetFrameTreeNodeId();
   navigation_id_ = navigation_handle->GetNavigationId();
-  navigation_start_ = navigation_handle->NavigationStart();
 }
 
 void NavigationHandleObserver::DidFinishNavigation(
diff --git a/content/public/test/navigation_handle_observer.h b/content/public/test/navigation_handle_observer.h
index 7fc6ee6..e2b9f09e 100644
--- a/content/public/test/navigation_handle_observer.h
+++ b/content/public/test/navigation_handle_observer.h
@@ -37,7 +37,6 @@
   base::Optional<net::AuthChallengeInfo> auth_challenge_info() {
     return auth_challenge_info_;
   }
-  base::TimeTicks navigation_start() { return navigation_start_; }
 
  private:
   // A reference to the NavigationHandle so this class will track only
@@ -59,7 +58,6 @@
   int64_t navigation_id_ = -1;
   bool is_download_ = false;
   base::Optional<net::AuthChallengeInfo> auth_challenge_info_;
-  base::TimeTicks navigation_start_;
 
   DISALLOW_COPY_AND_ASSIGN(NavigationHandleObserver);
 };
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 7635ba48..374f186 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -428,14 +428,6 @@
       mojo::MakeRequest(
           &view_params->main_frame_interface_bundle->interface_provider));
 
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker;
-  ignore_result(document_interface_broker.InitWithNewPipeAndPassReceiver());
-  view_params->main_frame_interface_bundle->document_interface_broker_content =
-      std::move(document_interface_broker);
-  ignore_result(document_interface_broker.InitWithNewPipeAndPassReceiver());
-  view_params->main_frame_interface_bundle->document_interface_broker_blink =
-      std::move(document_interface_broker);
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker;
   // Ignoring the returned PendingReceiver because it is not bound to anything
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 00def03..1e85f64 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -90,6 +90,7 @@
 #include "content/public/renderer/render_frame_observer.h"
 #include "content/public/renderer/render_frame_visitor.h"
 #include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/render_view_observer.h"
 #include "content/public/renderer/renderer_ppapi_host.h"
 #include "content/renderer/accessibility/aom_content_ax_tree.h"
 #include "content/renderer/accessibility/render_accessibility_impl.h"
@@ -1358,14 +1359,11 @@
     RenderViewImpl* render_view,
     int32_t routing_id,
     service_manager::mojom::InterfaceProviderPtr interface_provider,
-    mojo::Remote<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_content,
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker,
     const base::UnguessableToken& devtools_frame_token) {
   DCHECK(routing_id != MSG_ROUTING_NONE);
   CreateParams params(render_view, routing_id, std::move(interface_provider),
-                      std::move(document_interface_broker_content),
                       std::move(browser_interface_broker),
                       devtools_frame_token);
 
@@ -1405,26 +1403,16 @@
   service_manager::mojom::InterfaceProviderPtr main_frame_interface_provider(
       std::move(params->main_frame_interface_bundle->interface_provider));
 
-  mojo::Remote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_content(
-          std::move(params->main_frame_interface_bundle
-                        ->document_interface_broker_content));
   RenderFrameImpl* render_frame = RenderFrameImpl::Create(
       render_view, params->main_frame_routing_id,
       std::move(main_frame_interface_provider),
-      std::move(document_interface_broker_content),
       std::move(params->main_frame_interface_bundle->browser_interface_broker),
       params->devtools_main_frame_token);
   render_frame->InitializeBlameContext(nullptr);
 
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_blink(
-          std::move(params->main_frame_interface_bundle
-                        ->document_interface_broker_blink));
   WebLocalFrame* web_frame = WebLocalFrame::CreateMainFrame(
       render_view->webview(), render_frame,
-      render_frame->blink_interface_registry_.get(),
-      document_interface_broker_blink.PassPipe(), opener,
+      render_frame->blink_interface_registry_.get(), opener,
       // This conversion is a little sad, as this often comes from a
       // WebString...
       WebString::FromUTF8(params->replicated_frame_state.name),
@@ -1473,10 +1461,6 @@
 void RenderFrameImpl::CreateFrame(
     int routing_id,
     service_manager::mojom::InterfaceProviderPtr interface_provider,
-    mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_content,
-    mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_blink,
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker,
     int previous_routing_id,
@@ -1520,8 +1504,6 @@
     // Create the RenderFrame and WebLocalFrame, linking the two.
     render_frame = RenderFrameImpl::Create(
         parent_proxy->render_view(), routing_id, std::move(interface_provider),
-        mojo::Remote<blink::mojom::DocumentInterfaceBroker>(
-            std::move(document_interface_broker_content)),
         std::move(browser_interface_broker), devtools_frame_token);
     render_frame->InitializeBlameContext(FromRoutingID(parent_routing_id));
     render_frame->unique_name_helper_.set_propagated_name(
@@ -1530,7 +1512,7 @@
         replicated_state.scope, WebString::FromUTF8(replicated_state.name),
         replicated_state.frame_policy, render_frame,
         render_frame->blink_interface_registry_.get(),
-        document_interface_broker_blink.PassPipe(), previous_sibling_web_frame,
+        previous_sibling_web_frame,
         ConvertFrameOwnerPropertiesToWebFrameOwnerProperties(
             frame_owner_properties),
         replicated_state.frame_owner_element_type,
@@ -1559,16 +1541,13 @@
     render_view = proxy->render_view();
     render_frame = RenderFrameImpl::Create(
         render_view, routing_id, std::move(interface_provider),
-        mojo::Remote<blink::mojom::DocumentInterfaceBroker>(
-            std::move(document_interface_broker_content)),
         std::move(browser_interface_broker), devtools_frame_token);
     render_frame->InitializeBlameContext(nullptr);
     render_frame->previous_routing_id_ = previous_routing_id;
     proxy->set_provisional_frame_routing_id(routing_id);
     web_frame = blink::WebLocalFrame::CreateProvisional(
         render_frame, render_frame->blink_interface_registry_.get(),
-        document_interface_broker_blink.PassPipe(), proxy->web_frame(),
-        replicated_state.frame_policy);
+        proxy->web_frame(), replicated_state.frame_policy);
     // The new |web_frame| is a main frame iff the proxy's frame was.
     DCHECK_EQ(proxy_is_main_frame, !web_frame->Parent());
   }
@@ -1803,16 +1782,12 @@
     RenderViewImpl* render_view,
     int32_t routing_id,
     service_manager::mojom::InterfaceProviderPtr interface_provider,
-    mojo::Remote<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_content,
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker,
     const base::UnguessableToken& devtools_frame_token)
     : render_view(render_view),
       routing_id(routing_id),
       interface_provider(std::move(interface_provider)),
-      document_interface_broker_content(
-          std::move(document_interface_broker_content)),
       browser_interface_broker(std::move(browser_interface_broker)),
       devtools_frame_token(devtools_frame_token) {}
 RenderFrameImpl::CreateParams::~CreateParams() = default;
@@ -1860,12 +1835,6 @@
   blink_interface_registry_.reset(new BlinkInterfaceRegistryImpl(
       registry_.GetWeakPtr(), associated_interfaces_.GetWeakPtr()));
 
-  // The DocumentInterfaceBroker to access Mojo services exposed by the RFHI
-  // must be provided at construction time. See: https://crbug.com/718652/.
-  CHECK(params.document_interface_broker_content.is_bound());
-  document_interface_broker_ =
-      std::move(params.document_interface_broker_content);
-
   CHECK(params.browser_interface_broker.is_valid());
   browser_interface_broker_proxy_.Bind(
       std::move(params.browser_interface_broker));
@@ -3061,18 +3030,6 @@
   return &remote_interfaces_;
 }
 
-blink::mojom::DocumentInterfaceBroker*
-RenderFrameImpl::GetDocumentInterfaceBroker() {
-  DCHECK(document_interface_broker_.is_bound());
-  return document_interface_broker_.get();
-}
-
-void RenderFrameImpl::SetDocumentInterfaceBrokerForTesting(
-    mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker> test_broker) {
-  document_interface_broker_.reset();
-  document_interface_broker_.Bind(std::move(test_broker));
-}
-
 blink::AssociatedInterfaceRegistry*
 RenderFrameImpl::GetAssociatedInterfaceRegistry() {
   return &associated_interfaces_;
@@ -3246,11 +3203,11 @@
 }
 
 void RenderFrameImpl::AllowBindings(int32_t enabled_bindings_flags) {
+  // TODO(nasko): WebUIExtensionsData might be useful to be registered for
+  // subframes as well, though at this time there is no such usage.
   if (IsMainFrame() && (enabled_bindings_flags & BINDINGS_POLICY_WEB_UI) &&
       !(enabled_bindings_ & BINDINGS_POLICY_WEB_UI)) {
-    // TODO(sammc): Move WebUIExtensionData to be a RenderFrameObserver.
-    // WebUIExtensionData deletes itself when |render_view_| is destroyed.
-    new WebUIExtensionData(render_view_);
+    new WebUIExtensionData(this);
   }
 
   enabled_bindings_ |= enabled_bindings_flags;
@@ -4179,28 +4136,8 @@
           0u),
       GetTaskRunner(blink::TaskType::kInternalIPC));
 
-  DCHECK(params_reply.document_interface_broker_content_handle.is_valid());
-  DCHECK(params_reply.document_interface_broker_blink_handle.is_valid());
   DCHECK(params_reply.browser_interface_broker_handle.is_valid());
 
-  mojo::Remote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_content;
-  document_interface_broker_content.Bind(
-      mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>(
-          mojo::ScopedMessagePipeHandle(
-              params_reply.document_interface_broker_content_handle),
-          blink::mojom::DocumentInterfaceBroker::Version_),
-      GetTaskRunner(blink::TaskType::kInternalIPC));
-
-  mojo::Remote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_blink;
-  document_interface_broker_blink.Bind(
-      mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>(
-          mojo::ScopedMessagePipeHandle(
-              params_reply.document_interface_broker_blink_handle),
-          blink::mojom::DocumentInterfaceBroker::Version_),
-      GetTaskRunner(blink::TaskType::kInternalIPC));
-
   // This method is always called by local frames, never remote frames.
 
   // Tracing analysis uses this to find main frames when this value is
@@ -4212,7 +4149,6 @@
   RenderFrameImpl* child_render_frame = RenderFrameImpl::Create(
       render_view_, params_reply.child_routing_id,
       std::move(child_interface_provider),
-      std::move(document_interface_broker_content),
       mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>(
           mojo::ScopedMessagePipeHandle(
               params_reply.browser_interface_broker_handle),
@@ -4225,8 +4161,7 @@
   child_render_frame->InitializeBlameContext(this);
   blink::WebLocalFrame* web_frame = parent->CreateLocalChild(
       scope, child_render_frame,
-      child_render_frame->blink_interface_registry_.get(),
-      document_interface_broker_blink.Unbind().PassPipe());
+      child_render_frame->blink_interface_registry_.get());
 
   child_render_frame->in_frame_tree_ = true;
   child_render_frame->Initialize();
@@ -4532,7 +4467,6 @@
 void RenderFrameImpl::DidCommitProvisionalLoad(
     const blink::WebHistoryItem& item,
     blink::WebHistoryCommitType commit_type,
-    mojo::ScopedMessagePipeHandle document_interface_broker_blink_handle,
     bool should_reset_browser_interface_broker) {
   TRACE_EVENT2("navigation,rail", "RenderFrameImpl::didCommitProvisionalLoad",
                "id", routing_id_,
@@ -4569,8 +4503,6 @@
 
   service_manager::mojom::InterfaceProviderRequest
       remote_interface_provider_request;
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_receiver;
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker_receiver;
 
@@ -4592,22 +4524,6 @@
     remote_interfaces_.Close();
     remote_interfaces_.Bind(std::move(interfaces_provider));
 
-    // If we're navigating to a new document, bind |document_interface_broker_|
-    // to a new message pipe. The receiver end of the new
-    // DocumentInterfaceBroker interface will be sent over as part of
-    // DidCommitProvisionalLoad. After the RFHI receives the commit
-    // confirmation, it will immediately close the old message pipe to avoid
-    // Get<interface> calls racing with navigation commit, and bind the receiver
-    // end of the message pipe created here. Must initialize
-    // |document_interface_broker_| with a new working pipe *before* observers
-    // receive DidCommitProvisionalLoad, so they can already receive remote
-    // interfaces. The interface receivers will be serviced once the
-    // DocumentInterfaceBroker interface receiver is bound by the
-    // RenderFrameHostImpl.
-    document_interface_broker_.reset();
-    document_interface_broker_receiver =
-        document_interface_broker_.BindNewPipeAndPassReceiver();
-
     // If we're navigating to a new document, bind
     // |browser_interface_broker_proxy_| to a new browser interface broker. The
     // request end of the new BrowserInterfaceBroker interface will be sent over
@@ -4662,9 +4578,6 @@
       should_reset_browser_interface_broker
           ? mojom::DidCommitProvisionalLoadInterfaceParams::New(
                 std::move(remote_interface_provider_request),
-                std::move(document_interface_broker_receiver),
-                mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>(
-                    std::move(document_interface_broker_blink_handle)),
                 std::move(browser_interface_broker_receiver))
           : nullptr);
 
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 77744ae5..1fe73946 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -219,10 +219,6 @@
   static void CreateFrame(
       int routing_id,
       service_manager::mojom::InterfaceProviderPtr interface_provider,
-      mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-          document_interface_broker_content,
-      mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-          document_interface_broker_blink,
       mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker,
       int previous_routing_id,
@@ -248,8 +244,6 @@
         RenderViewImpl* render_view,
         int32_t routing_id,
         service_manager::mojom::InterfaceProviderPtr interface_provider,
-        mojo::Remote<blink::mojom::DocumentInterfaceBroker>
-            document_interface_broker_content,
         mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
             browser_interface_broker,
         const base::UnguessableToken& devtools_frame_token);
@@ -261,8 +255,6 @@
     RenderViewImpl* render_view;
     int32_t routing_id;
     service_manager::mojom::InterfaceProviderPtr interface_provider;
-    mojo::Remote<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_content;
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker;
     base::UnguessableToken devtools_frame_token;
@@ -464,7 +456,6 @@
       const std::string& interface_name,
       mojo::ScopedMessagePipeHandle interface_pipe) override;
   service_manager::InterfaceProvider* GetRemoteInterfaces() override;
-  blink::mojom::DocumentInterfaceBroker* GetDocumentInterfaceBroker() override;
   blink::AssociatedInterfaceRegistry* GetAssociatedInterfaceRegistry() override;
   blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override;
 #if BUILDFLAG(ENABLE_PLUGINS)
@@ -729,7 +720,6 @@
   void DidCommitProvisionalLoad(
       const blink::WebHistoryItem& item,
       blink::WebHistoryCommitType commit_type,
-      mojo::ScopedMessagePipeHandle document_interface_broker_blink_handle,
       bool should_reset_browser_interface_broker) override;
   void DidCreateNewDocument() override;
   void DidClearWindowObject() override;
@@ -973,10 +963,6 @@
 
   void TransferUserActivationFrom(blink::WebLocalFrame* source_frame) override;
 
-  // Used in tests to override DocumentInterfaceBroker's methods
-  void SetDocumentInterfaceBrokerForTesting(
-      mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker> test_broker);
-
   // Used in tests to install a fake WebURLLoaderFactory via
   // RenderViewTest::CreateFakeWebURLLoaderFactory().
   void SetWebURLLoaderFactoryOverrideForTest(
@@ -1060,15 +1046,13 @@
   // Creates a new RenderFrame. |render_view| is the RenderView object that this
   // frame belongs to, |interface_provider| is the RenderFrameHost's
   // InterfaceProvider through which services are exposed to the RenderFrame,
-  // and |document_interface_broker_content| is the RenderFrameHost's
-  // DocumentInterfaceBroker through which services are exposed to the
+  // and |browser_interface_broker| is the RenderFrameHost's
+  // BrowserInterfaceBroker through which services are exposed to the
   // RenderFrame.
   static RenderFrameImpl* Create(
       RenderViewImpl* render_view,
       int32_t routing_id,
       service_manager::mojom::InterfaceProviderPtr interface_provider,
-      mojo::Remote<blink::mojom::DocumentInterfaceBroker>
-          document_interface_broker_content,
       mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker,
       const base::UnguessableToken& devtools_frame_token);
@@ -1552,8 +1536,6 @@
   service_manager::InterfaceProvider remote_interfaces_;
   std::unique_ptr<BlinkInterfaceRegistryImpl> blink_interface_registry_;
 
-  mojo::Remote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_;
   blink::BrowserInterfaceBrokerProxy browser_interface_broker_proxy_;
 
   service_manager::BindSourceInfo local_info_;
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc
index 1822a3c4..1f18f9f3 100644
--- a/content/renderer/render_frame_impl_browsertest.cc
+++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -38,7 +38,6 @@
 #include "content/renderer/render_view_impl.h"
 #include "content/test/fake_compositor_dependencies.h"
 #include "content/test/frame_host_test_interface.mojom.h"
-#include "content/test/test_document_interface_broker.h"
 #include "content/test/test_render_frame.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -73,9 +72,6 @@
 const char kParentFrameHTML[] = "Parent frame <iframe name='frame'></iframe>";
 
 const char kAutoplayTestOrigin[] = "https://www.google.com";
-
-constexpr char kGetNameTestResponse[] = "TestName";
-
 }  // namespace
 
 // RenderFrameImplTest creates a RenderFrameImpl that is a child of the
@@ -113,16 +109,6 @@
     service_manager::mojom::InterfaceProviderPtr stub_interface_provider;
     mojo::MakeRequest(&stub_interface_provider);
 
-    mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-        stub_document_interface_broker_content;
-    ignore_result(stub_document_interface_broker_content
-                      .InitWithNewPipeAndPassReceiver());
-
-    mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-        stub_document_interface_broker_blink;
-    ignore_result(
-        stub_document_interface_broker_blink.InitWithNewPipeAndPassReceiver());
-
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
         stub_browser_interface_broker;
     ignore_result(
@@ -130,8 +116,6 @@
 
     RenderFrameImpl::CreateFrame(
         kSubframeRouteId, std::move(stub_interface_provider),
-        std::move(stub_document_interface_broker_content),
-        std::move(stub_document_interface_broker_blink),
         std::move(stub_browser_interface_broker), MSG_ROUTING_NONE,
         MSG_ROUTING_NONE, kFrameProxyRouteId, MSG_ROUTING_NONE,
         base::UnguessableToken::Create(), frame_replication_state,
@@ -267,11 +251,6 @@
 TEST_F(RenderFrameImplTest, LocalChildFrameWasShown) {
   service_manager::mojom::InterfaceProviderPtr stub_interface_provider;
   mojo::MakeRequest(&stub_interface_provider);
-
-  mojo::Remote<blink::mojom::DocumentInterfaceBroker>
-      stub_document_interface_broker;
-  ignore_result(stub_document_interface_broker.BindNewPipeAndPassReceiver());
-
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       stub_browser_interface_broker;
   ignore_result(stub_browser_interface_broker.InitWithNewPipeAndPassReceiver());
@@ -281,15 +260,13 @@
   RenderFrameImpl* grandchild =
       RenderFrameImpl::Create(frame()->render_view(), kEmbeddedSubframeRouteId,
                               std::move(stub_interface_provider),
-                              std::move(stub_document_interface_broker),
                               std::move(stub_browser_interface_broker),
                               base::UnguessableToken::Create());
   blink::WebLocalFrame* parent_web_frame = frame()->GetWebFrame();
 
   parent_web_frame->CreateLocalChild(
       blink::WebTreeScopeType::kDocument, grandchild,
-      grandchild->blink_interface_registry_.get(),
-      stub_document_interface_broker.BindNewPipeAndPassReceiver().PassPipe());
+      grandchild->blink_interface_registry_.get());
   grandchild->in_frame_tree_ = true;
   grandchild->Initialize();
 
@@ -521,74 +498,6 @@
   }
 };
 
-// TODO(crbug.com/718652): this is a blink version of the FrameHostTestInterface
-// implementation. The non-blink one will be removed when all clients are
-// converted to use DocumentInterfaceBroker.
-class BlinkFrameHostTestInterfaceImpl
-    : public blink::mojom::FrameHostTestInterface {
- public:
-  BlinkFrameHostTestInterfaceImpl() {}
-  ~BlinkFrameHostTestInterfaceImpl() override {}
-
-  void BindAndFlush(
-      mojo::PendingReceiver<blink::mojom::FrameHostTestInterface> receiver) {
-    receiver_.Bind(std::move(receiver));
-    receiver_.WaitForIncomingCall();
-  }
-
-  const base::Optional<SourceAnnotation>& ping_source() const {
-    return ping_source_;
-  }
-
- protected:
-  // blink::mojom::FrameHostTestInterface
-  void Ping(const GURL& url, const std::string& event) override {
-    ping_source_ = SourceAnnotation{url, event};
-  }
-  void GetName(GetNameCallback callback) override {
-    std::move(callback).Run(kGetNameTestResponse);
-  }
-
- private:
-  mojo::Receiver<blink::mojom::FrameHostTestInterface> receiver_{this};
-  base::Optional<SourceAnnotation> ping_source_;
-
-  DISALLOW_COPY_AND_ASSIGN(BlinkFrameHostTestInterfaceImpl);
-};
-
-class FrameHostTestDocumentInterfaceBroker
-    : public TestDocumentInterfaceBroker {
- public:
-  FrameHostTestDocumentInterfaceBroker(
-      blink::mojom::DocumentInterfaceBroker* document_interface_broker,
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker> receiver)
-      : TestDocumentInterfaceBroker(document_interface_broker,
-                                    std::move(receiver)) {}
-
-  void GetFrameHostTestInterface(
-      mojo::PendingReceiver<blink::mojom::FrameHostTestInterface> receiver)
-      override {
-    BlinkFrameHostTestInterfaceImpl impl;
-    impl.BindAndFlush(std::move(receiver));
-  }
-};
-
-TEST_F(RenderFrameImplTest, TestDocumentInterfaceBrokerOverride) {
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker> doc;
-  FrameHostTestDocumentInterfaceBroker frame_interface_broker(
-      frame()->GetDocumentInterfaceBroker(),
-      doc.InitWithNewPipeAndPassReceiver());
-  frame()->SetDocumentInterfaceBrokerForTesting(std::move(doc));
-
-  mojo::Remote<blink::mojom::FrameHostTestInterface> frame_test;
-  frame()->GetDocumentInterfaceBroker()->GetFrameHostTestInterface(
-      frame_test.BindNewPipeAndPassReceiver());
-  frame_test->GetName(base::BindOnce([](const std::string& result) {
-    EXPECT_EQ(result, kGetNameTestResponse);
-  }));
-  frame_interface_broker.Flush();
-}
-
 // RenderFrameRemoteInterfacesTest ------------------------------------
 
 namespace {
@@ -650,34 +559,6 @@
   DISALLOW_COPY_AND_ASSIGN(TestSimpleInterfaceProviderImpl);
 };
 
-class TestSimpleDocumentInterfaceBrokerImpl
-    : public blink::mojom::DocumentInterfaceBroker {
- public:
-  using BinderCallback = base::RepeatingCallback<void(
-      mojo::PendingReceiver<blink::mojom::FrameHostTestInterface>)>;
-  explicit TestSimpleDocumentInterfaceBrokerImpl(BinderCallback binder_callback)
-      : binder_callback_(binder_callback) {}
-  void BindAndFlush(
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker> receiver) {
-    ASSERT_FALSE(receiver_.is_bound());
-    receiver_.Bind(std::move(receiver));
-    receiver_.FlushForTesting();
-  }
-
- private:
-  // blink::mojom::DocumentInterfaceBroker
-  void GetFrameHostTestInterface(
-      mojo::PendingReceiver<blink::mojom::FrameHostTestInterface> receiver)
-      override {
-    binder_callback_.Run(std::move(receiver));
-  }
-
-  mojo::Receiver<blink::mojom::DocumentInterfaceBroker> receiver_{this};
-  BinderCallback binder_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestSimpleDocumentInterfaceBrokerImpl);
-};
-
 class TestSimpleBrowserInterfaceBrokerImpl
     : public blink::mojom::BrowserInterfaceBroker {
  public:
@@ -759,16 +640,6 @@
         !document.IsNull() ? GURL(document.Url()) : GURL(kNoDocumentMarkerURL),
         event);
 
-    mojo::Remote<blink::mojom::FrameHostTestInterface> blink_remote;
-    blink::mojom::DocumentInterfaceBroker* document_interface_broker =
-        render_frame()->GetDocumentInterfaceBroker();
-    DCHECK(document_interface_broker);
-    document_interface_broker->GetFrameHostTestInterface(
-        blink_remote.BindNewPipeAndPassReceiver());
-    blink_remote->Ping(
-        !document.IsNull() ? GURL(document.Url()) : GURL(kNoDocumentMarkerURL),
-        event);
-
     remote.reset();
     render_frame()->GetBrowserInterfaceBroker()->GetInterface(
         remote.BindNewPipeAndPassReceiver());
@@ -891,9 +762,6 @@
     interface_request_for_first_document_ =
         frame_->TakeLastInterfaceProviderRequest();
 
-    document_interface_broker_receiver_for_first_document_ =
-        frame_->TakeLastDocumentInterfaceBrokerReceiver();
-
     browser_interface_broker_receiver_for_first_document_ =
         frame_->TakeLastBrowserInterfaceBrokerReceiver();
   }
@@ -903,12 +771,6 @@
     return std::move(interface_request_for_initial_empty_document_);
   }
 
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-  document_interface_broker_receiver_for_initial_empty_document() {
-    return std::move(
-        document_interface_broker_receiver_for_initial_empty_document_);
-  }
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
   browser_interface_broker_receiver_for_initial_empty_document() {
     return std::move(
@@ -920,11 +782,6 @@
     return std::move(interface_request_for_first_document_);
   }
 
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-  document_interface_broker_receiver_for_first_document() {
-    return std::move(document_interface_broker_receiver_for_first_document_);
-  }
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
   browser_interface_broker_receiver_for_first_document() {
     return std::move(browser_interface_broker_receiver_for_first_document_);
@@ -950,8 +807,6 @@
 
     interface_request_for_initial_empty_document_ =
         frame->TakeLastInterfaceProviderRequest();
-    document_interface_broker_receiver_for_initial_empty_document_ =
-        frame->TakeLastDocumentInterfaceBrokerReceiver();
     browser_interface_broker_receiver_for_initial_empty_document_ =
         frame_->TakeLastBrowserInterfaceBrokerReceiver();
     EXPECT_TRUE(frame->current_history_item().IsNull());
@@ -970,11 +825,6 @@
   service_manager::mojom::InterfaceProviderRequest
       interface_request_for_first_document_;
 
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_receiver_for_initial_empty_document_;
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_receiver_for_first_document_;
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker_receiver_for_initial_empty_document_;
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
@@ -989,8 +839,6 @@
 // FrameHostTestInterface requests.
 void ExpectPendingInterfaceRequestsFromSources(
     service_manager::mojom::InterfaceProviderRequest interface_provider_request,
-    mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_receiver,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker_receiver,
     std::vector<SourceAnnotation> expected_sources) {
@@ -1010,21 +858,6 @@
   provider.BindAndFlush(std::move(interface_provider_request));
   EXPECT_THAT(sources, ::testing::ElementsAreArray(expected_sources));
 
-  std::vector<SourceAnnotation> document_interface_broker_sources;
-  ASSERT_TRUE(document_interface_broker_receiver.is_valid());
-  TestSimpleDocumentInterfaceBrokerImpl broker(base::BindLambdaForTesting(
-      [&document_interface_broker_sources](
-          mojo::PendingReceiver<blink::mojom::FrameHostTestInterface>
-              receiver) {
-        BlinkFrameHostTestInterfaceImpl impl;
-        impl.BindAndFlush(std::move(receiver));
-        ASSERT_TRUE(impl.ping_source().has_value());
-        document_interface_broker_sources.push_back(impl.ping_source().value());
-      }));
-  broker.BindAndFlush(std::move(document_interface_broker_receiver));
-  EXPECT_THAT(document_interface_broker_sources,
-              ::testing::ElementsAreArray(expected_sources));
-
   std::vector<SourceAnnotation> browser_interface_broker_sources;
   ASSERT_TRUE(browser_interface_broker_receiver.is_valid());
   TestSimpleBrowserInterfaceBrokerImpl browser_broker(
@@ -1088,7 +921,7 @@
 // Expect that |remote_interfaces_| is bound before the first committed load in
 // a child frame, and then re-bound on the first commit.
 // TODO(crbug.com/718652): when all clients are converted to use
-// DocumentInterfaceBroker, InterfaceProviderRequest-related code will be
+// BrowserInterfaceBroker, InterfaceProviderRequest-related code will be
 // removed.
 TEST_F(RenderFrameRemoteInterfacesTest, ChildFrameAtFirstCommittedLoad) {
   ScopedNewFrameInterfaceProviderExerciser child_frame_exerciser(
@@ -1107,8 +940,6 @@
   ExpectPendingInterfaceRequestsFromSources(
       child_frame_exerciser.interface_request_for_initial_empty_document(),
       child_frame_exerciser
-          .document_interface_broker_receiver_for_initial_empty_document(),
-      child_frame_exerciser
           .browser_interface_broker_receiver_for_initial_empty_document(),
       {{GURL(kNoDocumentMarkerURL), kFrameEventDidCreateNewFrame},
        {initial_empty_url, kFrameEventDidCreateNewDocument},
@@ -1121,8 +952,6 @@
   ExpectPendingInterfaceRequestsFromSources(
       child_frame_exerciser.interface_request_for_first_document(),
       child_frame_exerciser
-          .document_interface_broker_receiver_for_first_document(),
-      child_frame_exerciser
           .browser_interface_broker_receiver_for_first_document(),
       {{child_frame_url, kFrameEventDidCommitProvisionalLoad},
        {child_frame_url, kFrameEventDidCreateDocumentElement}});
@@ -1131,7 +960,7 @@
 // Expect that |remote_interfaces_| is bound before the first committed load in
 // the main frame of an opened window, and then re-bound on the first commit.
 // TODO(crbug.com/718652): when all clients are converted to use
-// DocumentInterfaceBroker, InterfaceProviderRequest-related code will be
+// BrowserInterfaceBroker, InterfaceProviderRequest-related code will be
 // removed.
 TEST_F(RenderFrameRemoteInterfacesTest,
        MainFrameOfOpenedWindowAtFirstCommittedLoad) {
@@ -1163,8 +992,6 @@
   ExpectPendingInterfaceRequestsFromSources(
       main_frame_exerciser.interface_request_for_initial_empty_document(),
       main_frame_exerciser
-          .document_interface_broker_receiver_for_initial_empty_document(),
-      main_frame_exerciser
           .browser_interface_broker_receiver_for_initial_empty_document(),
       {{initial_empty_url, kFrameEventDidCreateNewFrame},
        {new_window_url, kFrameEventReadyToCommitNavigation},
@@ -1172,8 +999,6 @@
   ExpectPendingInterfaceRequestsFromSources(
       main_frame_exerciser.interface_request_for_first_document(),
       main_frame_exerciser
-          .document_interface_broker_receiver_for_first_document(),
-      main_frame_exerciser
           .browser_interface_broker_receiver_for_first_document(),
       {{new_window_url, kFrameEventDidCommitProvisionalLoad},
        {new_window_url, kFrameEventDidCreateDocumentElement}});
@@ -1202,7 +1027,7 @@
 // their own DocumentLoader in blink and model them as a real navigation, we
 // should add a test case here.
 // TODO(crbug.com/718652): when all clients are converted to use
-// DocumentInterfaceBroker, InterfaceProviderRequest-related code will be
+// BrowserInterfaceBroker, InterfaceProviderRequest-related code will be
 // removed.
 TEST_F(RenderFrameRemoteInterfacesTest,
        ChildFrameReusingWindowOfInitialDocument) {
@@ -1229,8 +1054,6 @@
     ExpectPendingInterfaceRequestsFromSources(
         child_frame_exerciser.interface_request_for_initial_empty_document(),
         child_frame_exerciser
-            .document_interface_broker_receiver_for_initial_empty_document(),
-        child_frame_exerciser
             .browser_interface_broker_receiver_for_initial_empty_document(),
         {{GURL(kNoDocumentMarkerURL), kFrameEventDidCreateNewFrame},
          {initial_empty_url, kFrameEventDidCreateNewDocument},
@@ -1242,10 +1065,6 @@
 
     auto request = child_frame_exerciser.interface_request_for_first_document();
     ASSERT_FALSE(request.is_pending());
-    auto document_interface_broker_receiver =
-        child_frame_exerciser
-            .document_interface_broker_receiver_for_first_document();
-    ASSERT_FALSE(document_interface_broker_receiver.is_valid());
     auto browser_interface_broker_receiver =
         child_frame_exerciser
             .browser_interface_broker_receiver_for_first_document();
@@ -1256,7 +1075,7 @@
 // Expect that |remote_interfaces_| is bound to a new pipe on cross-document
 // navigations.
 // TODO(crbug.com/718652): when all clients are converted to use
-// DocumentInterfaceBroker, InterfaceProviderRequest-related code will be
+// BrowserInterfaceBroker, InterfaceProviderRequest-related code will be
 // removed.
 TEST_F(RenderFrameRemoteInterfacesTest, ReplacedOnNonSameDocumentNavigation) {
   LoadHTMLWithUrlOverride("", kTestFirstURL);
@@ -1264,9 +1083,6 @@
   auto interface_provider_request_for_first_document =
       GetMainRenderFrame()->TakeLastInterfaceProviderRequest();
 
-  auto document_interface_broker_receiver_for_first_document =
-      GetMainRenderFrame()->TakeLastDocumentInterfaceBrokerReceiver();
-
   auto browser_interface_broker_receiver_for_first_document =
       GetMainRenderFrame()->TakeLastBrowserInterfaceBrokerReceiver();
 
@@ -1278,31 +1094,24 @@
   auto interface_provider_request_for_second_document =
       GetMainRenderFrame()->TakeLastInterfaceProviderRequest();
 
-  auto document_interface_broker_request_for_second_document =
-      GetMainRenderFrame()->TakeLastDocumentInterfaceBrokerReceiver();
-
   auto browser_interface_broker_receiver_for_second_document =
       GetMainRenderFrame()->TakeLastBrowserInterfaceBrokerReceiver();
 
   ASSERT_TRUE(interface_provider_request_for_first_document.is_pending());
-  ASSERT_TRUE(document_interface_broker_receiver_for_first_document.is_valid());
   ASSERT_TRUE(browser_interface_broker_receiver_for_first_document.is_valid());
 
   ExpectPendingInterfaceRequestsFromSources(
       std::move(interface_provider_request_for_first_document),
-      std::move(document_interface_broker_receiver_for_first_document),
       std::move(browser_interface_broker_receiver_for_first_document),
       {{GURL(kTestFirstURL), kFrameEventAfterCommit},
        {GURL(kTestSecondURL), kFrameEventReadyToCommitNavigation},
        {GURL(kTestSecondURL), kFrameEventDidCreateNewDocument}});
 
   ASSERT_TRUE(interface_provider_request_for_second_document.is_pending());
-  ASSERT_TRUE(document_interface_broker_request_for_second_document.is_valid());
   ASSERT_TRUE(browser_interface_broker_receiver_for_second_document.is_valid());
 
   ExpectPendingInterfaceRequestsFromSources(
       std::move(interface_provider_request_for_second_document),
-      std::move(document_interface_broker_request_for_second_document),
       std::move(browser_interface_broker_receiver_for_second_document),
       {{GURL(kTestSecondURL), kFrameEventDidCommitProvisionalLoad},
        {GURL(kTestSecondURL), kFrameEventDidCreateDocumentElement}});
@@ -1312,7 +1121,7 @@
 // navigations, i.e. the existing InterfaceProvider connection is continued to
 // be used.
 // TODO(crbug.com/718652): when all clients are converted to use
-// DocumentInterfaceBroker, InterfaceProviderRequest-related code will be
+// BrowserInterfaceBroker, InterfaceProviderRequest-related code will be
 // removed.
 TEST_F(RenderFrameRemoteInterfacesTest, ReusedOnSameDocumentNavigation) {
   LoadHTMLWithUrlOverride("", kTestFirstURL);
@@ -1320,9 +1129,6 @@
   auto interface_provider_request =
       GetMainRenderFrame()->TakeLastInterfaceProviderRequest();
 
-  auto document_interface_broker =
-      GetMainRenderFrame()->TakeLastDocumentInterfaceBrokerReceiver();
-
   auto browser_interface_broker_receiver =
       GetMainRenderFrame()->TakeLastBrowserInterfaceBrokerReceiver();
 
@@ -1332,17 +1138,11 @@
   EXPECT_FALSE(
       GetMainRenderFrame()->TakeLastInterfaceProviderRequest().is_pending());
 
-  EXPECT_FALSE(GetMainRenderFrame()
-                   ->TakeLastDocumentInterfaceBrokerReceiver()
-                   .is_valid());
-
   ASSERT_TRUE(interface_provider_request.is_pending());
-  ASSERT_TRUE(document_interface_broker.is_valid());
   ASSERT_TRUE(browser_interface_broker_receiver.is_valid());
 
   ExpectPendingInterfaceRequestsFromSources(
       std::move(interface_provider_request),
-      std::move(document_interface_broker),
       std::move(browser_interface_broker_receiver),
       {{GURL(kTestFirstURL), kFrameEventDidCommitSameDocumentLoad}});
 }
diff --git a/content/renderer/render_frame_metadata_observer_impl.cc b/content/renderer/render_frame_metadata_observer_impl.cc
index ab4b2396..5a9aac9 100644
--- a/content/renderer/render_frame_metadata_observer_impl.cc
+++ b/content/renderer/render_frame_metadata_observer_impl.cc
@@ -151,7 +151,9 @@
       rfm1.viewport_size_in_pixels != rfm2.viewport_size_in_pixels ||
       rfm1.top_controls_height != rfm2.top_controls_height ||
       rfm1.top_controls_shown_ratio != rfm2.top_controls_shown_ratio ||
-      rfm1.local_surface_id_allocation != rfm2.local_surface_id_allocation) {
+      rfm1.local_surface_id_allocation != rfm2.local_surface_id_allocation ||
+      rfm2.new_vertical_scroll_direction !=
+          viz::VerticalScrollDirection::kNull) {
     *needs_activation_notification = true;
     return true;
   }
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 6bffd8b..a2a157c 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -2045,19 +2045,11 @@
   CompositorDependencies* compositor_deps = this;
   service_manager::mojom::InterfaceProviderPtr interface_provider(
       std::move(params->interface_bundle->interface_provider));
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_content(std::move(
-          params->interface_bundle->document_interface_broker_content));
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_blink(
-          std::move(params->interface_bundle->document_interface_broker_blink));
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker(
           std::move(params->interface_bundle->browser_interface_broker));
   RenderFrameImpl::CreateFrame(
       params->routing_id, std::move(interface_provider),
-      std::move(document_interface_broker_content),
-      std::move(document_interface_broker_blink),
       std::move(browser_interface_broker), params->previous_routing_id,
       params->opener_routing_id, params->parent_routing_id,
       params->previous_sibling_routing_id, params->devtools_frame_token,
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index b8c9f30..2e4920b0 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -1104,14 +1104,6 @@
   int routing_id = kProxyRoutingId + 1;
   service_manager::mojom::InterfaceProviderPtr stub_interface_provider;
   mojo::MakeRequest(&stub_interface_provider);
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      stub_document_interface_broker_content;
-  ignore_result(
-      stub_document_interface_broker_content.InitWithNewPipeAndPassReceiver());
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      stub_document_interface_broker_blink;
-  ignore_result(
-      stub_document_interface_broker_blink.InitWithNewPipeAndPassReceiver());
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       stub_browser_interface_broker;
   ignore_result(stub_browser_interface_broker.InitWithNewPipeAndPassReceiver());
@@ -1123,8 +1115,6 @@
   widget_params.visual_properties = test_visual_properties;
   RenderFrameImpl::CreateFrame(
       routing_id, std::move(stub_interface_provider),
-      std::move(stub_document_interface_broker_content),
-      std::move(stub_document_interface_broker_blink),
       std::move(stub_browser_interface_broker), kProxyRoutingId,
       MSG_ROUTING_NONE, MSG_ROUTING_NONE, MSG_ROUTING_NONE,
       base::UnguessableToken::Create(), replication_state, nullptr,
@@ -1182,22 +1172,12 @@
   int routing_id = kProxyRoutingId + 1;
   service_manager::mojom::InterfaceProviderPtr stub_interface_provider;
   mojo::MakeRequest(&stub_interface_provider);
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      stub_document_interface_broker_content;
-  ignore_result(
-      stub_document_interface_broker_content.InitWithNewPipeAndPassReceiver());
-  mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>
-      stub_document_interface_broker_blink;
-  ignore_result(
-      stub_document_interface_broker_blink.InitWithNewPipeAndPassReceiver());
   mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
       stub_browser_interface_broker;
   ignore_result(stub_browser_interface_broker.InitWithNewPipeAndPassReceiver());
 
   RenderFrameImpl::CreateFrame(
       routing_id, std::move(stub_interface_provider),
-      std::move(stub_document_interface_broker_content),
-      std::move(stub_document_interface_broker_blink),
       std::move(stub_browser_interface_broker), kProxyRoutingId,
       MSG_ROUTING_NONE, frame()->GetRoutingID(), MSG_ROUTING_NONE,
       base::UnguessableToken::Create(), replication_state, nullptr,
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index d66ff0b..ff25b83 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1394,10 +1394,6 @@
   view_params
       ->main_frame_interface_bundle = mojom::DocumentScopedInterfaceBundle::New(
       std::move(reply->main_frame_interface_bundle->interface_provider),
-      std::move(reply->main_frame_interface_bundle
-                    ->document_interface_broker_content),
-      std::move(
-          reply->main_frame_interface_bundle->document_interface_broker_blink),
       std::move(reply->main_frame_interface_bundle->browser_interface_broker));
   view_params->main_frame_widget_routing_id = reply->main_frame_widget_route_id;
   view_params->session_storage_namespace_id =
@@ -2000,10 +1996,9 @@
     webview()->PutPageIntoBackForwardCache();
 }
 
-void RenderViewImpl::RestorePageFromBackForwardCache(
-    base::TimeTicks navigation_start) {
+void RenderViewImpl::RestorePageFromBackForwardCache() {
   if (webview())
-    webview()->RestorePageFromBackForwardCache(navigation_start);
+    webview()->RestorePageFromBackForwardCache();
 }
 
 // This function receives TextAutosizerPageInfo from the main frame's renderer
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 978d8c2..d425817a 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -452,7 +452,6 @@
   void OnSetInitialFocus(bool reverse);
   void OnSetRendererPrefs(
       const blink::mojom::RendererPreferences& renderer_prefs);
-  void OnSetWebUIProperty(const std::string& name, const std::string& value);
   void OnSuppressDialogsUntilSwapOut();
   void OnUpdateTargetURLAck();
   void OnUpdateWebPreferences(const WebPreferences& prefs);
@@ -464,7 +463,7 @@
   void OnPageVisibilityChanged(PageVisibilityState visibility_state);
   void SetPageFrozen(bool frozen);
   void PutPageIntoBackForwardCache();
-  void RestorePageFromBackForwardCache(base::TimeTicks navigation_start);
+  void RestorePageFromBackForwardCache();
   void OnTextAutosizerPageInfoChanged(
       const blink::WebTextAutosizerPageInfo& page_info);
 
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index a347a09..c45fd8d 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -2898,20 +2898,6 @@
     else
       ShowVirtualKeyboard();
   }
-// TODO(ananta): Piggyback off existing IPCs to communicate this information,
-// crbug/420130.
-#if defined(OS_WIN)
-  if (event.GetType() == blink::WebGestureEvent::kGestureTap) {
-    // TODO(estade): hit test the event against focused node to make sure
-    // the tap actually hit the focused node.
-    blink::WebInputMethodController* controller = GetInputMethodController();
-    blink::WebTextInputType text_input_type =
-        controller ? controller->TextInputType() : blink::kWebTextInputTypeNone;
-
-    Send(new WidgetHostMsg_FocusedNodeTouched(
-        routing_id_, text_input_type != blink::kWebTextInputTypeNone));
-  }
-#endif
 #endif
 }
 
diff --git a/content/renderer/web_ui_extension.cc b/content/renderer/web_ui_extension.cc
index e39558f..dac750e 100644
--- a/content/renderer/web_ui_extension.cc
+++ b/content/renderer/web_ui_extension.cc
@@ -139,7 +139,7 @@
   if (!ShouldRespondToRequest(&frame, &render_frame))
     return std::string();
 
-  return WebUIExtensionData::Get(render_frame->GetRenderView())->GetValue(name);
+  return WebUIExtensionData::Get(render_frame)->GetValue(name);
 }
 
 }  // namespace content
diff --git a/content/renderer/web_ui_extension_data.cc b/content/renderer/web_ui_extension_data.cc
index 9d8c5ed..095342c 100644
--- a/content/renderer/web_ui_extension_data.cc
+++ b/content/renderer/web_ui_extension_data.cc
@@ -4,15 +4,14 @@
 
 #include "content/renderer/web_ui_extension_data.h"
 
-#include "content/common/view_messages.h"
-#include "content/public/renderer/render_view.h"
+#include "content/common/frame_messages.h"
+#include "content/public/renderer/render_frame.h"
 
 namespace content {
 
-WebUIExtensionData::WebUIExtensionData(RenderView* render_view)
-    : RenderViewObserver(render_view),
-      RenderViewObserverTracker<WebUIExtensionData>(render_view) {
-}
+WebUIExtensionData::WebUIExtensionData(RenderFrame* render_frame)
+    : RenderFrameObserver(render_frame),
+      RenderFrameObserverTracker<WebUIExtensionData>(render_frame) {}
 
 WebUIExtensionData::~WebUIExtensionData() {
 }
@@ -27,7 +26,7 @@
 bool WebUIExtensionData::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(WebUIExtensionData, message)
-    IPC_MESSAGE_HANDLER(ViewMsg_SetWebUIProperty, OnSetWebUIProperty)
+    IPC_MESSAGE_HANDLER(FrameMsg_SetWebUIProperty, OnSetWebUIProperty)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
diff --git a/content/renderer/web_ui_extension_data.h b/content/renderer/web_ui_extension_data.h
index 566faed..8fb97da 100644
--- a/content/renderer/web_ui_extension_data.h
+++ b/content/renderer/web_ui_extension_data.h
@@ -9,16 +9,16 @@
 #include <string>
 
 #include "base/macros.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "content/public/renderer/render_view_observer_tracker.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "content/public/renderer/render_frame_observer_tracker.h"
 
 namespace content {
 
 class WebUIExtensionData
-    : public RenderViewObserver,
-      public RenderViewObserverTracker<WebUIExtensionData> {
+    : public RenderFrameObserver,
+      public RenderFrameObserverTracker<WebUIExtensionData> {
  public:
-  explicit WebUIExtensionData(RenderView* render_view);
+  explicit WebUIExtensionData(RenderFrame* render_frame);
   ~WebUIExtensionData() override;
 
   // Returns value for a given |key|. Will return an empty string if no such key
@@ -26,7 +26,7 @@
   std::string GetValue(const std::string& key) const;
 
  private:
-  // RenderViewObserver implementation.
+  // RenderFrameObserver implementation.
   bool OnMessageReceived(const IPC::Message& message) override;
   void OnDestruct() override;
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 2270e1b..9d2ec04e 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -300,8 +300,6 @@
     "test_content_browser_client.h",
     "test_content_client.cc",
     "test_content_client.h",
-    "test_document_interface_broker.cc",
-    "test_document_interface_broker.h",
     "test_mojo_proxy_resolver_factory.cc",
     "test_mojo_proxy_resolver_factory.h",
     "test_navigation_url_loader.cc",
diff --git a/content/test/data/back_forward_cache/record_navigation_start_time_stamp.html b/content/test/data/back_forward_cache/record_navigation_start_time_stamp.html
deleted file mode 100644
index 1a280b5..0000000
--- a/content/test/data/back_forward_cache/record_navigation_start_time_stamp.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<html>
-<head></head>
-<body>
-This page records the navigationStart value and the initial and latest timestamp
-of the pageShow event.
-This page also has one same-origin and one cross-origin subframe, both of them
-have an onpageshow() event listener.
-</body>
-  <script>
-    window.addEventListener("pageshow", (e) => {
-      if (typeof window.initialPageShowTimeStamp === 'undefined') {
-        window.initialPageShowTimeStamp = e.timeStamp;
-      }
-      window.latestPageShowTimeStamp = e.timeStamp;
-    });
-    window.initialNavigationStart = performance.timing.navigationStart;
-  </script>
- <iframe src="/cross-site/bar.com/back_forward_cache/page_with_pageshow.html"/>
- <iframe src="page_with_pageshow.html"/>
-</html>
diff --git a/content/test/data/scrollable_page_with_content.html b/content/test/data/scrollable_page_with_content.html
index 6af1e007..7d783cd 100644
--- a/content/test/data/scrollable_page_with_content.html
+++ b/content/test/data/scrollable_page_with_content.html
@@ -4,6 +4,7 @@
     <style>
       p {
         position: absolute;
+        left: 10000px;
         top: 10000px;
       }
     </style>
@@ -11,4 +12,4 @@
   <body>
     <p>Some text</p>
   </body>
-</html>>
+</html>
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc
index f4f32d5..86becd6 100644
--- a/content/test/navigation_simulator_impl.cc
+++ b/content/test/navigation_simulator_impl.cc
@@ -344,13 +344,6 @@
 
   service_manager::mojom::InterfaceProviderPtr stub_interface_provider;
   interface_provider_request_ = mojo::MakeRequest(&stub_interface_provider);
-
-  document_interface_broker_content_receiver_ =
-      mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver();
-  document_interface_broker_blink_receiver_ =
-      mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver();
   browser_interface_broker_receiver_ =
       mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
           .InitWithNewPipeAndPassReceiver();
@@ -597,8 +590,6 @@
 
   if (same_document_) {
     interface_provider_request_ = nullptr;
-    document_interface_broker_content_receiver_.reset();
-    document_interface_broker_blink_receiver_.reset();
     browser_interface_broker_receiver_.reset();
   }
 
@@ -617,8 +608,6 @@
       false /* same_document */, false /* failed_navigation */);
   render_frame_host_->SimulateCommitProcessed(
       request_, std::move(params), std::move(interface_provider_request_),
-      std::move(document_interface_broker_content_receiver_),
-      std::move(document_interface_broker_blink_receiver_),
       std::move(browser_interface_broker_receiver_), same_document_);
 
   // Simulate the UnloadACK in the old RenderFrameHost if it was swapped out at
@@ -764,8 +753,6 @@
       false /* same_document */, true /* failed_navigation */);
   render_frame_host_->SimulateCommitProcessed(
       request_, std::move(params), std::move(interface_provider_request_),
-      std::move(document_interface_broker_content_receiver_),
-      std::move(document_interface_broker_blink_receiver_),
       std::move(browser_interface_broker_receiver_), false /* same_document */);
 
   // Simulate the UnloadACK in the old RenderFrameHost if it was swapped out at
@@ -798,14 +785,10 @@
       true /* same_document */, false /* failed_navigation */);
 
   interface_provider_request_ = nullptr;
-  document_interface_broker_content_receiver_.reset();
-  document_interface_broker_blink_receiver_.reset();
   browser_interface_broker_receiver_.reset();
 
   render_frame_host_->SimulateCommitProcessed(
       request_, std::move(params), nullptr /* interface_provider_request_ */,
-      mojo::NullReceiver() /* document_interface_broker_content_receiver */,
-      mojo::NullReceiver() /* document_interface_broker_blink_receiver */,
       mojo::NullReceiver() /* browser_interface_broker_receiver */,
       true /* same_document */);
 
diff --git a/content/test/navigation_simulator_impl.h b/content/test/navigation_simulator_impl.h
index 72a3603..e7b5a8c 100644
--- a/content/test/navigation_simulator_impl.h
+++ b/content/test/navigation_simulator_impl.h
@@ -22,7 +22,6 @@
 #include "net/base/host_port_pair.h"
 #include "net/base/ip_endpoint.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
 #include "third_party/blink/public/mojom/referrer.mojom.h"
 #include "url/gurl.h"
 
@@ -284,10 +283,6 @@
   int session_history_offset_ = 0;
   bool has_user_gesture_ = true;
   service_manager::mojom::InterfaceProviderRequest interface_provider_request_;
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_content_receiver_;
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_blink_receiver_;
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker_receiver_;
   std::string contents_mime_type_;
diff --git a/content/test/test_document_interface_broker.cc b/content/test/test_document_interface_broker.cc
deleted file mode 100644
index 564bcfd..0000000
--- a/content/test/test_document_interface_broker.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/test/test_document_interface_broker.h"
-
-namespace content {
-
-TestDocumentInterfaceBroker::TestDocumentInterfaceBroker(
-    blink::mojom::DocumentInterfaceBroker* document_interface_broker,
-    mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker> receiver)
-    : real_broker_(document_interface_broker),
-      receiver_(this, std::move(receiver)) {}
-
-TestDocumentInterfaceBroker::~TestDocumentInterfaceBroker() {}
-
-blink::mojom::DocumentInterfaceBroker*
-TestDocumentInterfaceBroker::GetForwardingInterface() {
-  return real_broker_;
-}
-
-void TestDocumentInterfaceBroker::Flush() {
-  receiver_.FlushForTesting();
-}
-
-}  // namespace content
\ No newline at end of file
diff --git a/content/test/test_document_interface_broker.h b/content/test/test_document_interface_broker.h
deleted file mode 100644
index e78c3296..0000000
--- a/content/test/test_document_interface_broker.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_TEST_TEST_DOCUMENT_INTERFACE_BROKER_H_
-#define CONTENT_TEST_TEST_DOCUMENT_INTERFACE_BROKER_H_
-
-#include <utility>
-
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-test-utils.h"
-
-namespace content {
-// This class can be subclassed to override specific methods of RenderFrame's
-// DocumentInterfaceBroker in tests. The rest of the calls will be forwarded to
-// the implementation passed to the constructor (typically returned by
-// RenderFrame::GetDocumentInterfaceBroker()).
-class TestDocumentInterfaceBroker
-    : public blink::mojom::DocumentInterfaceBrokerInterceptorForTesting {
- public:
-  TestDocumentInterfaceBroker(
-      blink::mojom::DocumentInterfaceBroker* document_interface_broker,
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker> receiver);
-  ~TestDocumentInterfaceBroker() override;
-  blink::mojom::DocumentInterfaceBroker* GetForwardingInterface() override;
-  void Flush();
-
- private:
-  blink::mojom::DocumentInterfaceBroker* real_broker_;
-  mojo::Receiver<DocumentInterfaceBroker> receiver_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_TEST_TEST_DOCUMENT_INTERFACE_BROKER_H_
\ No newline at end of file
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 19475ef..8e163ba 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -49,11 +49,6 @@
     return std::move(last_interface_provider_request_);
   }
 
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-  TakeLastDocumentInterfaceBrokerReceiver() {
-    return std::move(last_document_interface_broker_receiver_);
-  }
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
   TakeLastBrowserInterfaceBrokerReceiver() {
     return std::move(last_browser_interface_broker_receiver_);
@@ -74,17 +69,6 @@
     last_interface_provider_request_ = std::move(interface_provider_request);
   }
 
-  // Holds on to the receiver end of the DocumentInterfaceBroker interface whose
-  // client end is bound to the corresponding RenderFrame's
-  // |document_interface_broker_| to facilitate retrieving the most recent
-  // |document_interface_broker_receiver| in tests.
-  void PassLastDocumentInterfaceBrokerReceiver(
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-          document_interface_broker_receiver) {
-    last_document_interface_broker_receiver_ =
-        std::move(document_interface_broker_receiver);
-  }
-
   // Holds on to the request end of the BrowserInterfaceBroker interface whose
   // client end is bound to the corresponding RenderFrame's
   // |browser_interface_broker_proxy_| to facilitate retrieving the most recent
@@ -104,10 +88,6 @@
     if (interface_params) {
       last_interface_provider_request_ =
           std::move(interface_params->interface_provider_request);
-      last_document_interface_broker_receiver_ =
-          mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>(
-              std::move(interface_params
-                            ->document_interface_broker_content_receiver));
       last_browser_interface_broker_receiver_ =
           std::move(interface_params->browser_interface_broker_receiver);
     }
@@ -224,8 +204,6 @@
       last_commit_params_;
   service_manager::mojom::InterfaceProviderRequest
       last_interface_provider_request_;
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-      last_document_interface_broker_receiver_;
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
       last_browser_interface_broker_receiver_;
 
@@ -249,9 +227,6 @@
   mock_frame_host_->PassLastInterfaceProviderRequest(
       mock_render_thread->TakeInitialInterfaceProviderRequestForFrame(
           params.routing_id));
-  mock_frame_host_->PassLastDocumentInterfaceBrokerReceiver(
-      mock_render_thread->TakeInitialDocumentInterfaceBrokerReceiverForFrame(
-          params.routing_id));
   mock_frame_host_->PassLastBrowserInterfaceBrokerReceiver(
       mock_render_thread->TakeInitialBrowserInterfaceBrokerReceiverForFrame(
           params.routing_id));
@@ -401,11 +376,6 @@
   return mock_frame_host_->TakeLastInterfaceProviderRequest();
 }
 
-mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-TestRenderFrame::TakeLastDocumentInterfaceBrokerReceiver() {
-  return mock_frame_host_->TakeLastDocumentInterfaceBrokerReceiver();
-}
-
 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
 TestRenderFrame::TakeLastBrowserInterfaceBrokerReceiver() {
   return mock_frame_host_->TakeLastBrowserInterfaceBrokerReceiver();
diff --git a/content/test/test_render_frame.h b/content/test/test_render_frame.h
index 9853bce..c429df2b 100644
--- a/content/test/test_render_frame.h
+++ b/content/test/test_render_frame.h
@@ -78,9 +78,6 @@
   service_manager::mojom::InterfaceProviderRequest
   TakeLastInterfaceProviderRequest();
 
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-  TakeLastDocumentInterfaceBrokerReceiver();
-
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
   TakeLastBrowserInterfaceBrokerReceiver();
 
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index c973a7c..0e9ebb01 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -135,8 +135,6 @@
   std::string frame_unique_name = base::GenerateGUID();
   OnCreateChildFrame(
       GetProcess()->GetNextRoutingID(), CreateStubInterfaceProviderRequest(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
-      CreateStubDocumentInterfaceBrokerReceiver(),
       CreateStubBrowserInterfaceBrokerReceiver(),
       blink::WebTreeScopeType::kDocument, frame_name, frame_unique_name, false,
       base::UnguessableToken::Create(), blink::FramePolicy(),
@@ -434,10 +432,6 @@
     NavigationRequest* navigation_request,
     std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
     service_manager::mojom::InterfaceProviderRequest interface_provider_request,
-    mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_content_receiver,
-    mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-        document_interface_broker_blink_receiver,
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
         browser_interface_broker_receiver,
     bool same_document) {
@@ -455,8 +449,6 @@
             .Run(std::move(params),
                  mojom::DidCommitProvisionalLoadInterfaceParams::New(
                      std::move(interface_provider_request),
-                     std::move(document_interface_broker_content_receiver),
-                     std::move(document_interface_broker_blink_receiver),
                      std::move(browser_interface_broker_receiver)));
         did_commit = true;
       }
@@ -468,8 +460,6 @@
             .Run(std::move(params),
                  mojom::DidCommitProvisionalLoadInterfaceParams::New(
                      std::move(interface_provider_request),
-                     std::move(document_interface_broker_content_receiver),
-                     std::move(document_interface_broker_blink_receiver),
                      std::move(browser_interface_broker_receiver)));
         did_commit = true;
       }
@@ -481,8 +471,6 @@
         params.get(),
         mojom::DidCommitProvisionalLoadInterfaceParams::New(
             std::move(interface_provider_request),
-            std::move(document_interface_broker_content_receiver),
-            std::move(document_interface_broker_blink_receiver),
             std::move(browser_interface_broker_receiver)),
         same_document);
   }
@@ -605,21 +593,11 @@
   service_manager::mojom::InterfaceProviderPtr interface_provider;
   service_manager::mojom::InterfaceProviderRequest interface_provider_request;
 
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_content_receiver;
-  mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-      document_interface_broker_blink_receiver;
   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
       browser_interface_broker_receiver;
 
   if (!is_same_document) {
     interface_provider_request = mojo::MakeRequest(&interface_provider);
-    document_interface_broker_content_receiver =
-        mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-            .InitWithNewPipeAndPassReceiver();
-    document_interface_broker_blink_receiver =
-        mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-            .InitWithNewPipeAndPassReceiver();
     browser_interface_broker_receiver =
         mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
             .InitWithNewPipeAndPassReceiver();
@@ -627,8 +605,6 @@
 
   auto interface_params = mojom::DidCommitProvisionalLoadInterfaceParams::New(
       std::move(interface_provider_request),
-      std::move(document_interface_broker_content_receiver),
-      std::move(document_interface_broker_blink_receiver),
       std::move(browser_interface_broker_receiver));
   return interface_params;
 }
@@ -646,13 +622,6 @@
 }
 
 // static
-mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-TestRenderFrameHost::CreateStubDocumentInterfaceBrokerReceiver() {
-  return mojo::PendingRemote<::blink::mojom::DocumentInterfaceBroker>()
-      .InitWithNewPipeAndPassReceiver();
-}
-
-// static
 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
 TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver() {
   return mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h
index c1b6c436..beab678 100644
--- a/content/test/test_render_frame_host.h
+++ b/content/test/test_render_frame_host.h
@@ -155,10 +155,6 @@
       std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
       service_manager::mojom::InterfaceProviderRequest
           interface_provider_request,
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-          document_interface_broker_content_receiver,
-      mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-          document_interface_broker_blink_receiver,
       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
           browser_interface_broker_receiver,
       bool same_document);
@@ -182,11 +178,6 @@
   static service_manager::mojom::InterfaceProviderRequest
   CreateStubInterfaceProviderRequest();
 
-  // Returns a pending PendingReceiver<DocumentInterfaceBroker> that is safe to
-  // bind to an implementation, but will never receive any interface requests.
-  static mojo::PendingReceiver<blink::mojom::DocumentInterfaceBroker>
-  CreateStubDocumentInterfaceBrokerReceiver();
-
   // Returns a PendingReceiver<BrowserInterfaceBroker> that is safe to bind to
   // an implementation, but will never receive any interface requests.
   static mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
diff --git a/content/test/test_render_widget_host.cc b/content/test/test_render_widget_host.cc
index b36b491..857fb37e 100644
--- a/content/test/test_render_widget_host.cc
+++ b/content/test/test_render_widget_host.cc
@@ -5,6 +5,7 @@
 #include "content/test/test_render_widget_host.h"
 
 #include "base/run_loop.h"
+#include "content/browser/renderer_host/frame_token_message_queue.h"
 #include "content/public/common/content_features.h"
 
 namespace content {
@@ -33,7 +34,8 @@
                            process,
                            routing_id,
                            std::move(widget),
-                           hidden),
+                           hidden,
+                           std::make_unique<FrameTokenMessageQueue>()),
       widget_impl_(std::move(widget_impl)) {}
 
 TestRenderWidgetHost::~TestRenderWidgetHost() {}
diff --git a/docs/servicification.md b/docs/servicification.md
index d24dcd3..8e9735e 100644
--- a/docs/servicification.md
+++ b/docs/servicification.md
@@ -300,12 +300,6 @@
 The current way to set up that sort of thing looks like
 [this](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/battery-status/resources/mock-battery-monitor.js?rcl=be6e0001855f7f1cfc26205d0ff5a2b5b324fcbd&l=19).
 
-*** aside
-**NOTE:** The above approach to mocking in JS no longer applies when using
-the new recommended `DocumentInterfaceBroker` approach to exposing interfaces
-to documents. New JS mocking support is in development for this.
-***
-
 #### Feature Impls That Depend on Blink Headers
 In the course of servicifying a feature that has Blink as a client, you might
 encounter cases where the feature implementation has dependencies on Blink
diff --git a/extensions/renderer/DEPS b/extensions/renderer/DEPS
index 1e9c6096..ad6a8442 100644
--- a/extensions/renderer/DEPS
+++ b/extensions/renderer/DEPS
@@ -9,7 +9,6 @@
   "+third_party/cld_3",
 
   "+third_party/blink/public/mojom/devtools/console_message.mojom.h",
-  "+third_party/blink/public/mojom/frame/document_interface_broker.mojom.h",
   "+third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h",
   "+third_party/blink/public/platform",
   "+third_party/blink/public/strings/grit/blink_strings.h",
diff --git a/extensions/renderer/scoped_web_frame.cc b/extensions/renderer/scoped_web_frame.cc
index 18bcd84..1531ca6 100644
--- a/extensions/renderer/scoped_web_frame.cc
+++ b/extensions/renderer/scoped_web_frame.cc
@@ -5,31 +5,21 @@
 #include "extensions/renderer/scoped_web_frame.h"
 
 #include "mojo/public/cpp/bindings/pending_remote.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
 #include "third_party/blink/public/web/web_heap.h"
 #include "third_party/blink/public/web/web_view.h"
 #include "third_party/blink/public/web/web_widget.h"
 
 namespace extensions {
 
-// returns a valid handle that can be passed to WebLocalFrame constructor
-mojo::ScopedMessagePipeHandle CreateStubDocumentInterfaceBrokerHandle() {
-  return mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-      .InitWithNewPipeAndPassReceiver()
-      .PassPipe();
-}
-
 ScopedWebFrame::ScopedWebFrame()
     : view_(blink::WebView::Create(/*client=*/nullptr,
                                    /*is_hidden=*/false,
                                    /*compositing_enabled=*/false,
                                    /*opener=*/nullptr)),
-      frame_(blink::WebLocalFrame::CreateMainFrame(
-          view_,
-          &frame_client_,
-          nullptr,
-          CreateStubDocumentInterfaceBrokerHandle(),
-          nullptr)) {}
+      frame_(blink::WebLocalFrame::CreateMainFrame(view_,
+                                                   &frame_client_,
+                                                   nullptr,
+                                                   nullptr)) {}
 
 ScopedWebFrame::~ScopedWebFrame() {
   view_->Close();
diff --git a/fuchsia/base/agent_manager.h b/fuchsia/base/agent_manager.h
index 21dff25f..08da2ec 100644
--- a/fuchsia/base/agent_manager.h
+++ b/fuchsia/base/agent_manager.h
@@ -17,7 +17,7 @@
 
 // Connects to the ComponentContext service from the supplied ServiceDirectory,
 // and uses it to connect-to and manage one or more Agents used by the caller.
-class BASE_EXPORT AgentManager {
+class AgentManager {
  public:
   explicit AgentManager(const sys::ServiceDirectory* incoming);
   ~AgentManager();
diff --git a/fuchsia/engine/BUILD.gn b/fuchsia/engine/BUILD.gn
index 3581651..cd9e0afb9 100644
--- a/fuchsia/engine/BUILD.gn
+++ b/fuchsia/engine/BUILD.gn
@@ -150,8 +150,6 @@
     "browser/web_engine_net_log.h",
     "browser/web_engine_permission_manager.cc",
     "browser/web_engine_permission_manager.h",
-    "browser/web_engine_screen.cc",
-    "browser/web_engine_screen.h",
     "common/web_engine_content_client.cc",
     "common/web_engine_content_client.h",
     "common/web_engine_url_loader_throttle.cc",
diff --git a/fuchsia/engine/browser/web_engine_browser_main_parts.cc b/fuchsia/engine/browser/web_engine_browser_main_parts.cc
index 3fba044..2ad89fec 100644
--- a/fuchsia/engine/browser/web_engine_browser_main_parts.cc
+++ b/fuchsia/engine/browser/web_engine_browser_main_parts.cc
@@ -16,7 +16,6 @@
 #include "fuchsia/engine/browser/context_impl.h"
 #include "fuchsia/engine/browser/web_engine_browser_context.h"
 #include "fuchsia/engine/browser/web_engine_devtools_controller.h"
-#include "fuchsia/engine/browser/web_engine_screen.h"
 #include "fuchsia/engine/switches.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "ui/aura/screen_ozone.h"
diff --git a/fuchsia/engine/browser/web_engine_screen.cc b/fuchsia/engine/browser/web_engine_screen.cc
deleted file mode 100644
index 21be4b84..0000000
--- a/fuchsia/engine/browser/web_engine_screen.cc
+++ /dev/null
@@ -1,15 +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 "fuchsia/engine/browser/web_engine_screen.h"
-
-#include "ui/display/display.h"
-
-WebEngineScreen::WebEngineScreen() {
-  const int64_t kDefaultDisplayId = 1;
-  display::Display display(kDefaultDisplayId);
-  ProcessDisplayChanged(display, /*is_primary=*/true);
-}
-
-WebEngineScreen::~WebEngineScreen() = default;
diff --git a/fuchsia/engine/browser/web_engine_screen.h b/fuchsia/engine/browser/web_engine_screen.h
deleted file mode 100644
index ac6289b..0000000
--- a/fuchsia/engine/browser/web_engine_screen.h
+++ /dev/null
@@ -1,22 +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 FUCHSIA_ENGINE_BROWSER_WEB_ENGINE_SCREEN_H_
-#define FUCHSIA_ENGINE_BROWSER_WEB_ENGINE_SCREEN_H_
-
-#include "base/macros.h"
-
-#include "ui/display/screen_base.h"
-
-// display::Screen implementation for WebEngine on Fuchsia.
-class DISPLAY_EXPORT WebEngineScreen : public display::ScreenBase {
- public:
-  WebEngineScreen();
-  ~WebEngineScreen() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WebEngineScreen);
-};
-
-#endif  // FUCHSIA_ENGINE_BROWSER_WEB_ENGINE_SCREEN_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm
index 3d9e556..a813932 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm
@@ -276,6 +276,11 @@
 
 // Tests the "Open in New Tab" action of the Most Visited context menu.
 - (void)testMostVisitedNewTab {
+// TODO(crbug.com/1022152): Enable this test.
+#if defined(CHROME_EARL_GREY_2)
+  EARL_GREY_TEST_DISABLED(@"Fails with EG2");
+#endif
+
   [self setupMostVisitedTileLongPress];
   const GURL pageURL = self.testServer->GetURL(kPageURL);
 
@@ -313,6 +318,11 @@
 // Tests the "Open in New Incognito Tab" action of the Most Visited context
 // menu.
 - (void)testMostVisitedNewIncognitoTab {
+// TODO(crbug.com/1022152): Enable this test.
+#if defined(CHROME_EARL_GREY_2)
+  EARL_GREY_TEST_DISABLED(@"Fails with EG2");
+#endif
+
   [self setupMostVisitedTileLongPress];
   const GURL pageURL = self.testServer->GetURL(kPageURL);
 
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index b4658d2..3f1b4883 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -304,6 +304,7 @@
     "//ios/web/public/test",
     "//ios/web/public/test/fakes",
     "//net",
+    "//net:test_support",
     "//testing/gtest",
     "//third_party/ocmock",
     "//url",
diff --git a/ios/chrome/browser/web/chrome_web_client_unittest.mm b/ios/chrome/browser/web/chrome_web_client_unittest.mm
index 5601003..eb39f58 100644
--- a/ios/chrome/browser/web/chrome_web_client_unittest.mm
+++ b/ios/chrome/browser/web/chrome_web_client_unittest.mm
@@ -24,6 +24,9 @@
 #import "ios/web/public/test/fakes/test_web_state.h"
 #import "ios/web/public/test/js_test_util.h"
 #include "ios/web/public/test/scoped_testing_web_client.h"
+#include "net/ssl/ssl_info.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
 #include "testing/platform_test.h"
@@ -292,5 +295,40 @@
               page);
 }
 
-// TODO(crbug.com/1017406): Add tests for SSL committed interstitials, where
-// an SSLInfo value is passed into PrepareErrorPage.
+// Tests PrepareErrorPage with SSLInfo, which results in an SSL committed
+// interstitial.
+TEST_F(ChromeWebClientTest, PrepareErrorPageWithSSLInfo) {
+  net::SSLInfo info;
+  info.cert =
+      net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
+  info.is_fatal_cert_error = false;
+  info.cert_status = net::CERT_STATUS_COMMON_NAME_INVALID;
+  base::Optional<net::SSLInfo> ssl_info =
+      base::make_optional<net::SSLInfo>(info);
+  ChromeWebClient web_client;
+  NSError* error =
+      [NSError errorWithDomain:NSURLErrorDomain
+                          code:NSURLErrorServerCertificateHasUnknownRoot
+                      userInfo:nil];
+  __block bool callback_called = false;
+  __block NSString* page = nil;
+  base::OnceCallback<void(NSString*)> callback =
+      base::BindOnce(^(NSString* error_html) {
+        callback_called = true;
+        page = error_html;
+      });
+  web::TestWebState test_web_state;
+  test_web_state.SetBrowserState(browser_state());
+  web_client.PrepareErrorPage(&test_web_state, GURL(kTestUrl), error,
+                              /*is_post=*/false,
+                              /*is_off_the_record=*/false,
+                              /*info=*/ssl_info,
+                              /*navigation_id=*/0, std::move(callback));
+  EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^bool {
+    base::RunLoop().RunUntilIdle();
+    return callback_called;
+  }));
+  NSString* error_string = base::SysUTF8ToNSString(
+      net::ErrorToShortString(net::ERR_CERT_COMMON_NAME_INVALID));
+  EXPECT_TRUE([page containsString:error_string]);
+}
diff --git a/ios/net/cookies/system_cookie_util.mm b/ios/net/cookies/system_cookie_util.mm
index a38d323..0739470 100644
--- a/ios/net/cookies/system_cookie_util.mm
+++ b/ios/net/cookies/system_cookie_util.mm
@@ -33,6 +33,11 @@
 // Undocumented property of NSHTTPCookie.
 NSString* const kNSHTTPCookieHttpOnly = @"HttpOnly";
 
+// Possible value for SameSite policy. WebKit doesn't use the value "none" or
+// any other value, it uses the empty value to represent none, and any value
+// that is not "strict" or "lax" will be considered as none.
+NSString* const kNSHTTPCookieSameSiteNone = @"none";
+
 // Key in NSUserDefaults telling wether a low cookie count must be reported as
 // an error.
 NSString* const kCheckCookieLossKey = @"CookieUtilIOSCheckCookieLoss";
@@ -70,16 +75,30 @@
 net::CanonicalCookie CanonicalCookieFromSystemCookie(
     NSHTTPCookie* cookie,
     const base::Time& ceation_time) {
+  net::CookieSameSite same_site = net::CookieSameSite::NO_RESTRICTION;
+  if (@available(iOS 13, *)) {
+    same_site = net::CookieSameSite::UNSPECIFIED;
+    if ([cookie.sameSitePolicy isEqual:NSHTTPCookieSameSiteLax])
+      same_site = net::CookieSameSite::LAX_MODE;
+
+    if ([cookie.sameSitePolicy isEqual:NSHTTPCookieSameSiteStrict])
+      same_site = net::CookieSameSite::STRICT_MODE;
+
+    if ([[cookie.sameSitePolicy lowercaseString]
+            isEqual:kNSHTTPCookieSameSiteNone])
+      same_site = net::CookieSameSite::NO_RESTRICTION;
+  }
+
   return net::CanonicalCookie(
       base::SysNSStringToUTF8([cookie name]),
       base::SysNSStringToUTF8([cookie value]),
       base::SysNSStringToUTF8([cookie domain]),
       base::SysNSStringToUTF8([cookie path]), ceation_time,
       base::Time::FromDoubleT([[cookie expiresDate] timeIntervalSince1970]),
-      base::Time(), [cookie isSecure], [cookie isHTTPOnly],
-      // TODO(mkwst): When iOS begins to support 'SameSite' and 'Priority'
-      // attributes, pass them through here.
-      net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_DEFAULT);
+      base::Time(), [cookie isSecure], [cookie isHTTPOnly], same_site,
+      // When iOS begins to support 'Priority' attribute, pass it
+      // through here.
+      net::COOKIE_PRIORITY_DEFAULT);
 }
 
 void ReportGetCookiesForURLResult(SystemCookieStoreType store_type,
@@ -140,6 +159,28 @@
         [NSDate dateWithTimeIntervalSince1970:cookie.ExpiryDate().ToDoubleT()];
     [properties setObject:expiry forKey:NSHTTPCookieExpires];
   }
+
+  if (@available(iOS 13, *)) {
+    // In iOS 13 sameSite property in NSHTTPCookie is used to specify the
+    // samesite policy.
+    NSString* same_site = @"";
+    switch (cookie.SameSite()) {
+      case net::CookieSameSite::LAX_MODE:
+        same_site = NSHTTPCookieSameSiteLax;
+        break;
+      case net::CookieSameSite::STRICT_MODE:
+        same_site = NSHTTPCookieSameSiteStrict;
+        break;
+      case net::CookieSameSite::NO_RESTRICTION:
+        same_site = kNSHTTPCookieSameSiteNone;
+        break;
+      case net::CookieSameSite::UNSPECIFIED:
+        // All other values of same site policy will be treated as no value .
+        break;
+    }
+    properties[NSHTTPCookieSameSitePolicy] = same_site;
+  }
+
   if (cookie.IsSecure())
     [properties setObject:@"Y" forKey:NSHTTPCookieSecure];
   if (cookie.IsHttpOnly())
diff --git a/ios/net/cookies/system_cookie_util_unittest.mm b/ios/net/cookies/system_cookie_util_unittest.mm
index fa53a02..84d8387 100644
--- a/ios/net/cookies/system_cookie_util_unittest.mm
+++ b/ios/net/cookies/system_cookie_util_unittest.mm
@@ -32,14 +32,18 @@
     "IOS.Cookies.GetCookiesForURLCallResult";
 
 void CheckSystemCookie(const base::Time& expires, bool secure, bool httponly) {
+  net::CookieSameSite same_site = net::CookieSameSite::NO_RESTRICTION;
+  if (@available(iOS 13, *)) {
+    // SamesitePolicy property of NSHTTPCookieStore is available on iOS 13+.
+    same_site = net::CookieSameSite::LAX_MODE;
+  }
   // Generate a canonical cookie.
   net::CanonicalCookie canonical_cookie(
       kCookieName, kCookieValue, kCookieDomain, kCookiePath,
       base::Time(),  // creation
       expires,
       base::Time(),  // last_access
-      secure, httponly, net::CookieSameSite::NO_RESTRICTION,
-      net::COOKIE_PRIORITY_DEFAULT);
+      secure, httponly, same_site, net::COOKIE_PRIORITY_DEFAULT);
   // Convert it to system cookie.
   NSHTTPCookie* system_cookie =
       SystemCookieFromCanonicalCookie(canonical_cookie);
@@ -53,6 +57,10 @@
   EXPECT_EQ(secure, [system_cookie isSecure]);
   EXPECT_EQ(httponly, [system_cookie isHTTPOnly]);
   EXPECT_EQ(expires.is_null(), [system_cookie isSessionOnly]);
+
+  if (@available(iOS 13, *)) {
+    EXPECT_NSEQ(NSHTTPCookieSameSiteLax, [system_cookie sameSitePolicy]);
+  }
   // Allow 1 second difference as iOS rounds expiry time to the nearest second.
   base::Time system_cookie_expire_date = base::Time::FromDoubleT(
       [[system_cookie expiresDate] timeIntervalSince1970]);
@@ -79,14 +87,23 @@
   base::Time expire_date = creation_time + base::TimeDelta::FromHours(2);
   NSDate* system_expire_date =
       [NSDate dateWithTimeIntervalSince1970:expire_date.ToDoubleT()];
-  NSHTTPCookie* system_cookie = [[NSHTTPCookie alloc] initWithProperties:@{
-    NSHTTPCookieDomain : @"foo",
-    NSHTTPCookieName : @"a",
-    NSHTTPCookiePath : @"/",
-    NSHTTPCookieValue : @"b",
-    NSHTTPCookieExpires : system_expire_date,
-    @"HttpOnly" : @YES,
-  }];
+  NSMutableDictionary* properties =
+      [NSMutableDictionary dictionaryWithDictionary:@{
+        NSHTTPCookieDomain : @"foo",
+        NSHTTPCookieName : @"a",
+        NSHTTPCookiePath : @"/",
+        NSHTTPCookieValue : @"b",
+        NSHTTPCookieExpires : system_expire_date,
+        @"HttpOnly" : @YES,
+      }];
+  if (@available(iOS 13, *)) {
+    // sameSitePolicy is only available on iOS 13+.
+    properties[NSHTTPCookieSameSitePolicy] = NSHTTPCookieSameSiteStrict;
+  }
+
+  NSHTTPCookie* system_cookie =
+      [[NSHTTPCookie alloc] initWithProperties:properties];
+
   ASSERT_TRUE(system_cookie);
   net::CanonicalCookie chrome_cookie =
       CanonicalCookieFromSystemCookie(system_cookie, creation_time);
@@ -105,6 +122,9 @@
   EXPECT_FALSE(chrome_cookie.IsSecure());
   EXPECT_TRUE(chrome_cookie.IsHttpOnly());
   EXPECT_EQ(net::COOKIE_PRIORITY_DEFAULT, chrome_cookie.Priority());
+  if (@available(iOS 13, *)) {
+    EXPECT_EQ(net::CookieSameSite::STRICT_MODE, chrome_cookie.SameSite());
+  }
 
   // Test session and secure cookie.
   system_cookie = [[NSHTTPCookie alloc] initWithProperties:@{
diff --git a/ios/web/download/download_session_cookie_storage.mm b/ios/web/download/download_session_cookie_storage.mm
index 9138bea..a9296f92 100644
--- a/ios/web/download/download_session_cookie_storage.mm
+++ b/ios/web/download/download_session_cookie_storage.mm
@@ -39,12 +39,23 @@
 - (nullable NSArray<NSHTTPCookie*>*)cookiesForURL:(NSURL*)URL {
   NSMutableArray<NSHTTPCookie*>* result = [NSMutableArray array];
   GURL gURL = net::GURLWithNSURL(URL);
-  net::CookieOptions options;
-  options.set_include_httponly();
+  // TODO(crbug.com/1018272): Compute the cookie access semantic, and update
+  // |options| with it.
+  net::CookieOptions options = net::CookieOptions::MakeAllInclusive();
+  net::CookieAccessSemantics cookieAccessSemantics =
+      net::CookieAccessSemantics::LEGACY;
+  if (@available(iOS 13, *)) {
+    // Using |UNKNOWN| semantics to allow the experiment to switch between non
+    // legacy (where cookies that don't have a specific same-site access policy
+    // and not secure will not be included), and legacy mode.
+    cookieAccessSemantics = net::CookieAccessSemantics::UNKNOWN;
+  }
   for (NSHTTPCookie* cookie in self.cookies) {
     net::CanonicalCookie canonical_cookie =
         net::CanonicalCookieFromSystemCookie(cookie, base::Time());
-    if (canonical_cookie.IncludeForRequestURL(gURL, options).IsInclude())
+    if (canonical_cookie
+            .IncludeForRequestURL(gURL, options, cookieAccessSemantics)
+            .IsInclude())
       [result addObject:cookie];
   }
   return [result copy];
diff --git a/ios/web/net/cookies/wk_http_system_cookie_store.mm b/ios/web/net/cookies/wk_http_system_cookie_store.mm
index f5c0c12..ac89fb4 100644
--- a/ios/web/net/cookies/wk_http_system_cookie_store.mm
+++ b/ios/web/net/cookies/wk_http_system_cookie_store.mm
@@ -43,9 +43,20 @@
   // to support cookieOptions this function can be modified to support that.
   net::CanonicalCookie canonical_cookie =
       net::CanonicalCookieFromSystemCookie(cookie, base::Time());
-  net::CookieOptions options;
-  options.set_include_httponly();
-  return canonical_cookie.IncludeForRequestURL(url, options).IsInclude();
+  // Cookies handled by this method are app specific cookies, so it's safe to
+  // use strict same site context.
+  net::CookieOptions options = net::CookieOptions::MakeAllInclusive();
+  net::CookieAccessSemantics cookie_access_semantics =
+      net::CookieAccessSemantics::LEGACY;
+  if (@available(iOS 13, *)) {
+    // Using |UNKNOWN| semantics to allow the experiment to switch between non
+    // legacy (where cookies that don't have a specific same-site access policy
+    // and not secure will not be included), and legacy mode.
+    cookie_access_semantics = net::CookieAccessSemantics::UNKNOWN;
+  }
+  return canonical_cookie
+      .IncludeForRequestURL(url, options, cookie_access_semantics)
+      .IsInclude();
 }
 
 }  // namespace
diff --git a/media/base/eme_constants.h b/media/base/eme_constants.h
index ba9387f..2664065 100644
--- a/media/base/eme_constants.h
+++ b/media/base/eme_constants.h
@@ -49,7 +49,7 @@
 namespace {
 
 constexpr SupportedCodecs GetMp4AudioCodecs() {
-  SupportedCodecs codecs = EME_CODEC_FLAC;
+  SupportedCodecs codecs = EME_CODEC_OPUS | EME_CODEC_FLAC;
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
   codecs |= EME_CODEC_AAC;
 #if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
diff --git a/media/base/test_data_util.cc b/media/base/test_data_util.cc
index bb615c1..469be49a 100644
--- a/media/base/test_data_util.cc
+++ b/media/base/test_data_util.cc
@@ -29,6 +29,7 @@
 const char kMp4AacAudio[] = "audio/mp4; codecs=\"mp4a.40.2\"";
 const char kMp4Av110bitVideo[] = "video/mp4; codecs=\"av01.0.04M.10\"";
 const char kMp4Av1Video[] = "video/mp4; codecs=\"av01.0.04M.08\"";
+const char kMp4Av1VideoOpusAudio[] = "video/mp4; codecs=\"av01.0.04M.08,opus\"";
 const char kMp4Avc1Video[] = "video/mp4; codecs=\"avc1.64001E\"";
 const char kMp4AacAudioAvc1Video[] =
     "video/mp4; codecs=\"mp4a.40.2, avc1.64001E\"";
@@ -125,12 +126,14 @@
       {"bear-av1-480x360.webm", kWebMAv1Video},
       {"bear-av1-cenc.mp4", kMp4Av1Video},
       {"bear-av1-cenc.webm", kWebMAv1Video},
+      {"bear-av1-opus.mp4", kMp4Av1VideoOpusAudio},
       {"bear-av1.mp4", kMp4Av1Video},
       {"bear-av1.webm", kWebMAv1Video},
       {"bear-flac-cenc.mp4", kMp4FlacAudio},
       {"bear-flac_frag.mp4", kMp4FlacAudio},
       {"bear-opus.mp4", kMp4OpusAudio},
       {"bear-opus.webm", kWebMOpusAudio},
+      {"bear-opus-cenc.mp4", kMp4OpusAudio},
       {"bear-vp8a.webm", kWebMVp8Video},
       {"bear-vp9-blockgroup.webm", kWebMVp9Video},
       {"bear-vp9.webm", kWebMVp9Video},
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc
index 9f16754..78d508ca 100644
--- a/media/blink/webmediaplayer_impl_unittest.cc
+++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -51,7 +51,6 @@
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
 #include "third_party/blink/public/platform/media/webmediaplayer_delegate.h"
 #include "third_party/blink/public/platform/web_fullscreen_video_status.h"
 #include "third_party/blink/public/platform/web_media_player.h"
@@ -102,13 +101,6 @@
                                   std::string(new_rate_string));
 }
 
-// returns a valid handle that can be passed to WebLocalFrame constructor
-mojo::ScopedMessagePipeHandle CreateStubDocumentInterfaceBrokerHandle() {
-  return mojo::PendingRemote<blink::mojom::DocumentInterfaceBroker>()
-      .InitWithNewPipeAndPassReceiver()
-      .PassPipe();
-}
-
 class MockWebMediaPlayerClient : public blink::WebMediaPlayerClient {
  public:
   MockWebMediaPlayerClient() = default;
@@ -314,12 +306,11 @@
                                          /*is_hidden=*/false,
                                          /*compositing_enabled=*/false,
                                          nullptr)),
-        web_local_frame_(blink::WebLocalFrame::CreateMainFrame(
-            web_view_,
-            &web_frame_client_,
-            nullptr,
-            CreateStubDocumentInterfaceBrokerHandle(),
-            nullptr)),
+        web_local_frame_(
+            blink::WebLocalFrame::CreateMainFrame(web_view_,
+                                                  &web_frame_client_,
+                                                  nullptr,
+                                                  nullptr)),
         context_provider_(viz::TestContextProvider::Create()),
         audio_parameters_(TestAudioParameters::Normal()) {
     media_thread_.StartAndWaitForTesting();
diff --git a/media/gpu/test/video_frame_helpers.cc b/media/gpu/test/video_frame_helpers.cc
index 8401071..d0fb485 100644
--- a/media/gpu/test/video_frame_helpers.cc
+++ b/media/gpu/test/video_frame_helpers.cc
@@ -16,6 +16,7 @@
 #include "media/base/video_frame.h"
 #include "media/gpu/buildflags.h"
 #include "media/gpu/test/image.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/libyuv/include/libyuv.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/gpu_memory_buffer.h"
@@ -31,10 +32,19 @@
 
 namespace {
 
+#define ASSERT_TRUE_AND_RETURN(predicate, return_value) \
+  do {                                                  \
+    if (!(predicate)) {                                 \
+      ADD_FAILURE();                                    \
+      return (return_value);                            \
+    }                                                   \
+  } while (0)
+
 bool ConvertVideoFrameToI420(const VideoFrame* src_frame,
                              VideoFrame* dst_frame) {
-  LOG_ASSERT(src_frame->visible_rect() == dst_frame->visible_rect());
-  LOG_ASSERT(dst_frame->format() == PIXEL_FORMAT_I420);
+  ASSERT_TRUE_AND_RETURN(src_frame->visible_rect() == dst_frame->visible_rect(),
+                         false);
+  ASSERT_TRUE_AND_RETURN(dst_frame->format() == PIXEL_FORMAT_I420, false);
 
   const auto& visible_rect = src_frame->visible_rect();
   const int width = visible_rect.width();
@@ -81,8 +91,9 @@
 
 bool ConvertVideoFrameToARGB(const VideoFrame* src_frame,
                              VideoFrame* dst_frame) {
-  LOG_ASSERT(src_frame->visible_rect() == dst_frame->visible_rect());
-  LOG_ASSERT(dst_frame->format() == PIXEL_FORMAT_ARGB);
+  ASSERT_TRUE_AND_RETURN(src_frame->visible_rect() == dst_frame->visible_rect(),
+                         false);
+  ASSERT_TRUE_AND_RETURN(dst_frame->format() == PIXEL_FORMAT_ARGB, false);
 
   const auto& visible_rect = src_frame->visible_rect();
   const int width = visible_rect.width();
@@ -126,7 +137,7 @@
 // Copy memory based |src_frame| buffer to |dst_frame| buffer.
 bool CopyVideoFrame(const VideoFrame* src_frame,
                     scoped_refptr<VideoFrame> dst_frame) {
-  LOG_ASSERT(src_frame->IsMappable());
+  ASSERT_TRUE_AND_RETURN(src_frame->IsMappable(), false);
 #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
   // If |dst_frame| is a Dmabuf-backed VideoFrame, we need to map its underlying
   // buffer into memory. We use a VideoFrameMapper to create a memory-based
@@ -134,7 +145,7 @@
   if (dst_frame->storage_type() == VideoFrame::STORAGE_DMABUFS) {
     auto video_frame_mapper = VideoFrameMapperFactory::CreateMapper(
         dst_frame->format(), VideoFrame::STORAGE_DMABUFS, true);
-    LOG_ASSERT(video_frame_mapper);
+    ASSERT_TRUE_AND_RETURN(video_frame_mapper, false);
     dst_frame = video_frame_mapper->Map(std::move(dst_frame));
     if (!dst_frame) {
       LOG(ERROR) << "Failed to map DMABuf video frame.";
@@ -142,13 +153,15 @@
     }
   }
 #endif  // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
-  LOG_ASSERT(dst_frame->IsMappable());
-  LOG_ASSERT(src_frame->format() == dst_frame->format());
+  ASSERT_TRUE_AND_RETURN(dst_frame->IsMappable(), false);
+  ASSERT_TRUE_AND_RETURN(src_frame->format() == dst_frame->format(), false);
 
   // Copy every plane's content from |src_frame| to |dst_frame|.
   const size_t num_planes = VideoFrame::NumPlanes(dst_frame->format());
-  LOG_ASSERT(dst_frame->layout().planes().size() == num_planes);
-  LOG_ASSERT(src_frame->layout().planes().size() == num_planes);
+  ASSERT_TRUE_AND_RETURN(dst_frame->layout().planes().size() == num_planes,
+                         false);
+  ASSERT_TRUE_AND_RETURN(src_frame->layout().planes().size() == num_planes,
+                         false);
   for (size_t i = 0; i < num_planes; ++i) {
     // |width| in libyuv::CopyPlane() is in bytes, not pixels.
     gfx::Size plane_size = VideoFrame::PlaneSize(dst_frame->format(), i,
@@ -164,8 +177,10 @@
 }  // namespace
 
 bool ConvertVideoFrame(const VideoFrame* src_frame, VideoFrame* dst_frame) {
-  LOG_ASSERT(src_frame->visible_rect() == dst_frame->visible_rect());
-  LOG_ASSERT(src_frame->IsMappable() && dst_frame->IsMappable());
+  ASSERT_TRUE_AND_RETURN(src_frame->visible_rect() == dst_frame->visible_rect(),
+                         false);
+  ASSERT_TRUE_AND_RETURN(src_frame->IsMappable() && dst_frame->IsMappable(),
+                         false);
 
   // Writing into non-owned memory might produce some unexpected side effects.
   if (dst_frame->storage_type() != VideoFrame::STORAGE_OWNED_MEMORY)
@@ -347,11 +362,14 @@
 size_t CompareFramesWithErrorDiff(const VideoFrame& frame1,
                                   const VideoFrame& frame2,
                                   uint8_t tolerance) {
-  LOG_ASSERT(frame1.format() == frame2.format());
-  LOG_ASSERT(frame1.visible_rect() == frame2.visible_rect());
-  LOG_ASSERT(frame1.visible_rect().origin() == gfx::Point(0, 0));
-  LOG_ASSERT(frame1.IsMappable() && frame2.IsMappable());
-
+  ASSERT_TRUE_AND_RETURN(frame1.format() == frame2.format(),
+                         std::numeric_limits<std::size_t>::max());
+  ASSERT_TRUE_AND_RETURN(frame1.visible_rect() == frame2.visible_rect(),
+                         std::numeric_limits<std::size_t>::max());
+  ASSERT_TRUE_AND_RETURN(frame1.visible_rect().origin() == gfx::Point(0, 0),
+                         std::numeric_limits<std::size_t>::max());
+  ASSERT_TRUE_AND_RETURN(frame1.IsMappable() && frame2.IsMappable(),
+                         std::numeric_limits<std::size_t>::max());
   size_t diff_cnt = 0;
 
   const VideoPixelFormat format = frame1.format();
diff --git a/media/gpu/test/video_frame_validator.cc b/media/gpu/test/video_frame_validator.cc
index 5963a6a..0488e12 100644
--- a/media/gpu/test/video_frame_validator.cc
+++ b/media/gpu/test/video_frame_validator.cc
@@ -176,7 +176,7 @@
     if (!video_frame_mapper_) {
       video_frame_mapper_ = VideoFrameMapperFactory::CreateMapper(
           video_frame->format(), video_frame->storage_type());
-      LOG_ASSERT(video_frame_mapper_) << "Failed to create VideoFrameMapper";
+      ASSERT_TRUE(video_frame_mapper_) << "Failed to create VideoFrameMapper";
     }
 
     validated_frame = video_frame_mapper_->Map(std::move(validated_frame));
@@ -187,7 +187,7 @@
   }
 #endif  // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
 
-  LOG_ASSERT(validated_frame->IsMappable());
+  ASSERT_TRUE(validated_frame->IsMappable());
 
   base::Optional<MismatchedFrameInfo> mismatched_info;
   switch (validate_mode_) {
diff --git a/media/gpu/test/video_player/video_player.cc b/media/gpu/test/video_player/video_player.cc
index 4a9b64d..7e55b74 100644
--- a/media/gpu/test/video_player/video_player.cc
+++ b/media/gpu/test/video_player/video_player.cc
@@ -15,6 +15,30 @@
 namespace media {
 namespace test {
 
+namespace {
+// Get the name of the specified video player |event|.
+const char* EventName(VideoPlayerEvent event) {
+  switch (event) {
+    case VideoPlayerEvent::kInitialized:
+      return "Initialized";
+    case VideoPlayerEvent::kFrameDecoded:
+      return "FrameDecoded";
+    case VideoPlayerEvent::kFlushing:
+      return "Flushing";
+    case VideoPlayerEvent::kFlushDone:
+      return "FlushDone";
+    case VideoPlayerEvent::kResetting:
+      return "Resetting";
+    case VideoPlayerEvent::kResetDone:
+      return "ResetDone";
+    case VideoPlayerEvent::kConfigInfo:
+      return "ConfigInfo";
+    default:
+      return "Unknown";
+  }
+}
+}  // namespace
+
 VideoPlayer::VideoPlayer()
     : video_(nullptr),
       video_player_state_(VideoPlayerState::kUninitialized),
@@ -183,8 +207,11 @@
     }
 
     // Check whether we've exceeded the maximum time we're allowed to wait.
-    if (time_waiting >= event_timeout_)
+    if (time_waiting >= event_timeout_) {
+      LOG(ERROR) << "Timeout while waiting for '" << EventName(event)
+                 << "' event";
       return false;
+    }
 
     const base::TimeTicks start_time = base::TimeTicks::Now();
     event_cv_.TimedWait(event_timeout_ - time_waiting);
diff --git a/media/test/data/README.md b/media/test/data/README.md
index d860edd..54639f9 100644
--- a/media/test/data/README.md
+++ b/media/test/data/README.md
@@ -152,6 +152,16 @@
   -o bear-av1-320x180-10bit.webm
 ```
 
+#### bear-av1-opus.mp4
+Created by combining bear-av1.mp4 and bear-opus.mp4.
+```
+ffmpeg -i bear-av1.mp4 -i bear-opus.mp4 -c copy -strict -2 \
+  -movflags frag_keyframe+empty_moov+default_base_moof \
+  bear-av1-opus.mp4
+```
+**Note**: "-strict -2" was required because the current ffmpeg version
+has support for OPUS in MP4 as experimental.
+
 ### Alpha Channel
 
 #### bear-vp8a.webm
@@ -450,6 +460,20 @@
          --pssh 000000327073736800000000EDEF8BA979D64ACEA3C827DCD51D21ED000000121210303132333435363738393031323334350000003470737368010000001077EFECC0B24D02ACE33C1E52E2FB4B000000013031323334353637383930313233343500000000
 ```
 
+#### bear-opus-cenc.mp4
+Encrypted version of bear-opus.mp4, encrypted by [Shaka Packager] v2.3.0 using
+key ID [1] and key [2].
+
+```
+packager in=bear-opus.mp4,stream=audio,output=bear-opus-cenc.mp4
+         --enable_raw_key_encryption
+         --protection_scheme cenc
+         --clear_lead 0
+         --segment_duration 0.5
+         --keys label=:key_id=30313233343536373839303132333435:key=ebdd62f16814d27b68ef122afce4ae3c
+         --pssh 000000327073736800000000EDEF8BA979D64ACEA3C827DCD51D21ED000000121210303132333435363738393031323334350000003470737368010000001077EFECC0B24D02ACE33C1E52E2FB4B000000013031323334353637383930313233343500000000
+```
+
 #### bear-a_enc-a.webm
 bear-320x240-audio-only.webm encrypted using key ID [1] and key [2].
 
diff --git a/media/test/data/bear-av1-opus.mp4 b/media/test/data/bear-av1-opus.mp4
new file mode 100644
index 0000000..64a5e1f
--- /dev/null
+++ b/media/test/data/bear-av1-opus.mp4
Binary files differ
diff --git a/media/test/data/bear-opus-cenc.mp4 b/media/test/data/bear-opus-cenc.mp4
new file mode 100644
index 0000000..649a5ee
--- /dev/null
+++ b/media/test/data/bear-opus-cenc.mp4
Binary files differ
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc
index 8a5d707..312e2d3 100644
--- a/media/test/pipeline_integration_test.cc
+++ b/media/test/pipeline_integration_test.cc
@@ -1821,6 +1821,23 @@
   Stop();
 }
 
+TEST_F(PipelineIntegrationTest, MSE_BasicPlayback_AV1_Audio_OPUS_MP4) {
+  TestMediaSource source("bear-av1-opus.mp4", 50253);
+  EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
+  source.EndOfStream();
+
+  EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
+  EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
+  EXPECT_EQ(kVP9WebMFileDurationMs,
+            pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
+
+  Play();
+
+  ASSERT_TRUE(WaitUntilOnEnded());
+  source.Shutdown();
+  Stop();
+}
+
 TEST_F(PipelineIntegrationTest, MSE_BasicPlayback_AV1_10bit_MP4) {
   TestMediaSource source("bear-av1-320x180-10bit.mp4", 19658);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
@@ -1881,6 +1898,12 @@
   Play();
   ASSERT_TRUE(WaitUntilOnEnded());
 }
+
+TEST_F(PipelineIntegrationTest, BasicPlayback_Video_AV1_Audio_Opus_Mp4) {
+  ASSERT_EQ(PIPELINE_OK, Start("bear-av1-opus.mp4"));
+  Play();
+  ASSERT_TRUE(WaitUntilOnEnded());
+}
 #endif
 
 class Mp3FastSeekParams {
diff --git a/mojo/core/core.cc b/mojo/core/core.cc
index 8ad3a9e..d923787 100644
--- a/mojo/core/core.cc
+++ b/mojo/core/core.cc
@@ -169,9 +169,8 @@
   return dispatcher;
 }
 
-void Core::SetDefaultProcessErrorCallback(
-    const ProcessErrorCallback& callback) {
-  default_process_error_callback_ = callback;
+void Core::SetDefaultProcessErrorCallback(ProcessErrorCallback callback) {
+  default_process_error_callback_ = std::move(callback);
 }
 
 MojoHandle Core::CreatePartialMessagePipe(ports::PortRef* peer) {
@@ -252,8 +251,8 @@
     handles_->CancelTransit(dispatchers);
 }
 
-void Core::RequestShutdown(const base::Closure& callback) {
-  GetNodeController()->RequestShutdown(callback);
+void Core::RequestShutdown(base::OnceClosure callback) {
+  GetNodeController()->RequestShutdown(std::move(callback));
 }
 
 MojoHandle Core::ExtractMessagePipeFromInvitation(const std::string& name) {
diff --git a/mojo/core/core.h b/mojo/core/core.h
index 8c561ab0..6e7c9de 100644
--- a/mojo/core/core.h
+++ b/mojo/core/core.h
@@ -54,7 +54,7 @@
   scoped_refptr<Dispatcher> GetDispatcher(MojoHandle handle);
   scoped_refptr<Dispatcher> GetAndRemoveDispatcher(MojoHandle handle);
 
-  void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback);
+  void SetDefaultProcessErrorCallback(ProcessErrorCallback callback);
 
   // Creates a message pipe endpoint with an unbound peer port returned in
   // |*peer|. Useful for setting up cross-process bootstrap message pipes. The
@@ -136,7 +136,7 @@
   // loop, and the calling thread must continue running a MessageLoop at least
   // until the callback is called. If there is no running loop, the |callback|
   // may be called from any thread. Beware!
-  void RequestShutdown(const base::Closure& callback);
+  void RequestShutdown(base::OnceClosure callback);
 
   // ---------------------------------------------------------------------------
 
diff --git a/mojo/core/data_pipe_unittest.cc b/mojo/core/data_pipe_unittest.cc
index f8210b77..ab712fa 100644
--- a/mojo/core/data_pipe_unittest.cc
+++ b/mojo/core/data_pipe_unittest.cc
@@ -1992,7 +1992,7 @@
   {
     base::RunLoop run_loop;
     int count = 0;
-    auto callback = base::Bind(
+    auto callback = base::BindRepeating(
         [](base::RunLoop* loop, int* count, MojoResult result) {
           EXPECT_EQ(MOJO_RESULT_OK, result);
           if (++*count == 2)
diff --git a/mojo/core/embedder/embedder.cc b/mojo/core/embedder/embedder.cc
index a25d5013..ec68e37 100644
--- a/mojo/core/embedder/embedder.cc
+++ b/mojo/core/embedder/embedder.cc
@@ -31,8 +31,8 @@
   Init(Configuration());
 }
 
-void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback) {
-  Core::Get()->SetDefaultProcessErrorCallback(callback);
+void SetDefaultProcessErrorCallback(ProcessErrorCallback callback) {
+  Core::Get()->SetDefaultProcessErrorCallback(std::move(callback));
 }
 
 scoped_refptr<base::TaskRunner> GetIOTaskRunner() {
diff --git a/mojo/core/embedder/embedder.h b/mojo/core/embedder/embedder.h
index 2b7d7db..0cd7644 100644
--- a/mojo/core/embedder/embedder.h
+++ b/mojo/core/embedder/embedder.h
@@ -21,7 +21,8 @@
 namespace mojo {
 namespace core {
 
-using ProcessErrorCallback = base::Callback<void(const std::string& error)>;
+using ProcessErrorCallback =
+    base::RepeatingCallback<void(const std::string& error)>;
 
 // Basic configuration/initialization ------------------------------------------
 
@@ -38,7 +39,7 @@
 // Sets a default callback to invoke when an internal error is reported but
 // cannot be associated with a specific child process. Calling this is optional.
 COMPONENT_EXPORT(MOJO_CORE_EMBEDDER)
-void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback);
+void SetDefaultProcessErrorCallback(ProcessErrorCallback callback);
 
 // Initialialization/shutdown for interprocess communication (IPC) -------------
 
diff --git a/mojo/core/embedder/scoped_ipc_support.cc b/mojo/core/embedder/scoped_ipc_support.cc
index 71174f5..f6f90c80 100644
--- a/mojo/core/embedder/scoped_ipc_support.cc
+++ b/mojo/core/embedder/scoped_ipc_support.cc
@@ -15,8 +15,8 @@
 
 namespace {
 
-void ShutdownIPCSupport(const base::Closure& callback) {
-  Core::Get()->RequestShutdown(callback);
+void ShutdownIPCSupport(base::OnceClosure callback) {
+  Core::Get()->RequestShutdown(std::move(callback));
 }
 
 }  // namespace
@@ -37,8 +37,8 @@
   base::WaitableEvent shutdown_event(
       base::WaitableEvent::ResetPolicy::MANUAL,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
-  ShutdownIPCSupport(base::Bind(&base::WaitableEvent::Signal,
-                                base::Unretained(&shutdown_event)));
+  ShutdownIPCSupport(base::BindOnce(&base::WaitableEvent::Signal,
+                                    base::Unretained(&shutdown_event)));
 
   base::ScopedAllowBaseSyncPrimitives allow_io;
   shutdown_event.Wait();
diff --git a/mojo/core/message_unittest.cc b/mojo/core/message_unittest.cc
index 48cf664..c079e11 100644
--- a/mojo/core/message_unittest.cc
+++ b/mojo/core/message_unittest.cc
@@ -100,11 +100,11 @@
 class NeverSerializedMessage : public TestMessageBase {
  public:
   NeverSerializedMessage(
-      const base::Closure& destruction_callback = base::Closure())
-      : destruction_callback_(destruction_callback) {}
+      base::OnceClosure destruction_callback = base::OnceClosure())
+      : destruction_callback_(std::move(destruction_callback)) {}
   ~NeverSerializedMessage() override {
     if (destruction_callback_)
-      destruction_callback_.Run();
+      std::move(destruction_callback_).Run();
   }
 
  private:
@@ -115,7 +115,7 @@
   void SerializeHandles(MojoHandle* handles) override { NOTREACHED(); }
   void SerializePayload(void* buffer) override { NOTREACHED(); }
 
-  const base::Closure destruction_callback_;
+  base::OnceClosure destruction_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(NeverSerializedMessage);
 };
@@ -123,12 +123,13 @@
 class SimpleMessage : public TestMessageBase {
  public:
   SimpleMessage(const std::string& contents,
-                const base::Closure& destruction_callback = base::Closure())
-      : contents_(contents), destruction_callback_(destruction_callback) {}
+                base::OnceClosure destruction_callback = base::OnceClosure())
+      : contents_(contents),
+        destruction_callback_(std::move(destruction_callback)) {}
 
   ~SimpleMessage() override {
     if (destruction_callback_)
-      destruction_callback_.Run();
+      std::move(destruction_callback_).Run();
   }
 
   void AddMessagePipe(mojo::ScopedMessagePipeHandle handle) {
@@ -156,7 +157,7 @@
   }
 
   const std::string contents_;
-  const base::Closure destruction_callback_;
+  base::OnceClosure destruction_callback_;
   std::vector<mojo::ScopedMessagePipeHandle> handles_;
 
   DISALLOW_COPY_AND_ASSIGN(SimpleMessage);
@@ -212,8 +213,8 @@
 TEST_F(MessageTest, DestroyMessageWithContext) {
   // Tests that |MojoDestroyMessage()| destroys any attached context.
   bool was_deleted = false;
-  auto message = std::make_unique<NeverSerializedMessage>(
-      base::Bind([](bool* was_deleted) { *was_deleted = true; }, &was_deleted));
+  auto message = std::make_unique<NeverSerializedMessage>(base::BindOnce(
+      [](bool* was_deleted) { *was_deleted = true; }, &was_deleted));
   MojoMessageHandle handle =
       TestMessageBase::MakeMessageHandle(std::move(message));
   EXPECT_FALSE(was_deleted);
@@ -371,8 +372,8 @@
   bool message_was_destroyed = false;
   auto message = std::make_unique<SimpleMessage>(
       kTestMessageWithContext1,
-      base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
-                 &message_was_destroyed));
+      base::BindOnce([](bool* was_destroyed) { *was_destroyed = true; },
+                     &message_was_destroyed));
 
   mojo::MessagePipe pipe;
   message->AddMessagePipe(std::move(pipe.handle0));
@@ -441,8 +442,8 @@
   bool message_was_destroyed = false;
   std::unique_ptr<TestMessageBase> message =
       std::make_unique<NeverSerializedMessage>(
-          base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
-                     &message_was_destroyed));
+          base::BindOnce([](bool* was_destroyed) { *was_destroyed = true; },
+                         &message_was_destroyed));
 
   MojoHandle a, b;
   CreateMessagePipe(&a, &b);
@@ -493,8 +494,8 @@
   bool message_was_destroyed = false;
   auto message = std::make_unique<SimpleMessage>(
       kTestMessageWithContext1,
-      base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
-                 &message_was_destroyed));
+      base::BindOnce([](bool* was_destroyed) { *was_destroyed = true; },
+                     &message_was_destroyed));
   auto message_handle = TestMessageBase::MakeMessageHandle(std::move(message));
   EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle, nullptr));
   EXPECT_TRUE(message_was_destroyed);
@@ -505,8 +506,8 @@
   message_was_destroyed = false;
   message = std::make_unique<SimpleMessage>(
       kTestMessageWithContext1,
-      base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
-                 &message_was_destroyed));
+      base::BindOnce([](bool* was_destroyed) { *was_destroyed = true; },
+                     &message_was_destroyed));
   MessagePipe pipe1;
   message->AddMessagePipe(std::move(pipe1.handle0));
   message_handle = TestMessageBase::MakeMessageHandle(std::move(message));
@@ -520,8 +521,8 @@
   message_was_destroyed = false;
   message = std::make_unique<SimpleMessage>(
       kTestMessageWithContext1,
-      base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
-                 &message_was_destroyed));
+      base::BindOnce([](bool* was_destroyed) { *was_destroyed = true; },
+                     &message_was_destroyed));
   MessagePipe pipe2;
   message->AddMessagePipe(std::move(pipe2.handle0));
   message_handle = TestMessageBase::MakeMessageHandle(std::move(message));
@@ -557,8 +558,8 @@
   bool message_was_destroyed = false;
   auto message = std::make_unique<SimpleMessage>(
       kTestMessageWithContext1,
-      base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
-                 &message_was_destroyed));
+      base::BindOnce([](bool* was_destroyed) { *was_destroyed = true; },
+                     &message_was_destroyed));
   auto message_handle = TestMessageBase::MakeMessageHandle(std::move(message));
 
   // Ensure we can safely call |MojoSerializeMessage()| twice on the same
diff --git a/mojo/core/multiprocess_message_pipe_unittest.cc b/mojo/core/multiprocess_message_pipe_unittest.cc
index bb06bccb..af71b7ca 100644
--- a/mojo/core/multiprocess_message_pipe_unittest.cc
+++ b/mojo/core/multiprocess_message_pipe_unittest.cc
@@ -1283,7 +1283,7 @@
     SimpleWatcher watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC,
                           base::SequencedTaskRunnerHandle::Get());
     watcher.Watch(Handle(handles[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
-                  base::Bind(
+                  base::BindRepeating(
                       [](base::RunLoop* loop, MojoResult result) {
                         EXPECT_EQ(MOJO_RESULT_OK, result);
                         loop->Quit();
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
index 8b34f582..9b878dc 100644
--- a/mojo/core/node_controller.cc
+++ b/mojo/core/node_controller.cc
@@ -111,19 +111,19 @@
     : public base::MessageLoopCurrent::DestructionObserver {
  public:
   static void Create(scoped_refptr<base::TaskRunner> task_runner,
-                     const base::Closure& callback) {
+                     base::OnceClosure callback) {
     if (task_runner->RunsTasksInCurrentSequence()) {
       // Owns itself.
-      new ThreadDestructionObserver(callback);
+      new ThreadDestructionObserver(std::move(callback));
     } else {
-      task_runner->PostTask(FROM_HERE,
-                            base::BindOnce(&Create, task_runner, callback));
+      task_runner->PostTask(
+          FROM_HERE, base::BindOnce(&Create, task_runner, std::move(callback)));
     }
   }
 
  private:
-  explicit ThreadDestructionObserver(const base::Closure& callback)
-      : callback_(callback) {
+  explicit ThreadDestructionObserver(base::OnceClosure callback)
+      : callback_(std::move(callback)) {
     base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
   }
 
@@ -133,11 +133,11 @@
 
   // base::MessageLoopCurrent::DestructionObserver:
   void WillDestroyCurrentMessageLoop() override {
-    callback_.Run();
+    std::move(callback_).Run();
     delete this;
   }
 
-  const base::Closure callback_;
+  base::OnceClosure callback_;
 
   DISALLOW_COPY_AND_ASSIGN(ThreadDestructionObserver);
 };
@@ -158,7 +158,7 @@
   io_task_runner_ = task_runner;
   ThreadDestructionObserver::Create(
       io_task_runner_,
-      base::Bind(&NodeController::DropAllPeers, base::Unretained(this)));
+      base::BindOnce(&NodeController::DropAllPeers, base::Unretained(this)));
 }
 
 void NodeController::SendBrokerClientInvitation(
@@ -312,10 +312,10 @@
   return base::WritableSharedMemoryRegion::Create(num_bytes);
 }
 
-void NodeController::RequestShutdown(const base::Closure& callback) {
+void NodeController::RequestShutdown(base::OnceClosure callback) {
   {
     base::AutoLock lock(shutdown_lock_);
-    shutdown_callback_ = callback;
+    shutdown_callback_ = std::move(callback);
     shutdown_callback_flag_.Set(true);
   }
 
@@ -1272,7 +1272,7 @@
   if (!shutdown_callback_flag_)
     return;
 
-  base::Closure callback;
+  base::OnceClosure callback;
   {
     base::AutoLock lock(shutdown_lock_);
     if (shutdown_callback_.is_null())
@@ -1283,14 +1283,13 @@
       return;
     }
 
-    callback = shutdown_callback_;
-    shutdown_callback_.Reset();
+    callback = std::move(shutdown_callback_);
     shutdown_callback_flag_.Set(false);
   }
 
   DCHECK(!callback.is_null());
 
-  callback.Run();
+  std::move(callback).Run();
 }
 
 void NodeController::ForceDisconnectProcessForTestingOnIOThread(
diff --git a/mojo/core/node_controller.h b/mojo/core/node_controller.h
index cfd55e75..9129781 100644
--- a/mojo/core/node_controller.h
+++ b/mojo/core/node_controller.h
@@ -114,7 +114,7 @@
   // interface after requesting shutdown, you do so at your own risk and there
   // is NO guarantee that new messages will be sent or ports will complete
   // transfer.
-  void RequestShutdown(const base::Closure& callback);
+  void RequestShutdown(base::OnceClosure callback);
 
   // Notifies the NodeController that we received a bad message from the given
   // node.
@@ -309,7 +309,7 @@
   // Set by RequestShutdown(). If this is non-null, the controller will
   // begin polling the Node to see if clean shutdown is possible any time the
   // Node's state is modified by the controller.
-  base::Closure shutdown_callback_;
+  base::OnceClosure shutdown_callback_;
   // Flag to fast-path checking |shutdown_callback_|.
   AtomicFlag shutdown_callback_flag_;
 
diff --git a/mojo/core/test/mojo_test_base.h b/mojo/core/test/mojo_test_base.h
index 8110cfc..23c55b3 100644
--- a/mojo/core/test/mojo_test_base.h
+++ b/mojo/core/test/mojo_test_base.h
@@ -31,7 +31,6 @@
   ~MojoTestBase() override;
 
   using LaunchType = MultiprocessTestHelper::LaunchType;
-  using HandlerCallback = base::Callback<void(ScopedMessagePipeHandle)>;
 
   class ClientController {
    public:
@@ -197,8 +196,8 @@
       ::mojo::core::test::MultiprocessTestHelper::ChildSetup) {         \
     client_name##_MainFixture test;                                     \
     return ::mojo::core::test::MultiprocessTestHelper::RunClientMain(   \
-        base::Bind(&client_name##_MainFixture::Main,                    \
-                   base::Unretained(&test)));                           \
+        base::BindOnce(&client_name##_MainFixture::Main,                \
+                       base::Unretained(&test)));                       \
   }                                                                     \
   int client_name##_MainFixture::Main(MojoHandle pipe_name)
 
@@ -216,8 +215,8 @@
       ::mojo::core::test::MultiprocessTestHelper::ChildSetup) {              \
     client_name##_MainFixture test;                                          \
     return ::mojo::core::test::MultiprocessTestHelper::RunClientTestMain(    \
-        base::Bind(&client_name##_MainFixture::Main,                         \
-                   base::Unretained(&test)));                                \
+        base::BindOnce(&client_name##_MainFixture::Main,                     \
+                       base::Unretained(&test)));                            \
   }                                                                          \
   void client_name##_MainFixture::Main(MojoHandle pipe_name)
 #else  // !defined(OS_IOS)
diff --git a/mojo/core/test/multiprocess_test_helper.cc b/mojo/core/test/multiprocess_test_helper.cc
index 5afb0fb2..26b0c76 100644
--- a/mojo/core/test/multiprocess_test_helper.cc
+++ b/mojo/core/test/multiprocess_test_helper.cc
@@ -54,14 +54,14 @@
 // For use (and only valid) in a test child process:
 base::LazyInstance<IsolatedConnection>::Leaky g_child_isolated_connection;
 
-template <typename Func>
-int RunClientFunction(Func handler, bool pass_pipe_ownership_to_main) {
+int RunClientFunction(base::OnceCallback<int(MojoHandle)> handler,
+                      bool pass_pipe_ownership_to_main) {
   CHECK(MultiprocessTestHelper::primordial_pipe.is_valid());
   ScopedMessagePipeHandle pipe =
       std::move(MultiprocessTestHelper::primordial_pipe);
   MessagePipeHandle pipe_handle =
       pass_pipe_ownership_to_main ? pipe.release() : pipe.get();
-  return handler(pipe_handle.value());
+  return std::move(handler).Run(pipe_handle.value());
 }
 
 }  // namespace
@@ -290,24 +290,24 @@
 
 // static
 int MultiprocessTestHelper::RunClientMain(
-    const base::Callback<int(MojoHandle)>& main,
+    base::OnceCallback<int(MojoHandle)> main,
     bool pass_pipe_ownership_to_main) {
-  return RunClientFunction(
-      [main](MojoHandle handle) { return main.Run(handle); },
-      pass_pipe_ownership_to_main);
+  return RunClientFunction(std::move(main), pass_pipe_ownership_to_main);
 }
 
 // static
 int MultiprocessTestHelper::RunClientTestMain(
-    const base::Callback<void(MojoHandle)>& main) {
+    base::OnceCallback<void(MojoHandle)> main) {
   return RunClientFunction(
-      [main](MojoHandle handle) {
-        main.Run(handle);
-        return (::testing::Test::HasFatalFailure() ||
-                ::testing::Test::HasNonfatalFailure())
-                   ? 1
-                   : 0;
-      },
+      base::BindOnce(
+          [](base::OnceCallback<void(MojoHandle)> main, MojoHandle handle) {
+            std::move(main).Run(handle);
+            return (::testing::Test::HasFatalFailure() ||
+                    ::testing::Test::HasNonfatalFailure())
+                       ? 1
+                       : 0;
+          },
+          std::move(main)),
       true /* pass_pipe_ownership_to_main */);
 }
 
diff --git a/mojo/core/test/multiprocess_test_helper.h b/mojo/core/test/multiprocess_test_helper.h
index 953718a5..f74ec31 100644
--- a/mojo/core/test/multiprocess_test_helper.h
+++ b/mojo/core/test/multiprocess_test_helper.h
@@ -25,8 +25,6 @@
 
 class MultiprocessTestHelper {
  public:
-  using HandlerCallback = base::Callback<void(ScopedMessagePipeHandle)>;
-
   enum class LaunchType {
     // Launch the child process as a child in the mojo system.
     CHILD,
@@ -85,9 +83,9 @@
   // Used by macros in mojo/core/test/mojo_test_base.h to support multiprocess
   // test client initialization.
   static void ChildSetup();
-  static int RunClientMain(const base::Callback<int(MojoHandle)>& main,
+  static int RunClientMain(base::OnceCallback<int(MojoHandle)> main,
                            bool pass_pipe_ownership_to_main = false);
-  static int RunClientTestMain(const base::Callback<void(MojoHandle)>& main);
+  static int RunClientTestMain(base::OnceCallback<void(MojoHandle)> main);
 
   // For use (and only valid) in the child process:
   static mojo::ScopedMessagePipeHandle primordial_pipe;
diff --git a/mojo/core/test/run_all_unittests.cc b/mojo/core/test/run_all_unittests.cc
index e666d89..08524b8 100644
--- a/mojo/core/test/run_all_unittests.cc
+++ b/mojo/core/test/run_all_unittests.cc
@@ -53,5 +53,5 @@
       mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
   return base::LaunchUnitTests(
       argc, argv,
-      base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
+      base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
 }
diff --git a/mojo/core/trap_unittest.cc b/mojo/core/trap_unittest.cc
index b7ae4f3..f543b2f 100644
--- a/mojo/core/trap_unittest.cc
+++ b/mojo/core/trap_unittest.cc
@@ -1650,7 +1650,7 @@
   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
 }
 
-base::Closure g_do_random_thing_callback;
+base::RepeatingClosure g_do_random_thing_callback;
 
 void ReadAllMessages(const MojoTrapEvent* event) {
   if (event->result == MOJO_RESULT_OK) {
diff --git a/printing/backend/cups_ipp_util_unittest.cc b/printing/backend/cups_ipp_util_unittest.cc
index dce6598..8b9e56b6 100644
--- a/printing/backend/cups_ipp_util_unittest.cc
+++ b/printing/backend/cups_ipp_util_unittest.cc
@@ -187,7 +187,7 @@
 
   PrinterSemanticCapsAndDefaults::Paper paper = caps.papers[0];
   // media display name localization is handled more fully in
-  // GetPrinterCapabilitiesOnBlockingPoolThread().
+  // GetPrinterCapabilitiesOnBlockingTaskRunner().
   EXPECT_EQ("iso a4", paper.display_name);
   EXPECT_EQ("iso_a4_210x297mm", paper.vendor_id);
   EXPECT_EQ(210000, paper.size_um.width());
@@ -200,7 +200,7 @@
   PrinterSemanticCapsAndDefaults caps;
   CapsAndDefaultsFromPrinter(*printer_, &caps);
   // media display name localization is handled more fully in
-  // GetPrinterCapabilitiesOnBlockingPoolThread().
+  // GetPrinterCapabilitiesOnBlockingTaskRunner().
   EXPECT_EQ("na legal", caps.default_paper.display_name);
   EXPECT_EQ("na_legal_8.5x14in", caps.default_paper.vendor_id);
   EXPECT_EQ(215900, caps.default_paper.size_um.width());
diff --git a/remoting/host/host_exit_codes.cc b/remoting/host/host_exit_codes.cc
index daec9bb..ce070ab 100644
--- a/remoting/host/host_exit_codes.cc
+++ b/remoting/host/host_exit_codes.cc
@@ -12,6 +12,7 @@
     {kSuccessExitCode, "SUCCESS_EXIT"},
     {kInitializationFailed, "INITIALIZATION_FAILED"},
     {kInvalidCommandLineExitCode, "INVALID_COMMAND_LINE"},
+    {kNoPermissionExitCode, "NO_PERMISSION"},
     {kInvalidHostConfigurationExitCode, "INVALID_HOST_CONFIGURATION"},
     {kInvalidHostIdExitCode, "INVALID_HOST_ID"},
     {kInvalidOauthCredentialsExitCode, "INVALID_OAUTH_CREDENTIALS"},
diff --git a/remoting/host/host_exit_codes.h b/remoting/host/host_exit_codes.h
index b48c284..9193416 100644
--- a/remoting/host/host_exit_codes.h
+++ b/remoting/host/host_exit_codes.h
@@ -18,6 +18,7 @@
   kReservedForX11ExitCode = 1,
   kInitializationFailed = 2,
   kInvalidCommandLineExitCode = 3,
+  kNoPermissionExitCode = 4,
 
   // Error codes that do indicate a permanent error condition.
   kInvalidHostConfigurationExitCode = 100,
diff --git a/remoting/host/setup/daemon_controller.cc b/remoting/host/setup/daemon_controller.cc
index 0591a21..b68a991 100644
--- a/remoting/host/setup/daemon_controller.cc
+++ b/remoting/host/setup/daemon_controller.cc
@@ -51,6 +51,11 @@
   ServiceOrQueueRequest(request);
 }
 
+bool DaemonController::CheckPermission() {
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
+  return delegate_->CheckPermission();
+}
+
 void DaemonController::SetConfigAndStart(
     std::unique_ptr<base::DictionaryValue> config,
     bool consent,
diff --git a/remoting/host/setup/daemon_controller.h b/remoting/host/setup/daemon_controller.h
index 94c6422..a51a3a6 100644
--- a/remoting/host/setup/daemon_controller.h
+++ b/remoting/host/setup/daemon_controller.h
@@ -109,6 +109,11 @@
     // sensitive have been filtered out.
     virtual std::unique_ptr<base::DictionaryValue> GetConfig() = 0;
 
+    // Checks to verify that the required OS permissions have been granted to
+    // the host process, querying the user if necessary. Returns true iff all
+    // required permissions have been granted.
+    virtual bool CheckPermission() = 0;
+
     // Starts the daemon process. This may require that the daemon be
     // downloaded and installed. |done| is invoked on the calling thread when
     // the operation is completed.
@@ -150,6 +155,11 @@
   // sensitive have been filtered out.
   void GetConfig(const GetConfigCallback& done);
 
+  // Checks to see if the required OS permissions have been granted. This may
+  // show a dialog to the user requesting the permissions.
+  // Returns true iff all required permissions have been granted.
+  bool CheckPermission();
+
   // Start the daemon process. This may require that the daemon be
   // downloaded and installed. |done| is called when the
   // operation is finished or fails.
diff --git a/remoting/host/setup/daemon_controller_delegate_linux.cc b/remoting/host/setup/daemon_controller_delegate_linux.cc
index a00f052..5e0b8c39 100644
--- a/remoting/host/setup/daemon_controller_delegate_linux.cc
+++ b/remoting/host/setup/daemon_controller_delegate_linux.cc
@@ -165,6 +165,10 @@
   return result;
 }
 
+bool DaemonControllerDelegateLinux::CheckPermission() {
+  return true;
+}
+
 void DaemonControllerDelegateLinux::SetConfigAndStart(
     std::unique_ptr<base::DictionaryValue> config,
     bool consent,
diff --git a/remoting/host/setup/daemon_controller_delegate_linux.h b/remoting/host/setup/daemon_controller_delegate_linux.h
index eee9839..6b91e52 100644
--- a/remoting/host/setup/daemon_controller_delegate_linux.h
+++ b/remoting/host/setup/daemon_controller_delegate_linux.h
@@ -20,6 +20,7 @@
   // DaemonController::Delegate interface.
   DaemonController::State GetState() override;
   std::unique_ptr<base::DictionaryValue> GetConfig() override;
+  bool CheckPermission() override;
   void SetConfigAndStart(
       std::unique_ptr<base::DictionaryValue> config,
       bool consent,
diff --git a/remoting/host/setup/daemon_controller_delegate_mac.h b/remoting/host/setup/daemon_controller_delegate_mac.h
index 523cb54..b4f3339 100644
--- a/remoting/host/setup/daemon_controller_delegate_mac.h
+++ b/remoting/host/setup/daemon_controller_delegate_mac.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "remoting/host/setup/daemon_controller.h"
@@ -21,6 +22,7 @@
   // DaemonController::Delegate interface.
   DaemonController::State GetState() override;
   std::unique_ptr<base::DictionaryValue> GetConfig() override;
+  bool CheckPermission() override;
   void SetConfigAndStart(
       std::unique_ptr<base::DictionaryValue> config,
       bool consent,
diff --git a/remoting/host/setup/daemon_controller_delegate_mac.mm b/remoting/host/setup/daemon_controller_delegate_mac.mm
index 5eae253..97f2e6d 100644
--- a/remoting/host/setup/daemon_controller_delegate_mac.mm
+++ b/remoting/host/setup/daemon_controller_delegate_mac.mm
@@ -8,7 +8,8 @@
 #include <sys/types.h>
 
 #include "base/bind.h"
-#include "base/files/file_path.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
 #include "base/mac/authorization_util.h"
@@ -18,7 +19,10 @@
 #include "base/mac/scoped_authorizationref.h"
 #include "base/mac/scoped_launch_data.h"
 #include "base/memory/ptr_util.h"
+#include "base/path_service.h"
 #include "base/posix/eintr_wrapper.h"
+#include "base/process/launch.h"
+#include "base/process/process.h"
 #include "base/values.h"
 #include "remoting/base/string_resources.h"
 #include "remoting/host/host_config.h"
@@ -239,6 +243,59 @@
   return config;
 }
 
+base::FilePath GetHostExePath() {
+  // Get path to directory that contains the NMH Application bundle.
+  base::FilePath nmh_dir;
+  base::PathService::Get(base::DIR_EXE, &nmh_dir);
+  // The NMH path ends with <nmh>.app/Contents/MacOS/, so we need to strip
+  // off the last 3 parent dirs to get to the app's directory.
+  auto host_path = nmh_dir.DirName().DirName().DirName();
+
+  // For installed builds, the host exe should be in this directory.
+  // TODO(garykac) This assumes that the location of the host exe is relative
+  // to the location of the NMH exe, which may not be true in the future. The
+  // relative path is needed for dev builds (where the binaries are written to
+  // the Chromium 'out' directory), but the release version should get this
+  // path from the build script to ensure that it matches where we install the
+  // host.
+  base::FilePath host_path_exe = host_path.Append("remoting_me2me_host");
+  if (!base::PathExists(host_path_exe)) {
+    // For local dev builds, the host exe is in an app container, so we have to
+    // navigate down to it.
+    host_path_exe = host_path.Append(
+        "remoting_me2me_host.app/Contents/MacOS/remoting_me2me_host");
+    if (!base::PathExists(host_path_exe))
+      LOG(ERROR) << "Path doesn't exist: " << host_path_exe;
+  }
+
+  return host_path_exe;
+}
+
+bool CheckHostPermission(std::string perm) {
+  base::CommandLine cmdLine(GetHostExePath());
+  cmdLine.AppendSwitch(perm);
+
+  base::LaunchOptions options;
+  options.disclaim_responsibility = true;
+  base::Process process = base::LaunchProcess(cmdLine, options);
+  if (!process.IsValid()) {
+    LOG(ERROR) << "Unable to launch host process";
+    return false;
+  }
+  int exit_code;
+  process.WaitForExit(&exit_code);
+  LOG(INFO) << "Permission '" << perm << "' is "
+            << ((exit_code == 0) ? "granted" : "denied");
+  return exit_code == 0;
+}
+
+bool DaemonControllerDelegateMac::CheckPermission() {
+  if (CheckHostPermission("check-accessibility-permission")) {
+    return CheckHostPermission("check-screen-recording-permission");
+  }
+  return false;
+}
+
 void DaemonControllerDelegateMac::SetConfigAndStart(
     std::unique_ptr<base::DictionaryValue> config,
     bool consent,
diff --git a/remoting/host/setup/daemon_controller_delegate_win.cc b/remoting/host/setup/daemon_controller_delegate_win.cc
index cee87c1..576bce2 100644
--- a/remoting/host/setup/daemon_controller_delegate_win.cc
+++ b/remoting/host/setup/daemon_controller_delegate_win.cc
@@ -439,6 +439,10 @@
   return consent;
 }
 
+bool DaemonControllerDelegateWin::CheckPermission() {
+  return true;
+}
+
 void DaemonControllerDelegateWin::SetConfigAndStart(
     std::unique_ptr<base::DictionaryValue> config,
     bool consent,
diff --git a/remoting/host/setup/daemon_controller_delegate_win.h b/remoting/host/setup/daemon_controller_delegate_win.h
index dddd3e0..3d63fd3 100644
--- a/remoting/host/setup/daemon_controller_delegate_win.h
+++ b/remoting/host/setup/daemon_controller_delegate_win.h
@@ -18,6 +18,7 @@
   // DaemonController::Delegate interface.
   DaemonController::State GetState() override;
   std::unique_ptr<base::DictionaryValue> GetConfig() override;
+  bool CheckPermission() override;
   void SetConfigAndStart(
       std::unique_ptr<base::DictionaryValue> config,
       bool consent,
diff --git a/remoting/host/setup/me2me_native_messaging_host_main.cc b/remoting/host/setup/me2me_native_messaging_host_main.cc
index 7873622..8534041 100644
--- a/remoting/host/setup/me2me_native_messaging_host_main.cc
+++ b/remoting/host/setup/me2me_native_messaging_host_main.cc
@@ -62,6 +62,9 @@
   base::AtExitManager exit_manager;
 
   base::CommandLine::Init(argc, argv);
+  const base::CommandLine* command_line =
+      base::CommandLine::ForCurrentProcess();
+
   remoting::InitHostLogging();
 
 #if defined(OS_MACOSX)
@@ -105,10 +108,15 @@
   scoped_refptr<DaemonController> daemon_controller =
       DaemonController::Create();
 
+#if defined(OS_MACOSX)
+  if (command_line->HasSwitch(kCheckPermissionSwitchName)) {
+    bool perm = daemon_controller->CheckPermission();
+    return perm ? kSuccessExitCode : kNoPermissionExitCode;
+  }
+#endif  // defined(OS_MACOSX)
+
   // Pass handle of the native view to the controller so that the UAC prompts
   // are focused properly.
-  const base::CommandLine* command_line =
-      base::CommandLine::ForCurrentProcess();
   int64_t native_view_handle = 0;
   if (command_line->HasSwitch(kParentWindowSwitchName)) {
     std::string native_view =
diff --git a/remoting/host/setup/me2me_native_messaging_host_unittest.cc b/remoting/host/setup/me2me_native_messaging_host_unittest.cc
index 9ce0809..c7ed9121 100644
--- a/remoting/host/setup/me2me_native_messaging_host_unittest.cc
+++ b/remoting/host/setup/me2me_native_messaging_host_unittest.cc
@@ -175,6 +175,7 @@
   // DaemonController::Delegate interface.
   DaemonController::State GetState() override;
   std::unique_ptr<base::DictionaryValue> GetConfig() override;
+  bool CheckPermission() override;
   void SetConfigAndStart(
       std::unique_ptr<base::DictionaryValue> config,
       bool consent,
@@ -201,6 +202,10 @@
   return std::make_unique<base::DictionaryValue>();
 }
 
+bool MockDaemonControllerDelegate::CheckPermission() {
+  return true;
+}
+
 void MockDaemonControllerDelegate::SetConfigAndStart(
     std::unique_ptr<base::DictionaryValue> config,
     bool consent,
diff --git a/remoting/host/switches.cc b/remoting/host/switches.cc
index 097efc40..fae564a2 100644
--- a/remoting/host/switches.cc
+++ b/remoting/host/switches.cc
@@ -41,4 +41,8 @@
 
 const char kUpgradeTokenSwitchName[] = "upgrade-token";
 
+#if defined(OS_MACOSX)
+const char kCheckPermissionSwitchName[] = "check-permission";
+#endif  // defined OS_MACOSX
+
 }  // namespace remoting
diff --git a/remoting/host/switches.h b/remoting/host/switches.h
index 2d18ef5..319c59a 100644
--- a/remoting/host/switches.h
+++ b/remoting/host/switches.h
@@ -64,6 +64,12 @@
 // Switch to upgrade the host config with a new refresh token.
 extern const char kUpgradeTokenSwitchName[];
 
+#if defined(OS_MACOSX)
+// NativeMessagingHost switch to check for required OS permissions and request
+// them if necessary.
+extern const char kCheckPermissionSwitchName[];
+#endif  // defined OS_MACOSX
+
 }  // namespace remoting
 
 #endif  // REMOTING_HOST_SWITCHES_H_
diff --git a/services/viz/public/cpp/compositing/typemaps.gni b/services/viz/public/cpp/compositing/typemaps.gni
index 240834f..c6439863 100644
--- a/services/viz/public/cpp/compositing/typemaps.gni
+++ b/services/viz/public/cpp/compositing/typemaps.gni
@@ -25,4 +25,5 @@
   "//services/viz/public/cpp/compositing/surface_range.typemap",
   "//services/viz/public/cpp/compositing/surface_info.typemap",
   "//services/viz/public/cpp/compositing/transferable_resource.typemap",
+  "//services/viz/public/cpp/compositing/vertical_scroll_direction.typemap",
 ]
diff --git a/services/viz/public/cpp/compositing/vertical_scroll_direction.typemap b/services/viz/public/cpp/compositing/vertical_scroll_direction.typemap
new file mode 100644
index 0000000..6b2291ea4
--- /dev/null
+++ b/services/viz/public/cpp/compositing/vertical_scroll_direction.typemap
@@ -0,0 +1,10 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom =
+    "//services/viz/public/mojom/compositing/vertical_scroll_direction.mojom"
+public_headers = [ "//components/viz/common/vertical_scroll_direction.h" ]
+traits_headers = [ "//services/viz/public/cpp/compositing/vertical_scroll_direction_mojom_traits.h" ]
+type_mappings =
+    [ "viz.mojom.VerticalScrollDirection=::viz::VerticalScrollDirection" ]
diff --git a/services/viz/public/cpp/compositing/vertical_scroll_direction_mojom_traits.h b/services/viz/public/cpp/compositing/vertical_scroll_direction_mojom_traits.h
new file mode 100644
index 0000000..9bc1ac2
--- /dev/null
+++ b/services/viz/public/cpp/compositing/vertical_scroll_direction_mojom_traits.h
@@ -0,0 +1,50 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_VERTICAL_SCROLL_DIRECTION_MOJOM_TRAITS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_VERTICAL_SCROLL_DIRECTION_MOJOM_TRAITS_H_
+
+#include "components/viz/common/vertical_scroll_direction.h"
+#include "services/viz/public/mojom/compositing/vertical_scroll_direction.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct EnumTraits<viz::mojom::VerticalScrollDirection,
+                  viz::VerticalScrollDirection> {
+  static viz::mojom::VerticalScrollDirection ToMojom(
+      viz::VerticalScrollDirection in) {
+    switch (in) {
+      case viz::VerticalScrollDirection::kNull:
+        return viz::mojom::VerticalScrollDirection::kNull;
+      case viz::VerticalScrollDirection::kDown:
+        return viz::mojom::VerticalScrollDirection::kDown;
+      case viz::VerticalScrollDirection::kUp:
+        return viz::mojom::VerticalScrollDirection::kUp;
+    }
+    NOTREACHED();
+    return viz::mojom::VerticalScrollDirection::kNull;
+  }
+
+  static bool FromMojom(viz::mojom::VerticalScrollDirection in,
+                        viz::VerticalScrollDirection* out) {
+    switch (in) {
+      case viz::mojom::VerticalScrollDirection::kNull:
+        *out = viz::VerticalScrollDirection::kNull;
+        return true;
+      case viz::mojom::VerticalScrollDirection::kDown:
+        *out = viz::VerticalScrollDirection::kDown;
+        return true;
+      case viz::mojom::VerticalScrollDirection::kUp:
+        *out = viz::VerticalScrollDirection::kUp;
+        return true;
+    }
+    NOTREACHED();
+    return false;
+  }
+};
+
+}  // namespace mojo
+
+#endif  // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_VERTICAL_SCROLL_DIRECTION_MOJOM_TRAITS_H_
diff --git a/services/viz/public/mojom/BUILD.gn b/services/viz/public/mojom/BUILD.gn
index cb97e65c..e4fd42d 100644
--- a/services/viz/public/mojom/BUILD.gn
+++ b/services/viz/public/mojom/BUILD.gn
@@ -33,6 +33,7 @@
     "compositing/surface_range.mojom",
     "compositing/texture_releaser.mojom",
     "compositing/transferable_resource.mojom",
+    "compositing/vertical_scroll_direction.mojom",
     "compositing/video_detector_observer.mojom",
     "gpu.mojom",
     "hit_test/aggregated_hit_test_region.mojom",
diff --git a/services/viz/public/mojom/compositing/vertical_scroll_direction.mojom b/services/viz/public/mojom/compositing/vertical_scroll_direction.mojom
new file mode 100644
index 0000000..7181e4e
--- /dev/null
+++ b/services/viz/public/mojom/compositing/vertical_scroll_direction.mojom
@@ -0,0 +1,10 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module viz.mojom;
+
+// Used to indicate the vertical scroll direction of the root layer. Note that
+// |kNull| is only used to represent the absence of a vertical scroll direction.
+// See components/viz/common/vertical_scroll_direction.h.
+enum VerticalScrollDirection { kNull, kDown, kUp };
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 46a561a..35e7de5 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -275,6 +275,24 @@
         "test": "latency_unittests"
       },
       {
+        "experiment_percentage": 100,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests.cros-vm"
+            }
+          ]
+        },
+        "test": "libcups_unittests"
+      },
+      {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.media_unittests.filter"
         ],
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index e5d40e5..b08cb43 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -290,6 +290,24 @@
         "test": "latency_unittests"
       },
       {
+        "experiment_percentage": 100,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04",
+              "pool": "Chrome-CrOS-VM"
+            }
+          ]
+        },
+        "test": "libcups_unittests"
+      },
+      {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.media_unittests.filter"
         ],
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 9a67a2e2..afdc5d0 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -11212,6 +11212,27 @@
         "test": "latency_unittests"
       },
       {
+        "experiment_percentage": 100,
+        "isolate_coverage_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "kvm": "1",
+              "os": "Ubuntu-16.04",
+              "pool": "Chrome-CrOS-VM"
+            }
+          ],
+          "hard_timeout": 3600,
+          "io_timeout": 3600
+        },
+        "test": "libcups_unittests"
+      },
+      {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.media_unittests.filter"
         ],
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index b834cde..9dcffaa 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1527,6 +1527,10 @@
     "label": "//third_party/libaddressinput:libaddressinput_parse_format_rule_fuzzer",
     "type": "fuzzer",
   },
+  "libcups_unittests": {
+    "label": "//chrome/services/cups_proxy:libcups_unittests",
+    "type": "console_test_launcher",
+  },
   "libjingle_xmpp_unittests": {
     "label": "//third_party/libjingle_xmpp:libjingle_xmpp_unittests",
     "type": "console_test_launcher",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 8fc4f6b6..c3d5e4b4 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -499,6 +499,9 @@
       'ipc_tests': {},
       'jingle_unittests': {},
       'latency_unittests': {},
+      'libcups_unittests': {
+	'experiment_percentage': 100,
+      },
       'media_unittests': {
         'args': [
           '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.media_unittests.filter',
diff --git a/testing/scripts/run_wpt_tests.py b/testing/scripts/run_wpt_tests.py
index 24569058..5c3556af 100755
--- a/testing/scripts/run_wpt_tests.py
+++ b/testing/scripts/run_wpt_tests.py
@@ -73,7 +73,7 @@
             "--manifest=../../third_party/blink/web_tests/external/"
                 "WPT_BASE_MANIFEST_6.json",
             # Enable mach logging to aid debugging
-            "--log-mach -"
+            "--log-mach=-"
         ])
         return rest_args
 
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index dc5aef70..6db1757b 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1517,21 +1517,6 @@
             ]
         }
     ],
-    "ChromeCleanupProtobufIPC": [
-        {
-            "platforms": [
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "ChromeCleanupProtobufIPC"
-                    ]
-                }
-            ]
-        }
-    ],
     "ChromeSmartSelection": [
         {
             "platforms": [
@@ -5315,6 +5300,24 @@
             ]
         }
     ],
+    "SafeBrowsingRealTimeUrlLookupEnabled": [
+        {
+            "platforms": [
+                "chromeos",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "SafeBrowsingRealTimeUrlLookupEnabled"
+                    ]
+                }
+            ]
+        }
+    ],
     "SafeBrowsingRealTimeUrlLookupFetchAllowlist": [
         {
             "platforms": [
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 9b5692d2..47d71cb 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -52,10 +52,8 @@
     "fetch/fetch_api_response.mojom",
     "file/file_utilities.mojom",
     "filesystem/file_system.mojom",
-    "frame/document_interface_broker.mojom",
     "frame/find_in_page.mojom",
     "frame/frame.mojom",
-    "frame/frame_host_test_interface.mojom",
     "frame/fullscreen.mojom",
     "frame/lifecycle.mojom",
     "frame/navigation_initiator.mojom",
diff --git a/third_party/blink/public/mojom/frame/document_interface_broker.mojom b/third_party/blink/public/mojom/frame/document_interface_broker.mojom
deleted file mode 100644
index c036ff4..0000000
--- a/third_party/blink/public/mojom/frame/document_interface_broker.mojom
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module blink.mojom;
-
-import "third_party/blink/public/mojom/frame/frame_host_test_interface.mojom";
-
-// An interface through which the renderer may request document-scoped
-// interfaces from the browser.
-interface DocumentInterfaceBroker {
-  // Binds the blink.mojom.FrameHostTestInterface pending receiver to its
-  // remote implementation in the browser process, to allow using this test
-  // interface to exercise requesting document-scoped interfaces from the
-  // RenderFrameHost through the DocumentInterfaceBroker interface.
-  GetFrameHostTestInterface(
-      pending_receiver<blink.mojom.FrameHostTestInterface> receiver);
-};
diff --git a/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom b/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom
deleted file mode 100644
index fdfcf38..0000000
--- a/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom
+++ /dev/null
@@ -1,26 +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.
-
-module blink.mojom;
-
-import "url/mojom/url.mojom";
-
-// TODO(crbug.com/718652) This is a copy of
-// content/test/frame_host_test_interface.mojom to be used in parallel while
-// InterfaceProvider->DocumentInterfaceBroker conversion is taking place.
-
-// Test interface used in RenderFrame and RenderFrameHost tests to exercise
-// requesting document-scoped interfaces from the RenderFrameHost through
-// the DocumentInterfaceBroker interface.
-//
-// The `Ping` method is invoked by clients immediately after making the
-// FrameHostTestInterfaceRequest, so as to annotate where the request
-// originates from. This allows verification that the request was delivered /
-// not delivered to a certain DocumentInterfaceBroker implementation.
-interface FrameHostTestInterface {
-  Ping(url.mojom.Url source_url, string source_event);
-  // Used in tests to distinguish between the different implementations
-  // and verify that interface requests are routed to the proper override.
-  GetName() => (string name);
-};
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index 1357eb3..ebf2ca9 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -84,7 +84,6 @@
       WebView*,
       WebLocalFrameClient*,
       blink::InterfaceRegistry*,
-      mojo::ScopedMessagePipeHandle,
       WebFrame* opener = nullptr,
       const WebString& name = WebString(),
       WebSandboxFlags = WebSandboxFlags::kNone,
@@ -112,7 +111,6 @@
   BLINK_EXPORT static WebLocalFrame* CreateProvisional(
       WebLocalFrameClient*,
       blink::InterfaceRegistry*,
-      mojo::ScopedMessagePipeHandle,
       WebFrame* previous_web_frame,
       const FramePolicy&);
 
@@ -121,8 +119,7 @@
   // it's no longer needed.
   virtual WebLocalFrame* CreateLocalChild(WebTreeScopeType,
                                           WebLocalFrameClient*,
-                                          blink::InterfaceRegistry*,
-                                          mojo::ScopedMessagePipeHandle) = 0;
+                                          blink::InterfaceRegistry*) = 0;
 
   // Returns the WebFrame associated with the current V8 context. This
   // function can return 0 if the context is associated with a Document that
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index f4566aa..a8cf9f6 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -399,14 +399,6 @@
   // The provisional datasource is now committed.  The first part of the
   // response body has been received, and the encoding of the response
   // body is known.
-  // The mojo::ScopedMessagePipeHandle is a DocumentInterfaceBroker handle. When
-  // a load commits and a new Document is created, Blink creates a new
-  // DocumentInterfaceBroker endpoint to ensure that interface requests in the
-  // newly committed Document are associated with the correct origin (even if
-  // the origin of the old and the new Document are the same). The one
-  // exception is if the Window object is reused; in that case, the old
-  // DocumentInterfaceBroker handle will be reused, and the endpoint won't be
-  // bound to any requests.
   // When a load commits and a new Document is created, WebLocalFrameClient
   // creates a new BrowserInterfaceBroker endpoint to ensure that interface
   // receivers in the newly committed Document are associated with the correct
@@ -417,7 +409,6 @@
   virtual void DidCommitProvisionalLoad(
       const WebHistoryItem&,
       WebHistoryCommitType,
-      mojo::ScopedMessagePipeHandle,
       bool should_reset_browser_interface_broker) {}
 
   // The frame's document has just been initialized.
diff --git a/third_party/blink/public/web/web_remote_frame.h b/third_party/blink/public/web/web_remote_frame.h
index d924afe8..f7da7a8 100644
--- a/third_party/blink/public/web/web_remote_frame.h
+++ b/third_party/blink/public/web/web_remote_frame.h
@@ -73,7 +73,6 @@
                                           const FramePolicy&,
                                           WebLocalFrameClient*,
                                           blink::InterfaceRegistry*,
-                                          mojo::ScopedMessagePipeHandle,
                                           WebFrame* previous_sibling,
                                           const WebFrameOwnerProperties&,
                                           FrameOwnerElementType,
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h
index 0981d5a..09e75e9d 100644
--- a/third_party/blink/public/web/web_view.h
+++ b/third_party/blink/public/web/web_view.h
@@ -436,8 +436,7 @@
   virtual void PutPageIntoBackForwardCache() = 0;
 
   // Unhooks eviction, resumes a page and dispatches a pageshow event.
-  virtual void RestorePageFromBackForwardCache(
-      base::TimeTicks navigation_start) = 0;
+  virtual void RestorePageFromBackForwardCache() = 0;
 
   // Testing functionality for TestRunner ---------------------------------
 
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc
index 8053c879..c3aad5ee 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.cc
@@ -28,13 +28,18 @@
       break;
   }
 
-  switch (color_params.PixelFormat()) {
-    case kRGBA8CanvasPixelFormat:
-      pixel_format_ = SerializedPixelFormat::kRGBA8;
-      break;
-    case kF16CanvasPixelFormat:
-      pixel_format_ = SerializedPixelFormat::kF16;
-      break;
+  // todo(crbug/1021986) remove force_rgba in canvasColorParams
+  if (color_params.GetForceRGBA() == CanvasForceRGBA::kForced) {
+    pixel_format_ = SerializedPixelFormat::kForceRGBA8;
+  } else {
+    switch (color_params.PixelFormat()) {
+      case kRGBA8CanvasPixelFormat:
+        pixel_format_ = SerializedPixelFormat::kRGBA8;
+        break;
+      case kF16CanvasPixelFormat:
+        pixel_format_ = SerializedPixelFormat::kF16;
+        break;
+    }
   }
 
   opacity_mode_ = SerializedOpacityMode::kNonOpaque;
@@ -89,13 +94,21 @@
       break;
   }
 
+  // todo(crbug/1021986) remove force_rgba in canvasColorParams
+  CanvasForceRGBA force_rgba = CanvasForceRGBA::kNotForced;
   CanvasPixelFormat pixel_format = kRGBA8CanvasPixelFormat;
-  if (pixel_format_ == SerializedPixelFormat::kF16)
+  if (pixel_format_ == SerializedPixelFormat::kForceRGBA8) {
+    force_rgba = CanvasForceRGBA::kForced;
+  } else if (pixel_format_ == SerializedPixelFormat::kF16)
     pixel_format = kF16CanvasPixelFormat;
+  else if (pixel_format_ == SerializedPixelFormat::kRGBA8)
+    pixel_format = kRGBA8CanvasPixelFormat;
+
   blink::OpacityMode opacity_mode = blink::kNonOpaque;
   if (opacity_mode_ == SerializedOpacityMode::kOpaque)
     opacity_mode = blink::kOpaque;
-  return CanvasColorParams(color_space, pixel_format, opacity_mode);
+
+  return CanvasColorParams(color_space, pixel_format, opacity_mode, force_rgba);
 }
 
 CanvasColorSpace SerializedColorParams::GetColorSpace() const {
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.h b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.h
index 3665c19..8820a9d 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.h
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.h
@@ -46,10 +46,13 @@
 };
 
 // This enumeration specifies the values used to serialize CanvasPixelFormat.
+// todo(crbug/1021986) remove force_rgba in canvasColorParams and better reflect
+// logic of BGRA vs RGBA
 enum class SerializedPixelFormat : uint32_t {
   kRGBA8 = 0,
   kF16 = 1,
-  kLast = kF16,
+  kForceRGBA8 = 2,
+  kLast = kForceRGBA8,
 };
 
 // This enumeration specifies the values used to serialize
diff --git a/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py b/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
index a55a922..c1ce714 100644
--- a/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
+++ b/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
@@ -16,6 +16,7 @@
     'Base64',
     'IFrame',
     'Latin1',
+    'MathML',
     'PlugIn',
     'SQLite',
     'Uint16',
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 1ace50d..ee34acc9 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -188,6 +188,7 @@
     "//third_party/blink/renderer/core/layout",
     "//third_party/blink/renderer/core/layout/svg:svg_layout",
     "//third_party/blink/renderer/core/loader",
+    "//third_party/blink/renderer/core/mathml",
     "//third_party/blink/renderer/core/messaging",
     "//third_party/blink/renderer/core/mojo",
     "//third_party/blink/renderer/core/offscreencanvas",
@@ -272,8 +273,6 @@
     "testing/death_aware_script_wrappable.h",
     "testing/dictionary_test.cc",
     "testing/dictionary_test.h",
-    "testing/document_interface_broker_test_helpers.cc",
-    "testing/document_interface_broker_test_helpers.h",
     "testing/dummy_modulator.cc",
     "testing/dummy_modulator.h",
     "testing/dummy_page_holder.cc",
@@ -306,8 +305,6 @@
     "testing/sequence_test.h",
     "testing/static_selection.cc",
     "testing/static_selection.h",
-    "testing/test_document_interface_broker.cc",
-    "testing/test_document_interface_broker.h",
     "testing/type_conversions.h",
     "testing/union_types_test.cc",
     "testing/union_types_test.h",
@@ -653,6 +650,33 @@
   ]
 }
 
+process_json5_files("make_core_generated_mathml_names") {
+  script = "../build/scripts/make_element_factory.py"
+
+  in_files = [
+    "mathml/mathml_tag_names.json5",
+    "mathml/mathml_attribute_names.json5",
+  ]
+  other_inputs = make_element_factory_files
+  outputs = [
+    "$blink_core_output_dir/mathml_element_factory.cc",
+    "$blink_core_output_dir/mathml_element_factory.h",
+    "$blink_core_output_dir/mathml_names.cc",
+    "$blink_core_output_dir/mathml_names.h",
+  ]
+}
+
+process_json5_files("make_core_generated_mathml_element_type_helpers") {
+  script = "../build/scripts/make_element_type_helpers.py"
+
+  in_files = [ "mathml/mathml_tag_names.json5" ]
+  other_inputs = make_element_type_helpers_files
+  outputs = [
+    "$blink_core_output_dir/mathml_element_type_helpers.cc",
+    "$blink_core_output_dir/mathml_element_type_helpers.h",
+  ]
+}
+
 process_json5_files("make_core_generated_svg_names") {
   script = "../build/scripts/make_element_factory.py"
 
@@ -755,17 +779,6 @@
 
 # make_qualified_names ---------------------------------------------------------
 
-make_qualified_names("make_core_generated_math_ml_names") {
-  in_files = [
-    "html/parser/mathml_tag_names.json5",
-    "html/parser/mathml_attribute_names.json5",
-  ]
-  outputs = [
-    "$blink_core_output_dir/mathml_names.cc",
-    "$blink_core_output_dir/mathml_names.h",
-  ]
-}
-
 make_qualified_names("make_core_generated_xlink_names") {
   in_files = [ "svg/xlink_attribute_names.json5" ]
   outputs = [
@@ -1033,7 +1046,8 @@
   ":make_core_generated_html_tokenizer_names",
   ":make_core_generated_input_mode_names",
   ":make_core_generated_input_type_names",
-  ":make_core_generated_math_ml_names",
+  ":make_core_generated_mathml_names",
+  ":make_core_generated_mathml_element_type_helpers",
   ":make_core_generated_media_feature_names",
   ":make_core_generated_media_type_names",
   ":make_core_generated_performance_entry_names",
@@ -1259,7 +1273,6 @@
     "frame/local_frame_view_test.cc",
     "frame/mhtml_archive_test.cc",
     "frame/mhtml_loading_test.cc",
-    "frame/origins_using_features_test.cc",
     "frame/performance_monitor_test.cc",
     "frame/reporting_context_test.cc",
     "frame/root_frame_viewport_test.cc",
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 75cadba97..3d5a605 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -51,7 +51,6 @@
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
 #include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom-blink.h"
 #include "third_party/blink/public/mojom/ukm/ukm.mojom-blink.h"
 #include "third_party/blink/public/platform/interface_provider.h"
@@ -244,6 +243,9 @@
 #include "third_party/blink/renderer/core/loader/prerenderer_client.h"
 #include "third_party/blink/renderer/core/loader/progress_tracker.h"
 #include "third_party/blink/renderer/core/loader/text_resource_decoder_builder.h"
+#include "third_party/blink/renderer/core/mathml/mathml_element.h"
+#include "third_party/blink/renderer/core/mathml_element_factory.h"
+#include "third_party/blink/renderer/core/mathml_names.h"
 #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
 #include "third_party/blink/renderer/core/page/event_with_hit_test_results.h"
@@ -1385,6 +1387,14 @@
     if (!element)
       element = MakeGarbageCollected<SVGUnknownElement>(qname, *this);
     saw_elements_in_known_namespaces_ = true;
+  } else if (RuntimeEnabledFeatures::MathMLCoreEnabled() &&
+             qname.NamespaceURI() == mathml_names::kNamespaceURI) {
+    element = MathMLElementFactory::Create(qname.LocalName(), *this, flags);
+    // TODO(crbug.com/1021837): Determine if we need to introduce a
+    // MathMLUnknownClass.
+    if (!element)
+      element = MakeGarbageCollected<MathMLElement>(qname, *this);
+    saw_elements_in_known_namespaces_ = true;
   } else {
     element = Element::Create(qname, this);
   }
@@ -8028,13 +8038,6 @@
   return is_secure;
 }
 
-mojo::ScopedMessagePipeHandle Document::SetDocumentInterfaceBrokerForTesting(
-    mojo::ScopedMessagePipeHandle blink_handle) {
-  DCHECK(GetFrame());
-  return GetFrame()->SetDocumentInterfaceBrokerForTesting(
-      std::move(blink_handle));
-}
-
 void Document::DidEnforceInsecureRequestPolicy() {
   if (!GetFrame())
     return;
@@ -8131,13 +8134,6 @@
   return &GetFrame()->GetInterfaceProvider();
 }
 
-mojom::blink::DocumentInterfaceBroker* Document::GetDocumentInterfaceBroker() {
-  if (!GetFrame())
-    return nullptr;
-
-  return &GetFrame()->GetDocumentInterfaceBroker();
-}
-
 BrowserInterfaceBrokerProxy& Document::GetBrowserInterfaceBroker() {
   if (!GetFrame())
     return GetEmptyBrowserInterfaceBroker();
@@ -8156,13 +8152,6 @@
   return resource_coordinator_.get();
 }
 
-void Document::BindDocumentInterfaceBroker(
-    mojo::ScopedMessagePipeHandle js_handle) {
-  if (!GetFrame())
-    return;
-  GetFrame()->BindDocumentInterfaceBroker(std::move(js_handle));
-}
-
 FrameOrWorkerScheduler* Document::GetScheduler() {
   DCHECK(IsMainThread());
 
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index d84d6f6..8261c70a 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -1359,11 +1359,6 @@
     secure_context_state_ = state;
   }
 
-  void BindDocumentInterfaceBroker(mojo::ScopedMessagePipeHandle js_handle);
-
-  mojo::ScopedMessagePipeHandle SetDocumentInterfaceBrokerForTesting(
-      mojo::ScopedMessagePipeHandle blink_handle);
-
   CanvasFontCache* GetCanvasFontCache();
 
   // Used by unit tests so that all parsing will be main thread for
@@ -1430,7 +1425,6 @@
 
   CoreProbeSink* GetProbeSink() final;
   service_manager::InterfaceProvider* GetInterfaceProvider() final;
-  mojom::blink::DocumentInterfaceBroker* GetDocumentInterfaceBroker() final;
 
   BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() final;
 
diff --git a/third_party/blink/renderer/core/dom/events/event.cc b/third_party/blink/renderer/core/dom/events/event.cc
index 89fa303..395de26 100644
--- a/third_party/blink/renderer/core/dom/events/event.cc
+++ b/third_party/blink/renderer/core/dom/events/event.cc
@@ -316,10 +316,6 @@
 
 HeapVector<Member<EventTarget>> Event::PathInternal(ScriptState* script_state,
                                                     EventPathMode mode) const {
-  if (target_)
-    HostsUsingFeatures::CountHostOrIsolatedWorldHumanReadableName(
-        script_state, *target_, HostsUsingFeatures::Feature::kEventPath);
-
   if (!current_target_) {
     DCHECK_EQ(Event::kNone, event_phase_);
     if (!event_path_) {
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc
index 51eb10c..48fa8a9 100644
--- a/third_party/blink/renderer/core/dom/node.cc
+++ b/third_party/blink/renderer/core/dom/node.cc
@@ -1701,8 +1701,8 @@
 // inline style, or other things that this apparently guards against.
 bool Node::IsStyledElement() const {
   auto* this_element = DynamicTo<Element>(this);
-  return IsHTMLElement() || IsSVGElement() ||
-         (this_element &&
+  return IsHTMLElement() || IsSVGElement() || IsMathMLElement() ||
+         (!RuntimeEnabledFeatures::MathMLCoreEnabled() && this_element &&
           this_element->namespaceURI() == mathml_names::kNamespaceURI);
 }
 
diff --git a/third_party/blink/renderer/core/dom/node.h b/third_party/blink/renderer/core/dom/node.h
index 826e74e..4155913 100644
--- a/third_party/blink/renderer/core/dom/node.h
+++ b/third_party/blink/renderer/core/dom/node.h
@@ -58,6 +58,7 @@
 class LayoutBox;
 class LayoutBoxModelObject;
 class LayoutObject;
+class MathMLQualifiedName;
 class MutationObserver;
 class MutationObserverRegistration;
 class NodeList;
@@ -79,8 +80,8 @@
 class WebPluginContainerImpl;
 struct PhysicalRect;
 
-const int kNodeStyleChangeShift = 18;
-const int kNodeCustomElementShift = 20;
+const int kNodeStyleChangeShift = 19;
+const int kNodeCustomElementShift = 21;
 
 // Values for kChildNeedsStyleRecalcFlag, controlling whether a node gets its
 // style recalculated.
@@ -180,6 +181,7 @@
   // DOM methods & attributes for Node
 
   bool HasTagName(const HTMLQualifiedName&) const;
+  bool HasTagName(const MathMLQualifiedName&) const;
   bool HasTagName(const SVGQualifiedName&) const;
   virtual String nodeName() const = 0;
   virtual String nodeValue() const;
@@ -272,6 +274,7 @@
   bool IsContainerNode() const { return GetFlag(kIsContainerFlag); }
   bool IsTextNode() const { return GetFlag(kIsTextFlag); }
   bool IsHTMLElement() const { return GetFlag(kIsHTMLFlag); }
+  bool IsMathMLElement() const { return GetFlag(kIsMathMLFlag); }
   bool IsSVGElement() const { return GetFlag(kIsSVGFlag); }
 
   DISABLE_CFI_PERF bool IsPseudoElement() const {
@@ -915,56 +918,57 @@
     kIsContainerFlag = 1 << 2,
     kIsElementFlag = 1 << 3,
     kIsHTMLFlag = 1 << 4,
-    kIsSVGFlag = 1 << 5,
-    kIsDocumentFragmentFlag = 1 << 6,
-    kIsV0InsertionPointFlag = 1 << 7,
+    kIsMathMLFlag = 1 << 5,
+    kIsSVGFlag = 1 << 6,
+    kIsDocumentFragmentFlag = 1 << 7,
+    kIsV0InsertionPointFlag = 1 << 8,
 
     // Changes based on if the element should be treated like a link,
     // ex. When setting the href attribute on an <a>.
-    kIsLinkFlag = 1 << 8,
+    kIsLinkFlag = 1 << 9,
 
     // Changes based on :hover, :active and :focus state.
-    kIsUserActionElementFlag = 1 << 9,
+    kIsUserActionElementFlag = 1 << 10,
 
     // Tree state flags. These change when the element is added/removed
     // from a DOM tree.
-    kIsConnectedFlag = 1 << 10,
-    kIsInShadowTreeFlag = 1 << 11,
+    kIsConnectedFlag = 1 << 11,
+    kIsInShadowTreeFlag = 1 << 12,
 
     // Set by the parser when the children are done parsing.
-    kIsFinishedParsingChildrenFlag = 1 << 12,
+    kIsFinishedParsingChildrenFlag = 1 << 13,
 
     // Flags related to recalcStyle.
-    kHasCustomStyleCallbacksFlag = 1 << 13,
-    kChildNeedsStyleInvalidationFlag = 1 << 14,
-    kNeedsStyleInvalidationFlag = 1 << 15,
-    kChildNeedsDistributionRecalcFlag = 1 << 16,
-    kChildNeedsStyleRecalcFlag = 1 << 17,
+    kHasCustomStyleCallbacksFlag = 1 << 14,
+    kChildNeedsStyleInvalidationFlag = 1 << 15,
+    kNeedsStyleInvalidationFlag = 1 << 16,
+    kChildNeedsDistributionRecalcFlag = 1 << 17,
+    kChildNeedsStyleRecalcFlag = 1 << 18,
     kStyleChangeMask =
         1 << kNodeStyleChangeShift | 1 << (kNodeStyleChangeShift + 1),
 
     kCustomElementStateMask = 0x3 << kNodeCustomElementShift,
 
-    kHasNameOrIsEditingTextFlag = 1 << 22,
-    kHasEventTargetDataFlag = 1 << 23,
+    kHasNameOrIsEditingTextFlag = 1 << 23,
+    kHasEventTargetDataFlag = 1 << 24,
 
-    kV0CustomElementFlag = 1 << 24,
-    kV0CustomElementUpgradedFlag = 1 << 25,
+    kV0CustomElementFlag = 1 << 25,
+    kV0CustomElementUpgradedFlag = 1 << 26,
 
-    kNeedsReattachLayoutTree = 1 << 26,
-    kChildNeedsReattachLayoutTree = 1 << 27,
+    kNeedsReattachLayoutTree = 1 << 27,
+    kChildNeedsReattachLayoutTree = 1 << 28,
 
-    kHasDuplicateAttributes = 1 << 28,
+    kHasDuplicateAttributes = 1 << 29,
 
     // Temporary flag for some UseCounter items. crbug.com/859391.
-    kInDOMNodeRemovedHandler = 1 << 29,
+    kInDOMNodeRemovedHandler = 1 << 30,
 
-    kForceReattachLayoutTree = 1 << 30,
+    kForceReattachLayoutTree = 1 << 31,
 
     kDefaultNodeFlags = kIsFinishedParsingChildrenFlag,
   };
 
-  // 1 bit remaining.
+  // 0 bits remaining.
 
   bool GetFlag(NodeFlags mask) const { return node_flags_ & mask; }
   void SetFlag(bool f, NodeFlags mask) {
@@ -983,6 +987,7 @@
         kCreateContainer | kIsDocumentFragmentFlag | kIsInShadowTreeFlag,
     kCreateDocumentFragment = kCreateContainer | kIsDocumentFragmentFlag,
     kCreateHTMLElement = kCreateElement | kIsHTMLFlag,
+    kCreateMathMLElement = kCreateElement | kIsMathMLFlag,
     kCreateSVGElement = kCreateElement | kIsSVGFlag,
     kCreateDocument = kCreateContainer | kIsConnectedFlag,
     kCreateV0InsertionPoint = kCreateHTMLElement | kIsV0InsertionPointFlag,
diff --git a/third_party/blink/renderer/core/events/page_transition_event.cc b/third_party/blink/renderer/core/events/page_transition_event.cc
index d96e160b..7d63456 100644
--- a/third_party/blink/renderer/core/events/page_transition_event.cc
+++ b/third_party/blink/renderer/core/events/page_transition_event.cc
@@ -35,13 +35,6 @@
                                          bool persisted)
     : Event(type, Bubbles::kYes, Cancelable::kYes), persisted_(persisted) {}
 
-PageTransitionEvent::PageTransitionEvent(base::TimeTicks navigation_start)
-    : Event(event_type_names::kPageshow,
-            Bubbles::kYes,
-            Cancelable::kYes,
-            navigation_start),
-      persisted_(true) {}
-
 PageTransitionEvent::PageTransitionEvent(
     const AtomicString& type,
     const PageTransitionEventInit* initializer)
diff --git a/third_party/blink/renderer/core/events/page_transition_event.h b/third_party/blink/renderer/core/events/page_transition_event.h
index da175f11..9570909 100644
--- a/third_party/blink/renderer/core/events/page_transition_event.h
+++ b/third_party/blink/renderer/core/events/page_transition_event.h
@@ -27,7 +27,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_PAGE_TRANSITION_EVENT_H_
 
 #include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/event_type_names.h"
 #include "third_party/blink/renderer/core/events/page_transition_event_init.h"
 
 namespace blink {
@@ -40,16 +39,8 @@
     return MakeGarbageCollected<PageTransitionEvent>();
   }
   static PageTransitionEvent* Create(const AtomicString& type, bool persisted) {
-    // Persisted pageshow events must be created through CreatePersistedPageshow
-    // (because it needs |navigation_start|).
-    DCHECK(!(persisted && type == event_type_names::kPageshow));
     return MakeGarbageCollected<PageTransitionEvent>(type, persisted);
   }
-  static PageTransitionEvent* CreatePersistedPageshow(
-      base::TimeTicks navigation_start) {
-    return MakeGarbageCollected<PageTransitionEvent>(navigation_start);
-  }
-
   static PageTransitionEvent* Create(
       const AtomicString& type,
       const PageTransitionEventInit* initializer) {
@@ -59,7 +50,6 @@
   PageTransitionEvent();
   PageTransitionEvent(const AtomicString& type, bool persisted);
   PageTransitionEvent(const AtomicString&, const PageTransitionEventInit*);
-  explicit PageTransitionEvent(base::TimeTicks navigation_start);
   ~PageTransitionEvent() override;
 
   const AtomicString& InterfaceName() const override;
@@ -69,7 +59,6 @@
   void Trace(blink::Visitor*) override;
 
  private:
-  // TODO(rakina): change to PageTransitionEventPersistence.
   bool persisted_;
 };
 
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.h b/third_party/blink/renderer/core/execution_context/execution_context.h
index 727817f..7ead7f12 100644
--- a/third_party/blink/renderer/core/execution_context/execution_context.h
+++ b/third_party/blink/renderer/core/execution_context/execution_context.h
@@ -36,7 +36,6 @@
 #include "base/optional.h"
 #include "base/unguessable_token.h"
 #include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
 #include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -276,10 +275,6 @@
     return nullptr;
   }
 
-  virtual mojom::blink::DocumentInterfaceBroker* GetDocumentInterfaceBroker() {
-    return nullptr;
-  }
-
   virtual BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() = 0;
 
   virtual FrameOrWorkerScheduler* GetScheduler() = 0;
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
index 3f3401ed..3e6a2487 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -161,16 +161,8 @@
 
 }  // namespace
 
-LocalFrameClientImpl::LocalFrameClientImpl(
-    WebLocalFrameImpl* frame,
-    mojo::ScopedMessagePipeHandle document_interface_broker_handle)
-    : web_frame_(frame) {
-  DCHECK(document_interface_broker_handle.is_valid());
-  document_interface_broker_.Bind(
-      mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker>(
-          std::move(document_interface_broker_handle),
-          mojom::blink::DocumentInterfaceBroker::Version_));
-}
+LocalFrameClientImpl::LocalFrameClientImpl(WebLocalFrameImpl* frame)
+    : web_frame_(frame) {}
 
 LocalFrameClientImpl::~LocalFrameClientImpl() = default;
 
@@ -443,17 +435,8 @@
   }
 
   if (web_frame_->Client()) {
-    mojo::PendingReceiver<mojom::blink::DocumentInterfaceBroker>
-        document_interface_broker_receiver;
-    if (global_object_reuse_policy != GlobalObjectReusePolicy::kUseExisting) {
-      document_interface_broker_.reset();
-      document_interface_broker_receiver =
-          document_interface_broker_.BindNewPipeAndPassReceiver();
-    }
-
     web_frame_->Client()->DidCommitProvisionalLoad(
         WebHistoryItem(item), commit_type,
-        document_interface_broker_receiver.PassPipe(),
         global_object_reuse_policy == GlobalObjectReusePolicy::kCreateNew);
     if (web_frame_->GetFrame()->IsLocalRoot()) {
       // This update should be sent as soon as loading the new document begins
@@ -1061,40 +1044,11 @@
   return web_frame_->Client()->GetInterfaceProvider();
 }
 
-mojom::blink::DocumentInterfaceBroker*
-LocalFrameClientImpl::GetDocumentInterfaceBroker() {
-  DCHECK(document_interface_broker_.is_bound());
-  return document_interface_broker_.get();
-}
-
 blink::BrowserInterfaceBrokerProxy&
 LocalFrameClientImpl::GetBrowserInterfaceBroker() {
   return *web_frame_->Client()->GetBrowserInterfaceBroker();
 }
 
-void LocalFrameClientImpl::BindDocumentInterfaceBroker(
-    mojo::ScopedMessagePipeHandle js_handle) {
-  document_interface_broker_receivers_.Add(
-      this, mojo::PendingReceiver<mojom::blink::DocumentInterfaceBroker>(
-                std::move(js_handle)));
-}
-
-mojo::ScopedMessagePipeHandle
-LocalFrameClientImpl::SetDocumentInterfaceBrokerForTesting(
-    mojo::ScopedMessagePipeHandle blink_handle) {
-  // Ensure all pending calls get dispatched before the implementation swap
-  document_interface_broker_receivers_.FlushForTesting();
-
-  mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker> test_broker(
-      std::move(blink_handle), mojom::blink::DocumentInterfaceBroker::Version_);
-
-  mojo::ScopedMessagePipeHandle real_handle =
-      document_interface_broker_.Unbind().PassPipe();
-  document_interface_broker_.Bind(std::move(test_broker));
-
-  return real_handle;
-}
-
 AssociatedInterfaceProvider*
 LocalFrameClientImpl::GetRemoteNavigationAssociatedInterfaces() {
   return web_frame_->Client()->GetRemoteNavigationAssociatedInterfaces();
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
index 38f5e390..51822fd3 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -41,7 +41,6 @@
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
 #include "third_party/blink/public/platform/web_insecure_request_policy.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
@@ -59,7 +58,7 @@
 
 class LocalFrameClientImpl final : public LocalFrameClient {
  public:
-  LocalFrameClientImpl(WebLocalFrameImpl*, mojo::ScopedMessagePipeHandle);
+  explicit LocalFrameClientImpl(WebLocalFrameImpl*);
   ~LocalFrameClientImpl() override;
 
   void Trace(blink::Visitor*) override;
@@ -248,21 +247,6 @@
 
   service_manager::InterfaceProvider* GetInterfaceProvider() override;
 
-  // Binds |js_handle| to the current implementation bound to
-  // |document_interface_broker_| to share the same broker between C++ and
-  // JavaScript clients.
-  void BindDocumentInterfaceBroker(
-      mojo::ScopedMessagePipeHandle js_handle) override;
-
-  mojom::blink::DocumentInterfaceBroker* GetDocumentInterfaceBroker() override;
-
-  // Binds |document_interface_broker_| to |blink_handle|. Used in tests to set
-  // a custom override for DocumentInterfaceBroker methods. Returns the handle
-  // to the previously bound 'production' implementation, which will be used to
-  // forward the calls to methods that have not been overridden.
-  mojo::ScopedMessagePipeHandle SetDocumentInterfaceBrokerForTesting(
-      mojo::ScopedMessagePipeHandle blink_handle) override;
-
   blink::BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() override;
 
   AssociatedInterfaceProvider* GetRemoteNavigationAssociatedInterfaces()
@@ -318,18 +302,6 @@
       std::unique_ptr<blink::URLLoaderFactoryBundleInfo> info) override;
 
  private:
-  struct DocumentInterfaceBrokerForwarderTraits {
-    using Interface = mojom::blink::DocumentInterfaceBroker;
-    using PointerType = WeakPersistent<LocalFrameClientImpl>;
-    static bool IsNull(PointerType ptr) {
-      return !ptr || !ptr->document_interface_broker_;
-    }
-    static Interface* GetRawPointer(PointerType* ptr) {
-      return (*ptr)->GetDocumentInterfaceBroker();
-    }
-  };
-  friend struct DocumentInterfaceBrokerForwarderTraits;
-
   bool IsLocalFrameClientImpl() const override { return true; }
   WebDevToolsAgentImpl* DevToolsAgent();
 
@@ -339,19 +311,6 @@
 
   String user_agent_;
   blink::UserAgentMetadata user_agent_metadata_;
-
-  mojo::Remote<mojom::blink::DocumentInterfaceBroker>
-      document_interface_broker_;
-
-  // |document_interface_broker_receivers_| basically just forwards the broker
-  // methods to GetDocumentInterfaceBroker()
-  // via DocumentInterfaceBrokerForwarderTraits.
-  // Used to connect JavaScript clients of DocumentInterfaceBroker with the same
-  // implementation that |document_interface_broker_| is bound to.
-  mojo::ReceiverSetBase<mojo::Receiver<mojom::blink::DocumentInterfaceBroker,
-                                       DocumentInterfaceBrokerForwarderTraits>,
-                        void>
-      document_interface_broker_receivers_;
 };
 
 DEFINE_TYPE_CASTS(LocalFrameClientImpl,
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl_test.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl_test.cc
index 6f9d0fe..72d5ced 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl_test.cc
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl_test.cc
@@ -39,7 +39,6 @@
 #include "third_party/blink/public/web/web_view.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
@@ -111,23 +110,5 @@
   EXPECT_TRUE(default_user_agent.Equals(UserAgent()));
 }
 
-TEST_F(LocalFrameClientImplTest, TestDocumentInterfaceBrokerOverride) {
-  mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker> doc;
-  FrameHostTestDocumentInterfaceBroker frame_interface_broker(
-      &MainFrame()->GetFrame()->GetDocumentInterfaceBroker(),
-      doc.InitWithNewPipeAndPassReceiver());
-  MainFrame()->GetFrame()->SetDocumentInterfaceBrokerForTesting(doc.PassPipe());
-
-  mojo::Remote<mojom::blink::FrameHostTestInterface> frame_test;
-  MainFrame()
-      ->GetFrame()
-      ->GetDocumentInterfaceBroker()
-      .GetFrameHostTestInterface(frame_test.BindNewPipeAndPassReceiver());
-  frame_test->GetName(base::BindOnce([](const WTF::String& result) {
-    EXPECT_EQ(result, kGetNameTestResponse);
-  }));
-  frame_interface_broker.Flush();
-}
-
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 0a56e715..15c97a8 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -4226,7 +4226,6 @@
   // frame_test_helpers::TestWebFrameClient:
   void DidCommitProvisionalLoad(const WebHistoryItem&,
                                 WebHistoryCommitType,
-                                mojo::ScopedMessagePipeHandle,
                                 bool) override {
     Frame()->View()->ResetScrollAndScaleState();
   }
@@ -6352,7 +6351,6 @@
   // frame_test_helpers::TestWebFrameClient:
   void DidCommitProvisionalLoad(const WebHistoryItem&,
                                 WebHistoryCommitType,
-                                mojo::ScopedMessagePipeHandle,
                                 bool) override {
     did_load_ = true;
   }
@@ -9428,7 +9426,6 @@
   // frame_test_helpers::TestWebFrameClient:
   void DidCommitProvisionalLoad(const WebHistoryItem&,
                                 WebHistoryCommitType history_commit_type,
-                                mojo::ScopedMessagePipeHandle,
                                 bool) override {
     history_commit_type_ = history_commit_type;
     remote_frame_->Swap(Frame());
@@ -9656,7 +9653,6 @@
   // frame_test_helpers::TestWebFrameClient:
   void DidCommitProvisionalLoad(const WebHistoryItem&,
                                 WebHistoryCommitType history_commit_type,
-                                mojo::ScopedMessagePipeHandle,
                                 bool) override {
     history_commit_type_ = history_commit_type;
   }
@@ -10563,7 +10559,6 @@
   }
   void DidCommitProvisionalLoad(const WebHistoryItem&,
                                 WebHistoryCommitType,
-                                mojo::ScopedMessagePipeHandle,
                                 bool) override {
     EXPECT_EQ(2, callback_count_++);
   }
diff --git a/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc b/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
index 20baab55..d464250 100644
--- a/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc
@@ -191,14 +191,12 @@
     const FramePolicy& frame_policy,
     WebLocalFrameClient* client,
     blink::InterfaceRegistry* interface_registry,
-    mojo::ScopedMessagePipeHandle document_interface_broker_handle,
     WebFrame* previous_sibling,
     const WebFrameOwnerProperties& frame_owner_properties,
     FrameOwnerElementType frame_owner_element_type,
     WebFrame* opener) {
-  auto* child = MakeGarbageCollected<WebLocalFrameImpl>(
-      scope, client, interface_registry,
-      std::move(document_interface_broker_handle));
+  auto* child = MakeGarbageCollected<WebLocalFrameImpl>(scope, client,
+                                                        interface_registry);
   child->SetOpener(opener);
   InsertAfter(child, previous_sibling);
   auto* owner = MakeGarbageCollected<RemoteFrameOwner>(
diff --git a/third_party/blink/renderer/core/exported/web_remote_frame_impl.h b/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
index 3593f32..74f8b63 100644
--- a/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
+++ b/third_party/blink/renderer/core/exported/web_remote_frame_impl.h
@@ -63,7 +63,6 @@
                                   const FramePolicy&,
                                   WebLocalFrameClient*,
                                   blink::InterfaceRegistry*,
-                                  mojo::ScopedMessagePipeHandle,
                                   WebFrame* previous_sibling,
                                   const WebFrameOwnerProperties&,
                                   FrameOwnerElementType,
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 2556772..ce62b5a 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -3452,8 +3452,7 @@
   }
 }
 
-void WebViewImpl::RestorePageFromBackForwardCache(
-    base::TimeTicks navigation_start) {
+void WebViewImpl::RestorePageFromBackForwardCache() {
   // Unhook eviction.
   Page* page = AsView().page;
   if (page) {
@@ -3472,8 +3471,8 @@
     for (Frame* frame = page->MainFrame(); frame;
          frame = frame->Tree().TraverseNext()) {
       if (frame->DomWindow() && frame->DomWindow()->IsLocalDOMWindow()) {
-        frame->DomWindow()->ToLocalDOMWindow()->DispatchPersistedPageshowEvent(
-            navigation_start);
+        frame->DomWindow()->ToLocalDOMWindow()->DispatchPageshowEvent(
+            PageTransitionEventPersistence::kPageTransitionEventPersisted);
       }
     }
   }
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
index b90eb91..85ecd3a 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -199,8 +199,7 @@
   void AcceptLanguagesChanged() override;
   void SetPageFrozen(bool frozen) override;
   void PutPageIntoBackForwardCache() override;
-  void RestorePageFromBackForwardCache(
-      base::TimeTicks navigation_start) override;
+  void RestorePageFromBackForwardCache() override;
   WebWidget* MainFrameWidget() override;
   void SetBaseBackgroundColor(SkColor) override;
   void SetBackgroundColorOverride(SkColor) override;
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index 2d236e4..4eca1d7 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -49,7 +49,6 @@
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/common/frame/frame_owner_element_type.h"
 #include "third_party/blink/public/common/page/page_zoom.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
 #include "third_party/blink/public/platform/web_coalesced_input_event.h"
 #include "third_party/blink/public/platform/web_cursor_info.h"
@@ -507,11 +506,7 @@
 
   frame_test_helpers::TestWebFrameClient web_frame_client;
   WebLocalFrame* frame = WebLocalFrame::CreateMainFrame(
-      web_view, &web_frame_client, nullptr,
-      mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver()
-          .PassPipe(),
-      nullptr);
+      web_view, &web_frame_client, nullptr, nullptr);
   web_frame_client.Bind(frame);
 
   {
@@ -2647,11 +2642,7 @@
   frame_test_helpers::TestWebFrameClient web_frame_client;
   frame_test_helpers::TestWebWidgetClient web_widget_client;
   WebLocalFrame* local_frame = WebLocalFrame::CreateMainFrame(
-      web_view, &web_frame_client, nullptr,
-      mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver()
-          .PassPipe(),
-      nullptr);
+      web_view, &web_frame_client, nullptr, nullptr);
   web_frame_client.Bind(local_frame);
   blink::WebFrameWidget::CreateForMainFrame(&web_widget_client, local_frame);
 
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc
index aaaa464..ce1131c1 100644
--- a/third_party/blink/renderer/core/frame/deprecation.cc
+++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -57,6 +57,7 @@
   kM79,
   kM80,
   kM81,
+  kM82,
 };
 
 // Returns estimated milestone dates as human-readable strings.
@@ -95,6 +96,8 @@
       return "M80, around February 2020";
     case kM81:
       return "M81, around March 2020";
+    case kM82:
+      return "M82, around April 2020";
   }
 
   NOTREACHED();
@@ -135,9 +138,11 @@
     case kM79:
       return 1575950400000;  // December 10, 2019.
     case kM80:
-      return 1580529600000;  // February 1, 2020. (This is a guess!)
+      return 1580788800000;  // February 4, 2020.
     case kM81:
-      return 1585022400000;  // March 24, 2020
+      return 1584417600000;  // March 17, 2020.
+    case kM82:
+      return 1588046400000;  // April 28, 2020.
   }
 
   NOTREACHED();
@@ -309,13 +314,23 @@
           "https://www.chromestatus.com/features/6107495151960064 for more "
           "details."};
 
-    case WebFeature::kApplicationCacheManifestSelectInsecureOrigin:
     case WebFeature::kApplicationCacheAPIInsecureOrigin:
+    case WebFeature::kApplicationCacheManifestSelectInsecureOrigin:
       return {"ApplicationCacheAPIInsecureOrigin", kM70,
-              "Application Cache is restricted to secure contexts. Please "
-              "consider migrating your application to HTTPS, and eventually "
-              "shifting over to Service Workers. See https://goo.gl/rStTGz for "
-              "more details."};
+              "Application Cache was previously restricted to secure origins "
+              "only from M70 on but now secure origin use is deprecated and "
+              "will be removed in M82.  Please shift your use case over to "
+              "Service Workers."};
+
+    case WebFeature::kApplicationCacheAPISecureOrigin:
+      return {
+          "ApplicationCacheAPISecureOrigin", kM82,
+          WillBeRemoved("Application Cache API use", kM82, "6192449487634432")};
+
+    case WebFeature::kApplicationCacheManifestSelectSecureOrigin:
+      return {"ApplicationCacheAPISecureOrigin", kM82,
+              WillBeRemoved("Application Cache API manifest selection", kM82,
+                            "6192449487634432")};
 
     case WebFeature::kNotificationInsecureOrigin:
     case WebFeature::kNotificationAPIInsecureOriginIframe:
diff --git a/third_party/blink/renderer/core/frame/frame_test.cc b/third_party/blink/renderer/core/frame/frame_test.cc
index aa5e866..8fbde69 100644
--- a/third_party/blink/renderer/core/frame/frame_test.cc
+++ b/third_party/blink/renderer/core/frame/frame_test.cc
@@ -9,7 +9,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -185,23 +184,4 @@
       LocalFrame::ConsumeTransientUserActivation(GetDocument().GetFrame()));
 }
 
-TEST_F(FrameTest, TestDocumentInterfaceBrokerOverride) {
-  mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker> doc;
-  FrameHostTestDocumentInterfaceBroker frame_interface_broker(
-      &GetDocument().GetFrame()->GetDocumentInterfaceBroker(),
-      doc.InitWithNewPipeAndPassReceiver());
-  GetDocument().GetFrame()->SetDocumentInterfaceBrokerForTesting(
-      doc.PassPipe());
-
-  mojo::Remote<mojom::blink::FrameHostTestInterface> frame_test;
-  GetDocument()
-      .GetFrame()
-      ->GetDocumentInterfaceBroker()
-      .GetFrameHostTestInterface(frame_test.BindNewPipeAndPassReceiver());
-  frame_test->GetName(base::BindOnce([](const WTF::String& result) {
-    EXPECT_EQ(result, kGetNameTestResponse);
-  }));
-  frame_interface_broker.Flush();
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index 999e5c6..e77c1f4 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -212,11 +212,8 @@
                                     TestWebFrameClient* client) {
   std::unique_ptr<TestWebFrameClient> owned_client;
   client = CreateDefaultClientIfNeeded(client, owned_client);
-  auto* frame = To<WebLocalFrameImpl>(parent.CreateLocalChild(
-      scope, client, nullptr,
-      mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver()
-          .PassPipe()));
+  auto* frame =
+      To<WebLocalFrameImpl>(parent.CreateLocalChild(scope, client, nullptr));
   client->Bind(frame, std::move(owned_client));
   return frame;
 }
@@ -227,11 +224,8 @@
     std::unique_ptr<TestWebFrameClient> self_owned) {
   DCHECK(self_owned);
   TestWebFrameClient* client = self_owned.get();
-  auto* frame = To<WebLocalFrameImpl>(parent.CreateLocalChild(
-      scope, client, nullptr,
-      mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver()
-          .PassPipe()));
+  auto* frame =
+      To<WebLocalFrameImpl>(parent.CreateLocalChild(scope, client, nullptr));
   client->Bind(frame, std::move(self_owned));
   return frame;
 }
@@ -241,11 +235,7 @@
   std::unique_ptr<TestWebFrameClient> owned_client;
   client = CreateDefaultClientIfNeeded(client, owned_client);
   auto* frame = To<WebLocalFrameImpl>(WebLocalFrame::CreateProvisional(
-      client, nullptr,
-      mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver()
-          .PassPipe(),
-      &old_frame, FramePolicy()));
+      client, nullptr, &old_frame, FramePolicy()));
   client->Bind(frame, std::move(owned_client));
   std::unique_ptr<TestWebWidgetClient> widget_client;
   // Create a local root, if necessary.
@@ -289,9 +279,6 @@
   client = CreateDefaultClientIfNeeded(client, owned_client);
   auto* frame = To<WebLocalFrameImpl>(parent.CreateLocalChild(
       WebTreeScopeType::kDocument, name, FramePolicy(), client, nullptr,
-      mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver()
-          .PassPipe(),
       previous_sibling, properties, FrameOwnerElementType::kIframe, nullptr));
   client->Bind(frame, std::move(owned_client));
 
@@ -356,11 +343,7 @@
   web_frame_client =
       CreateDefaultClientIfNeeded(web_frame_client, owned_web_frame_client);
   WebLocalFrame* frame = WebLocalFrame::CreateMainFrame(
-      web_view_, web_frame_client, nullptr,
-      mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker>()
-          .InitWithNewPipeAndPassReceiver()
-          .PassPipe(),
-      opener);
+      web_view_, web_frame_client, nullptr, opener);
   web_frame_client->Bind(frame, std::move(owned_web_frame_client));
 
   test_web_widget_client_ = CreateDefaultClientIfNeeded(
diff --git a/third_party/blink/renderer/core/frame/hosts_using_features.cc b/third_party/blink/renderer/core/frame/hosts_using_features.cc
index 2af25c9..81c07e5 100644
--- a/third_party/blink/renderer/core/frame/hosts_using_features.cc
+++ b/third_party/blink/renderer/core/frame/hosts_using_features.cc
@@ -55,10 +55,6 @@
     document->HostsUsingFeaturesValue().Count(feature);
     return;
   }
-  if (Page* page = document->GetPage()) {
-    page->GetHostsUsingFeatures().CountName(
-        feature, script_state->World().NonMainWorldHumanReadableName());
-  }
 }
 
 void HostsUsingFeatures::Value::Count(Feature feature) {
@@ -66,13 +62,7 @@
   count_bits_ |= 1 << static_cast<unsigned>(feature);
 }
 
-void HostsUsingFeatures::CountName(Feature feature, const String& name) {
-  auto result = value_by_name_.insert(name, Value());
-  result.stored_value->value.Count(feature);
-}
-
 void HostsUsingFeatures::Clear() {
-  value_by_name_.clear();
   url_and_values_.clear();
 }
 
@@ -96,8 +86,6 @@
     RecordETLDPlus1ToRappor();
     url_and_values_.clear();
   }
-  if (!value_by_name_.IsEmpty())
-    RecordNamesToRappor();
 }
 
 void HostsUsingFeatures::RecordHostToRappor() {
@@ -136,22 +124,11 @@
     url_and_value.value.RecordETLDPlus1ToRappor(KURL(url_and_value.key));
 }
 
-void HostsUsingFeatures::RecordNamesToRappor() {
-  DCHECK(!value_by_name_.IsEmpty());
-
-  for (auto& name_and_value : value_by_name_)
-    name_and_value.value.RecordNameToRappor(name_and_value.key);
-
-  value_by_name_.clear();
-}
-
 void HostsUsingFeatures::Value::Aggregate(HostsUsingFeatures::Value other) {
   count_bits_ |= other.count_bits_;
 }
 
 void HostsUsingFeatures::Value::RecordHostToRappor(const String& host) {
-  if (Get(Feature::kEventPath))
-    Platform::Current()->RecordRappor("WebComponents.EventPath", host);
   if (Get(Feature::kDeviceMotionInsecureHost))
     Platform::Current()->RecordRappor(
         "PowerfulFeatureUse.Host.DeviceMotion.Insecure", host);
@@ -173,12 +150,6 @@
         "PowerfulFeatureUse.Host.ApplicationCacheAPI.Insecure", host);
 }
 
-void HostsUsingFeatures::Value::RecordNameToRappor(const String& name) {
-  if (Get(Feature::kEventPath))
-    Platform::Current()->RecordRappor("WebComponents.EventPath.Extensions",
-                                      name);
-}
-
 void HostsUsingFeatures::Value::RecordETLDPlus1ToRappor(const KURL& url) {
   if (Get(Feature::kGetUserMediaInsecureHost))
     Platform::Current()->RecordRapporURL(
diff --git a/third_party/blink/renderer/core/frame/hosts_using_features.h b/third_party/blink/renderer/core/frame/hosts_using_features.h
index 044fb33..f773348f 100644
--- a/third_party/blink/renderer/core/frame/hosts_using_features.h
+++ b/third_party/blink/renderer/core/frame/hosts_using_features.h
@@ -29,7 +29,7 @@
   enum class Feature {
     kElementCreateShadowRoot_Unused,
     kDocumentRegisterElement_Unused,
-    kEventPath,
+    kEventPath_Unused,
     kDeviceMotionInsecureHost,
     kDeviceOrientationInsecureHost,
     kFullscreenInsecureHost,
@@ -72,15 +72,12 @@
 
     void Aggregate(Value);
     void RecordHostToRappor(const String& host);
-    void RecordNameToRappor(const String& name);
     void RecordETLDPlus1ToRappor(const KURL&);
 
    private:
     unsigned count_bits_ : static_cast<unsigned>(Feature::kNumberOfFeatures);
   };
 
-  void CountName(Feature, const String&);
-  HashMap<String, Value>& ValueByName() { return value_by_name_; }
   void Clear();
 
  private:
@@ -89,7 +86,6 @@
   void RecordETLDPlus1ToRappor();
 
   Vector<std::pair<KURL, HostsUsingFeatures::Value>, 1> url_and_values_;
-  HashMap<String, HostsUsingFeatures::Value> value_by_name_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index f43ca0d..1d6131b 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -311,12 +311,13 @@
 
 void LocalDOMWindow::DocumentWasClosed() {
   DispatchWindowLoadEvent();
-  EnqueueNonPersistedPageshowEvent();
+  EnqueuePageshowEvent(kPageTransitionEventNotPersisted);
   if (pending_state_object_)
     EnqueuePopstateEvent(std::move(pending_state_object_));
 }
 
-void LocalDOMWindow::EnqueueNonPersistedPageshowEvent() {
+void LocalDOMWindow::EnqueuePageshowEvent(
+    PageTransitionEventPersistence persisted) {
   // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36334 Pageshow event needs
   // to fire asynchronously.  As per spec pageshow must be triggered
   // asynchronously.  However to be compatible with other browsers blink fires
@@ -324,23 +325,14 @@
   if (ScopedEventQueue::Instance()->ShouldQueueEvents() && document_) {
     // The task source should be kDOMManipulation, but the spec doesn't say
     // anything about this.
-    EnqueueWindowEvent(*PageTransitionEvent::Create(event_type_names::kPageshow,
-                                                    false /* persisted */),
-                       TaskType::kMiscPlatformAPI);
+    EnqueueWindowEvent(
+        *PageTransitionEvent::Create(event_type_names::kPageshow, persisted),
+        TaskType::kMiscPlatformAPI);
     return;
   }
-  DispatchEvent(*PageTransitionEvent::Create(event_type_names::kPageshow,
-                                             false /* persisted */),
-                document_.Get());
-}
-
-void LocalDOMWindow::DispatchPersistedPageshowEvent(
-    base::TimeTicks navigation_start) {
-  // Persisted pageshow events are dispatched for pages that are restored from
-  // the back forward cache, and the event's timestamp should reflect the
-  // |navigation_start| time of the back navigation.
-  DispatchEvent(*PageTransitionEvent::CreatePersistedPageshow(navigation_start),
-                document_.Get());
+  DispatchEvent(
+      *PageTransitionEvent::Create(event_type_names::kPageshow, persisted),
+      document_.Get());
 }
 
 void LocalDOMWindow::EnqueueHashchangeEvent(const String& old_url,
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
index 1fba857..bc91bd5c 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -298,7 +298,7 @@
 
   void EnqueueWindowEvent(Event&, TaskType);
   void EnqueueDocumentEvent(Event&, TaskType);
-  void EnqueueNonPersistedPageshowEvent();
+  void EnqueuePageshowEvent(PageTransitionEventPersistence);
   void EnqueueHashchangeEvent(const String& old_url, const String& new_url);
   void EnqueuePopstateEvent(scoped_refptr<SerializedScriptValue>);
   void DispatchWindowLoadEvent();
@@ -309,7 +309,11 @@
 
   TrustedTypePolicyFactory* trustedTypes() const;
 
-  void DispatchPersistedPageshowEvent(base::TimeTicks navigation_start);
+  void DispatchPageshowEvent(PageTransitionEventPersistence persistence) {
+    DispatchEvent(
+        *PageTransitionEvent::Create(event_type_names::kPageshow, persistence),
+        document_.Get());
+  }
 
   void DispatchPagehideEvent(PageTransitionEventPersistence persistence) {
     DispatchEvent(
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 2e89bd6..24ea8a0 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -41,7 +41,6 @@
 #include "third_party/blink/public/common/frame/blocked_navigation_types.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
 #include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
 #include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
 #include "third_party/blink/public/platform/interface_provider.h"
 #include "third_party/blink/public/platform/interface_registry.h"
@@ -1135,30 +1134,11 @@
   return *Client()->GetInterfaceProvider();
 }
 
-void LocalFrame::BindDocumentInterfaceBroker(
-    mojo::ScopedMessagePipeHandle js_handle) {
-  DCHECK(Client());
-  Client()->BindDocumentInterfaceBroker(std::move(js_handle));
-}
-
-mojom::blink::DocumentInterfaceBroker&
-LocalFrame::GetDocumentInterfaceBroker() {
-  DCHECK(Client());
-  return *Client()->GetDocumentInterfaceBroker();
-}
-
 BrowserInterfaceBrokerProxy& LocalFrame::GetBrowserInterfaceBroker() {
   DCHECK(Client());
   return Client()->GetBrowserInterfaceBroker();
 }
 
-mojo::ScopedMessagePipeHandle LocalFrame::SetDocumentInterfaceBrokerForTesting(
-    mojo::ScopedMessagePipeHandle blink_handle) {
-  DCHECK(Client());
-  return Client()->SetDocumentInterfaceBrokerForTesting(
-      std::move(blink_handle));
-}
-
 AssociatedInterfaceProvider*
 LocalFrame::GetRemoteNavigationAssociatedInterfaces() {
   DCHECK(Client());
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 0fdcfa4..a5e3023a 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -40,7 +40,6 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/unique_receiver_set.h"
 #include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
 #include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom-blink-forward.h"
@@ -278,10 +277,6 @@
   bool CanNavigate(const Frame&, const KURL& destination_url = KURL());
 
   service_manager::InterfaceProvider& GetInterfaceProvider();
-  void BindDocumentInterfaceBroker(mojo::ScopedMessagePipeHandle js_handle);
-  mojom::blink::DocumentInterfaceBroker& GetDocumentInterfaceBroker();
-  mojo::ScopedMessagePipeHandle SetDocumentInterfaceBrokerForTesting(
-      mojo::ScopedMessagePipeHandle blink_handle);
 
   BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker();
 
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
index 12937e8..41e8871 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -84,10 +84,6 @@
 namespace blink {
 namespace mojom {
 enum class WebFeature : int32_t;
-
-namespace blink {
-class DocumentInterfaceBroker;
-}  // namespace blink
 }  // namespace mojom
 
 class AssociatedInterfaceProvider;
@@ -372,28 +368,8 @@
     return nullptr;
   }
 
-  // Binds |js_handle| to the currently bound implementation of
-  // DocumentInterfaceBroker to share the same broker between C++ and JavaScript
-  // clients.
-  virtual void BindDocumentInterfaceBroker(
-      mojo::ScopedMessagePipeHandle js_handle) {}
-
-  virtual mojom::blink::DocumentInterfaceBroker* GetDocumentInterfaceBroker() {
-    return nullptr;
-  }
-
   virtual BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() = 0;
 
-  // Used in tests to set a custom override for DocumentInterfaceBroker methods.
-  // |blink_handle| is bound to the test implementation on the caller side.
-  // Returns the handle to the previously bound 'production' implementation,
-  // which will be used to forward the calls to methods that have not been
-  // overridden.
-  virtual mojo::ScopedMessagePipeHandle SetDocumentInterfaceBrokerForTesting(
-      mojo::ScopedMessagePipeHandle blink_handle) {
-    return mojo::ScopedMessagePipeHandle();
-  }
-
   virtual AssociatedInterfaceProvider*
   GetRemoteNavigationAssociatedInterfaces() = 0;
 
diff --git a/third_party/blink/renderer/core/frame/origins_using_features_test.cc b/third_party/blink/renderer/core/frame/origins_using_features_test.cc
deleted file mode 100644
index ce6d1577..0000000
--- a/third_party/blink/renderer/core/frame/origins_using_features_test.cc
+++ /dev/null
@@ -1,28 +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 "third_party/blink/renderer/core/frame/hosts_using_features.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-TEST(HostsUsingFeaturesTest, countName) {
-  HostsUsingFeatures hosts_using_features;
-  hosts_using_features.CountName(HostsUsingFeatures::Feature::kEventPath,
-                                 "test 1");
-  EXPECT_EQ(1u, hosts_using_features.ValueByName().size());
-  hosts_using_features.CountName(HostsUsingFeatures::Feature::kEventPath,
-                                 "test 2");
-  EXPECT_EQ(2u, hosts_using_features.ValueByName().size());
-
-  EXPECT_TRUE(hosts_using_features.ValueByName().at("test 1").Get(
-      HostsUsingFeatures::Feature::kEventPath));
-  EXPECT_TRUE(hosts_using_features.ValueByName().at("test 2").Get(
-      HostsUsingFeatures::Feature::kEventPath));
-
-  hosts_using_features.Clear();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
index edd395d..851f1611 100644
--- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc
+++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -84,11 +84,6 @@
   settings->SetShrinksViewportContentToFit(true);
 }
 
-const cc::ScrollNode* GetScrollNode(const cc::Layer* layer) {
-  return layer->layer_tree_host()->property_trees()->scroll_tree.Node(
-      layer->scroll_tree_index());
-}
-
 const cc::EffectNode* GetEffectNode(const cc::Layer* layer) {
   return layer->layer_tree_host()->property_trees()->effect_tree.Node(
       layer->effect_tree_index());
@@ -837,10 +832,7 @@
   UpdateAllLifecyclePhases();
 
   // Ensure the scroll contents size matches the frame view's size.
-  if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
-    EXPECT_EQ(IntSize(320, 240),
-              IntSize(visual_viewport.LayerForScrolling()->bounds()));
-  }
+  EXPECT_EQ(gfx::Size(320, 240), visual_viewport.LayerForScrolling()->bounds());
   EXPECT_EQ(IntSize(320, 240), visual_viewport.GetScrollNode()->ContentsSize());
 
   // Ensure the location and scale were reset.
@@ -1632,9 +1624,6 @@
 // layer when hideScrollbars WebSetting is true.
 TEST_P(VisualViewportTest,
        TestScrollbarsNotAttachedWhenHideScrollbarsSettingIsTrue) {
-  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
-    return;
-
   InitializeWithAndroidSettings(configureHiddenScrollbarsSettings);
   WebView()->MainFrameWidget()->Resize(IntSize(100, 150));
   NavigateTo("about:blank");
@@ -1648,9 +1637,6 @@
 // layer when hideScrollbars WebSetting is false.
 TEST_P(VisualViewportTest,
        TestScrollbarsAttachedWhenHideScrollbarsSettingIsFalse) {
-  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
-    return;
-
   InitializeWithAndroidSettings();
   WebView()->MainFrameWidget()->Resize(IntSize(100, 150));
   NavigateTo("about:blank");
@@ -1660,12 +1646,9 @@
   EXPECT_TRUE(visual_viewport.LayerForVerticalScrollbar());
 }
 
-// Tests that the layout viewport's scroll layer bounds are updated in a
-// compositing change update. crbug.com/423188.
+// Tests that the layout viewport's scroll node bounds are updated.
+// crbug.com/423188.
 TEST_P(VisualViewportTest, TestChangingContentSizeAffectsScrollBounds) {
-  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
-    return;
-
   InitializeWithAndroidSettings();
   WebView()->MainFrameWidget()->Resize(IntSize(100, 150));
 
@@ -1680,13 +1663,13 @@
                       "content.style.height = \"2400px\";"));
   frame_view.UpdateAllLifecyclePhases(
       DocumentLifecycle::LifecycleUpdateReason::kTest);
-  const auto* scroll_layer = frame_view.LayoutViewport()->LayerForScrolling();
-  const auto* scroll_node = GetScrollNode(scroll_layer);
 
-  EXPECT_EQ(gfx::Size(1500, 2400), scroll_layer->bounds());
-  float scale = scroll_layer->layer_tree_host()->page_scale_factor();
-  EXPECT_EQ(gfx::Size(100 / scale, 150 / scale), scroll_node->container_bounds);
-  EXPECT_EQ(gfx::Size(1500, 2400), scroll_node->bounds);
+  const auto* scroll_node =
+      frame_view.GetLayoutView()->FirstFragment().PaintProperties()->Scroll();
+  float scale = GetFrame()->GetPage()->GetVisualViewport().Scale();
+  EXPECT_EQ(IntSize(100 / scale, 150 / scale),
+            scroll_node->ContainerRect().Size());
+  EXPECT_EQ(IntSize(1500, 2400), scroll_node->ContentsSize());
 }
 
 // Tests that resizing the visual viepwort keeps its bounds within the outer
@@ -2144,14 +2127,14 @@
   UpdateAllLifecyclePhases();
   Document* document =
       To<LocalFrame>(web_view_impl->GetPage()->MainFrame())->GetDocument();
-  GraphicsLayer* backgroundLayer = document->GetLayoutView()
-                                       ->Layer()
-                                       ->GetCompositedLayerMapping()
-                                       ->MainGraphicsLayer();
-  ASSERT_TRUE(backgroundLayer);
+  GraphicsLayer* background_layer = document->GetLayoutView()
+                                        ->Layer()
+                                        ->GetCompositedLayerMapping()
+                                        ->MainGraphicsLayer();
+  ASSERT_TRUE(background_layer);
 
-  ASSERT_EQ(page_width, backgroundLayer->Size().width());
-  ASSERT_EQ(page_height, backgroundLayer->Size().height());
+  ASSERT_EQ(page_width, background_layer->Size().width());
+  ASSERT_EQ(page_height, background_layer->Size().height());
   ASSERT_EQ(page_width, document->View()->GetLayoutSize().Width());
   ASSERT_EQ(smallest_height, document->View()->GetLayoutSize().Height());
 
@@ -2163,15 +2146,15 @@
   ASSERT_EQ(smallest_height, document->View()->GetLayoutSize().Height());
 
   // The background layer's size should have changed though.
-  EXPECT_EQ(page_width, backgroundLayer->Size().width());
-  EXPECT_EQ(smallest_height, backgroundLayer->Size().height());
+  EXPECT_EQ(page_width, background_layer->Size().width());
+  EXPECT_EQ(smallest_height, background_layer->Size().height());
 
   web_view_impl->ResizeWithBrowserControls(WebSize(page_width, page_height),
                                            browser_controls_height, 0, true);
 
   // The background layer's size should change again.
-  EXPECT_EQ(page_width, backgroundLayer->Size().width());
-  EXPECT_EQ(page_height, backgroundLayer->Size().height());
+  EXPECT_EQ(page_width, background_layer->Size().width());
+  EXPECT_EQ(page_height, background_layer->Size().height());
 }
 
 static void ConfigureAndroidNonCompositing(WebSettings* settings) {
@@ -2389,10 +2372,6 @@
 
 // Ensure we create effect node for scrollbar properly.
 TEST_P(VisualViewportTest, EnsureEffectNodeForScrollbars) {
-  // TODO(wangxianzhu): Should this work for CompositeAfterPaint?
-  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
-    return;
-
   InitializeWithAndroidSettings();
   WebView()->MainFrameWidget()->Resize(IntSize(400, 400));
   NavigateTo("about:blank");
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 41107ab..75fecf47 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1598,40 +1598,34 @@
     WebView* web_view,
     WebLocalFrameClient* client,
     InterfaceRegistry* interface_registry,
-    mojo::ScopedMessagePipeHandle document_interface_broker_handle,
     WebFrame* opener,
     const WebString& name,
     WebSandboxFlags sandbox_flags,
     const FeaturePolicy::FeatureState& opener_feature_state) {
   return WebLocalFrameImpl::CreateMainFrame(
-      web_view, client, interface_registry,
-      std::move(document_interface_broker_handle), opener, name, sandbox_flags,
+      web_view, client, interface_registry, opener, name, sandbox_flags,
       opener_feature_state);
 }
 
 WebLocalFrame* WebLocalFrame::CreateProvisional(
     WebLocalFrameClient* client,
     InterfaceRegistry* interface_registry,
-    mojo::ScopedMessagePipeHandle document_interface_broker_handle,
     WebFrame* previous_frame,
     const FramePolicy& frame_policy) {
-  return WebLocalFrameImpl::CreateProvisional(
-      client, interface_registry, std::move(document_interface_broker_handle),
-      previous_frame, frame_policy);
+  return WebLocalFrameImpl::CreateProvisional(client, interface_registry,
+                                              previous_frame, frame_policy);
 }
 
 WebLocalFrameImpl* WebLocalFrameImpl::CreateMainFrame(
     WebView* web_view,
     WebLocalFrameClient* client,
     InterfaceRegistry* interface_registry,
-    mojo::ScopedMessagePipeHandle document_interface_broker_handle,
     WebFrame* opener,
     const WebString& name,
     WebSandboxFlags sandbox_flags,
     const FeaturePolicy::FeatureState& opener_feature_state) {
   WebLocalFrameImpl* frame = MakeGarbageCollected<WebLocalFrameImpl>(
-      WebTreeScopeType::kDocument, client, interface_registry,
-      std::move(document_interface_broker_handle));
+      WebTreeScopeType::kDocument, client, interface_registry);
   frame->SetOpener(opener);
   Page& page = *static_cast<WebViewImpl*>(web_view)->GetPage();
   DCHECK(!page.MainFrame());
@@ -1645,14 +1639,13 @@
 WebLocalFrameImpl* WebLocalFrameImpl::CreateProvisional(
     WebLocalFrameClient* client,
     blink::InterfaceRegistry* interface_registry,
-    mojo::ScopedMessagePipeHandle document_interface_broker_handle,
     WebFrame* previous_web_frame,
     const FramePolicy& frame_policy) {
   DCHECK(client);
   auto* web_frame = MakeGarbageCollected<WebLocalFrameImpl>(
       previous_web_frame->InShadowTree() ? WebTreeScopeType::kShadow
                                          : WebTreeScopeType::kDocument,
-      client, interface_registry, std::move(document_interface_broker_handle));
+      client, interface_registry);
   Frame* previous_frame = ToCoreFrame(*previous_web_frame);
   web_frame->SetParent(previous_web_frame->Parent());
   web_frame->SetOpener(previous_web_frame->Opener());
@@ -1697,11 +1690,9 @@
 WebLocalFrameImpl* WebLocalFrameImpl::CreateLocalChild(
     WebTreeScopeType scope,
     WebLocalFrameClient* client,
-    blink::InterfaceRegistry* interface_registry,
-    mojo::ScopedMessagePipeHandle document_interface_broker_handle) {
+    blink::InterfaceRegistry* interface_registry) {
   WebLocalFrameImpl* frame = MakeGarbageCollected<WebLocalFrameImpl>(
-      scope, client, interface_registry,
-      std::move(document_interface_broker_handle));
+      scope, client, interface_registry);
   AppendChild(frame);
   return frame;
 }
@@ -1709,13 +1700,10 @@
 WebLocalFrameImpl::WebLocalFrameImpl(
     WebTreeScopeType scope,
     WebLocalFrameClient* client,
-    blink::InterfaceRegistry* interface_registry,
-    mojo::ScopedMessagePipeHandle document_interface_broker_handle)
+    blink::InterfaceRegistry* interface_registry)
     : WebNavigationControl(scope),
       client_(client),
-      local_frame_client_(MakeGarbageCollected<LocalFrameClientImpl>(
-          this,
-          std::move(document_interface_broker_handle))),
+      local_frame_client_(MakeGarbageCollected<LocalFrameClientImpl>(this)),
       autofill_client_(nullptr),
       find_in_page_(
           MakeGarbageCollected<FindInPage>(*this, interface_registry)),
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index 7313ce1..ef0067c 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -103,8 +103,7 @@
   // WebLocalFrame overrides:
   WebLocalFrameImpl* CreateLocalChild(WebTreeScopeType,
                                       WebLocalFrameClient*,
-                                      blink::InterfaceRegistry*,
-                                      mojo::ScopedMessagePipeHandle) override;
+                                      blink::InterfaceRegistry*) override;
   WebLocalFrameClient* Client() const override { return client_; }
   void SetAutofillClient(WebAutofillClient*) override;
   WebAutofillClient* AutofillClient() override;
@@ -355,21 +354,18 @@
   static WebLocalFrameImpl* CreateMainFrame(WebView*,
                                             WebLocalFrameClient*,
                                             InterfaceRegistry*,
-                                            mojo::ScopedMessagePipeHandle,
                                             WebFrame* opener,
                                             const WebString& name,
                                             WebSandboxFlags,
                                             const FeaturePolicy::FeatureState&);
   static WebLocalFrameImpl* CreateProvisional(WebLocalFrameClient*,
                                               InterfaceRegistry*,
-                                              mojo::ScopedMessagePipeHandle,
                                               WebFrame*,
                                               const FramePolicy&);
 
   WebLocalFrameImpl(WebTreeScopeType,
                     WebLocalFrameClient*,
-                    blink::InterfaceRegistry*,
-                    mojo::ScopedMessagePipeHandle);
+                    blink::InterfaceRegistry*);
   ~WebLocalFrameImpl() override;
 
   LocalFrame* CreateChildFrame(const AtomicString& name,
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
index 4923001..24c7b599 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
@@ -39,7 +39,10 @@
     CanvasRenderingContextHost* host,
     const CanvasContextCreationAttributesCore& attrs)
     : host_(host),
-      color_params_(kSRGBCanvasColorSpace, kRGBA8CanvasPixelFormat, kNonOpaque),
+      color_params_(kSRGBCanvasColorSpace,
+                    kRGBA8CanvasPixelFormat,
+                    kNonOpaque,
+                    CanvasForceRGBA::kNotForced),
       creation_attributes_(attrs) {
   // Supported color spaces and pixel formats: sRGB in uint8, e-sRGB in f16,
   // linear sRGB and p3 and rec2020 with linear gamma transfer function in f16.
diff --git a/third_party/blink/renderer/core/html/canvas/image_data.cc b/third_party/blink/renderer/core/html/canvas/image_data.cc
index d08940b..8c21a4e 100644
--- a/third_party/blink/renderer/core/html/canvas/image_data.cc
+++ b/third_party/blink/renderer/core/html/canvas/image_data.cc
@@ -746,7 +746,8 @@
   CanvasPixelFormat pixel_format = kRGBA8CanvasPixelFormat;
   if (color_settings_->storageFormat() != kUint8ClampedArrayStorageFormatName)
     pixel_format = kF16CanvasPixelFormat;
-  return CanvasColorParams(color_space, pixel_format, kNonOpaque);
+  return CanvasColorParams(color_space, pixel_format, kNonOpaque,
+                           CanvasForceRGBA::kNotForced);
 }
 
 bool ImageData::ImageDataInCanvasColorSettings(
@@ -760,7 +761,8 @@
     return false;
 
   CanvasColorParams canvas_color_params =
-      CanvasColorParams(canvas_color_space, canvas_pixel_format, kNonOpaque);
+      CanvasColorParams(canvas_color_space, canvas_pixel_format, kNonOpaque,
+                        CanvasForceRGBA::kNotForced);
 
   unsigned char* src_data = static_cast<unsigned char*>(BufferBase()->Data());
 
diff --git a/third_party/blink/renderer/core/html/parser/mathml_tag_names.json5 b/third_party/blink/renderer/core/html/parser/mathml_tag_names.json5
deleted file mode 100644
index 4326dd7..0000000
--- a/third_party/blink/renderer/core/html/parser/mathml_tag_names.json5
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  metadata: {
-    namespace: "MathML",
-    namespaceURI: "http://www.w3.org/1998/Math/MathML",
-  },
-
-  data: [
-    "math",
-    "mi",
-    "mn",
-    "mo",
-    "mtext",
-    "ms",
-    "mglyph",
-    "malignmark",
-    "annotation-xml",
-  ],
-}
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache.cc b/third_party/blink/renderer/core/loader/appcache/application_cache.cc
index 2c65c7d..ec3dd69 100644
--- a/third_party/blink/renderer/core/loader/appcache/application_cache.cc
+++ b/third_party/blink/renderer/core/loader/appcache/application_cache.cc
@@ -155,7 +155,8 @@
     return;
 
   if (document->IsSecureContext()) {
-    UseCounter::Count(document, WebFeature::kApplicationCacheAPISecureOrigin);
+    Deprecation::CountDeprecation(document,
+                                  WebFeature::kApplicationCacheAPISecureOrigin);
   } else {
     Deprecation::CountDeprecation(
         document, WebFeature::kApplicationCacheAPIInsecureOrigin);
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc b/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc
index ef36211..7309680 100644
--- a/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc
+++ b/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc
@@ -210,13 +210,11 @@
     return;
   }
   if (document->IsSecureContext()) {
-    UseCounter::Count(document,
-                      WebFeature::kApplicationCacheManifestSelectSecureOrigin);
+    Deprecation::CountDeprecation(
+        document, WebFeature::kApplicationCacheManifestSelectSecureOrigin);
   } else {
     Deprecation::CountDeprecation(
         document, WebFeature::kApplicationCacheManifestSelectInsecureOrigin);
-    Deprecation::CountDeprecationCrossOriginIframe(
-        *document, WebFeature::kApplicationCacheManifestSelectInsecureOrigin);
     HostsUsingFeatures::CountAnyWorld(
         *document, HostsUsingFeatures::Feature::
                        kApplicationCacheManifestSelectInsecureHost);
diff --git a/third_party/blink/renderer/core/loader/empty_clients.cc b/third_party/blink/renderer/core/loader/empty_clients.cc
index 2cc6662..cf9c781 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.cc
+++ b/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -120,26 +120,6 @@
                                               std::move(navigation_params));
 }
 
-mojom::blink::DocumentInterfaceBroker*
-EmptyLocalFrameClient::GetDocumentInterfaceBroker() {
-  if (!document_interface_broker_.is_bound())
-    ignore_result(document_interface_broker_.BindNewPipeAndPassReceiver());
-  return document_interface_broker_.get();
-}
-
-mojo::ScopedMessagePipeHandle
-EmptyLocalFrameClient::SetDocumentInterfaceBrokerForTesting(
-    mojo::ScopedMessagePipeHandle blink_handle) {
-  mojo::PendingRemote<mojom::blink::DocumentInterfaceBroker> test_broker(
-      std::move(blink_handle), mojom::blink::DocumentInterfaceBroker::Version_);
-
-  mojo::ScopedMessagePipeHandle real_handle =
-      document_interface_broker_.Unbind().PassPipe();
-  document_interface_broker_.Bind(std::move(test_broker));
-
-  return real_handle;
-}
-
 LocalFrame* EmptyLocalFrameClient::CreateFrame(const AtomicString&,
                                                HTMLFrameOwnerElement*) {
   return nullptr;
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index 583983c..2d0434f 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -37,7 +37,6 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_focus_type.h"
 #include "third_party/blink/public/platform/web_menu_source_type.h"
@@ -382,10 +381,6 @@
     return &interface_provider_;
   }
 
-  mojom::blink::DocumentInterfaceBroker* GetDocumentInterfaceBroker() override;
-  mojo::ScopedMessagePipeHandle SetDocumentInterfaceBrokerForTesting(
-      mojo::ScopedMessagePipeHandle blink_handle) override;
-
   BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() override {
     return GetEmptyBrowserInterfaceBroker();
   }
@@ -435,8 +430,6 @@
   WebTextCheckClient* text_check_client_;
 
   service_manager::InterfaceProvider interface_provider_;
-  mojo::Remote<mojom::blink::DocumentInterfaceBroker>
-      document_interface_broker_;
 
   DISALLOW_COPY_AND_ASSIGN(EmptyLocalFrameClient);
 };
diff --git a/third_party/blink/renderer/core/mathml/BUILD.gn b/third_party/blink/renderer/core/mathml/BUILD.gn
new file mode 100644
index 0000000..be46256d
--- /dev/null
+++ b/third_party/blink/renderer/core/mathml/BUILD.gn
@@ -0,0 +1,12 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/core/core.gni")
+
+blink_core_sources("mathml") {
+  sources = [
+    "mathml_element.cc",
+    "mathml_element.h",
+  ]
+}
diff --git a/third_party/blink/renderer/core/html/parser/mathml_attribute_names.json5 b/third_party/blink/renderer/core/mathml/mathml_attribute_names.json5
similarity index 87%
rename from third_party/blink/renderer/core/html/parser/mathml_attribute_names.json5
rename to third_party/blink/renderer/core/mathml/mathml_attribute_names.json5
index 464ce18..a50a993 100644
--- a/third_party/blink/renderer/core/html/parser/mathml_attribute_names.json5
+++ b/third_party/blink/renderer/core/mathml/mathml_attribute_names.json5
@@ -3,6 +3,7 @@
     namespace: "MathML",
     namespaceURI: "http://www.w3.org/1998/Math/MathML",
     attrsNullNamespace: true,
+    export: "CORE_EXPORT",
   },
 
   data: [
diff --git a/third_party/blink/renderer/core/mathml/mathml_element.cc b/third_party/blink/renderer/core/mathml/mathml_element.cc
new file mode 100644
index 0000000..b7fe430
--- /dev/null
+++ b/third_party/blink/renderer/core/mathml/mathml_element.cc
@@ -0,0 +1,16 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/mathml/mathml_element.h"
+
+namespace blink {
+
+MathMLElement::MathMLElement(const QualifiedName& tagName,
+                             Document& document,
+                             ConstructionType constructionType)
+    : Element(tagName, &document, constructionType) {}
+
+MathMLElement::~MathMLElement() {}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/mathml/mathml_element.h b/third_party/blink/renderer/core/mathml/mathml_element.h
new file mode 100644
index 0000000..d3d0eb23
--- /dev/null
+++ b/third_party/blink/renderer/core/mathml/mathml_element.h
@@ -0,0 +1,78 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_ELEMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_ELEMENT_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/mathml_names.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+
+namespace blink {
+
+class CORE_EXPORT MathMLElement : public Element {
+ public:
+  MathMLElement(const QualifiedName& tagName,
+                Document& document,
+                ConstructionType constructionType = kCreateMathMLElement);
+  ~MathMLElement() override;
+
+  bool HasTagName(const MathMLQualifiedName& name) const {
+    return HasLocalName(name.LocalName());
+  }
+
+ private:
+  bool IsMathMLElement() const =
+      delete;  // This will catch anyone doing an unnecessary check.
+};
+
+DEFINE_ELEMENT_TYPE_CASTS(MathMLElement, IsMathMLElement());
+
+template <>
+struct DowncastTraits<MathMLElement> {
+  static bool AllowFrom(const Node& node) { return node.IsMathMLElement(); }
+};
+
+template <typename T>
+bool IsElementOfType(const MathMLElement&);
+template <>
+inline bool IsElementOfType<const MathMLElement>(const MathMLElement&) {
+  return true;
+}
+
+inline bool Node::HasTagName(const MathMLQualifiedName& name) const {
+  auto* mathml_element = DynamicTo<MathMLElement>(this);
+  return mathml_element && mathml_element->HasTagName(name);
+}
+
+// This requires IsMathML*Element(const MathMLElement&).
+#define DEFINE_MATHMLELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType)               \
+  inline bool Is##thisType(const thisType* element);                          \
+  inline bool Is##thisType(const thisType& element);                          \
+  inline bool Is##thisType(const MathMLElement* element) {                    \
+    return element && Is##thisType(*element);                                 \
+  }                                                                           \
+  inline bool Is##thisType(const Node& node) {                                \
+    auto* mathml_element = DynamicTo<MathMLElement>(node);                    \
+    return mathml_element && Is##thisType(mathml_element);                    \
+  }                                                                           \
+  inline bool Is##thisType(const Node* node) {                                \
+    return node && Is##thisType(*node);                                       \
+  }                                                                           \
+  template <typename T>                                                       \
+  inline bool Is##thisType(const Member<T>& node) {                           \
+    return Is##thisType(node.Get());                                          \
+  }                                                                           \
+  template <>                                                                 \
+  inline bool IsElementOfType<const thisType>(const MathMLElement& element) { \
+    return Is##thisType(element);                                             \
+  }                                                                           \
+  DEFINE_ELEMENT_TYPE_CASTS_WITH_FUNCTION(thisType)
+
+}  // namespace blink
+
+#include "third_party/blink/renderer/core/mathml_element_type_helpers.h"
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_MATHML_MATHML_ELEMENT_H_
diff --git a/third_party/blink/renderer/core/mathml/mathml_tag_names.json5 b/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
new file mode 100644
index 0000000..020c736
--- /dev/null
+++ b/third_party/blink/renderer/core/mathml/mathml_tag_names.json5
@@ -0,0 +1,55 @@
+{
+  metadata: {
+    namespace: "MathML",
+    namespaceURI: "http://www.w3.org/1998/Math/MathML",
+    fallbackInterfaceName: "MathMLElement",
+    fallbackJSInterfaceName: "Element",
+    export: "CORE_EXPORT",
+  },
+  data: [
+    {
+      name: "math",
+      interfaceName: "MathMLElement",
+    },
+    {
+      name: "mi",
+      interfaceName: "MathMLElement",
+    },
+    {
+      name: "mn",
+      interfaceName: "MathMLElement",
+    },
+    {
+      name: "mo",
+      interfaceName: "MathMLElement",
+    },
+    {
+      name: "mtext",
+      interfaceName: "MathMLElement",
+    },
+    {
+      name: "ms",
+      interfaceName: "MathMLElement",
+    },
+    {
+      name: "mglyph",
+      interfaceName: "MathMLElement",
+    },
+    {
+      name: "malignmark",
+      interfaceName: "MathMLElement",
+    },
+    {
+      name: "annotation",
+      interfaceName: "MathMLElement",
+    },
+    {
+      name: "annotation-xml",
+      interfaceName: "MathMLElement",
+    },
+    {
+      name: "semantics",
+      interfaceName: "MathMLElement",
+    },
+  ]
+}
diff --git a/third_party/blink/renderer/core/mojo/mojo.cc b/third_party/blink/renderer/core/mojo/mojo.cc
index 6a22d23..aab3fa5c 100644
--- a/third_party/blink/renderer/core/mojo/mojo.cc
+++ b/third_party/blink/renderer/core/mojo/mojo.cc
@@ -9,7 +9,6 @@
 
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h"
 #include "third_party/blink/public/platform/interface_provider.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/core/dom/document.h"
@@ -128,32 +127,4 @@
   }
 }
 
-// static
-MojoHandle* Mojo::getDocumentInterfaceBrokerHandle(ScriptState* script_state) {
-  ExecutionContext* execution_context = ExecutionContext::From(script_state);
-  DCHECK(execution_context);
-  Document* document = static_cast<Document*>(execution_context);
-  DCHECK(document);
-
-  mojo::MessagePipe pipe;
-  document->BindDocumentInterfaceBroker(std::move(pipe.handle0));
-  return MakeGarbageCollected<MojoHandle>(
-      mojo::ScopedHandle::From(std::move(pipe.handle1)));
-}
-
-// static
-MojoHandle* Mojo::replaceDocumentInterfaceBrokerForTesting(
-    ScriptState* script_state,
-    MojoHandle* test_broker_handle) {
-  ExecutionContext* execution_context = ExecutionContext::From(script_state);
-  DCHECK(execution_context);
-  Document* document = static_cast<Document*>(execution_context);
-  DCHECK(document);
-
-  return MakeGarbageCollected<MojoHandle>(
-      mojo::ScopedHandle::From(document->SetDocumentInterfaceBrokerForTesting(
-          mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(
-              test_broker_handle->TakeHandle().release().value())))));
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/mojo/mojo.h b/third_party/blink/renderer/core/mojo/mojo.h
index 4fe5d108..b0e8b78 100644
--- a/third_party/blink/renderer/core/mojo/mojo.h
+++ b/third_party/blink/renderer/core/mojo/mojo.h
@@ -56,9 +56,6 @@
                             MojoHandle*,
                             const String& scope,
                             bool use_browser_interface_broker);
-  static MojoHandle* getDocumentInterfaceBrokerHandle(ScriptState*);
-  static MojoHandle* replaceDocumentInterfaceBrokerForTesting(ScriptState*,
-                                                              MojoHandle*);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/mojo/mojo.idl b/third_party/blink/renderer/core/mojo/mojo.idl
index 7bcfb127d..9bfcfc6 100644
--- a/third_party/blink/renderer/core/mojo/mojo.idl
+++ b/third_party/blink/renderer/core/mojo/mojo.idl
@@ -47,6 +47,4 @@
     static MojoCreateSharedBufferResult createSharedBuffer(unsigned long numBytes);
 
     [CallWith=ScriptState] static void bindInterface(DOMString interfaceName, MojoHandle request_handle, optional MojoScope scope = "context", optional boolean useBrowserInterfaceBroker = false);
-    [CallWith=ScriptState] static MojoHandle getDocumentInterfaceBrokerHandle();
-    [CallWith=ScriptState] static MojoHandle replaceDocumentInterfaceBrokerForTesting(MojoHandle test_broker_handle);
 };
diff --git a/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.cc b/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.cc
deleted file mode 100644
index 9a00ab9..0000000
--- a/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h"
-
-#include <utility>
-
-namespace blink {
-
-void FrameHostTestInterfaceImpl::BindAndFlush(
-    mojo::PendingReceiver<mojom::blink::FrameHostTestInterface> receiver) {
-  receiver_.Bind(std::move(receiver));
-  receiver_.WaitForIncomingCall();
-}
-
-void FrameHostTestInterfaceImpl::GetName(GetNameCallback callback) {
-  std::move(callback).Run(kGetNameTestResponse);
-}
-
-void FrameHostTestDocumentInterfaceBroker::GetFrameHostTestInterface(
-    mojo::PendingReceiver<mojom::blink::FrameHostTestInterface> receiver) {
-  FrameHostTestInterfaceImpl impl;
-  impl.BindAndFlush(std::move(receiver));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h b/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h
deleted file mode 100644
index f00a018a..0000000
--- a/third_party/blink/renderer/core/testing/document_interface_broker_test_helpers.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_DOCUMENT_INTERFACE_BROKER_TEST_HELPERS_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_DOCUMENT_INTERFACE_BROKER_TEST_HELPERS_H_
-
-#include <utility>
-
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/frame/frame_host_test_interface.mojom-blink.h"
-#include "third_party/blink/renderer/core/testing/test_document_interface_broker.h"
-
-namespace blink {
-
-constexpr char kGetNameTestResponse[] = "BlinkTestName";
-
-// These classes can be used for verifying that overriding mechanism for
-// DocumentInterfaceBroker method calls works as expected with LocalFrameClient
-// implementations. See frame_test.cc and local_frame_client_impl.cc for
-// examples.
-class FrameHostTestInterfaceImpl : public mojom::blink::FrameHostTestInterface {
- public:
-  FrameHostTestInterfaceImpl() = default;
-  ~FrameHostTestInterfaceImpl() override {}
-
-  void BindAndFlush(
-      mojo::PendingReceiver<mojom::blink::FrameHostTestInterface> receiver);
-
- protected:
-  void Ping(const KURL& url, const WTF::String& event) override {}
-  void GetName(GetNameCallback callback) override;
-
- private:
-  mojo::Receiver<mojom::blink::FrameHostTestInterface> receiver_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(FrameHostTestInterfaceImpl);
-};
-
-class FrameHostTestDocumentInterfaceBroker
-    : public TestDocumentInterfaceBroker {
- public:
-  FrameHostTestDocumentInterfaceBroker(
-      mojom::blink::DocumentInterfaceBroker* document_interface_broker,
-      mojo::PendingReceiver<mojom::blink::DocumentInterfaceBroker> receiver)
-      : TestDocumentInterfaceBroker(document_interface_broker,
-                                    std::move(receiver)) {}
-
-  void GetFrameHostTestInterface(
-      mojo::PendingReceiver<mojom::blink::FrameHostTestInterface> receiver)
-      override;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_DOCUMENT_INTERFACE_BROKER_TEST_HELPERS_H_
diff --git a/third_party/blink/renderer/core/testing/test_document_interface_broker.cc b/third_party/blink/renderer/core/testing/test_document_interface_broker.cc
deleted file mode 100644
index 9ad8a94..0000000
--- a/third_party/blink/renderer/core/testing/test_document_interface_broker.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/testing/test_document_interface_broker.h"
-
-#include <utility>
-
-namespace blink {
-
-TestDocumentInterfaceBroker::TestDocumentInterfaceBroker(
-    mojom::blink::DocumentInterfaceBroker* document_interface_broker,
-    mojo::PendingReceiver<mojom::blink::DocumentInterfaceBroker> receiver)
-    : real_broker_(document_interface_broker),
-      receiver_(this, std::move(receiver)) {}
-
-TestDocumentInterfaceBroker::~TestDocumentInterfaceBroker() {}
-
-mojom::blink::DocumentInterfaceBroker*
-TestDocumentInterfaceBroker::GetForwardingInterface() {
-  return real_broker_;
-}
-
-void TestDocumentInterfaceBroker::Flush() {
-  receiver_.FlushForTesting();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/testing/test_document_interface_broker.h b/third_party/blink/renderer/core/testing/test_document_interface_broker.h
deleted file mode 100644
index 5786f31..0000000
--- a/third_party/blink/renderer/core/testing/test_document_interface_broker.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_TEST_DOCUMENT_INTERFACE_BROKER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_TEST_DOCUMENT_INTERFACE_BROKER_H_
-
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink-test-utils.h"
-
-namespace blink {
-
-// This class can be subclassed to override specific methods of
-// LocalFrameClient's DocumentInterfaceBroker in tests. The rest of the calls
-// will be forwarded to the implementation passed to the constructor (typically
-// returned by LocalFrameClient::GetDocumentInterfaceBroker()).
-class TestDocumentInterfaceBroker
-    : public mojom::blink::DocumentInterfaceBrokerInterceptorForTesting {
- public:
-  TestDocumentInterfaceBroker(
-      mojom::blink::DocumentInterfaceBroker* document_interface_broker,
-      mojo::PendingReceiver<mojom::blink::DocumentInterfaceBroker> receiver);
-  ~TestDocumentInterfaceBroker() override;
-  mojom::blink::DocumentInterfaceBroker* GetForwardingInterface() override;
-  void Flush();
-
- private:
-  mojom::blink::DocumentInterfaceBroker* real_broker_;
-  mojo::Receiver<mojom::blink::DocumentInterfaceBroker> receiver_;
-};
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_TEST_DOCUMENT_INTERFACE_BROKER_H_
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
index 69e5632..b16a090 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -1738,7 +1738,8 @@
   // additional swizzling is needed.
   CanvasColorParams data_color_params = data->GetCanvasColorParams();
   CanvasColorParams context_color_params =
-      CanvasColorParams(ColorParams().ColorSpace(), PixelFormat(), kNonOpaque);
+      CanvasColorParams(ColorParams().ColorSpace(), PixelFormat(), kNonOpaque,
+                        CanvasForceRGBA::kNotForced);
   if (data_color_params.NeedsColorConversion(context_color_params) ||
       PixelFormat() == kF16CanvasPixelFormat) {
     size_t data_length;
diff --git a/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc b/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
index ba24867c..5bbdf2e 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
@@ -62,9 +62,6 @@
   UseCounter::Count(GetDocument(), WebFeature::kDeviceMotionSecureOrigin);
 
   if (!has_event_listener_) {
-    Platform::Current()->RecordRapporURL("DeviceSensors.DeviceMotion",
-                                         WebURL(GetDocument().Url()));
-
     if (!IsSameSecurityOriginAsMainFrame()) {
       Platform::Current()->RecordRapporURL(
           "DeviceSensors.DeviceMotionCrossOrigin", WebURL(GetDocument().Url()));
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
index e5824342..876aacbf 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
@@ -72,9 +72,6 @@
   UseCounter::Count(GetDocument(), WebFeature::kDeviceOrientationSecureOrigin);
 
   if (!has_event_listener_) {
-    Platform::Current()->RecordRapporURL("DeviceSensors.DeviceOrientation",
-                                         WebURL(GetDocument().Url()));
-
     if (!IsSameSecurityOriginAsMainFrame()) {
       Platform::Current()->RecordRapporURL(
           "DeviceSensors.DeviceOrientationCrossOrigin",
diff --git a/third_party/blink/renderer/modules/xr/xr_input_source.cc b/third_party/blink/renderer/modules/xr/xr_input_source.cc
index a10b98b..af14ac9 100644
--- a/third_party/blink/renderer/modules/xr/xr_input_source.cc
+++ b/third_party/blink/renderer/modules/xr/xr_input_source.cc
@@ -5,7 +5,6 @@
 #include "third_party/blink/renderer/modules/xr/xr_input_source.h"
 
 #include "base/time/time.h"
-#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/xr/xr.h"
 #include "third_party/blink/renderer/modules/xr/xr_grip_space.h"
@@ -235,7 +234,7 @@
   event->frame()->Deactivate();
 }
 
-void XRInputSource::OnSelectEnd(UserActivation user_activation) {
+void XRInputSource::OnSelectEnd() {
   // Discard duplicate events and ones after the session has ended.
   if (!state_.primary_input_pressed || session_->ended())
     return;
@@ -246,11 +245,6 @@
   if (!frame)
     return;
 
-  std::unique_ptr<UserGestureIndicator> gesture_indicator =
-      user_activation == UserActivation::kEnabled
-          ? LocalFrame::NotifyUserActivation(frame)
-          : nullptr;
-
   XRInputSourceEvent* event =
       CreateInputSourceEvent(event_type_names::kSelectend);
   session_->DispatchEvent(*event);
@@ -270,16 +264,14 @@
     OnSelectStart();
   }
 
+  LocalFrame* frame = session_->xr()->GetFrame();
+  LocalFrame::NotifyUserActivation(frame);
+
   // If SelectStart caused the session to end, we shouldn't try to fire the
   // select event.
   if (!state_.selection_cancelled && !session_->ended()) {
-    LocalFrame* frame = session_->xr()->GetFrame();
     if (!frame)
       return;
-
-    std::unique_ptr<UserGestureIndicator> gesture_indicator =
-        LocalFrame::NotifyUserActivation(frame);
-
     XRInputSourceEvent* event =
         CreateInputSourceEvent(event_type_names::kSelect);
     session_->DispatchEvent(*event);
@@ -288,7 +280,7 @@
     event->frame()->Deactivate();
   }
 
-  OnSelectEnd(UserActivation::kEnabled);
+  OnSelectEnd();
 }
 
 void XRInputSource::UpdateSelectState(
@@ -308,7 +300,7 @@
     // treat this as a cancelled selection, firing the selectend event so the
     // page stays in sync with the controller state but won't fire the
     // usual select event.
-    OnSelectEnd(UserActivation::kDisabled);
+    OnSelectEnd();
   }
 }
 
diff --git a/third_party/blink/renderer/modules/xr/xr_input_source.h b/third_party/blink/renderer/modules/xr/xr_input_source.h
index 492043d..c99dca2 100644
--- a/third_party/blink/renderer/modules/xr/xr_input_source.h
+++ b/third_party/blink/renderer/modules/xr/xr_input_source.h
@@ -31,8 +31,6 @@
   USING_GARBAGE_COLLECTED_MIXIN(XRInputSource);
 
  public:
-  enum class UserActivation { kEnabled, kDisabled };
-
   static XRInputSource* CreateOrUpdateFrom(
       XRInputSource* other /* may be null, input */,
       XRSession* session,
@@ -85,7 +83,7 @@
   base::Optional<XRNativeOriginInformation> nativeOrigin() const;
 
   void OnSelectStart();
-  void OnSelectEnd(UserActivation user_activation);
+  void OnSelectEnd();
   void OnSelect();
   void UpdateSelectState(
       const device::mojom::blink::XRInputSourceStatePtr& state);
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 798f747..f25b577 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1662,7 +1662,7 @@
   ]
 
   # fuzzed_data_provider may not work with a custom toolchain.
-  if (custom_toolchain == "") {
+  if (custom_toolchain == "" && is_clang) {
     sources += [
       "testing/fuzzed_data_provider.cc",
       "testing/fuzzed_data_provider.h",
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
index aa146496..3965f28 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -1047,7 +1047,8 @@
 
 TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) {
   auto color_params =
-      CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque);
+      CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque,
+                        CanvasForceRGBA::kNotForced);
 
   std::unique_ptr<Canvas2DLayerBridge> bridge =
       MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
@@ -1071,8 +1072,9 @@
 }
 
 TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUseWithColorConversion) {
-  auto color_params = CanvasColorParams(kSRGBCanvasColorSpace,
-                                        kRGBA8CanvasPixelFormat, kOpaque);
+  auto color_params =
+      CanvasColorParams(kSRGBCanvasColorSpace, kRGBA8CanvasPixelFormat, kOpaque,
+                        CanvasForceRGBA::kNotForced);
   std::unique_ptr<Canvas2DLayerBridge> bridge =
       MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
                  color_params);
@@ -1095,7 +1097,8 @@
 
 TEST_F(Canvas2DLayerBridgeTest, ImagesLockedUntilCacheLimit) {
   auto color_params =
-      CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque);
+      CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque,
+                        CanvasForceRGBA::kNotForced);
   std::unique_ptr<Canvas2DLayerBridge> bridge =
       MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
                  color_params, true);
@@ -1129,7 +1132,8 @@
 
 TEST_F(Canvas2DLayerBridgeTest, QueuesCleanupTaskForLockedImages) {
   auto color_params =
-      CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque);
+      CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque,
+                        CanvasForceRGBA::kNotForced);
   std::unique_ptr<Canvas2DLayerBridge> bridge =
       MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
                  color_params, true);
@@ -1147,7 +1151,8 @@
 
 TEST_F(Canvas2DLayerBridgeTest, ImageCacheOnContextLost) {
   auto color_params =
-      CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque);
+      CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque,
+                        CanvasForceRGBA::kNotForced);
   std::unique_ptr<Canvas2DLayerBridge> bridge =
       MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
                  color_params, true);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
index 1aedba2..f136d65 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
@@ -40,16 +40,11 @@
 
 CanvasColorParams::CanvasColorParams(CanvasColorSpace color_space,
                                      CanvasPixelFormat pixel_format,
-                                     OpacityMode opacity_mode)
+                                     OpacityMode opacity_mode,
+                                     CanvasForceRGBA force_rgba)
     : color_space_(color_space),
       pixel_format_(pixel_format),
-      opacity_mode_(opacity_mode) {}
-
-CanvasColorParams::CanvasColorParams(const CanvasColorParams& params,
-                                     bool force_rgba)
-    : color_space_(params.color_space_),
-      pixel_format_(params.pixel_format_),
-      opacity_mode_(params.opacity_mode_),
+      opacity_mode_(opacity_mode),
       force_rgba_(force_rgba) {}
 
 CanvasColorParams::CanvasColorParams(const SkImageInfo& info)
@@ -70,7 +65,8 @@
 SkColorType CanvasColorParams::GetSkColorType() const {
   if (pixel_format_ == kF16CanvasPixelFormat)
     return kRGBA_F16_SkColorType;
-  return force_rgba_ ? kRGBA_8888_SkColorType : kN32_SkColorType;
+  return force_rgba_ == CanvasForceRGBA::kForced ? kRGBA_8888_SkColorType
+                                                 : kN32_SkColorType;
 }
 
 SkAlphaType CanvasColorParams::GetSkAlphaType() const {
@@ -243,7 +239,7 @@
   if (color_type == kRGBA_F16_SkColorType)
     pixel_format_ = kF16CanvasPixelFormat;
   else if (color_type == kRGBA_8888_SkColorType)
-    force_rgba_ = true;
+    force_rgba_ = CanvasForceRGBA::kForced;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_color_params.h b/third_party/blink/renderer/platform/graphics/canvas_color_params.h
index 11a140f..22a36162 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_color_params.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_color_params.h
@@ -37,19 +37,25 @@
   kF16CanvasPixelFormat,
 };
 
+// todo(crbug/1021986) remove force_rgba in canvasColorParams
+enum class CanvasForceRGBA { kForced, kNotForced };
+
 class PLATFORM_EXPORT CanvasColorParams {
   DISALLOW_NEW();
 
  public:
   // The default constructor will create an output-blended 8-bit surface.
   CanvasColorParams();
-  CanvasColorParams(CanvasColorSpace, CanvasPixelFormat, OpacityMode);
-  CanvasColorParams(const CanvasColorParams& params, bool force_rgba);
+  CanvasColorParams(CanvasColorSpace,
+                    CanvasPixelFormat,
+                    OpacityMode,
+                    CanvasForceRGBA);
   explicit CanvasColorParams(const SkImageInfo&);
 
   CanvasColorSpace ColorSpace() const { return color_space_; }
   CanvasPixelFormat PixelFormat() const { return pixel_format_; }
   OpacityMode GetOpacityMode() const { return opacity_mode_; }
+  CanvasForceRGBA GetForceRGBA() const { return force_rgba_; }
 
   void SetCanvasColorSpace(CanvasColorSpace c) { color_space_ = c; }
   void SetCanvasPixelFormat(CanvasPixelFormat f) { pixel_format_ = f; }
@@ -95,7 +101,7 @@
   CanvasColorSpace color_space_ = kSRGBCanvasColorSpace;
   CanvasPixelFormat pixel_format_ = kRGBA8CanvasPixelFormat;
   OpacityMode opacity_mode_ = kNonOpaque;
-  bool force_rgba_ = false;
+  CanvasForceRGBA force_rgba_ = CanvasForceRGBA::kNotForced;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_color_params_test.cc b/third_party/blink/renderer/platform/graphics/canvas_color_params_test.cc
index 2b3d5ac..164e49d 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_color_params_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_color_params_test.cc
@@ -25,7 +25,8 @@
   };
   for (int iter_color_space = 0; iter_color_space < 4; iter_color_space++) {
     CanvasColorParams color_params(canvas_color_spaces[iter_color_space],
-                                   kF16CanvasPixelFormat, kNonOpaque);
+                                   kF16CanvasPixelFormat, kNonOpaque,
+                                   CanvasForceRGBA::kNotForced);
     sk_sp<SkColorSpace> canvas_drawing_color_space =
         color_params.GetSkColorSpace();
     sk_sp<SkColorSpace> canvas_media_color_space =
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index e5f7122..2f5d4eb 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -144,7 +144,11 @@
             filter_quality,
             // TODO(khushalsagar): The software path seems to be assuming N32
             // somewhere in the later pipeline but for offscreen canvas only.
-            CanvasColorParams(color_params, is_accelerated /* force_rgba */),
+            CanvasColorParams(color_params.ColorSpace(),
+                              color_params.PixelFormat(),
+                              color_params.GetOpacityMode(),
+                              is_accelerated ? CanvasForceRGBA::kForced
+                                             : CanvasForceRGBA::kNotForced),
             is_origin_top_left,
             std::move(context_provider_wrapper),
             std::move(resource_dispatcher)),
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
index 1f0eb8f..4a55245 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider_test.cc
@@ -90,7 +90,8 @@
 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderAcceleratedOverlay) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
   EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
   EnsureOverlaysSupported();
 
@@ -120,7 +121,8 @@
 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderTexture) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
 
   auto provider = CanvasResourceProvider::Create(
       kSize, CanvasResourceProvider::ResourceUsage::kAcceleratedResourceUsage,
@@ -145,7 +147,8 @@
 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderUnacceleratedOverlay) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
   EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
   EnsureOverlaysSupported();
 
@@ -175,7 +178,8 @@
        CanvasResourceProviderSharedImageResourceRecycling) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
   EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
 
   auto provider = CanvasResourceProvider::Create(
@@ -229,7 +233,8 @@
        CanvasResourceProviderSharedImageStaticBitmapImage) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
   EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
 
   auto provider = CanvasResourceProvider::Create(
@@ -273,7 +278,8 @@
 
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
   EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
 
   auto provider = CanvasResourceProvider::Create(
@@ -296,7 +302,8 @@
 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderBitmap) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
 
   auto provider = CanvasResourceProvider::Create(
       kSize, CanvasResourceProvider::ResourceUsage::kSoftwareResourceUsage,
@@ -321,7 +328,8 @@
 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderSharedBitmap) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
 
   MockCanvasResourceDispatcherClient client;
   CanvasResourceDispatcher resource_dispatcher(
@@ -355,7 +363,8 @@
        CanvasResourceProviderDirect2DGpuMemoryBuffer) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
   EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
   EnsureOverlaysSupported();
 
@@ -386,7 +395,8 @@
        CanvasResourceProviderDirect3DGpuMemoryBuffer) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
   EnsureBufferFormatIsSupported(kColorParams.GetBufferFormat());
 
   auto provider = CanvasResourceProvider::Create(
@@ -432,7 +442,8 @@
 TEST_F(CanvasResourceProviderTest, CanvasResourceProviderDirect3D) {
   const IntSize kSize(10, 10);
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
 
   auto provider = CanvasResourceProvider::Create(
       kSize,
@@ -468,7 +479,8 @@
 
 TEST_F(CanvasResourceProviderTest, DimensionsExceedMaxTextureSize) {
   const CanvasColorParams kColorParams(kSRGBCanvasColorSpace,
-                                       kRGBA8CanvasPixelFormat, kNonOpaque);
+                                       kRGBA8CanvasPixelFormat, kNonOpaque,
+                                       CanvasForceRGBA::kNotForced);
   const int max_texture_size = context_provider_wrapper_->ContextProvider()
                                    ->GetCapabilities()
                                    .max_texture_size;
diff --git a/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc b/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
index 482341c5..8ff1e3a3 100644
--- a/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
+++ b/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
@@ -221,13 +221,14 @@
                         (src_storage_format == kUint8ClampedArrayStorageFormat)
                             ? kRGBA8CanvasPixelFormat
                             : kF16CanvasPixelFormat,
-                        kNonOpaque)
+                        kNonOpaque, CanvasForceRGBA::kNotForced)
           .GetSkColorSpaceForSkSurfaces();
   if (!src_sk_color_space.get())
     src_sk_color_space = SkColorSpace::MakeSRGB();
 
   sk_sp<SkColorSpace> dst_sk_color_space =
-      CanvasColorParams(dst_color_space, dst_canvas_pixel_format, kNonOpaque)
+      CanvasColorParams(dst_color_space, dst_canvas_pixel_format, kNonOpaque,
+                        CanvasForceRGBA::kNotForced)
           .GetSkColorSpaceForSkSurfaces();
   if (!dst_sk_color_space.get())
     dst_sk_color_space = SkColorSpace::MakeSRGB();
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index fbba60c4..8d7a5004 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -926,6 +926,9 @@
       status:"experimental",
     },
     {
+      name: "MathMLCore",
+    },
+    {
       name:"MeasureMemory",
       status:"experimental",
     },
diff --git a/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item b/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item
index 6b848790..5747369 100644
--- a/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item
+++ b/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item
@@ -4038,7 +4038,6 @@
 Bug(none) virtual/composite-after-paint/paint/background/background-clip-text-inline.html [ Failure ]
 crbug.com/980290 virtual/composite-after-paint/scrollingcoordinator/non-fast-scrollable-visibility-change.html [ Crash ]
 crbug.com/982194 virtual/compositor_threaded_scrollbar_scrolling/fast/scrolling/scrollbars/scrollbar-occluded-by-div.html [ Crash Pass ]
-crbug.com/982194 virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/scrollbar-occluded-by-div.html [ Crash Pass ]
 
 crbug.com/982194 animations/state-at-end-event.html [ Crash ]
 crbug.com/982194 animations/timing/keyframe-timing-functions.html [ Crash ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index f798d55..654c607a 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -98,8 +98,6 @@
 [ Mac ]   fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Skip ]
 [ Linux ] virtual/compositor_threaded_scrollbar_scrolling/fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Skip ]
 [ Mac ]   virtual/compositor_threaded_scrollbar_scrolling/fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Skip ]
-[ Linux ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Skip ]
-[ Mac ]   virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Skip ]
 [ Linux ] virtual/scroll_customization/fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Skip ]
 [ Mac ]   virtual/scroll_customization/fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Skip ]
 [ Linux ] virtual/threaded-prefer-compositing/fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index c510446..dc41f73 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2462,11 +2462,6 @@
 crbug.com/953847 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling/fast/scrolling/scrollbars/scroll-chaining-for-gesture-based-scrolling.html [ Failure ]
 crbug.com/953847 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling/fast/scrolling/scrollbars/scrollbar-occluded-by-div.html [ Failure ]
 crbug.com/953847 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling/fast/scrolling/scrollbars/mouse-autoscrolling-on-scrollbar.html [ Failure Timeout ]
-crbug.com/953847 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/mouse-scrolling-on-div-scrollbar.html [ Failure ]
-crbug.com/953847 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/mouse-scrolling-on-root-scrollbar.html [ Failure ]
-crbug.com/953847 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/scrollbar-button-gesture-target.html [ Failure ]
-crbug.com/953847 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/scrollbar-occluded-by-div.html [ Failure ]
-crbug.com/953847 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/mouse-autoscrolling-on-scrollbar.html [ Failure Timeout ]
 crbug.com/953847 [ Mac ] virtual/scroll_customization/fast/scrolling/scrollbars/mouse-scrolling-on-div-scrollbar.html [ Failure ]
 crbug.com/953847 [ Mac ] virtual/scroll_customization/fast/scrolling/scrollbars/mouse-scrolling-on-root-scrollbar.html [ Failure ]
 crbug.com/953847 [ Mac ] virtual/scroll_customization/fast/scrolling/scrollbars/scroll-chaining-for-gesture-based-scrolling.html [ Failure ]
@@ -2482,13 +2477,7 @@
 crbug.com/953847 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling/fast/scrolling/scrollbars/scrollbar-button-gesture-target.html [ Failure ]
 
 # 1px scroll offset difference for compositor threaded scrollbar scrolling on Linux.
-crbug.com/1009892 [ Win ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/mouse-scrolling-on-div-scrollbar.html [ Failure ]
-crbug.com/1009892 [ Win ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Failure ]
-
-# TODO(arakeri): Mac is the only platform that runs with use_zoom_for_dsf=false. Get rid of this suite when crbug.com/716231 is fixed.
-# When DSF = 2 and use_zoom_for_dsf=false, the scroll offsets are different when compared to DSF = 2 and use_zoom_for_dsf=true.
-crbug.com/1016186 [ Win ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/dsf-ready/mouse-interactions-dsf-2.html [ Failure Timeout ]
-crbug.com/1016186 [ Linux ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/dsf-ready/mouse-interactions-dsf-2.html [ Failure Timeout ]
+crbug.com/1009892 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling_hidpi/fast/scrolling/scrollbars/dsf-ready/mouse-interactions-dsf-2.html [ Failure Timeout ]
 
 # TODO (arakeri): Mac uses the "Option" modifier instead of "Shift" to do the non-animated jump. This hasn't been implemented yet.
 crbug.com/1016955 [ Mac ] fast/scrolling/scrollbars/dsf-ready/mouse-interactions-dsf-2.html [ Failure Timeout ]
@@ -2496,8 +2485,6 @@
 crbug.com/1016955 [ Mac ] virtual/scroll_customization/fast/scrolling/scrollbars/dsf-ready/mouse-interactions-dsf-2.html [ Failure Timeout ]
 crbug.com/1016955 [ Mac ] virtual/hidpi/fast/scrolling/scrollbars/dsf-ready/mouse-interactions-dsf-2.html [ Failure Timeout ]
 crbug.com/1016955 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling/fast/scrolling/scrollbars/dsf-ready/mouse-interactions-dsf-2.html [ Failure Timeout ]
-crbug.com/1016955 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling_hidpi/fast/scrolling/scrollbars/dsf-ready/mouse-interactions-dsf-2.html [ Failure Timeout ]
-crbug.com/1016955 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/fast/scrolling/scrollbars/dsf-ready/mouse-interactions-dsf-2.html [ Failure Timeout ]
 
 # Some control characters still not visible
 crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-001.html [ Failure ]
@@ -2606,6 +2593,9 @@
 
 crbug.com/1012627 [ Win7 ] external/wpt/css/css-text/line-breaking/line-breaking-021.html [ Failure ]
 
+crbug.com/1022141 external/wpt/speech-api/SpeechSynthesis-speak-events.html [ Crash Timeout ]
+crbug.com/1022141 virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechSynthesis-speak-events.html [ Crash Timeout ]
+
 # ====== New tests from wpt-importer added here ======
 crbug.com/626703 [ Linux ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-iframe-messagechannel.https.html [ Timeout ]
 crbug.com/626703 [ Mac ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-iframe-messagechannel.https.html [ Timeout ]
@@ -3116,10 +3106,8 @@
 crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-display-rendering.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/css/css-text/hyphens/hyphens-auto-001.html [ Failure ]
 crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-tall.html [ Failure ]
-crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-speak-events.html [ Timeout ]
 crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-pause-resume.tentative.html [ Timeout ]
 crbug.com/626703 virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechSynthesis-pause-resume.tentative.html [ Timeout ]
-crbug.com/626703 virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechSynthesis-speak-events.html [ Timeout ]
 crbug.com/626703 virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html [ Failure ]
 crbug.com/880983 external/wpt/css/css-masking/clip-path/clip-path-path-interpolation-001.html [ Failure ]
 crbug.com/880983 external/wpt/css/css-masking/clip-path/clip-path-path-interpolation-002.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 94ac358..907b0b5 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -310,16 +310,6 @@
              "--force-device-scale-factor=2"]
   },
   {
-    "prefix": "compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf",
-    "bases": ["fast/scrolling/scrollbars"],
-    "args": ["--enable-features=CompositorThreadedScrollbarScrolling",
-             "--enable-threaded-compositing",
-             "--enable-prefer-compositing-to-lcd-text",
-             "--disable-smooth-scrolling",
-             "--force-device-scale-factor=2",
-             "--enable-use-zoom-for-dsf=false"]
-  },
-  {
     "prefix": "speech-with-unified-autoplay",
     "bases": ["external/wpt/speech-api"],
     "args": ["--autoplay-policy=document-user-activation-required"]
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/cts.html b/third_party/blink/web_tests/external/wpt/webgpu/cts.html
index b60faec9..b66553d 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/cts.html
+++ b/third_party/blink/web_tests/external/wpt/webgpu/cts.html
@@ -3,18 +3,23 @@
     This test suite is built from the TypeScript sources at:
     https://github.com/gpuweb/cts
 
+    If you are debugging WebGPU conformance tests, it's highly recommended that
+    you use the standalone interactive runner in that repository, which
+    provides tools for easier debugging and editing (source maps, debug
+    logging, warn/skip functionality, etc.)
+
     NOTE:
-    The WPT version of this file is generated with *one test spec per variant*.
-    If your harness needs more fine-grained suppressions, you'll need to
+    The WPT version of this file is generated with *one variant per test spec
+    file*. If your harness needs more fine-grained suppressions, you'll need to
     generate your own variants list from your suppression list. For example, if
     test file cts:a/b: has 3 tests and you need to suppress a single case, you
     might break it out into the following variants:
 
-    - cts:a/b:test1~
-    - cts:a/b:test2={"x":1}
-    - cts:a/b:test2={"x":2}  // <- suppress this one
-    - cts:a/b:test2={"x":3}
-    - cts:a/b:test3~
+      - cts:a/b:test1~
+      - cts:a/b:test2={"x":1}
+      - cts:a/b:test2={"x":2}  // <- suppress this one
+      - cts:a/b:test2={"x":3}
+      - cts:a/b:test3~
 
     When run under browser CI, the original cts.html should be skipped, and
     this alternate version should be run instead, under a non-exported WPT test
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/framework/fixture.js b/third_party/blink/web_tests/external/wpt/webgpu/framework/fixture.js
index 2c1ea8314..12793122 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/framework/fixture.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/framework/fixture.js
@@ -4,9 +4,10 @@
 
 function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
 
-// A Fixture is a class used to instantiate each test case at run time.
+export class SkipTestCase extends Error {} // A Fixture is a class used to instantiate each test case at run time.
 // A new instance of the Fixture is created for every single test case
 // (i.e. every time the test function is run).
+
 export class Fixture {
   constructor(rec, params) {
     _defineProperty(this, "params", void 0);
@@ -33,6 +34,10 @@
     this.rec.log(msg);
   }
 
+  skip(msg) {
+    throw new SkipTestCase(msg);
+  }
+
   async finalize() {
     if (this.numOutstandingAsyncExpectations !== 0) {
       throw new Error('there were outstanding asynchronous expectations (e.g. shouldReject) at the end of the test');
@@ -64,14 +69,14 @@
 
   expectErrorValue(expectedName, ex, m) {
     if (!(ex instanceof Error)) {
-      this.fail('THREW NON-ERROR');
+      this.fail('THREW non-error value, of type ' + typeof ex);
       return;
     }
 
     const actualName = ex.name;
 
     if (actualName !== expectedName) {
-      this.fail(`THREW ${actualName} INSTEAD OF ${expectedName}${m}`);
+      this.fail(`THREW ${actualName}, instead of ${expectedName}${m}`);
     } else {
       this.debug(`OK: threw ${actualName}${m}`);
     }
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/framework/logger.js b/third_party/blink/web_tests/external/wpt/webgpu/framework/logger.js
index e8542924..ee869196 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/framework/logger.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/framework/logger.js
@@ -4,6 +4,7 @@
 
 function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
 
+import { SkipTestCase } from './fixture.js';
 import { makeQueryString } from './url_query.js';
 import { extractPublicParams } from './url_query.js';
 import { getStackTrace, now } from './util/index.js';
@@ -49,13 +50,20 @@
   }
 
 }
+var PassState;
+
+(function (PassState) {
+  PassState[PassState["pass"] = 0] = "pass";
+  PassState[PassState["skip"] = 1] = "skip";
+  PassState[PassState["warn"] = 2] = "warn";
+  PassState[PassState["fail"] = 3] = "fail";
+})(PassState || (PassState = {}));
+
 export class TestCaseRecorder {
   constructor(result) {
     _defineProperty(this, "result", void 0);
 
-    _defineProperty(this, "failed", false);
-
-    _defineProperty(this, "warned", false);
+    _defineProperty(this, "state", PassState.pass);
 
     _defineProperty(this, "startTime", -1);
 
@@ -69,8 +77,7 @@
   start(debug = false) {
     this.startTime = now();
     this.logs = [];
-    this.failed = false;
-    this.warned = false;
+    this.state = PassState.pass;
     this.debugging = debug;
   }
 
@@ -82,7 +89,7 @@
     const endTime = now(); // Round to next microsecond to avoid storing useless .xxxx00000000000002 in results.
 
     this.result.timems = Math.ceil((endTime - this.startTime) * 1000) / 1000;
-    this.result.status = this.failed ? 'fail' : this.warned ? 'warn' : 'pass';
+    this.result.status = PassState[this.state];
     this.result.logs = this.logs;
     this.debugging = false;
   }
@@ -100,7 +107,7 @@
   }
 
   warn(msg) {
-    this.warned = true;
+    this.setState(PassState.warn);
     let m = 'WARN';
 
     if (msg) {
@@ -112,20 +119,35 @@
   }
 
   fail(msg) {
-    this.failed = true;
+    this.setState(PassState.fail);
     let m = 'FAIL';
 
     if (msg) {
       m += ': ' + msg;
     }
 
-    m += ' ' + getStackTrace(new Error());
+    m += '\n' + getStackTrace(new Error());
     this.log(m);
   }
 
-  threw(e) {
-    this.failed = true;
-    this.log('EXCEPTION: ' + e.name + ': ' + e.message + '\n' + getStackTrace(e));
+  skipped(ex) {
+    this.setState(PassState.skip);
+    const m = 'SKIPPED: ' + getStackTrace(ex);
+    this.log(m);
+  }
+
+  threw(ex) {
+    if (ex instanceof SkipTestCase) {
+      this.skipped(ex);
+      return;
+    }
+
+    this.setState(PassState.fail);
+    this.log('EXCEPTION: ' + ex.name + ':\n' + ex.message + '\n' + getStackTrace(ex));
+  }
+
+  setState(state) {
+    this.state = Math.max(this.state, state);
   }
 
 }
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/framework/test_group.js b/third_party/blink/web_tests/external/wpt/webgpu/framework/test_group.js
index 69d8cc04..68527a5 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/framework/test_group.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/framework/test_group.js
@@ -136,20 +136,18 @@
 
     try {
       const inst = new this.fixture(rec, this.params || {});
-      await inst.init();
 
       try {
+        await inst.init();
         await this.fn(inst);
-      } catch (ex) {
-        // There was an exception from the test itself.
-        rec.threw(ex);
-      } // Runs as long as constructor and init succeeded, even if the test rejected.
-
-
-      await inst.finalize();
+      } finally {
+        // Runs as long as constructor succeeded, even if initialization or the test failed.
+        await inst.finalize();
+      }
     } catch (ex) {
-      // There was an exception from constructor, init, or finalize.
-      // (An error from finalize may have been an eventualAsyncExpectation failure.)
+      // There was an exception from constructor, init, test, or finalize.
+      // An error from init or test may have been a SkipTestCase.
+      // An error from finalize may have been an eventualAsyncExpectation failure.
       rec.threw(ex);
     }
 
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/framework/util/stack.js b/third_party/blink/web_tests/external/wpt/webgpu/framework/util/stack.js
index ae99ac9..bd51d54 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/framework/util/stack.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/framework/util/stack.js
@@ -24,10 +24,9 @@
     }
 
     if (isSuites) {
+      stack.push(part);
       found = true;
     }
-
-    stack.push(part);
   }
 
   return stack.join('\n');
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/framework/version.js b/third_party/blink/web_tests/external/wpt/webgpu/framework/version.js
index 55a72f5..154f062 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/framework/version.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/framework/version.js
@@ -1,3 +1,3 @@
 // AUTO-GENERATED - DO NOT EDIT. See tools/gen_version.
 
-export const version = 'ba0a130a078256d45504069de88f0d91d4631578';
+export const version = '3dc37c83a70667e9a92df773f34d154ec600d203';
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/runtime/wpt.js b/third_party/blink/web_tests/external/wpt/webgpu/runtime/wpt.js
index c87f9167..e078f67 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/runtime/wpt.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/runtime/wpt.js
@@ -39,6 +39,7 @@
           }
 
           this.step(() => {
+            // Unfortunately, it seems not possible to surface any logs for warn/skip.
             if (r.status === 'fail') {
               throw (r.logs || []).join('\n');
             }
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/canvas/context_creation.spec.js b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/canvas/context_creation.spec.js
index ba0d4722..a693b002 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/canvas/context_creation.spec.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/canvas/context_creation.spec.js
@@ -3,15 +3,12 @@
 **/
 
 export const description = ``;
-import { TestGroup } from '../../../framework/index.js';
-import { GPUTest } from '../gpu_test.js'; // TODO: doesn't need to use GPUTest
-
-export const g = new TestGroup(GPUTest);
-g.test('getContext returns GPUCanvasContext', async t => {
+import { Fixture, TestGroup } from '../../../framework/index.js';
+export const g = new TestGroup(Fixture);
+g.test('canvas element getContext returns GPUCanvasContext', async t => {
   if (typeof document === 'undefined') {
     // Skip if there is no document (Workers, Node)
-    // TODO: Use t.skip()
-    return;
+    t.skip('DOM is not available to create canvas element');
   }
 
   const canvas = document.createElement('canvas');
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/compute/basic.spec.js b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/compute/basic.spec.js
index 8fcc7ef..8a5fc16 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/compute/basic.spec.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/compute/basic.spec.js
@@ -48,7 +48,7 @@
     }],
     layout: bgl
   });
-  const module = t.device.createShaderModule({
+  const module = t.createShaderModule({
     code:
     /* GLSL(
      *       'compute',
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/render/rendering.spec.js b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/render/rendering.spec.js
index 46829a8..43c4566 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/render/rendering.spec.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/render/rendering.spec.js
@@ -21,7 +21,7 @@
     usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.OUTPUT_ATTACHMENT
   });
   const colorAttachmentView = colorAttachment.createView();
-  const vertexModule = t.device.createShaderModule({
+  const vertexModule = t.createShaderModule({
     code:
     /* GLSL(
      *       'vertex',
@@ -36,7 +36,7 @@
      */
     new Uint32Array([119734787, 66304, 524295, 39, 0, 131089, 1, 393227, 1, 1280527431, 1685353262, 808793134, 0, 196622, 0, 1, 458767, 0, 4, 1852399981, 0, 10, 26, 196611, 1, 310, 262149, 4, 1852399981, 0, 393221, 8, 1348430951, 1700164197, 2019914866, 0, 393222, 8, 0, 1348430951, 1953067887, 7237481, 458758, 8, 1, 1348430951, 1953393007, 1702521171, 0, 196613, 10, 0, 393221, 26, 1449094247, 1702130277, 1684949368, 30821, 327685, 29, 1701080681, 1818386808, 101, 327752, 8, 0, 11, 0, 327752, 8, 1, 11, 1, 196679, 8, 2, 262215, 26, 11, 42, 131091, 2, 196641, 3, 2, 196630, 6, 32, 262167, 7, 6, 4, 262174, 8, 7, 6, 262176, 9, 3, 8, 262203, 9, 10, 3, 262165, 11, 32, 1, 262187, 11, 12, 0, 262167, 13, 6, 2, 262165, 14, 32, 0, 262187, 14, 15, 3, 262172, 16, 13, 15, 262187, 6, 17, 3212836864, 262187, 6, 18, 3225419776, 327724, 13, 19, 17, 18, 262187, 6, 20, 1077936128, 262187, 6, 21, 1065353216, 327724, 13, 22, 20, 21, 327724, 13, 23, 17, 21, 393260, 16, 24, 19, 22, 23, 262176, 25, 1, 11, 262203, 25, 26, 1, 262176, 28, 7, 16, 262176, 30, 7, 13, 262187, 6, 33, 0, 262176, 37, 3, 7, 327734, 2, 4, 0, 3, 131320, 5, 262203, 28, 29, 7, 262205, 11, 27, 26, 196670, 29, 24, 327745, 30, 31, 29, 27, 262205, 13, 32, 31, 327761, 6, 34, 32, 0, 327761, 6, 35, 32, 1, 458832, 7, 36, 34, 35, 33, 21, 327745, 37, 38, 10, 12, 196670, 38, 36, 65789, 65592])
   });
-  const fragmentModule = t.device.createShaderModule({
+  const fragmentModule = t.createShaderModule({
     code:
     /* GLSL(
      *       'fragment',
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/render/storeop.spec.js b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/render/storeop.spec.js
index 0b38deb..0326cf6 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/render/storeop.spec.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/command_buffer/render/storeop.spec.js
@@ -18,7 +18,7 @@
     usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.OUTPUT_ATTACHMENT
   }); // create render pipeline
 
-  const vertexModule = t.device.createShaderModule({
+  const vertexModule = t.createShaderModule({
     code:
     /* GLSL(
      *       'vertex',
@@ -36,7 +36,7 @@
      */
     new Uint32Array([119734787, 66304, 524295, 39, 0, 131089, 1, 393227, 1, 1280527431, 1685353262, 808793134, 0, 196622, 0, 1, 458767, 0, 4, 1852399981, 0, 13, 26, 196611, 2, 450, 262149, 4, 1852399981, 0, 393221, 11, 1348430951, 1700164197, 2019914866, 0, 393222, 11, 0, 1348430951, 1953067887, 7237481, 458758, 11, 1, 1348430951, 1953393007, 1702521171, 0, 458758, 11, 2, 1130327143, 1148217708, 1635021673, 6644590, 458758, 11, 3, 1130327143, 1147956341, 1635021673, 6644590, 196613, 13, 0, 393221, 26, 1449094247, 1702130277, 1684949368, 30821, 327685, 29, 1701080681, 1818386808, 101, 327752, 11, 0, 11, 0, 327752, 11, 1, 11, 1, 327752, 11, 2, 11, 3, 327752, 11, 3, 11, 4, 196679, 11, 2, 262215, 26, 11, 42, 131091, 2, 196641, 3, 2, 196630, 6, 32, 262167, 7, 6, 4, 262165, 8, 32, 0, 262187, 8, 9, 1, 262172, 10, 6, 9, 393246, 11, 7, 6, 10, 10, 262176, 12, 3, 11, 262203, 12, 13, 3, 262165, 14, 32, 1, 262187, 14, 15, 0, 262167, 16, 6, 2, 262187, 8, 17, 3, 262172, 18, 16, 17, 262187, 6, 19, 1065353216, 262187, 6, 20, 3212836864, 327724, 16, 21, 19, 20, 327724, 16, 22, 19, 19, 327724, 16, 23, 20, 19, 393260, 18, 24, 21, 22, 23, 262176, 25, 1, 14, 262203, 25, 26, 1, 262176, 28, 7, 18, 262176, 30, 7, 16, 262187, 6, 33, 0, 262176, 37, 3, 7, 327734, 2, 4, 0, 3, 131320, 5, 262203, 28, 29, 7, 262205, 14, 27, 26, 196670, 29, 24, 327745, 30, 31, 29, 27, 262205, 16, 32, 31, 327761, 6, 34, 32, 0, 327761, 6, 35, 32, 1, 458832, 7, 36, 34, 35, 33, 19, 327745, 37, 38, 13, 15, 196670, 38, 36, 65789, 65592])
   });
-  const fragmentModule = t.device.createShaderModule({
+  const fragmentModule = t.createShaderModule({
     code:
     /* GLSL(
      *       'fragment',
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/gpu_test.js b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/gpu_test.js
index 96f109d..272b1b8 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/gpu_test.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/gpu_test.js
@@ -6,8 +6,7 @@
 
 import { getGPU } from '../../framework/gpu/implementation.js';
 import { Fixture } from '../../framework/index.js';
-let glslangInstance; // TODO: Should this gain some functionality currently only in UnitTest?
-
+let glslangInstance;
 export class GPUTest extends Fixture {
   constructor(...args) {
     super(...args);
@@ -15,6 +14,10 @@
     _defineProperty(this, "device", undefined);
 
     _defineProperty(this, "queue", undefined);
+
+    _defineProperty(this, "initialized", false);
+
+    _defineProperty(this, "supportsSPIRV", true);
   }
 
   async init() {
@@ -23,31 +26,53 @@
     const adapter = await gpu.requestAdapter();
     this.device = await adapter.requestDevice();
     this.queue = this.device.getQueue();
+    const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
+
+    if (isSafari) {
+      this.supportsSPIRV = false;
+    }
+
+    try {
+      await this.device.popErrorScope();
+      throw new Error('There was an error scope on the stack at the beginning of the test');
+    } catch (ex) {}
+
     this.device.pushErrorScope('out-of-memory');
     this.device.pushErrorScope('validation');
+    this.initialized = true;
   }
 
   async finalize() {
     super.finalize();
-    const gpuValidationError = await this.device.popErrorScope();
 
-    if (gpuValidationError !== null) {
-      if (!(gpuValidationError instanceof GPUValidationError)) throw new Error();
-      this.fail(`Unexpected validation error occurred: ${gpuValidationError.message}`);
-    }
+    if (this.initialized) {
+      const gpuValidationError = await this.device.popErrorScope();
 
-    const gpuOutOfMemoryError = await this.device.popErrorScope();
+      if (gpuValidationError !== null) {
+        if (!(gpuValidationError instanceof GPUValidationError)) throw new Error();
+        this.fail(`Unexpected validation error occurred: ${gpuValidationError.message}`);
+      }
 
-    if (gpuOutOfMemoryError !== null) {
-      if (!(gpuOutOfMemoryError instanceof GPUOutOfMemoryError)) throw new Error();
-      this.fail('Unexpected out-of-memory error occurred');
+      const gpuOutOfMemoryError = await this.device.popErrorScope();
+
+      if (gpuOutOfMemoryError !== null) {
+        if (!(gpuOutOfMemoryError instanceof GPUOutOfMemoryError)) throw new Error();
+        this.fail('Unexpected out-of-memory error occurred');
+      }
     }
   }
 
   async initGLSL() {
     if (!glslangInstance) {
       const glslangPath = '../../glslang.js';
-      const glslangModule = (await import(glslangPath)).default;
+      let glslangModule;
+
+      try {
+        glslangModule = (await import(glslangPath)).default;
+      } catch (ex) {
+        this.skip('glslang is not available');
+      }
+
       await new Promise(resolve => {
         glslangModule().then(glslang => {
           glslangInstance = glslang;
@@ -57,12 +82,20 @@
     }
   }
 
-  makeShaderModule(stage, source) {
-    if (!glslangInstance) {
-      throw new Error('GLSL is not instantiated. Run `await t.initGLSL()` first');
+  createShaderModule(desc) {
+    if (!this.supportsSPIRV) {
+      this.skip('SPIR-V not available');
     }
 
-    const code = glslangInstance.compileGLSL(source, stage, false);
+    return this.device.createShaderModule(desc);
+  }
+
+  makeShaderModuleFromGLSL(stage, glsl) {
+    if (!glslangInstance) {
+      throw new Error('GLSL compiler is not instantiated. Run `await t.initGLSL()` first');
+    }
+
+    const code = glslangInstance.compileGLSL(glsl, stage, false);
     return this.device.createShaderModule({
       code
     });
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/createRenderPipeline.spec.js b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/createRenderPipeline.spec.js
index cc838fc6..b66dabf2 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/createRenderPipeline.spec.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/createRenderPipeline.spec.js
@@ -38,7 +38,7 @@
 
   getVertexStage() {
     return {
-      module: this.device.createShaderModule({
+      module: this.createShaderModule({
         code:
         /* GLSL(
          *           'vertex',
@@ -74,7 +74,7 @@
       }
     `;
     return {
-      module: this.makeShaderModule('fragment', code),
+      module: this.makeShaderModuleFromGLSL('fragment', code),
       entryPoint: 'main'
     };
   }
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/render_pass.spec.js b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/render_pass.spec.js
index 52da36f..3e08dcc1 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/render_pass.spec.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/render_pass.spec.js
@@ -17,7 +17,7 @@
   }
 
   createRenderPipeline(pipelineLayout) {
-    const vertexModule = this.device.createShaderModule({
+    const vertexModule = this.createShaderModule({
       code:
       /* GLSL(
        *         'vertex',
@@ -34,7 +34,7 @@
        */
       new Uint32Array([119734787, 66304, 524295, 47, 0, 131089, 1, 393227, 1, 1280527431, 1685353262, 808793134, 0, 196622, 0, 1, 458767, 0, 4, 1852399981, 0, 13, 33, 196611, 2, 450, 262149, 4, 1852399981, 0, 393221, 11, 1348430951, 1700164197, 2019914866, 0, 393222, 11, 0, 1348430951, 1953067887, 7237481, 458758, 11, 1, 1348430951, 1953393007, 1702521171, 0, 458758, 11, 2, 1130327143, 1148217708, 1635021673, 6644590, 458758, 11, 3, 1130327143, 1147956341, 1635021673, 6644590, 196613, 13, 0, 458757, 18, 1953654134, 1851095141, 1919903337, 1718960749, 7497062, 393222, 18, 0, 1851880052, 1919903347, 109, 196613, 20, 0, 393221, 33, 1449094247, 1702130277, 1684949368, 30821, 327685, 36, 1701080681, 1818386808, 101, 327752, 11, 0, 11, 0, 327752, 11, 1, 11, 1, 327752, 11, 2, 11, 3, 327752, 11, 3, 11, 4, 196679, 11, 2, 262216, 18, 0, 5, 327752, 18, 0, 35, 0, 327752, 18, 0, 7, 16, 196679, 18, 2, 262215, 20, 34, 0, 262215, 20, 33, 0, 262215, 33, 11, 42, 131091, 2, 196641, 3, 2, 196630, 6, 32, 262167, 7, 6, 4, 262165, 8, 32, 0, 262187, 8, 9, 1, 262172, 10, 6, 9, 393246, 11, 7, 6, 10, 10, 262176, 12, 3, 11, 262203, 12, 13, 3, 262165, 14, 32, 1, 262187, 14, 15, 0, 262167, 16, 6, 2, 262168, 17, 16, 2, 196638, 18, 17, 262176, 19, 2, 18, 262203, 19, 20, 2, 262176, 21, 2, 17, 262187, 8, 24, 3, 262172, 25, 16, 24, 262187, 6, 26, 3212836864, 327724, 16, 27, 26, 26, 262187, 6, 28, 1065353216, 327724, 16, 29, 28, 26, 327724, 16, 30, 26, 28, 393260, 25, 31, 27, 29, 30, 262176, 32, 1, 14, 262203, 32, 33, 1, 262176, 35, 7, 25, 262176, 37, 7, 16, 262187, 6, 41, 0, 262176, 45, 3, 7, 327734, 2, 4, 0, 3, 131320, 5, 262203, 35, 36, 7, 327745, 21, 22, 20, 15, 262205, 17, 23, 22, 262205, 14, 34, 33, 196670, 36, 31, 327745, 37, 38, 36, 34, 262205, 16, 39, 38, 327825, 16, 40, 23, 39, 327761, 6, 42, 40, 0, 327761, 6, 43, 40, 1, 458832, 7, 44, 42, 43, 41, 28, 327745, 45, 46, 13, 15, 196670, 46, 44, 65789, 65592])
     });
-    const fragmentModule = this.device.createShaderModule({
+    const fragmentModule = this.createShaderModule({
       code:
       /* GLSL(
        *         'fragment',
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/setVertexBuffer.spec.js b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/setVertexBuffer.spec.js
index 1df4017..0f47e73 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/setVertexBuffer.spec.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/setVertexBuffer.spec.js
@@ -51,7 +51,7 @@
        }
     `;
     return {
-      module: this.makeShaderModule('vertex', code),
+      module: this.makeShaderModuleFromGLSL('vertex', code),
       entryPoint: 'main'
     };
   }
@@ -65,7 +65,7 @@
       }
     `;
     return {
-      module: this.makeShaderModule('fragment', code),
+      module: this.makeShaderModuleFromGLSL('fragment', code),
       entryPoint: 'main'
     };
   }
diff --git a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/vertex_input.spec.js b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/vertex_input.spec.js
index 951c9ea..c5978025 100644
--- a/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/vertex_input.spec.js
+++ b/third_party/blink/web_tests/external/wpt/webgpu/suites/cts/validation/vertex_input.spec.js
@@ -43,7 +43,7 @@
 
   getVertexStage(code) {
     return {
-      module: this.makeShaderModule('vertex', code),
+      module: this.makeShaderModuleFromGLSL('vertex', code),
       entryPoint: 'main'
     };
   }
@@ -57,7 +57,7 @@
       }
     `;
     return {
-      module: this.makeShaderModule('fragment', code),
+      module: this.makeShaderModuleFromGLSL('fragment', code),
       entryPoint: 'main'
     };
   }
diff --git a/third_party/blink/web_tests/fast/canvas/imagebitmap/transferToImageBitmapRGBorder-expected.html b/third_party/blink/web_tests/fast/canvas/imagebitmap/transferToImageBitmapRGBorder-expected.html
new file mode 100644
index 0000000..039bc49
--- /dev/null
+++ b/third_party/blink/web_tests/fast/canvas/imagebitmap/transferToImageBitmapRGBorder-expected.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<style>
+    body {
+        background-color: lightblue;
+    }
+    canvas {
+        width: 100px;
+        height: 50px;
+    }
+</style>
+
+<body>
+    <canvas id="canvas2"></canvas>
+</body>
+
+<script>
+    function createImage()
+    {
+        var canvas = new OffscreenCanvas(100, 50);
+        var ctx = canvas.getContext("2d");
+        for (var y = 0; y < 50; y += 10) {
+            for (var x = ((y / 10) % 2) ? 0 : 10; x < 100; x += 20) {
+                switch (Math.round(x / 20) % 3) {
+                case 0:
+                    ctx.fillStyle = "#f00";
+                    break;
+                case 1:
+                    ctx.fillStyle = "#0f0";
+                    break;
+                case 2:
+                    ctx.fillStyle = "#00f";
+                    break;
+                }
+                ctx.fillRect(x, y, 10, 10);
+            }
+        }
+        image = canvas.transferToImageBitmap();
+        return image;
+    }
+    var canvas = document.getElementById("canvas2");
+    canvas.width = 100; canvas.height = 50;
+    var ctx = canvas.getContext("2d");
+    var image = createImage();
+    ctx.drawImage(image, 0, 0);
+</script>
+</html>
diff --git a/third_party/blink/web_tests/fast/canvas/imagebitmap/transferToImageBitmapRGBorder.html b/third_party/blink/web_tests/fast/canvas/imagebitmap/transferToImageBitmapRGBorder.html
new file mode 100644
index 0000000..3e220be2
--- /dev/null
+++ b/third_party/blink/web_tests/fast/canvas/imagebitmap/transferToImageBitmapRGBorder.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+<style>
+    body {
+        background-color: lightblue;
+    }
+    canvas {
+        width: 100px;
+        height: 50px;
+    }
+</style>
+<script id="worker" type="text/worker">
+    function createImage()
+    {
+        var canvas = new OffscreenCanvas(100, 50);
+        var ctx = canvas.getContext("2d");
+        for (var y = 0; y < 50; y += 10) {
+            for (var x = ((y / 10) % 2) ? 0 : 10; x < 100; x += 20) {
+                switch (Math.round(x / 20) % 3) {
+                case 0:
+                    ctx.fillStyle = "#f00";
+                    break;
+                case 1:
+                    ctx.fillStyle = "#0f0";
+                    break;
+                case 2:
+                    ctx.fillStyle = "#00f";
+                    break;
+                }
+                ctx.fillRect(x, y, 10, 10);
+            }
+        }
+        image = canvas.transferToImageBitmap();
+        return image;
+    }
+
+    self.onmessage = function(e) {
+        switch (e.data) {
+        case 'test':
+            var image = createImage();
+            self.postMessage(image);
+            break;
+        }
+    }
+</script>
+
+<body>
+    <canvas id="canvas1"></canvas>
+</body>
+
+<script>
+    function requestAnimationFrameNtimesThen(times, fn) {
+      if(times>0) {
+        requestAnimationFrame(() => {
+          requestAnimationFrameNtimesThen(times-1, fn);
+        });
+      } else
+        fn();
+    };
+
+    if (window.testRunner) {
+      testRunner.waitUntilDone();
+    }
+    var blob = new Blob([document.getElementById("worker").textContent]);
+    var worker = new Worker(URL.createObjectURL(blob));
+    worker.addEventListener('message', function(message) {
+        var canvas = document.getElementById("canvas1");
+        canvas.width = 100; canvas.height = 50;
+        var ctx = canvas.getContext("2d");
+        ctx.drawImage(message.data, 0, 0);
+        if (window.testRunner) {
+          requestAnimationFrameNtimesThen(1, () => {
+            testRunner.notifyDone();
+          });
+        }
+    });
+    worker.postMessage("test");
+
+</script>
+</html>
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
index c92a4e5f..e9e75a3 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
@@ -1,4 +1,5 @@
 CONSOLE WARNING: line 124: 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.
+CONSOLE WARNING: line 124: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Tests access of cached DOMWindow properties after the associated frame is navigated. Test should not crash and properties should be set to sane defaults.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
index 4678fe0..7b9693a 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
@@ -1,4 +1,5 @@
 CONSOLE WARNING: line 124: 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.
+CONSOLE WARNING: line 124: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Tests access of cached DOMWindow properties after the associated frame is removed from a web page and garbage collected. Test should not crash and properties should be set to sane defaults.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
index 3675d65..d8ef365 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
@@ -1,4 +1,5 @@
 CONSOLE WARNING: line 124: 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.
+CONSOLE WARNING: line 124: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Tests access of cached DOMWindow properties after the associated frame is no longer in a web page. Test should not crash and properties should be set to sane defaults.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
index 5f27370..41151bf 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -1,4 +1,5 @@
 CONSOLE WARNING: line 124: 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.
+CONSOLE WARNING: line 124: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Tests property access on a cached DOMWindow after the associated frame is navigated. Test should not crash and properties read from the cached DOMWindow should be identical to properties through the 'current' DOMWindow.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
index b3820f1..719a3333 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
@@ -1,4 +1,5 @@
 CONSOLE WARNING: line 124: 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.
+CONSOLE WARNING: line 124: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Tests property access on a cached DOMWindow after the associated frame is removed from a web page and garbage collected. Test should not crash and properties should be set to sane defaults.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
index 029ef07..081d35d 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
@@ -1,4 +1,5 @@
 CONSOLE WARNING: line 124: 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.
+CONSOLE WARNING: line 124: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Tests property access on a cached DOMWindow after the associated frame is no longer in a web page. Test should not crash and properties should be set to sane defaults.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/appcache/foreign-iframe-main-expected.txt b/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/appcache/foreign-iframe-main-expected.txt
new file mode 100644
index 0000000..f84ca34
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/appcache/foreign-iframe-main-expected.txt
@@ -0,0 +1,12 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+Test for <rdar://problem/6284708> AppCache crashes in ApplicationCacheResource::addType().
+
+checking
+downloading
+progress
+progress
+progress
+progress
+cached
+SUCCESS
+
diff --git a/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/security/cross-origin-appcache-allowed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/security/cross-origin-appcache-allowed-expected.txt
new file mode 100644
index 0000000..4cebfa8
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/security/cross-origin-appcache-allowed-expected.txt
@@ -0,0 +1,14 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+This iframe should have a cache:
+
+This iframe should have a cache:
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+Cache found
+
+--------
+Frame: '<!--framePath //<!--frame1-->-->'
+--------
+Cache found
diff --git a/third_party/blink/web_tests/http/tests/appcache/404-manifest-expected.txt b/third_party/blink/web_tests/http/tests/appcache/404-manifest-expected.txt
index 20f3066..6cba9889 100644
--- a/third_party/blink/web_tests/http/tests/appcache/404-manifest-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/404-manifest-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 34: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that subresources can be loaded if manifest is not available.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/404-resource-cross-origin-expected.txt b/third_party/blink/web_tests/http/tests/appcache/404-resource-cross-origin-expected.txt
index cde521f..76db3b9 100644
--- a/third_party/blink/web_tests/http/tests/appcache/404-resource-cross-origin-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/404-resource-cross-origin-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a missing cross-origin resource failure doesn't leak details.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/http/tests/appcache/404-resource-expected.txt b/third_party/blink/web_tests/http/tests/appcache/404-resource-expected.txt
index 5e48eda4..06a6bfe 100644
--- a/third_party/blink/web_tests/http/tests/appcache/404-resource-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/404-resource-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a missing explicit resource makes caching fail.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-expected.txt b/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-expected.txt
index fbec09b0..4a4d34c 100644
--- a/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that download process was aborted after checking event.
 FAILURE CACHED
diff --git a/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-manifest-404-expected.txt b/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-manifest-404-expected.txt
index b8817513..c2b5347 100644
--- a/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-manifest-404-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-manifest-404-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that download process was aborted after checking event and before update failed.
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-resource-404-expected.txt b/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-resource-404-expected.txt
index b8817513..c2b5347 100644
--- a/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-resource-404-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/abort-cache-onchecking-resource-404-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that download process was aborted after checking event and before update failed.
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-expected.txt b/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-expected.txt
index 93ab870..dba9c03 100644
--- a/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that download process was aborted after downloading event.
 FAILURE CACHED
diff --git a/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-manifest-404-expected.txt b/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-manifest-404-expected.txt
index cef14c7..2ab2721 100644
--- a/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-manifest-404-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-manifest-404-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that download process was not aborted after downloading event since manifest was not found.
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-resource-404-expected.txt b/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-resource-404-expected.txt
index b62d9f33..89cf3d8 100644
--- a/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-resource-404-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/abort-cache-ondownloading-resource-404-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that download process was aborted after downloading event although resource was not found.
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/abort-cache-onprogress-expected.txt b/third_party/blink/web_tests/http/tests/appcache/abort-cache-onprogress-expected.txt
index fc1bd6f..736921c 100644
--- a/third_party/blink/web_tests/http/tests/appcache/abort-cache-onprogress-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/abort-cache-onprogress-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that download process was aborted after progress event.
 loading resource: 0 / 4 loading resource: 1 / 4 loading resource: 2 / 4 loading resource: 3 / 4 loading resource: 4 / 4 FAILURE CACHED
diff --git a/third_party/blink/web_tests/http/tests/appcache/access-via-redirect-expected.txt b/third_party/blink/web_tests/http/tests/appcache/access-via-redirect-expected.txt
index 38e3673..bc1fffe4 100644
--- a/third_party/blink/web_tests/http/tests/appcache/access-via-redirect-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/access-via-redirect-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 16: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 This tests that the start of redirect chain doesn't get into an application cache if the end of the chain has a manifest.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/crash-when-navigating-away-then-back-expected.txt b/third_party/blink/web_tests/http/tests/appcache/crash-when-navigating-away-then-back-expected.txt
index 0ad96dc..42bc7e6d 100644
--- a/third_party/blink/web_tests/http/tests/appcache/crash-when-navigating-away-then-back-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/crash-when-navigating-away-then-back-expected.txt
@@ -1,2 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that loading a page with a manifest, navigating away from the page, and then back does not cause a crash.
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/credential-url-expected.txt b/third_party/blink/web_tests/http/tests/appcache/credential-url-expected.txt
index 3076236..320b1819 100644
--- a/third_party/blink/web_tests/http/tests/appcache/credential-url-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/credential-url-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that application cache doesn't block loading resources from the same origin with credential.
 
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/cyrillic-uri-expected.txt b/third_party/blink/web_tests/http/tests/appcache/cyrillic-uri-expected.txt
index e79bcfc..42eab79 100644
--- a/third_party/blink/web_tests/http/tests/appcache/cyrillic-uri-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/cyrillic-uri-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 33: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that non-ASCII URIs work correctly in cache manifests.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/deferred-events-delete-while-raising-expected.txt b/third_party/blink/web_tests/http/tests/appcache/deferred-events-delete-while-raising-expected.txt
index c6228258..b6ff78d 100644
--- a/third_party/blink/web_tests/http/tests/appcache/deferred-events-delete-while-raising-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/deferred-events-delete-while-raising-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test the destruction of an iframe while deferred events are being raised does not crash the system.
 
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/deferred-events-delete-while-raising-timer-expected.txt b/third_party/blink/web_tests/http/tests/appcache/deferred-events-delete-while-raising-timer-expected.txt
index c6228258..b6ff78d 100644
--- a/third_party/blink/web_tests/http/tests/appcache/deferred-events-delete-while-raising-timer-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/deferred-events-delete-while-raising-timer-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test the destruction of an iframe while deferred events are being raised does not crash the system.
 
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/deferred-events-expected.txt b/third_party/blink/web_tests/http/tests/appcache/deferred-events-expected.txt
index 45af0afe..ddc9b8e 100644
--- a/third_party/blink/web_tests/http/tests/appcache/deferred-events-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/deferred-events-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that AppicationCache events are deferred until after onload has been fired.
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/different-https-origin-resource-main-expected.txt b/third_party/blink/web_tests/http/tests/appcache/different-https-origin-resource-main-expected.txt
index e680ea2..acde08e 100644
--- a/third_party/blink/web_tests/http/tests/appcache/different-https-origin-resource-main-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/different-https-origin-resource-main-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a resource from a different https origin is not cached.
 
 FAIL: Different https origin resource is getting downloaded to cache.
diff --git a/third_party/blink/web_tests/http/tests/appcache/different-origin-manifest-expected.txt b/third_party/blink/web_tests/http/tests/appcache/different-origin-manifest-expected.txt
index d08f58eb..ced99cb 100644
--- a/third_party/blink/web_tests/http/tests/appcache/different-origin-manifest-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/different-origin-manifest-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: line 28: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a different origin manifest is completely ignored.
 
 PASS
diff --git a/third_party/blink/web_tests/http/tests/appcache/different-scheme-expected.txt b/third_party/blink/web_tests/http/tests/appcache/different-scheme-expected.txt
index 3c2462b..0c2dbf548 100644
--- a/third_party/blink/web_tests/http/tests/appcache/different-scheme-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/different-scheme-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that application cache doesn't block loading resources with different schemes.
 
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/document-write-html-element-2-expected.txt b/third_party/blink/web_tests/http/tests/appcache/document-write-html-element-2-expected.txt
index 32581f4f..d45bc6d 100644
--- a/third_party/blink/web_tests/http/tests/appcache/document-write-html-element-2-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/document-write-html-element-2-expected.txt
@@ -1,2 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: line 11: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 SUCCESS, no assertion failure
 applicationCache.status == 1
diff --git a/third_party/blink/web_tests/http/tests/appcache/empty-manifest-expected.txt b/third_party/blink/web_tests/http/tests/appcache/empty-manifest-expected.txt
index bba93cfa..36e5d12 100644
--- a/third_party/blink/web_tests/http/tests/appcache/empty-manifest-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/empty-manifest-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that the cached event gets sent even if the manifest is empty.
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/exceptions-expected.txt b/third_party/blink/web_tests/http/tests/appcache/exceptions-expected.txt
index f0b1e6b8..b845fab 100644
--- a/third_party/blink/web_tests/http/tests/appcache/exceptions-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/exceptions-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that 'ApplicationCache' methods throw exceptions with reasonable messages.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/http/tests/appcache/fail-on-update-2-expected.txt b/third_party/blink/web_tests/http/tests/appcache/fail-on-update-2-expected.txt
deleted file mode 100644
index cd15247..0000000
--- a/third_party/blink/web_tests/http/tests/appcache/fail-on-update-2-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-SUCCESS: No crash.
diff --git a/third_party/blink/web_tests/http/tests/appcache/fail-on-update-2.html b/third_party/blink/web_tests/http/tests/appcache/fail-on-update-2.html
index ee85668..3ab4fa1 100644
--- a/third_party/blink/web_tests/http/tests/appcache/fail-on-update-2.html
+++ b/third_party/blink/web_tests/http/tests/appcache/fail-on-update-2.html
@@ -1,10 +1,11 @@
 <!DOCTYPE HTML>
 <html manifest="resources/fail-on-update-2.php">
+<head>
+<title>fail-on-update-2.html</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
 <script>
-if (window.testRunner) {
-    testRunner.dumpAsText();
-    testRunner.waitUntilDone();
-}
+setup({ single_test: true });
 
 function setManifestDeleted(state, callback)
 {
@@ -26,7 +27,7 @@
     function afterDelete()
     {
         applicationCache.update();
-        
+
         // Create two subframes at different times to make hitting the race condition more likely.
         var ifr = document.createElement("iframe");
         ifr.setAttribute("src", 'resources/fail-on-update-2.html');
@@ -46,7 +47,7 @@
     if (!--subframesLeft) {
         document.write('<p>SUCCESS: No crash.</p>');
         if (window.testRunner)
-            testRunner.notifyDone();
+            done();
     }
 }
 
@@ -69,6 +70,8 @@
 var timeoutId = setTimeout(resetManifest, 100);
 
 </script>
+</head>
+<body>
 <p>Test for a particular incorrect assertion failure.</p>
-
+</body>
 </html>
diff --git a/third_party/blink/web_tests/http/tests/appcache/fail-on-update-expected.txt b/third_party/blink/web_tests/http/tests/appcache/fail-on-update-expected.txt
deleted file mode 100644
index cd15247..0000000
--- a/third_party/blink/web_tests/http/tests/appcache/fail-on-update-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-SUCCESS: No crash.
diff --git a/third_party/blink/web_tests/http/tests/appcache/fail-on-update.html b/third_party/blink/web_tests/http/tests/appcache/fail-on-update.html
index 251a8e0..b6dbd6a 100644
--- a/third_party/blink/web_tests/http/tests/appcache/fail-on-update.html
+++ b/third_party/blink/web_tests/http/tests/appcache/fail-on-update.html
@@ -1,10 +1,11 @@
 <!DOCTYPE HTML>
 <html manifest="resources/fail-on-update.php">
+<head>
+<title>fail-on-update.html</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
 <script>
-if (window.testRunner) {
-    testRunner.dumpAsText();
-    testRunner.waitUntilDone();
-}
+setup({ single_test: true });
 
 function setManifestDeleted(state, callback)
 {
@@ -26,7 +27,7 @@
     function afterDelete()
     {
         applicationCache.update();
-        window.location = 'resources/notify-no-crash.html';
+        done();
     }
 }
 
@@ -49,6 +50,8 @@
 var timeoutId = setTimeout(resetManifest, 100);
 
 </script>
+</head>
+<body>
 <p>Test for a particular incorrect assertion failure.</p>
-
+</body>
 </html>
diff --git a/third_party/blink/web_tests/http/tests/appcache/fallback-expected.txt b/third_party/blink/web_tests/http/tests/appcache/fallback-expected.txt
index 4e55b71..d491465 100644
--- a/third_party/blink/web_tests/http/tests/appcache/fallback-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/fallback-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 24: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test application cache fallback entries.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/foreign-fallback-expected.txt b/third_party/blink/web_tests/http/tests/appcache/foreign-fallback-expected.txt
index 52a7d13..cf2e6a0 100644
--- a/third_party/blink/web_tests/http/tests/appcache/foreign-fallback-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/foreign-fallback-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test for bug 44406: Application Cache crash when a fallback document has a manifest URL.
 
 PASS
diff --git a/third_party/blink/web_tests/http/tests/appcache/foreign-iframe-main-expected.txt b/third_party/blink/web_tests/http/tests/appcache/foreign-iframe-main-expected.txt
index 1661ad3d..7e67c97 100644
--- a/third_party/blink/web_tests/http/tests/appcache/foreign-iframe-main-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/foreign-iframe-main-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test for <rdar://problem/6284708> AppCache crashes in ApplicationCacheResource::addType().
 
 checking
diff --git a/third_party/blink/web_tests/http/tests/appcache/local-content-expected.txt b/third_party/blink/web_tests/http/tests/appcache/local-content-expected.txt
index e7767dfb..73b2d72 100644
--- a/third_party/blink/web_tests/http/tests/appcache/local-content-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/local-content-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE ERROR: line 28: Not allowed to load local resource: stdio.h
 Test that documents loaded from application cache don't get access to local resources accidentally.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/main-resource-hash-expected.txt b/third_party/blink/web_tests/http/tests/appcache/main-resource-hash-expected.txt
index 93a11b10..68a7160 100644
--- a/third_party/blink/web_tests/http/tests/appcache/main-resource-hash-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/main-resource-hash-expected.txt
@@ -1,4 +1,5 @@
 CONSOLE WARNING: line 21: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that offline applications' main resources are not affected by URL hashes.
 
 Should say SUCCESS:
diff --git a/third_party/blink/web_tests/http/tests/appcache/main-resource-redirect-expected.txt b/third_party/blink/web_tests/http/tests/appcache/main-resource-redirect-expected.txt
index a3c3a553..bef7e98c 100644
--- a/third_party/blink/web_tests/http/tests/appcache/main-resource-redirect-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/main-resource-redirect-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: line 3: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that application cache is consulted again after a redirect response.
 
 PASS
diff --git a/third_party/blink/web_tests/http/tests/appcache/manifest-containing-itself-expected.txt b/third_party/blink/web_tests/http/tests/appcache/manifest-containing-itself-expected.txt
index 77e2506..666dc2b 100644
--- a/third_party/blink/web_tests/http/tests/appcache/manifest-containing-itself-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/manifest-containing-itself-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that a manifest can contain itself as a resource.
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/manifest-parsing-expected.txt b/third_party/blink/web_tests/http/tests/appcache/manifest-parsing-expected.txt
index 0448450..b100450 100644
--- a/third_party/blink/web_tests/http/tests/appcache/manifest-parsing-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/manifest-parsing-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 21: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test application cache manifest parsing.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/manifest-redirect-2-expected.txt b/third_party/blink/web_tests/http/tests/appcache/manifest-redirect-2-expected.txt
index 420e94b..11c0971 100644
--- a/third_party/blink/web_tests/http/tests/appcache/manifest-redirect-2-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/manifest-redirect-2-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: line 25: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a redirect makes resource caching fail.
 
 Should say SUCCESS:
diff --git a/third_party/blink/web_tests/http/tests/appcache/manifest-redirect-expected.txt b/third_party/blink/web_tests/http/tests/appcache/manifest-redirect-expected.txt
index 420e94b..11c0971 100644
--- a/third_party/blink/web_tests/http/tests/appcache/manifest-redirect-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/manifest-redirect-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: line 25: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a redirect makes resource caching fail.
 
 Should say SUCCESS:
diff --git a/third_party/blink/web_tests/http/tests/appcache/manifest-with-empty-file-expected.txt b/third_party/blink/web_tests/http/tests/appcache/manifest-with-empty-file-expected.txt
index 3cf2ce6b..2561765 100644
--- a/third_party/blink/web_tests/http/tests/appcache/manifest-with-empty-file-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/manifest-with-empty-file-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that a manifest that contains an empty file will not crash the browser.
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/modified-manifest-expected.txt b/third_party/blink/web_tests/http/tests/appcache/modified-manifest-expected.txt
index 1bfb2ef..2ffdc7e6 100644
--- a/third_party/blink/web_tests/http/tests/appcache/modified-manifest-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/modified-manifest-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a manifest that changes during an update fails.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/http/tests/appcache/multi-fallback-expected.txt b/third_party/blink/web_tests/http/tests/appcache/multi-fallback-expected.txt
index d0b085c..cf95cad2 100644
--- a/third_party/blink/web_tests/http/tests/appcache/multi-fallback-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/multi-fallback-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 24: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test application cache fallback entries with multiple candidates.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/navigating-away-while-cache-attempt-in-progress-expected.txt b/third_party/blink/web_tests/http/tests/appcache/navigating-away-while-cache-attempt-in-progress-expected.txt
index ca09f7e..e8c3739 100644
--- a/third_party/blink/web_tests/http/tests/appcache/navigating-away-while-cache-attempt-in-progress-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/navigating-away-while-cache-attempt-in-progress-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that navigating away while a cache is loading does not crash.
 SUCCESS - did not crash
diff --git a/third_party/blink/web_tests/http/tests/appcache/non-html-expected.txt b/third_party/blink/web_tests/http/tests/appcache/non-html-expected.txt
index 03bd099..e34d0e7 100644
--- a/third_party/blink/web_tests/http/tests/appcache/non-html-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/non-html-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 47: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that non-HTML main resources work with application cache correctly.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events-expected.txt b/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events-expected.txt
deleted file mode 100644
index dbdca0d51..0000000
--- a/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Test that master list entries receive errors when manifest becomes obsolete.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-PASS eventDetailsFromWindow.type is "obsolete"
-PASS eventDetailsFromFrame.type is "error"
-PASS eventDetailsFromFrame.reason is "manifest"
-PASS eventDetailsFromFrame.url is ""
-PASS eventDetailsFromFrame.status is 404
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events.html b/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events.html
index 4f5f21c..5457e234 100644
--- a/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events.html
+++ b/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events.html
@@ -1,8 +1,12 @@
+<!DOCTYPE HTML>
 <html manifest="resources/fail-on-update.php">
-<script src="/js-test-resources/js-test.js"></script>
+<head>
+<title>obsolete-error-events.html</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
 <script>
-var jsTestIsAsync = true;
-description("Test that master list entries receive errors when manifest becomes obsolete.");
+setup({ single_test: true });
+// Test that master list entries receive errors when manifest becomes obsolete.
 
 function setManifestState(state, callback)
 {
@@ -29,20 +33,20 @@
     if (!eventDetailsFromFrame || !eventDetailsFromWindow)
         return;
 
-    shouldBeEqualToString("eventDetailsFromWindow.type", "obsolete");
+    assert_equals(eventDetailsFromWindow.type, "obsolete");
 
-    shouldBeEqualToString("eventDetailsFromFrame.type", "error");
-    shouldBeEqualToString("eventDetailsFromFrame.reason", "manifest");
-    shouldBeEqualToString("eventDetailsFromFrame.url", "");
-    shouldBe("eventDetailsFromFrame.status", "404");
+    assert_equals(eventDetailsFromFrame.type, "error");
+    assert_equals(eventDetailsFromFrame.reason, "manifest");
+    assert_equals(eventDetailsFromFrame.url, "");
+    assert_equals(eventDetailsFromFrame.status, 404);
 
-    finishJSTest();
+    done();
 }
 
 function test()
 {
-    applicationCache.onnoupdate = function() { testFailed("Unexpected noupdate event") }
-    applicationCache.oncached = function() { testFailed("Unexpected cached event") }
+    applicationCache.onnoupdate = function() { assert_true(false, "Unexpected noupdate event") }
+    applicationCache.oncached = function() { assert_true(false, "Unexpected cached event") }
 
     setManifestState('delete', () => {
         // The frame will be associated to a cache, but update will obsolete it.
@@ -75,7 +79,6 @@
 // If the manifest script happened to be in a wrong state, reset it.
 var timeoutId = setTimeout(resetManifest, 100);
 
-setTimeout(finishJSTest, 2000);
+setTimeout(done, 2000);
 </script>
-</body>
 </html>
diff --git a/third_party/blink/web_tests/http/tests/appcache/offline-access-expected.txt b/third_party/blink/web_tests/http/tests/appcache/offline-access-expected.txt
index 48452744..fa0f090 100644
--- a/third_party/blink/web_tests/http/tests/appcache/offline-access-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/offline-access-expected.txt
@@ -1,4 +1,5 @@
 CONSOLE WARNING: line 21: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that offline applications work when there is no network access (simulated).
 
 Should say SUCCESS:
diff --git a/third_party/blink/web_tests/http/tests/appcache/online-fallback-layering-expected.txt b/third_party/blink/web_tests/http/tests/appcache/online-fallback-layering-expected.txt
index ab817c0..88a93c1 100644
--- a/third_party/blink/web_tests/http/tests/appcache/online-fallback-layering-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/online-fallback-layering-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 22: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that a network namespace trumps a fallback namespace where they overlap.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/online-whitelist-expected.txt b/third_party/blink/web_tests/http/tests/appcache/online-whitelist-expected.txt
index 20a4ca3..2f06beb 100644
--- a/third_party/blink/web_tests/http/tests/appcache/online-whitelist-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/online-whitelist-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 35: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test online whitelist functionality. Should say PASS:
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/progress-counter-expected.txt b/third_party/blink/web_tests/http/tests/appcache/progress-counter-expected.txt
index c9e3db2..2ff5587 100644
--- a/third_party/blink/web_tests/http/tests/appcache/progress-counter-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/progress-counter-expected.txt
@@ -1,2 +1,3 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This tests that the lengthComputable / loaded / total properties of the progress event are set correctly.
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/reload-expected.txt b/third_party/blink/web_tests/http/tests/appcache/reload-expected.txt
index 64c5ecb..c828fda 100644
--- a/third_party/blink/web_tests/http/tests/appcache/reload-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/reload-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 8: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that the manifest is picked correctly when reloading.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/remove-cache-expected.txt b/third_party/blink/web_tests/http/tests/appcache/remove-cache-expected.txt
index 8d54a3bc..356d414 100644
--- a/third_party/blink/web_tests/http/tests/appcache/remove-cache-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/remove-cache-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: line 13: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 22: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that a 404 response for manifest results in cache removal.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/resource-redirect-2-expected.txt b/third_party/blink/web_tests/http/tests/appcache/resource-redirect-2-expected.txt
index 420e94b..11c0971 100644
--- a/third_party/blink/web_tests/http/tests/appcache/resource-redirect-2-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/resource-redirect-2-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: line 25: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a redirect makes resource caching fail.
 
 Should say SUCCESS:
diff --git a/third_party/blink/web_tests/http/tests/appcache/resource-redirect-expected.txt b/third_party/blink/web_tests/http/tests/appcache/resource-redirect-expected.txt
index 7fa757a..932cefc 100644
--- a/third_party/blink/web_tests/http/tests/appcache/resource-redirect-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/resource-redirect-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a redirect makes resource caching fail.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/http/tests/appcache/simple-expected.txt b/third_party/blink/web_tests/http/tests/appcache/simple-expected.txt
index 4bba440..cab92b6 100644
--- a/third_party/blink/web_tests/http/tests/appcache/simple-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/simple-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 15: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 This tests that the application cache works by first loading a file that does not exist in the cache (to verify that a cache has been associated) and then loads a file that is in the cache
 SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/top-frame-1-expected.txt b/third_party/blink/web_tests/http/tests/appcache/top-frame-1-expected.txt
index f8935f1..7c5c65d 100644
--- a/third_party/blink/web_tests/http/tests/appcache/top-frame-1-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/top-frame-1-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 3: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that a subframe without manifest doesn't pick an application cache from parent frame (as long as no relevant cache contains its resource).
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/top-frame-2-expected.txt b/third_party/blink/web_tests/http/tests/appcache/top-frame-2-expected.txt
index 9e56c06..a8df8c4c 100644
--- a/third_party/blink/web_tests/http/tests/appcache/top-frame-2-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/top-frame-2-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 4: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that a subframe without manifest gets picked by a relevant application cache that contains its resource.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/top-frame-3-expected.txt b/third_party/blink/web_tests/http/tests/appcache/top-frame-3-expected.txt
index 0d0ec04..c484be6 100644
--- a/third_party/blink/web_tests/http/tests/appcache/top-frame-3-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/top-frame-3-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 9: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that a subframe with manifest that matches top frame manifest works correctly.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/top-frame-4-expected.txt b/third_party/blink/web_tests/http/tests/appcache/top-frame-4-expected.txt
index 46d08b58..f4557bc2 100644
--- a/third_party/blink/web_tests/http/tests/appcache/top-frame-4-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/top-frame-4-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 9: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that a subframe with manifest that matches top frame manifest works correctly.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/update-cache-expected.txt b/third_party/blink/web_tests/http/tests/appcache/update-cache-expected.txt
index 22c9a0e3..e8a7d4f 100644
--- a/third_party/blink/web_tests/http/tests/appcache/update-cache-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/update-cache-expected.txt
@@ -1,4 +1,6 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 20: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
+CONSOLE WARNING: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test a simple offline application self-update process. Should print a series of messages followed with DONE:
 
 Updating cache group...
diff --git a/third_party/blink/web_tests/http/tests/appcache/whitelist-wildcard-expected.txt b/third_party/blink/web_tests/http/tests/appcache/whitelist-wildcard-expected.txt
index ae5f39f..bd896da 100644
--- a/third_party/blink/web_tests/http/tests/appcache/whitelist-wildcard-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/whitelist-wildcard-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 14: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that online whitelist wildcard flag is implemented.
 
diff --git a/third_party/blink/web_tests/http/tests/appcache/wrong-content-type-expected.txt b/third_party/blink/web_tests/http/tests/appcache/wrong-content-type-expected.txt
index 99c5125e..c40f13f 100644
--- a/third_party/blink/web_tests/http/tests/appcache/wrong-content-type-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/wrong-content-type-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: line 26: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a manifest served with an arbitrary content-type is OK.
 
 Should say SUCCESS:
diff --git a/third_party/blink/web_tests/http/tests/appcache/wrong-signature-2-expected.txt b/third_party/blink/web_tests/http/tests/appcache/wrong-signature-2-expected.txt
index 7fb74b47..536baa2 100644
--- a/third_party/blink/web_tests/http/tests/appcache/wrong-signature-2-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/wrong-signature-2-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a manifest served with a wrong signature isn't treated as such.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/http/tests/appcache/wrong-signature-expected.txt b/third_party/blink/web_tests/http/tests/appcache/wrong-signature-expected.txt
index 7fb74b47..536baa2 100644
--- a/third_party/blink/web_tests/http/tests/appcache/wrong-signature-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/wrong-signature-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API use is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 Test that a manifest served with a wrong signature isn't treated as such.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/http/tests/appcache/xhr-foreign-resource-expected.txt b/third_party/blink/web_tests/http/tests/appcache/xhr-foreign-resource-expected.txt
index 6189d7e1..e12515b 100644
--- a/third_party/blink/web_tests/http/tests/appcache/xhr-foreign-resource-expected.txt
+++ b/third_party/blink/web_tests/http/tests/appcache/xhr-foreign-resource-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 CONSOLE WARNING: line 18: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 Test that a resource marked as foreign can still be loaded via XHR.
 
diff --git a/third_party/blink/web_tests/http/tests/credentialmanager/publickeycredential-basics.html b/third_party/blink/web_tests/http/tests/credentialmanager/publickeycredential-basics.html
index 4a76b66..165a519c 100644
--- a/third_party/blink/web_tests/http/tests/credentialmanager/publickeycredential-basics.html
+++ b/third_party/blink/web_tests/http/tests/credentialmanager/publickeycredential-basics.html
@@ -13,7 +13,6 @@
 <script src="/gen/third_party/blink/public/mojom/credentialmanager/credential_manager.mojom-lite.js"></script>
 <script src="/gen/third_party/blink/public/mojom/webauthn/authenticator.mojom-lite.js"></script>
 <script src="/gen/third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom-lite.js"></script>
-<script src="/gen/third_party/blink/public/mojom/frame/document_interface_broker.mojom-lite.js"></script>
 <script src="resources/virtual-navigator-credentials.js"></script>
 <script>
 
diff --git a/third_party/blink/web_tests/http/tests/loading/appcache-delay/appcache-loads-subresource-expected.txt b/third_party/blink/web_tests/http/tests/loading/appcache-delay/appcache-loads-subresource-expected.txt
index a787863b..b9c46db 100644
--- a/third_party/blink/web_tests/http/tests/loading/appcache-delay/appcache-loads-subresource-expected.txt
+++ b/third_party/blink/web_tests/http/tests/loading/appcache-delay/appcache-loads-subresource-expected.txt
@@ -1,6 +1,7 @@
 main frame - DidStartNavigation
 main frame - ReadyToCommitNavigation
 main frame - didCommitLoadForFrame
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 main frame - didReceiveTitle: 
 main frame - didFinishDocumentLoadForFrame
 main frame - didHandleOnloadEventsForFrame
diff --git a/third_party/blink/web_tests/http/tests/mojo/document-interface-broker-override.html b/third_party/blink/web_tests/http/tests/mojo/document-interface-broker-override.html
deleted file mode 100644
index 930f4a2..0000000
--- a/third_party/blink/web_tests/http/tests/mojo/document-interface-broker-override.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<body>
-<script src="/js-test-resources/document-interface-broker-helpers.js"></script>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings_lite.js"></script>
-<script src="/gen/mojo/public/mojom/base/unguessable_token.mojom-lite.js"></script>
-<script src="/gen/url/mojom/url.mojom-lite.js"></script>
-<script src="/gen/third_party/blink/public/mojom/frame/frame_host_test_interface.mojom-lite.js"></script>
-<script src="/gen/third_party/blink/public/mojom/frame/document_interface_broker.mojom-lite.js"></script>
-<script>
-'use strict';
-
-promise_test(async t => {
-  // Create a test implementation of FrameHostTestInterface
-  const frameHostTestImpl = new blink.mojom.FrameHostTestInterfaceCallbackRouter;
-  frameHostTestImpl.getName.addListener(() => ({ name: 'TestFrameHostTestImpl' }));
-
-  const broker = new blink.mojom.DocumentInterfaceBrokerRemote(
-      Mojo.getDocumentInterfaceBrokerHandle());
-
-  const testInterfaceBeforeOverride = new blink.mojom.FrameHostTestInterfaceRemote;
-  broker.getFrameHostTestInterface(testInterfaceBeforeOverride.$.bindNewPipeAndPassReceiver());
-
-  setDocumentInterfaceBrokerOverrides({ getFrameHostTestInterface: request => {
-    frameHostTestImpl.$.bindHandle(request.handle);
-  }});
-
-  const testInterfaceAfterOverride = new blink.mojom.FrameHostTestInterfaceRemote;
-  broker.getFrameHostTestInterface(testInterfaceAfterOverride.$.bindNewPipeAndPassReceiver());
-
-  // Verify that RenderFrameHostImpl's implementation gets called without an override
-  let reply = await testInterfaceBeforeOverride.getName();
-  assert_equals(reply.name, 'RenderFrameHostImpl');
-
-  // Verify that the test implementation gets called after the override
-  reply = await testInterfaceAfterOverride.getName();
-  assert_equals(reply.name, 'TestFrameHostTestImpl');
-},
-'Appropriate DocumentInterfaceBroker implementations are called before and after overriding');
-
-</script>
- </body>
- </html>
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-appcache-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-appcache-allowed-expected.txt
index bdddf836..87e2513 100644
--- a/third_party/blink/web_tests/http/tests/security/cross-origin-appcache-allowed-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/cross-origin-appcache-allowed-expected.txt
@@ -1,3 +1,5 @@
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
 This iframe should have a cache:
 
 This iframe should have a cache:
diff --git a/third_party/blink/web_tests/http/tests/security/powerfulFeatureRestrictions/old-powerful-features-on-insecure-origin-expected.txt b/third_party/blink/web_tests/http/tests/security/powerfulFeatureRestrictions/old-powerful-features-on-insecure-origin-expected.txt
index a6285a7..7777b27 100644
--- a/third_party/blink/web_tests/http/tests/security/powerfulFeatureRestrictions/old-powerful-features-on-insecure-origin-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/powerfulFeatureRestrictions/old-powerful-features-on-insecure-origin-expected.txt
@@ -1,4 +1,5 @@
-CONSOLE WARNING: Application Cache is restricted to secure contexts. Please consider migrating your application to HTTPS, and eventually shifting over to Service Workers. See https://goo.gl/rStTGz for more details.
+CONSOLE WARNING: Application Cache API manifest selection is deprecated and will be removed in M82, around April 2020. See https://www.chromestatus.com/features/6192449487634432 for more details.
+CONSOLE WARNING: Application Cache was previously restricted to secure origins only from M70 on but now secure origin use is deprecated and will be removed in M82.  Please shift your use case over to Service Workers.
 CONSOLE WARNING: line 21: getCurrentPosition() and watchPosition() no longer work on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.
 This is a testharness.js-based test.
 PASS getCurrentPosition
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index c1f2a4f..12996e81 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -834,8 +834,6 @@
     static method createDataPipe
     static method createMessagePipe
     static method createSharedBuffer
-    static method getDocumentInterfaceBrokerHandle
-    static method replaceDocumentInterfaceBrokerForTesting
     attribute @@toStringTag
     attribute RESULT_ABORTED
     attribute RESULT_ALREADY_EXISTS
diff --git a/third_party/blink/web_tests/resources/document-interface-broker-helpers.js b/third_party/blink/web_tests/resources/document-interface-broker-helpers.js
deleted file mode 100644
index 6cc6e88..0000000
--- a/third_party/blink/web_tests/resources/document-interface-broker-helpers.js
+++ /dev/null
@@ -1,30 +0,0 @@
-'use strict';
-
-/**
- * Allows to override specific interface request handlers for
- * DocumentInterfaceBroker for testing purposes
- * @param {Object} overrides an object where the keys are names of
- *     DocumentInterfaceBroker's methods and the values are corresponding handler
- *     functions taking a request parameter and binding its handle to the relevant
- *     testing implementation.
- * Example:
- *   const testFooImpl = new FooInterfaceCallbackRouter;
- *   ... override FooInterface methods ...
- *   setDocumentInterfaceBrokerOverrides({getFooInterface: request => {
- *     testFooImpl.$.bindHandle(request.handle);
- *   }});
- */
-function setDocumentInterfaceBrokerOverrides(overrides) {
-  const {handle0, handle1} = Mojo.createMessagePipe();
-  const realBrokerRemote = new blink.mojom.DocumentInterfaceBrokerRemote(
-      Mojo.replaceDocumentInterfaceBrokerForTesting(handle0));
-
-  for (const method of Object.keys(overrides)) {
-    realBrokerRemote[method] = overrides[method];
-  }
-
-  // Use the real broker (with overrides) as the implementation of the JS-side broker
-  const testBrokerReceiver =
-    new blink.mojom.DocumentInterfaceBrokerReceiver(realBrokerRemote);
-  testBrokerReceiver.$.bindHandle(handle1);
-}
diff --git a/third_party/blink/web_tests/virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/README.md b/third_party/blink/web_tests/virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/README.md
deleted file mode 100644
index a2696b5..0000000
--- a/third_party/blink/web_tests/virtual/compositor_threaded_scrollbar_scrolling_hidpi_nozoomfordsf/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory is dedicated for testing the "Compositor threaded
-scrollbar scrolling" feature with DSF = 2 and use_zoom_for_dsf set
-to false. This is done in order to simulate the current setup on Mac
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index f826dfe2..37974b2 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -806,8 +806,6 @@
 [Worker]     static method createDataPipe
 [Worker]     static method createMessagePipe
 [Worker]     static method createSharedBuffer
-[Worker]     static method getDocumentInterfaceBrokerHandle
-[Worker]     static method replaceDocumentInterfaceBrokerForTesting
 [Worker]     attribute @@toStringTag
 [Worker]     attribute RESULT_ABORTED
 [Worker]     attribute RESULT_ALREADY_EXISTS
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 531b4df..b1d280a4 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -4987,8 +4987,6 @@
     static method createDataPipe
     static method createMessagePipe
     static method createSharedBuffer
-    static method getDocumentInterfaceBrokerHandle
-    static method replaceDocumentInterfaceBrokerForTesting
     attribute @@toStringTag
     attribute RESULT_ABORTED
     attribute RESULT_ALREADY_EXISTS
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index 1e2f3bc5..f9e3191 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -788,8 +788,6 @@
 [Worker]     static method createDataPipe
 [Worker]     static method createMessagePipe
 [Worker]     static method createSharedBuffer
-[Worker]     static method getDocumentInterfaceBrokerHandle
-[Worker]     static method replaceDocumentInterfaceBrokerForTesting
 [Worker]     attribute @@toStringTag
 [Worker]     attribute RESULT_ABORTED
 [Worker]     attribute RESULT_ALREADY_EXISTS
diff --git a/third_party/boringssl/gtest_main_chromium.cc b/third_party/boringssl/gtest_main_chromium.cc
index 128c9be..7374f43 100644
--- a/third_party/boringssl/gtest_main_chromium.cc
+++ b/third_party/boringssl/gtest_main_chromium.cc
@@ -26,5 +26,5 @@
   BoringSSLTestSuite test_suite(argc, argv);
   return base::LaunchUnitTests(
       argc, argv,
-      base::Bind(&BoringSSLTestSuite::Run, base::Unretained(&test_suite)));
+      base::BindOnce(&BoringSSLTestSuite::Run, base::Unretained(&test_suite)));
 }
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 407bc07..ad39f2b9 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -70,7 +70,7 @@
 
       # This bot must use the gpu_tests mixin to match 'Android FYI Release (Nexus 5X)'
       # on the chromium.gpu waterfall, which it mirrors via trybots.pyl.
-      'android-marshmallow-arm64-rel': 'gpu_tests_android_release_bot_minimal_symbols_arm64',
+      'android-marshmallow-arm64-rel': 'gpu_tests_android_release_bot_minimal_symbols_arm64_fastbuild',
 
       'android-pie-arm64-rel': 'android_release_bot_minimal_symbols_arm64_webview_google',
     },
@@ -381,7 +381,7 @@
       'GPU Linux Builder (dbg)': 'gpu_tests_debug_trybot',
       'GPU Win x64 Builder': 'gpu_tests_release_trybot_resource_whitelisting',
       'GPU Win x64 Builder (dbg)': 'gpu_tests_debug_trybot',
-      'Android Release (Nexus 5X)': 'gpu_tests_android_release_trybot_arm64',
+      'Android Release (Nexus 5X)': 'gpu_tests_android_release_trybot_arm64_fastbuild',
     },
 
     'chromium.gpu.fyi': {
@@ -671,7 +671,7 @@
       'android-cronet-arm-dbg': 'android_cronet_debug_static_bot_arm_no_neon',
       'android-kitkat-arm-rel': 'android_release_trybot_fastbuild',
       'android-marshmallow-arm64-coverage-rel': 'gpu_tests_android_release_trybot_arm64_resource_whitelisting_java_coverage',
-      'android-marshmallow-arm64-rel': 'gpu_tests_android_release_trybot_arm64_resource_whitelisting',
+      'android-marshmallow-arm64-rel': 'gpu_tests_android_release_trybot_arm64_resource_whitelisting_fastbuild',
       'android-marshmallow-x86-fyi-rel': 'android_release_trybot_x86_resource_whitelisting',
       'android-oreo-arm64-cts-networkservice-dbg': 'android_debug_trybot_arm64',
       'android-pie-arm64-rel': 'android_release_trybot_arm64_webview_google',
@@ -682,11 +682,11 @@
       'android-webview-oreo-arm64-dbg': 'android_release_trybot_arm64_webview_google',
       'android-webview-pie-arm64-dbg': 'android_release_trybot_arm64_webview_google',
       'android_archive_rel_ng': 'android_release_trybot',
-      'android_arm64_dbg_recipe': 'android_debug_trybot_compile_only_arm64',
+      'android_arm64_dbg_recipe': 'android_debug_trybot_compile_only_arm64_fastbuild',
       'android-binary-size': 'android_binary_size',
       'android_blink_rel': 'android_release_trybot',
       'android_cfi_rel_ng': 'android_cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on_goma',
-      'android_clang_dbg_recipe': 'android_clang_asan_debug_trybot_compile_only',
+      'android_clang_dbg_recipe': 'android_clang_asan_debug_trybot_compile_only_fastbuild',
       'android_compile_dbg': 'android_debug_trybot_compile_only',
       'android_compile_x64_dbg': 'android_debug_trybot_compile_only_x64',
       'android_compile_x86_dbg': 'android_debug_trybot_compile_only_x86',
@@ -1006,8 +1006,9 @@
       'android', 'clang', 'asan', 'debug_bot', 'strip_debug_info',
     ],
 
-    'android_clang_asan_debug_trybot_compile_only': [
+    'android_clang_asan_debug_trybot_compile_only_fastbuild': [
       'android', 'clang', 'asan', 'debug_trybot', 'compile_only',
+      'android_fastbuild',
     ],
 
     'android_clang_asan_release_bot': [
@@ -1119,8 +1120,8 @@
       'android', 'debug_trybot', 'compile_only',
     ],
 
-    'android_debug_trybot_compile_only_arm64': [
-      'android', 'debug_trybot', 'compile_only', 'arm64',
+    'android_debug_trybot_compile_only_arm64_fastbuild': [
+      'android', 'debug_trybot', 'compile_only', 'arm64', 'android_fastbuild'
     ],
 
     'android_debug_trybot_compile_only_x64': [
@@ -1636,9 +1637,9 @@
       'gpu_fyi_tests', 'dx12vk', 'release_trybot',
     ],
 
-    'gpu_tests_android_release_bot_minimal_symbols_arm64': [
+    'gpu_tests_android_release_bot_minimal_symbols_arm64_fastbuild': [
       'android', 'release_bot', 'minimal_symbols', 'arm64',
-      'resource_whitelisting', 'static_angle',
+      'resource_whitelisting', 'static_angle', 'android_fastbuild'
     ],
 
     'gpu_tests_android_release_trybot': [
@@ -1649,8 +1650,14 @@
       'gpu_tests', 'android', 'release_trybot', 'arm64', 'static_angle',
     ],
 
-    'gpu_tests_android_release_trybot_arm64_resource_whitelisting': [
-      'android', 'release_trybot', 'arm64', 'static_angle', 'resource_whitelisting',
+    'gpu_tests_android_release_trybot_arm64_fastbuild': [
+      'gpu_tests', 'android', 'release_trybot', 'arm64', 'static_angle',
+      'android_fastbuild',
+    ],
+
+    'gpu_tests_android_release_trybot_arm64_resource_whitelisting_fastbuild': [
+      'android', 'release_trybot', 'arm64', 'static_angle',
+      'resource_whitelisting', 'android_fastbuild',
     ],
 
     'gpu_tests_android_release_trybot_arm64_resource_whitelisting_java_coverage': [
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 36ced86f..df21ac0 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -5268,7 +5268,7 @@
   <int value="208" label="RFH_CHILD_FRAME_NEEDS_OWNER_ELEMENT_TYPE"/>
   <int value="209" label="OBSOLETE_RFH_INVALID_WEB_REPORTING_CRASH_ID"/>
   <int value="210" label="RFH_DETACH_MAIN_FRAME"/>
-  <int value="211" label="RFH_DOCUMENT_INTERFACE_BROKER_MISSING"/>
+  <int value="211" label="RFH_BROWSER_INTERFACE_BROKER_MISSING"/>
   <int value="212" label="RFPH_POST_MESSAGE_INVALID_SOURCE_ORIGIN"/>
   <int value="213" label="INVALID_INITIATOR_ORIGIN"/>
   <int value="214" label="RFHI_BEGIN_NAVIGATION_MISSING_INITIATOR_ORIGIN"/>
@@ -15847,6 +15847,7 @@
   <int value="385" label="weba"/>
   <int value="386" label="webm"/>
   <int value="387" label="xbm"/>
+  <int value="388" label="accdb"/>
 </enum>
 
 <enum name="DownloadItem.DangerType">
@@ -55347,6 +55348,7 @@
   <int value="385" label="WEBA"/>
   <int value="386" label="WEBM"/>
   <int value="387" label="XBM"/>
+  <int value="388" label="ACCDB"/>
 </enum>
 
 <enum name="SBClientDownloadIsSignedBinary">
@@ -59550,6 +59552,18 @@
   <int value="2" label="ACTION_ADDED_ANOTHER_ACCOUNT"/>
 </enum>
 
+<enum name="StabilityEventType">
+  <summary>
+    One of several separate stability metrics. The values are non-contiguous as
+    they are a subset of values matching fields of the Stability proto (from the
+    SystemProfile).
+  </summary>
+  <int value="2" label="Pageload count"/>
+  <int value="3" label="Renderer crash count"/>
+  <int value="5" label="Extensions renderer count"/>
+  <int value="16" label="Browser crash count"/>
+</enum>
+
 <enum name="StarsLaunchLocation">
   <int value="0" label="All Items"/>
   <int value="1" label="Uncategorized"/>
@@ -59579,6 +59593,9 @@
   <int value="5"
       label="Abandoned because profiled content failed to load its main
              resource"/>
+  <int value="6"
+      label="Abandoned because no content was visible at the beginning of
+             startup"/>
 </enum>
 
 <enum name="StartupTemperature">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 63a19e4..7814f71 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -48566,7 +48566,7 @@
 </histogram>
 
 <histogram name="Feedback.HappinessTrackingSurvey.BubbleUsage"
-    enum="HappinessTrackingSurveyDesktopBubbleUsage" expires_after="M80">
+    enum="HappinessTrackingSurveyDesktopBubbleUsage" expires_after="M82">
   <owner>weili@chromium.org</owner>
   <owner>robliao@chromium.org</owner>
   <summary>
@@ -73816,9 +73816,10 @@
   <owner>michaelpg@chromium.org</owner>
   <owner>yilkal@chormium.org</owner>
   <summary>
-    The maximum number of frames that are present in a WebContents. Recorded
-    once when the main frame is moving away from current page. This can be when
-    the main frame is being destroyed or when it starts loading new content.
+    The maximum number of loaded frames that are present in a WebContents.
+    Recorded once when the main frame is moving away from current page. This can
+    be when the WebContents is being destroyed or when it starts loading new
+    content.
   </summary>
 </histogram>
 
@@ -103469,7 +103470,7 @@
 </histogram>
 
 <histogram name="PasswordManager.CredentialsWithDuplicates" units="units"
-    expires_after="M80">
+    expires_after="M82">
   <owner>dvadym@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <summary>
@@ -103484,7 +103485,7 @@
 </histogram>
 
 <histogram name="PasswordManager.CredentialsWithMismatchedDuplicates"
-    units="units" expires_after="M80">
+    units="units" expires_after="M82">
   <owner>dvadym@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <summary>
@@ -141410,6 +141411,16 @@
   </summary>
 </histogram>
 
+<histogram name="Stability.Experimental.Counts" enum="StabilityEventType"
+    expires_after="M82">
+  <owner>rkaplow@chromium.org</owner>
+  <owner>chrome-metrics-team@google.com</owner>
+  <summary>
+    Collects various counters related to stability. The majority of them are
+    crash types.
+  </summary>
+</histogram>
+
 <histogram name="Stability.Internals.DataDiscardCount" units="counts"
     expires_after="M77">
   <owner>siggi@chromium.org</owner>
diff --git a/tools/metrics/rappor/rappor.xml b/tools/metrics/rappor/rappor.xml
index 2d529b9..cc553ec8 100644
--- a/tools/metrics/rappor/rappor.xml
+++ b/tools/metrics/rappor/rappor.xml
@@ -137,13 +137,6 @@
   </summary>
 </rappor-metric>
 
-<rappor-metric name="DeviceSensors.DeviceMotion" type="ETLD_PLUS_ONE">
-  <owner>timvolodine@chromium.org</owner>
-  <summary>
-    The domain and registry of the URL that is using Device Motion API.
-  </summary>
-</rappor-metric>
-
 <rappor-metric name="DeviceSensors.DeviceMotionCrossOrigin"
     type="ETLD_PLUS_ONE">
   <owner>timvolodine@chromium.org</owner>
@@ -153,13 +146,6 @@
   </summary>
 </rappor-metric>
 
-<rappor-metric name="DeviceSensors.DeviceOrientation" type="ETLD_PLUS_ONE">
-  <owner>timvolodine@chromium.org</owner>
-  <summary>
-    The domain and registry of the URL that is using Device Orientation API.
-  </summary>
-</rappor-metric>
-
 <rappor-metric name="DeviceSensors.DeviceOrientationCrossOrigin"
     type="ETLD_PLUS_ONE">
   <owner>timvolodine@chromium.org</owner>
diff --git a/tools/perf/contrib/cluster_telemetry/generic_trace.py b/tools/perf/contrib/cluster_telemetry/generic_trace.py
index a87bc0af0..e02228e 100644
--- a/tools/perf/contrib/cluster_telemetry/generic_trace.py
+++ b/tools/perf/contrib/cluster_telemetry/generic_trace.py
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from collections import defaultdict
+
 from core import path_util
 path_util.AddTracingToPath()
 from core import perf_benchmark
@@ -34,6 +36,7 @@
   def ValidateAndMeasurePage(self, page, tab, results):
     with tab.browser.platform.tracing_controller.StopTracing() as trace_builder:
       trace_data = trace_builder.AsData()
+    measurements = defaultdict(list)
     for trace in trace_data.GetTracesFor(trace_data_module.CHROME_TRACE_PART):
       for event in trace['traceEvents']:
         # We collect data from duration begin, complete, instant and count
@@ -46,7 +49,9 @@
           if not isinstance(arg_value, int):
             continue
           value_name = '/'.join([event['cat'], event['name'], arg_name])
-          results.AddMeasurement(value_name, 'count', arg_value)
+          measurements[value_name].append(arg_value)
+    for name, value in measurements.items():
+      results.AddMeasurement(name, 'count', value)
 
 
 class _GenericTraceBenchmark(perf_benchmark.PerfBenchmark):
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index f046ea1..6f8e07b 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -224,6 +224,7 @@
 crbug.com/1000473 [ win ] rendering.desktop/balls_svg_animations [ Skip ]
 crbug.com/1017244 [ desktop ] rendering.desktop/youtube_2018 [ Skip ]
 crbug.com/1017244 [ desktop ] rendering.desktop/youtube_pinch_2018 [ Skip ]
+crbug.com/1021682 [ desktop ] rendering.desktop/runway [ Skip ]
 
 # Benchmark: rendering.mobile
 crbug.com/785485 [ android-webview ] rendering.mobile/kevs_3d [ Skip ]
@@ -268,6 +269,7 @@
 crbug.com/967809 [ android-webview ] rendering.mobile/microsoft_video_city [ Skip ]
 crbug.com/1000473 [ android ] rendering.mobile/balls_svg_animations [ Skip ]
 crbug.com/1017244 [ mobile ] rendering.mobile/youtube_2018 [ Skip ]
+crbug.com/1021682 [ mobile ] rendering.mobile/runway [ Skip ]
 
 # Benchmark: rasterize_and_record_micro.top_25
 crbug.com/764543 rasterize_and_record_micro.top_25/file://static_top_25/wikipedia.html [ Skip ]
diff --git a/ui/aura/test/test_screen.cc b/ui/aura/test/test_screen.cc
index 02a69ec6..24521cb 100644
--- a/ui/aura/test/test_screen.cc
+++ b/ui/aura/test/test_screen.cc
@@ -95,7 +95,7 @@
   display.set_rotation(rotation);
   display.SetScaleAndBounds(display.device_scale_factor(), new_bounds);
   display_list().UpdateDisplay(display);
-  host_->SetRootTransform(GetRotationTransform() * GetUIScaleTransform());
+  host_->SetRootTransform(GetUIScaleTransform() * GetRotationTransform());
 }
 
 void TestScreen::SetUIScale(float ui_scale) {
@@ -106,7 +106,7 @@
       gfx::ScaleRect(gfx::RectF(bounds_in_pixel), 1.0f / ui_scale));
   display.SetScaleAndBounds(display.device_scale_factor(), new_bounds);
   display_list().UpdateDisplay(display);
-  host_->SetRootTransform(GetRotationTransform() * GetUIScaleTransform());
+  host_->SetRootTransform(GetUIScaleTransform() * GetRotationTransform());
 }
 
 void TestScreen::SetWorkAreaInsets(const gfx::Insets& insets) {
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc
index 7f4bd21..df33de8 100644
--- a/ui/aura/window_tree_host.cc
+++ b/ui/aura/window_tree_host.cc
@@ -539,10 +539,8 @@
 
 gfx::Rect WindowTreeHost::GetTransformedRootWindowBoundsInPixels(
     const gfx::Size& size_in_pixels) const {
-  gfx::Rect bounds(size_in_pixels);
-  gfx::RectF new_bounds =
-      gfx::ScaleRect(gfx::RectF(bounds), 1.0f / device_scale_factor_);
-  window()->layer()->transform().TransformRect(&new_bounds);
+  gfx::RectF new_bounds = gfx::RectF(gfx::Rect(size_in_pixels));
+  GetInverseRootTransform().TransformRect(&new_bounds);
   return gfx::ToEnclosingRect(new_bounds);
 }
 
diff --git a/ui/aura/window_tree_host_unittest.cc b/ui/aura/window_tree_host_unittest.cc
index 545872bd..2fe69a6 100644
--- a/ui/aura/window_tree_host_unittest.cc
+++ b/ui/aura/window_tree_host_unittest.cc
@@ -34,7 +34,7 @@
   EXPECT_EQ(gfx::Rect(0, 0, 534, 400), root_window()->bounds());
 
   gfx::Transform transform;
-  transform.Translate(0, 1.1f);
+  transform.Translate(0, -1.1f);
   host()->SetRootTransform(transform);
   EXPECT_EQ(gfx::Rect(0, 1, 534, 401), root_window()->bounds());
 
@@ -55,7 +55,7 @@
             gfx::Size(400, 300));
   EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().bounds(),
             gfx::Rect(0, 0, 400, 300));
-  EXPECT_EQ(gfx::Size(400, 300), host()->window()->bounds().size());
+  EXPECT_EQ(gfx::Rect(400, 300), host()->window()->bounds());
 
   host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 300));
   test_screen()->SetDisplayRotation(display::Display::ROTATE_90);
@@ -66,7 +66,7 @@
             gfx::Size(300, 400));
   EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().bounds(),
             gfx::Rect(0, 0, 300, 400));
-  EXPECT_EQ(gfx::Size(300, 400), host()->window()->bounds().size());
+  EXPECT_EQ(gfx::Rect(300, 400), host()->window()->bounds());
 
   host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 300));
   test_screen()->SetDisplayRotation(display::Display::ROTATE_180);
@@ -77,7 +77,7 @@
             gfx::Size(400, 300));
   EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().bounds(),
             gfx::Rect(0, 0, 400, 300));
-  EXPECT_EQ(gfx::Size(400, 300), host()->window()->bounds().size());
+  EXPECT_EQ(gfx::Rect(400, 300), host()->window()->bounds());
 
   host()->SetBoundsInPixels(gfx::Rect(0, 0, 400, 300));
   test_screen()->SetDisplayRotation(display::Display::ROTATE_270);
@@ -88,7 +88,7 @@
             gfx::Size(300, 400));
   EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().bounds(),
             gfx::Rect(0, 0, 300, 400));
-  EXPECT_EQ(gfx::Size(300, 400), host()->window()->bounds().size());
+  EXPECT_EQ(gfx::Rect(300, 400), host()->window()->bounds());
 }
 
 #if defined(OS_CHROMEOS)
diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc
index ad865f0..2fd2d3e 100644
--- a/ui/aura/window_unittest.cc
+++ b/ui/aura/window_unittest.cc
@@ -53,6 +53,7 @@
 #include "ui/events/test/event_generator.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/vector2d.h"
+#include "ui/gfx/overlay_transform_utils.h"
 #include "ui/gfx/skia_util.h"
 
 DEFINE_UI_CLASS_PROPERTY_TYPE(const char*)
@@ -441,7 +442,8 @@
 TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
   gfx::Transform transform;
   transform.Translate(100.0, 100.0);
-  transform.Rotate(90.0);
+  transform = transform * OverlayTransformToTransform(
+                              gfx::OVERLAY_TRANSFORM_ROTATE_90, gfx::Size());
   transform.Scale(2.0, 5.0);
   host()->SetRootTransform(transform);
   host()->MoveCursorToLocationInDIP(gfx::Point(10, 10));
@@ -473,7 +475,8 @@
             display::Screen::GetScreen()->GetCursorScreenPoint().ToString());
 
   gfx::Transform transform3;
-  transform3.Rotate(90.0);
+  transform3 = transform3 * OverlayTransformToTransform(
+                                gfx::OVERLAY_TRANSFORM_ROTATE_90, gfx::Size());
   w1->SetTransform(transform3);
   w1->MoveCursorTo(gfx::Point(5, 5));
   EXPECT_EQ("5,15",
@@ -481,7 +484,8 @@
 
   gfx::Transform transform4;
   transform4.Translate(100.0, 100.0);
-  transform4.Rotate(90.0);
+  transform4 = transform4 * OverlayTransformToTransform(
+                                gfx::OVERLAY_TRANSFORM_ROTATE_90, gfx::Size());
   transform4.Scale(2.0, 5.0);
   w1->SetTransform(transform4);
   w1->MoveCursorTo(gfx::Point(10, 10));
@@ -505,7 +509,9 @@
   // The root window expects transforms that produce integer rects.
   gfx::Transform root_transform;
   root_transform.Translate(60.0, 70.0);
-  root_transform.Rotate(-90.0);
+  root_transform =
+      root_transform * OverlayTransformToTransform(
+                           gfx::OVERLAY_TRANSFORM_ROTATE_270, gfx::Size());
   root_transform.Translate(-50.0, -50.0);
   root_transform.Scale(2.0, 3.0);
 
@@ -1654,10 +1660,8 @@
                                  .bounds());
 
   // Rotate it clock-wise 90 degrees.
-  gfx::Transform transform;
-  transform.Translate(size.height(), 0);
-  transform.Rotate(90.0);
-  host()->SetRootTransform(transform);
+  host()->SetRootTransform(
+      OverlayTransformToTransform(gfx::OVERLAY_TRANSFORM_ROTATE_90, size));
 
   // The size should be the transformed size.
   gfx::Size transformed_size(size.height(), size.width());
@@ -1682,10 +1686,8 @@
       delegate.get(), -1234, gfx::Rect(0, 0, 20, 20), root_window()));
 
   // Rotate the root-window clock-wise 90 degrees.
-  gfx::Transform transform;
-  transform.Translate(size.height(), 0.0);
-  transform.Rotate(90.0);
-  host()->SetRootTransform(transform);
+  host()->SetRootTransform(
+      OverlayTransformToTransform(gfx::OVERLAY_TRANSFORM_ROTATE_90, size));
 
   ui::TouchEvent press(
       ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), getTime(),
diff --git a/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc b/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc
index ca0aeab1..a6e79b2 100644
--- a/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc
+++ b/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc
@@ -43,18 +43,9 @@
     AddCallbacksOnInputPaneShownOrHiddenInBackgroundThread();
   }
 
-  void TryShowInBackgroundThread(HWND hwnd) {
-    // TODO(crbug.com/1007958): Remove this API after landing TSF virtual keyboard
+  void RegisterForInputPaneVisibilityChangeInBackgroundThread(HWND hwnd) {
     DCHECK(!main_task_runner_->BelongsToCurrentThread());
-    if (!EnsureInputPanePointersInBackgroundThread(hwnd))
-      return;
-  }
-
-  void TryHideInBackgroundThread() {
-    // TODO(crbug.com/1007958): Remove this API after landing TSF virtual keyboard
-    DCHECK(!main_task_runner_->BelongsToCurrentThread());
-    if (!input_pane2_)
-      return;
+    EnsureInputPanePointersInBackgroundThread(hwnd);
   }
 
  private:
@@ -64,13 +55,13 @@
     DCHECK(!main_task_runner_->BelongsToCurrentThread());
   }
 
-  bool EnsureInputPanePointersInBackgroundThread(HWND hwnd) {
+  void EnsureInputPanePointersInBackgroundThread(HWND hwnd) {
     DCHECK(!main_task_runner_->BelongsToCurrentThread());
     if (input_pane2_)
-      return true;
+      return;
     if (!base::win::ResolveCoreWinRTDelayload() ||
         !base::win::ScopedHString::ResolveCoreWinRTStringDelayload()) {
-      return false;
+      return;
     }
 
     base::win::AssertComApartmentType(base::win::ComApartmentType::STA);
@@ -81,17 +72,16 @@
     HRESULT hr = base::win::RoGetActivationFactory(
         input_pane_guid.get(), IID_PPV_ARGS(&input_pane_interop));
     if (FAILED(hr))
-      return false;
+      return;
 
     hr = input_pane_interop->GetForWindow(hwnd, IID_PPV_ARGS(&input_pane_));
     if (FAILED(hr))
-      return false;
+      return;
 
     if (FAILED(input_pane_.As(&input_pane2_)))
-      return false;
+      return;
 
     AddCallbacksOnInputPaneShownOrHiddenInBackgroundThread();
-    return true;
   }
 
   // Add callbacks to notify virtual keyboard observers when the virtual
@@ -198,20 +188,14 @@
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   background_task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(&OnScreenKeyboardDisplayManagerInputPane::
-                         VirtualKeyboardInputPane::TryShowInBackgroundThread,
-                     base::RetainedRef(virtual_keyboard_input_pane_), hwnd_));
+      base::BindOnce(
+          &OnScreenKeyboardDisplayManagerInputPane::VirtualKeyboardInputPane::
+              RegisterForInputPaneVisibilityChangeInBackgroundThread,
+          base::RetainedRef(virtual_keyboard_input_pane_), hwnd_));
   return true;
 }
 
-void OnScreenKeyboardDisplayManagerInputPane::DismissVirtualKeyboard() {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  background_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&OnScreenKeyboardDisplayManagerInputPane::
-                         VirtualKeyboardInputPane::TryHideInBackgroundThread,
-                     base::RetainedRef(virtual_keyboard_input_pane_)));
-}
+void OnScreenKeyboardDisplayManagerInputPane::DismissVirtualKeyboard() {}
 
 void OnScreenKeyboardDisplayManagerInputPane::AddObserver(
     InputMethodKeyboardControllerObserver* observer) {
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc
index be0034a..7416011 100644
--- a/ui/base/ui_base_features.cc
+++ b/ui/base/ui_base_features.cc
@@ -82,6 +82,11 @@
     "CompositorThreadedScrollbarScrolling", base::FEATURE_DISABLED_BY_DEFAULT};
 
 #if defined(OS_WIN)
+// Enables the use of a touch fling curve that is based on the behavior of
+// native apps on Windows.
+const base::Feature kExperimentalFlingAnimation{
+    "ExperimentalFlingAnimation", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enables InputPane API for controlling on screen keyboard.
 const base::Feature kInputPaneOnScreenKeyboard = {
     "InputPaneOnScreenKeyboard", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h
index eed578b..7cbb38e3 100644
--- a/ui/base/ui_base_features.h
+++ b/ui/base/ui_base_features.h
@@ -43,6 +43,8 @@
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 extern const base::Feature kCalculateNativeWinOcclusion;
 COMPONENT_EXPORT(UI_BASE_FEATURES)
+extern const base::Feature kExperimentalFlingAnimation;
+COMPONENT_EXPORT(UI_BASE_FEATURES)
 extern const base::Feature kInputPaneOnScreenKeyboard;
 COMPONENT_EXPORT(UI_BASE_FEATURES)
 extern const base::Feature kPointerEventsForTouch;
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
index 0444d98..834c5ef5 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.cc
@@ -5,7 +5,13 @@
 #include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h"
 
 #include <algorithm>
+#include <functional>
+#include <memory>
 #include <queue>
+#include <string>
+#include <tuple>
+#include <unordered_set>
+#include <utility>
 #include <vector>
 
 #include "ui/events/ozone/evdev/event_device_info.h"
@@ -161,8 +167,8 @@
     }
 
     // Add the sample to the stroke.
-    stroke.AddSample(
-        CreatePalmFilterSample(touch, time, palm_filter_dev_info_));
+    stroke.AddSample(CreatePalmFilterSample(touch, time, model_->config(),
+                                            palm_filter_dev_info_));
     if (!is_palm_.test(slot) && ShouldDecideStroke(stroke)) {
       slots_to_decide.insert(slot);
     }
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.cc b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.cc
index 354489a..3f955bd 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.cc
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.cc
@@ -13,4 +13,6 @@
     NeuralStylusPalmDetectionFilterModelConfig(
         const NeuralStylusPalmDetectionFilterModelConfig& other) = default;
 
+NeuralStylusPalmDetectionFilterModelConfig::
+    ~NeuralStylusPalmDetectionFilterModelConfig() = default;
 }  // namespace ui
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h
index 360f3a0..fee837b6 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h
@@ -18,7 +18,7 @@
   NeuralStylusPalmDetectionFilterModelConfig();
   NeuralStylusPalmDetectionFilterModelConfig(
       const NeuralStylusPalmDetectionFilterModelConfig& other);
-
+  ~NeuralStylusPalmDetectionFilterModelConfig();
   // Number of nearest neighbors to use in vector construction.
   uint32_t nearest_neighbor_count = 0;
 
@@ -53,6 +53,14 @@
   // on them if the heuristic would have marked the touch as a palm at that
   // point.
   bool heuristic_delay_start_if_palm = false;
+
+  // If empty, the radius by the device is left as is.
+  // If non empty, the radius reported by device is re-sized in features by the
+  // polynomial defined in this vector. E.g. if this vector is {0.5, 1.3,
+  // -0.2, 1.0} Each radius r is replaced by
+  //
+  // R = 0.5 * r^3 + 1.3 * r^2 - 0.2 * r + 1
+  std::vector<float> radius_polynomial_resize;
 };
 
 // An abstract model utilized by NueralStylusPalmDetectionFilter.
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.cc b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.cc
index 924532e6..0c86872848 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.cc
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.cc
@@ -4,6 +4,8 @@
 
 #include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h"
 
+#include <algorithm>
+
 namespace ui {
 
 PalmFilterDeviceInfo CreatePalmFilterDeviceInfo(
@@ -41,23 +43,43 @@
   return info;
 }
 
-PalmFilterSample CreatePalmFilterSample(const InProgressTouchEvdev& touch,
-                                        const base::TimeTicks& time,
-                                        const PalmFilterDeviceInfo& dev_info) {
+namespace {
+float ScaledRadius(
+    float radius,
+    const NeuralStylusPalmDetectionFilterModelConfig& model_config) {
+  if (model_config.radius_polynomial_resize.empty()) {
+    return radius;
+  }
+  float return_value = 0.0f;
+  for (uint32_t i = 0; i < model_config.radius_polynomial_resize.size(); ++i) {
+    float power = model_config.radius_polynomial_resize.size() - 1 - i;
+    return_value +=
+        model_config.radius_polynomial_resize[i] * powf(radius, power);
+  }
+  return return_value;
+}
+}  // namespace
+
+PalmFilterSample CreatePalmFilterSample(
+    const InProgressTouchEvdev& touch,
+    const base::TimeTicks& time,
+    const NeuralStylusPalmDetectionFilterModelConfig& model_config,
+    const PalmFilterDeviceInfo& dev_info) {
   // radius_x and radius_y have been
   // scaled by resolution already.
 
   PalmFilterSample sample;
   sample.time = time;
 
-  // Original model here is not normalized appropriately, so we divide by 40.
-  sample.major_radius = std::max(touch.major, touch.minor) * dev_info.x_res /
-                        40.0 * dev_info.major_radius_res;
+  sample.major_radius = ScaledRadius(
+      std::max(touch.major, touch.minor) * dev_info.major_radius_res,
+      model_config);
   if (dev_info.minor_radius_supported) {
-    sample.minor_radius = std::min(touch.major, touch.minor) * dev_info.x_res /
-                          40.0 * dev_info.minor_radius_res;
+    sample.minor_radius = ScaledRadius(
+        std::min(touch.major, touch.minor) * dev_info.minor_radius_res,
+        model_config);
   } else {
-    sample.minor_radius = sample.major_radius;
+    sample.minor_radius = ScaledRadius(touch.major, model_config);
   }
 
   // Nearest edge distance, in cm.
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h
index 15367278..73b6c0c 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h
@@ -12,6 +12,7 @@
 #include "base/time/time.h"
 #include "ui/events/ozone/evdev/event_device_info.h"
 #include "ui/events/ozone/evdev/touch_evdev_types.h"
+#include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_model.h"
 #include "ui/gfx/geometry/point_f.h"
 
 namespace ui {
@@ -41,9 +42,11 @@
 };
 
 EVENTS_OZONE_EVDEV_EXPORT
-PalmFilterSample CreatePalmFilterSample(const InProgressTouchEvdev& touch,
-                                        const base::TimeTicks& time,
-                                        const PalmFilterDeviceInfo& dev_info);
+PalmFilterSample CreatePalmFilterSample(
+    const InProgressTouchEvdev& touch,
+    const base::TimeTicks& time,
+    const NeuralStylusPalmDetectionFilterModelConfig& model_config,
+    const PalmFilterDeviceInfo& dev_info);
 
 class EVENTS_OZONE_EVDEV_EXPORT PalmFilterStroke {
  public:
diff --git a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc
index bcb6d82..0113d8af 100644
--- a/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc
+++ b/ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util_unittest.cc
@@ -35,6 +35,7 @@
  protected:
   InProgressTouchEvdev touch_;
   EventDeviceInfo nocturne_touchscreen_;
+  NeuralStylusPalmDetectionFilterModelConfig model_config_;
 
   DISALLOW_COPY_AND_ASSIGN(NeuralStylusPalmDetectionFilterUtilTest);
 };
@@ -96,7 +97,7 @@
   const PalmFilterDeviceInfo nocturne_distilled =
       CreatePalmFilterDeviceInfo(nocturne_touchscreen_);
   const PalmFilterSample sample =
-      CreatePalmFilterSample(touch_, time, nocturne_distilled);
+      CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled);
   EXPECT_EQ(time, sample.time);
   EXPECT_EQ(25, sample.major_radius);
   EXPECT_EQ(24, sample.minor_radius);
@@ -113,8 +114,11 @@
   const PalmFilterDeviceInfo link_distilled =
       CreatePalmFilterDeviceInfo(link_touchscreen);
   touch_.minor = 0;  // no minor from link.
+  // use 40 as a base since model is trained on that kind of device.
+  model_config_.radius_polynomial_resize = {
+      link_touchscreen.GetAbsResolution(ABS_MT_POSITION_X) / 40.0, 0.0};
   const PalmFilterSample sample =
-      CreatePalmFilterSample(touch_, time, link_distilled);
+      CreatePalmFilterSample(touch_, time, model_config_, link_distilled);
   EXPECT_FLOAT_EQ(12.5, sample.major_radius);
   EXPECT_FLOAT_EQ(12.5, sample.minor_radius);
 }
@@ -132,7 +136,7 @@
   for (int i = 0; i < 500000; ++i) {
     touch_.x = 15 + i;
     PalmFilterSample sample =
-        CreatePalmFilterSample(touch_, time, nocturne_distilled);
+        CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled);
     stroke.AddSample(std::move(sample));
     EXPECT_EQ(touch_.tracking_id, stroke.tracking_id());
     if (i < 3) {
@@ -170,13 +174,13 @@
     touch_.major = 2 + i;
     touch_.minor = 1 + i;
     PalmFilterSample sample =
-        CreatePalmFilterSample(touch_, time, nocturne_distilled);
+        CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled);
     EXPECT_EQ(static_cast<uint64_t>(i), stroke.samples_seen());
     stroke.AddSample(sample);
     EXPECT_FLOAT_EQ((1 + i) * (2 + i), stroke.BiggestSize());
 
     PalmFilterSample second_sample =
-        CreatePalmFilterSample(touch_, time, nocturne_distilled);
+        CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled);
     second_sample.minor_radius = 0;
     no_minor_stroke.AddSample(std::move(second_sample));
     EXPECT_FLOAT_EQ((2 + i) * (2 + i), no_minor_stroke.BiggestSize());
@@ -195,7 +199,7 @@
     touch_.major = i;
     touch_.minor = i - 1;
     PalmFilterSample sample =
-        CreatePalmFilterSample(touch_, time, nocturne_distilled);
+        CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled);
     time += base::TimeDelta::FromMilliseconds(8);
     EXPECT_EQ(static_cast<uint64_t>(i - 1), stroke.samples_seen());
     stroke.AddSample(sample);
@@ -203,4 +207,24 @@
   }
 }
 
+TEST_F(NeuralStylusPalmDetectionFilterUtilTest, SampleRadiusConversion) {
+  // A single number: a _constant_.
+  model_config_.radius_polynomial_resize = {71.3};
+  base::TimeTicks time =
+      base::TimeTicks::UnixEpoch() + base::TimeDelta::FromSeconds(30);
+  const PalmFilterDeviceInfo nocturne_distilled =
+      CreatePalmFilterDeviceInfo(nocturne_touchscreen_);
+  PalmFilterSample sample =
+      CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled);
+  EXPECT_FLOAT_EQ(71.3, sample.major_radius);
+  EXPECT_FLOAT_EQ(71.3, sample.minor_radius);
+
+  // 0.1*r^2 + 0.4*r - 5.0
+  model_config_.radius_polynomial_resize = {0.1, 0.4, -5.0};
+  sample =
+      CreatePalmFilterSample(touch_, time, model_config_, nocturne_distilled);
+  EXPECT_FLOAT_EQ(0.1 * 25 * 25 + 0.4 * 25 - 5.0, sample.major_radius);
+  EXPECT_FLOAT_EQ(0.1 * 24 * 24 + 0.4 * 24 - 5.0, sample.minor_radius);
+}
+
 }  // namespace ui
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 1d989d90..0c9caab 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -194,6 +194,116 @@
   }
 }
 
+// Determines the equivalent codepoint (same rank) at |text[index]| in
+// |other_text|. The size of each codepoint may no longer match due to elision,
+// truncation or revision but their ordering is still the same. The following
+// code assumes that |other_text| is a transformation from |text| that preserves
+// the number and ordering of codepoints. Replacing a 1x with a 2x character
+// codepoint is valid, however replacing one codepoint with two codepoints is
+// not (see http://crbug.com/1021720).
+size_t GetTextIndexForOtherText(const base::string16& text,
+                                size_t index,
+                                const base::string16& other_text) {
+  // Move index to the beginning of the surrogate pair, if needed.
+  U16_SET_CP_START(text.data(), 0, index);
+
+  // Iterates through codepoints in both strings until we reach |index| in
+  // |text|.
+  base::i18n::UTF16CharIterator text_iter(&text);
+  base::i18n::UTF16CharIterator other_text_iter(&other_text);
+  while (!text_iter.end() && !other_text_iter.end()) {
+    // Codepoint at |index| is found, returns the corresponding index in
+    // |other_text|.
+    if (text_iter.array_pos() == static_cast<int32_t>(index))
+      return other_text_iter.array_pos();
+
+    // Move both iterator to the next codepoints.
+    if (!text_iter.Advance() || !other_text_iter.Advance())
+      break;
+  }
+
+  // The index is out-of-bound. Returns the end of other_text.
+  return other_text.length();
+}
+
+// Returns the codepoint at text[index]. This function handles that codepoint
+// can be one or two characters. It also handles offset in a middle of a
+// surrogate pair.
+UChar32 GetCodepointAtIndex(const base::string16& text, size_t index) {
+  // Move index to the beginning of the surrogate pair, if needed.
+  U16_SET_CP_START(text.data(), 0, index);
+  // Retrieve the codepoint at index.
+  UChar32 codepoint;
+  U16_NEXT(text.data(), index, text.length(), codepoint);
+  return codepoint;
+}
+
+// Replace a the codepoint at text[index] by the codepoint specified in
+// |new_codepoint|. This function handles that codepoint can be one or two
+// characters and enforce to replace a codepoint by a single codepoint.
+void ReplaceCodepointAtIndex(size_t index,
+                             UChar32 new_codepoint,
+                             base::string16* text) {
+  // Move index to the beginning of the surrogate pair, if needed.
+  U16_SET_CP_START(text->data(), 0, index);
+
+  // Gets the range to be replaced.
+  size_t end = index;
+  UChar32 original_codepoint;
+  U16_NEXT(text->data(), end, text->length(), original_codepoint);
+
+  DCHECK_LT(index, end);
+  DCHECK_LT(index, text->length());
+  DCHECK_LE(end, text->length());
+
+  // Encode the codepoint in utf16 (e.g. base::char16).
+  base::char16 replace_chars[U16_MAX_LENGTH];
+  size_t replace_length = U16_LENGTH(new_codepoint);
+  if (replace_length == 1) {
+    replace_chars[0] = new_codepoint;
+  } else {
+    replace_chars[0] = U16_LEAD(new_codepoint);
+    replace_chars[1] = U16_TRAIL(new_codepoint);
+  }
+
+  // Replace the codepoint range by the new codepoint characters.
+  text->replace(index, U16_LENGTH(original_codepoint), replace_chars,
+                replace_length);
+}
+
+// Create an obscured text for the given |text| where characters are replaced by
+// an bullet. In multiline, the newline character is not replaced. If
+// |reveal_index| is specify, the codepoint at |reveal_index| kept its original
+// value.
+base::string16 CreateObscuredText(const base::string16& text,
+                                  bool multiline,
+                                  int reveal_index) {
+  // Make an initial string with the same amount of characters.
+  size_t obscured_text_length =
+      static_cast<size_t>(UTF16IndexToOffset(text, 0, text.length()));
+  base::string16 output_text(obscured_text_length,
+                             RenderText::kPasswordReplacementChar);
+
+  // In multiline, do not replace the newline characters since they are used to
+  // split lines.
+  if (multiline) {
+    for (size_t i = 0; i < text.length(); ++i) {
+      if (text[i] == '\n')
+        output_text[i] = '\n';
+    }
+  }
+
+  // If needed, reveal the character at position |reveal_index|.
+  if (reveal_index >= 0 && reveal_index < static_cast<int>(text.length())) {
+    UChar32 original_codepoint = GetCodepointAtIndex(text, reveal_index);
+    size_t output_index =
+        GetTextIndexForOtherText(text, reveal_index, output_text);
+    ReplaceCodepointAtIndex(output_index, original_codepoint, &output_text);
+  }
+
+  return output_text;
+}
+
 // Replace the codepoints not handled by RenderText by an other compatible
 // codepoint. Replace the unicode control characters ISO 6429 (block C0) by
 // their corresponding visual symbols. Control characters can't be displayed but
@@ -229,50 +339,12 @@
       const int8_t codepoint_category = u_charType(codepoint);
       if (codepoint_category == U_PRIVATE_USE_CHAR ||
           codepoint_category == U_CONTROL_CHAR) {
-        (*text)[offset] = kReplacementCodepoint;
-        // We may need to replace the surrogate pair.
-        if (next_offset != offset + 1)
-          (*text)[offset + 1] = kReplacementCodepoint;
+        ReplaceCodepointAtIndex(offset, kReplacementCodepoint, text);
       }
     }
   }
 }
 
-// Determines the equivalent codepoint (same rank) at |text[index]| in
-// |other_text|. The size of each codepoint may no longer match due to elision,
-// truncation or revision but their ordering is still the same. The following
-// code assumes that |other_text| is a transformation from |text| that preserves
-// the number and ordering of codepoints. Replacing a 1x with a 2x character
-// codepoint is valid, however replacing one codepoint with two codepoints is
-// not (see http://crbug.com/1021720).
-size_t GetTextIndexForOtherText(const base::string16& text,
-                                size_t index,
-                                const base::string16& other_text) {
-  // Iterates through codepoints in both strings until we reach |index| in
-  // |text|.
-  base::i18n::UTF16CharIterator text_iter(&text);
-  base::i18n::UTF16CharIterator other_text_iter(&other_text);
-  size_t previous_index = 0;
-  do {
-    // Codepoint at |index| is found, returns the corresponding index in
-    // |other_text|.
-    if (text_iter.array_pos() == static_cast<int32_t>(index))
-      return other_text_iter.array_pos();
-    // The character at index is part of the previous codepoint (e.g. Surrogate
-    // pair). Returns the previous index.
-    if (text_iter.array_pos() > static_cast<int32_t>(index))
-      return previous_index;
-
-    // Move both iterator to the next codepoints.
-    previous_index = other_text_iter.array_pos();
-    if (!other_text_iter.Advance())
-      break;
-  } while (text_iter.Advance());
-
-  // The index is out-of-bound. Returns the end of other_text.
-  return other_text.length();
-}
-
 }  // namespace
 
 namespace internal {
@@ -1701,25 +1773,8 @@
   line_breaks_.SetMax(0);
 
   if (obscured_) {
-    size_t obscured_text_length =
-        static_cast<size_t>(UTF16IndexToOffset(text_, 0, text_.length()));
-    layout_text_.assign(obscured_text_length, kPasswordReplacementChar);
-
-    if (obscured_reveal_index_ >= 0 &&
-        obscured_reveal_index_ < static_cast<int>(text_.length())) {
-      // Gets the index range in |text_| to be revealed.
-      size_t start = obscured_reveal_index_;
-      U16_SET_CP_START(text_.data(), 0, start);
-      size_t end = start;
-      UChar32 unused_char;
-      U16_NEXT(text_.data(), end, text_.length(), unused_char);
-
-      // Gets the index in |layout_text_| to be replaced.
-      const size_t cp_start =
-          static_cast<size_t>(UTF16IndexToOffset(text_, 0, start));
-      if (layout_text_.length() > cp_start)
-        layout_text_.replace(cp_start, 1, text_.substr(start, end - start));
-    }
+    layout_text_ =
+        CreateObscuredText(text_, multiline_, obscured_reveal_index_);
   } else {
     layout_text_ = text_;
   }
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index 54202a8..193e8a361 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -766,6 +766,7 @@
   EXPECT_EQ(2U, render_text->cursor_position());
 
   // Test index conversion and cursor validity with a valid surrogate pair.
+  // Text contains "u+D800 u+DC00" and display text contains "u+2022".
   EXPECT_EQ(0U, test_api()->TextIndexToDisplayIndex(0U));
   EXPECT_EQ(0U, test_api()->TextIndexToDisplayIndex(1U));
   EXPECT_EQ(1U, test_api()->TextIndexToDisplayIndex(2U));
@@ -805,6 +806,19 @@
   }
 }
 
+TEST_F(RenderTextTest, ObscuredTextMultiline) {
+  const base::string16 test = UTF8ToUTF16("a\nbc\ndef");
+  RenderText* render_text = GetRenderText();
+  render_text->SetText(test);
+  render_text->SetObscured(true);
+  render_text->SetMultiline(true);
+
+  // Newlines should be kept in multiline mode.
+  base::string16 display_text = render_text->GetDisplayText();
+  EXPECT_EQ(display_text[1], '\n');
+  EXPECT_EQ(display_text[4], '\n');
+}
+
 TEST_F(RenderTextTest, RevealObscuredText) {
   const base::string16 seuss = UTF8ToUTF16("hop on pop");
   const base::string16 no_seuss = GetObscuredString(seuss.length());
@@ -4775,7 +4789,7 @@
 
   // The private use characters should have been replaced. If the code point is
   // a surrogate pair, it needs to be replaced by two characters.
-  EXPECT_EQ(WideToUTF16(L"xx\ufffd\ufffda\ufffd\ufffdz"),
+  EXPECT_EQ(WideToUTF16(L"xx\ufffd\ufffda\ufffdz"),
             render_text->GetDisplayText());
 }
 
diff --git a/ui/snapshot/snapshot_aura_unittest.cc b/ui/snapshot/snapshot_aura_unittest.cc
index 93afad6..578b3a0 100644
--- a/ui/snapshot/snapshot_aura_unittest.cc
+++ b/ui/snapshot/snapshot_aura_unittest.cc
@@ -318,7 +318,7 @@
   test_screen()->SetUIScale(kUIScale);
   test_screen()->SetDisplayRotation(display::Display::ROTATE_90);
 
-  gfx::Rect test_bounds(100, 100, 300, 200);
+  gfx::Rect test_bounds(100, 100, 200, 300);
   SetupTestWindow(test_bounds);
   WaitForDraw();
 
@@ -344,7 +344,7 @@
   test_screen()->SetUIScale(kUIScale);
   test_screen()->SetDisplayRotation(display::Display::ROTATE_90);
 
-  gfx::Rect test_bounds(20, 30, 150, 100);
+  gfx::Rect test_bounds(20, 30, 100, 150);
   SetupTestWindow(test_bounds);
   WaitForDraw();
 
diff --git a/ui/views/controls/focus_ring.cc b/ui/views/controls/focus_ring.cc
index 3f99aa6..53a03ac 100644
--- a/ui/views/controls/focus_ring.cc
+++ b/ui/views/controls/focus_ring.cc
@@ -71,7 +71,7 @@
 
 void FocusRing::SetHasFocusPredicate(const ViewPredicate& predicate) {
   has_focus_predicate_ = predicate;
-  SchedulePaint();
+  RefreshLayer();
 }
 
 void FocusRing::SetColor(base::Optional<SkColor> color) {
@@ -105,11 +105,18 @@
     // become a nullptr, it won't be able to do so in its destructor.
     details.parent->RemoveObserver(this);
   }
+  RefreshLayer();
 }
 
 void FocusRing::OnPaint(gfx::Canvas* canvas) {
-  if (!has_focus_predicate_(parent()))
+  // TODO(pbos): Reevaluate if this can turn into a DCHECK, e.g. we should
+  // never paint if there's no parent focus.
+  if (has_focus_predicate_) {
+    if (!(*has_focus_predicate_)(parent()))
+      return;
+  } else if (!parent()->HasFocus()) {
     return;
+  }
 
   cc::PaintFlags paint;
   paint.setAntiAlias(true);
@@ -145,21 +152,16 @@
 }
 
 void FocusRing::OnViewFocused(View* view) {
-  SchedulePaint();
+  RefreshLayer();
 }
 
 void FocusRing::OnViewBlurred(View* view) {
-  SchedulePaint();
+  RefreshLayer();
 }
 
 FocusRing::FocusRing() {
-  // A layer is necessary to paint beyond the parent's bounds.
-  SetPaintToLayer();
-  layer()->SetFillsBoundsOpaquely(false);
   // Don't allow the view to process events.
   set_can_process_events_within_subtree(false);
-
-  has_focus_predicate_ = [](View* p) -> bool { return p->HasFocus(); };
 }
 
 FocusRing::~FocusRing() {
@@ -167,6 +169,26 @@
     parent()->RemoveObserver(this);
 }
 
+void FocusRing::RefreshLayer() {
+  // TODO(pbos): This always keeps the layer alive if |has_focus_predicate_| is
+  // set. This is done because we're not notified when the predicate might
+  // return a different result and there are call sites that call SchedulePaint
+  // on FocusRings and expect that to be sufficient.
+  // The cleanup would be to always call has_focus_predicate_ here and make sure
+  // that RefreshLayer gets called somehow whenever |has_focused_predicate_|
+  // returns a new value.
+  const bool should_paint =
+      has_focus_predicate_.has_value() || (parent() && parent()->HasFocus());
+  SetVisible(should_paint);
+  if (should_paint) {
+    // A layer is necessary to paint beyond the parent's bounds.
+    SetPaintToLayer();
+    layer()->SetFillsBoundsOpaquely(false);
+  } else {
+    DestroyLayer();
+  }
+}
+
 SkRRect FocusRing::RingRectFromPathRect(const SkRect& rect) const {
   const double corner_radius = GetCornerRadius();
   return RingRectFromPathRect(
diff --git a/ui/views/controls/focus_ring.h b/ui/views/controls/focus_ring.h
index b54c8e39..c09c6aa 100644
--- a/ui/views/controls/focus_ring.h
+++ b/ui/views/controls/focus_ring.h
@@ -83,6 +83,8 @@
  private:
   FocusRing();
 
+  void RefreshLayer();
+
   // Translates the provided SkRect or SkRRect, which is in the parent's
   // coordinate system, into this view's coordinate system, then insets it
   // appropriately to produce the focus ring "halo" effect. If the supplied rect
@@ -102,7 +104,7 @@
   base::Optional<SkColor> color_;
 
   // The predicate used to determine whether the parent has focus.
-  ViewPredicate has_focus_predicate_;
+  base::Optional<ViewPredicate> has_focus_predicate_;
 
   DISALLOW_COPY_AND_ASSIGN(FocusRing);
 };
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 1cb6bc2..4169f58 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -1596,9 +1596,6 @@
   return gfx::Size();
 }
 
-void View::OnBoundsChanged(const gfx::Rect& previous_bounds) {
-}
-
 void View::PreferredSizeChanged() {
   if (parent_)
     parent_->ChildPreferredSizeChanged(this);
diff --git a/ui/views/view.h b/ui/views/view.h
index 3e83923..47214622 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -1353,7 +1353,7 @@
   virtual gfx::Size CalculatePreferredSize() const;
 
   // Override to be notified when the bounds of the view have changed.
-  virtual void OnBoundsChanged(const gfx::Rect& previous_bounds);
+  virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) {}
 
   // Called when the preferred size of a child view changed.  This gives the
   // parent an opportunity to do a fresh layout if that makes sense.
diff --git a/ui/web_dialogs/web_dialog_ui.cc b/ui/web_dialogs/web_dialog_ui.cc
index 58c11a2..15f230d 100644
--- a/ui/web_dialogs/web_dialog_ui.cc
+++ b/ui/web_dialogs/web_dialog_ui.cc
@@ -89,15 +89,13 @@
     delegate->GetWebUIMessageHandlers(&handlers);
   }
 
-  content::RenderViewHost* render_view_host =
-      render_frame_host->GetRenderViewHost();
   if (0 != (web_ui_->GetBindings() & content::BINDINGS_POLICY_WEB_UI))
-    render_view_host->SetWebUIProperty("dialogArguments", dialog_args);
+    render_frame_host->SetWebUIProperty("dialogArguments", dialog_args);
   for (WebUIMessageHandler* handler : handlers)
     web_ui_->AddMessageHandler(base::WrapUnique(handler));
 
   if (delegate)
-    delegate->OnDialogShown(web_ui_, render_view_host);
+    delegate->OnDialogShown(web_ui_, render_frame_host->GetRenderViewHost());
 }
 
 void WebDialogUIBase::OnDialogClosed(const base::ListValue* args) {
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn
index 1892e2b..a8ecc9f 100644
--- a/weblayer/browser/java/BUILD.gn
+++ b/weblayer/browser/java/BUILD.gn
@@ -70,6 +70,10 @@
   jar_excluded_patterns = [ "*/LocaleConfig.class" ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 
+  # Needed for android.webkit.WebView(Delegate|Factory)
+  alternative_android_sdk_dep =
+      "//third_party/android_sdk:public_framework_system_java"
+
   # TODO(timvolodine): once the downstream implementation of GmsBridgeImpl.java
   # lands make sure to exclude this when "enable_chrome_android_internal" is true.
   deps += [ ":gms_bridge_upstream_impl_java" ]
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
index 264f3e5b..e3717b2 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
@@ -82,7 +82,7 @@
 
     public BrowserViewController getViewController() {
         if (mViewController == null) {
-            throw new RuntimeException("Currently BrowserController requires Activity context, so "
+            throw new RuntimeException("Currently Tab requires Activity context, so "
                     + "it exists only while BrowserFragment is attached to an Activity");
         }
         return mViewController;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java b/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java
index a8b8777..10e01e2 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java
@@ -21,11 +21,11 @@
     private long mNativeDownloadCallbackProxy;
     private IDownloadCallbackClient mClient;
 
-    DownloadCallbackProxy(long browserController, IDownloadCallbackClient client) {
+    DownloadCallbackProxy(long tab, IDownloadCallbackClient client) {
         assert client != null;
         mClient = client;
         mNativeDownloadCallbackProxy =
-                DownloadCallbackProxyJni.get().createDownloadCallbackProxy(this, browserController);
+                DownloadCallbackProxyJni.get().createDownloadCallbackProxy(this, tab);
     }
 
     public void setClient(IDownloadCallbackClient client) {
@@ -46,7 +46,7 @@
 
     @NativeMethods
     interface Natives {
-        long createDownloadCallbackProxy(DownloadCallbackProxy proxy, long browserController);
+        long createDownloadCallbackProxy(DownloadCallbackProxy proxy, long tab);
         void deleteDownloadCallbackProxy(long proxy);
     }
 }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/FullscreenCallbackProxy.java b/weblayer/browser/java/org/chromium/weblayer_private/FullscreenCallbackProxy.java
index 98b047de..fb6b8a3 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/FullscreenCallbackProxy.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/FullscreenCallbackProxy.java
@@ -23,12 +23,11 @@
     private long mNativeFullscreenCallbackProxy;
     private IFullscreenCallbackClient mClient;
 
-    FullscreenCallbackProxy(long browserController, IFullscreenCallbackClient client) {
+    FullscreenCallbackProxy(long tab, IFullscreenCallbackClient client) {
         assert client != null;
         mClient = client;
         mNativeFullscreenCallbackProxy =
-                FullscreenCallbackProxyJni.get().createFullscreenCallbackProxy(
-                        this, browserController);
+                FullscreenCallbackProxyJni.get().createFullscreenCallbackProxy(this, tab);
     }
 
     public void setClient(IFullscreenCallbackClient client) {
@@ -64,7 +63,7 @@
 
     @NativeMethods
     interface Natives {
-        long createFullscreenCallbackProxy(FullscreenCallbackProxy proxy, long browserController);
+        long createFullscreenCallbackProxy(FullscreenCallbackProxy proxy, long tab);
         void deleteFullscreenCallbackProxy(long proxy);
         void doExitFullscreen(long nativeFullscreenCallbackProxy, FullscreenCallbackProxy proxy);
     }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/NavigationControllerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/NavigationControllerImpl.java
index 280a3898..3fb45d5 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/NavigationControllerImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/NavigationControllerImpl.java
@@ -24,8 +24,8 @@
     public NavigationControllerImpl(TabImpl tab, INavigationControllerClient client) {
         mNavigationControllerClient = client;
         mTab = tab;
-        mNativeNavigationController = NavigationControllerImplJni.get().getNavigationController(
-                tab.getNativeBrowserController());
+        mNativeNavigationController =
+                NavigationControllerImplJni.get().getNavigationController(tab.getNativeTab());
         NavigationControllerImplJni.get().setNavigationControllerImpl(
                 mNativeNavigationController, NavigationControllerImpl.this);
     }
@@ -140,7 +140,7 @@
     interface Natives {
         void setNavigationControllerImpl(
                 long nativeNavigationControllerImpl, NavigationControllerImpl caller);
-        long getNavigationController(long browserController);
+        long getNavigationController(long tab);
         void navigate(
                 long nativeNavigationControllerImpl, NavigationControllerImpl caller, String uri);
         void goBack(long nativeNavigationControllerImpl, NavigationControllerImpl caller);
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/NewBrowserCallbackProxy.java b/weblayer/browser/java/org/chromium/weblayer_private/NewBrowserCallbackProxy.java
deleted file mode 100644
index 229e909..0000000
--- a/weblayer/browser/java/org/chromium/weblayer_private/NewBrowserCallbackProxy.java
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.weblayer_private;
-
-import android.os.RemoteException;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.NativeMethods;
-import org.chromium.weblayer_private.interfaces.NewBrowserType;
-
-/**
- * Owns the c++ NewBrowserCallback class, which is responsible for forwarding all
- * NewBrowserCallback calls to this class, which in turn forwards to the
- * IBrowserFragmentControllerClient.
- */
-@JNINamespace("weblayer")
-public final class NewBrowserCallbackProxy {
-    private long mNativeNewBrowserCallbackProxy;
-    private final BrowserControllerImpl mBrowser;
-
-    public NewBrowserCallbackProxy(BrowserControllerImpl browser) {
-        mBrowser = browser;
-        mNativeNewBrowserCallbackProxy =
-                NewBrowserCallbackProxyJni.get().createNewBrowserCallbackProxy(
-                        this, browser.getNativeBrowserController());
-    }
-
-    public void destroy() {
-        NewBrowserCallbackProxyJni.get().deleteNewBrowserCallbackProxy(
-                mNativeNewBrowserCallbackProxy);
-        mNativeNewBrowserCallbackProxy = 0;
-    }
-
-    @NewBrowserType
-    private static int implTypeToJavaType(@ImplNewBrowserType int type) {
-        switch (type) {
-            case ImplNewBrowserType.FOREGROUND_TAB:
-                return NewBrowserType.FOREGROUND_TAB;
-            case ImplNewBrowserType.BACKGROUND_TAB:
-                return NewBrowserType.BACKGROUND_TAB;
-            case ImplNewBrowserType.NEW_POPUP:
-                return NewBrowserType.NEW_POPUP;
-            case ImplNewBrowserType.NEW_WINDOW:
-                return NewBrowserType.NEW_WINDOW;
-        }
-        assert false;
-        return NewBrowserType.FOREGROUND_TAB;
-    }
-
-    @CalledByNative
-    public void onNewBrowser(long nativeBrowser, @ImplNewBrowserType int mode)
-            throws RemoteException {
-        // This class should only be created while the browser is attached to a fragment.
-        assert mBrowser.getFragment() != null;
-        BrowserControllerImpl browser = new BrowserControllerImpl(
-                mBrowser.getProfile(), mBrowser.getFragment().getWindowAndroid(), nativeBrowser);
-        mBrowser.getFragment().attachBrowserController(browser);
-        mBrowser.getClient().onNewBrowser(browser, implTypeToJavaType(mode));
-    }
-
-    @NativeMethods
-    interface Natives {
-        long createNewBrowserCallbackProxy(NewBrowserCallbackProxy proxy, long browserController);
-        void deleteNewBrowserCallbackProxy(long proxy);
-    }
-}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/NewTabCallbackProxy.java b/weblayer/browser/java/org/chromium/weblayer_private/NewTabCallbackProxy.java
index fc048c7..bc9bd4a0 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/NewTabCallbackProxy.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/NewTabCallbackProxy.java
@@ -21,8 +21,8 @@
 
     public NewTabCallbackProxy(TabImpl tab) {
         mTab = tab;
-        mNativeNewTabCallbackProxy = NewTabCallbackProxyJni.get().createNewTabCallbackProxy(
-                this, tab.getNativeBrowserController());
+        mNativeNewTabCallbackProxy =
+                NewTabCallbackProxyJni.get().createNewTabCallbackProxy(this, tab.getNativeTab());
     }
 
     public void destroy() {
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TabCallbackProxy.java b/weblayer/browser/java/org/chromium/weblayer_private/TabCallbackProxy.java
index a459d06..1ece19a 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/TabCallbackProxy.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TabCallbackProxy.java
@@ -14,17 +14,16 @@
 /**
  * Owns the C++ TabCallbackProxy class, which is responsible for forwarding all
  * BrowserObserver calls to this class, which in turn forwards to the TabClient.
- * To avoid unnecessary IPC only one TabCallbackProxy is created per BrowserController.
+ * To avoid unnecessary IPC only one TabCallbackProxy is created per Tab.
  */
 @JNINamespace("weblayer")
 public final class TabCallbackProxy {
     private long mNativeTabCallbackProxy;
     private ITabClient mClient;
 
-    TabCallbackProxy(long browserController, ITabClient client) {
+    TabCallbackProxy(long tab, ITabClient client) {
         mClient = client;
-        mNativeTabCallbackProxy =
-                TabCallbackProxyJni.get().createTabCallbackProxy(this, browserController);
+        mNativeTabCallbackProxy = TabCallbackProxyJni.get().createTabCallbackProxy(this, tab);
     }
 
     public void destroy() {
@@ -39,7 +38,7 @@
 
     @NativeMethods
     interface Natives {
-        long createTabCallbackProxy(TabCallbackProxy proxy, long browserController);
+        long createTabCallbackProxy(TabCallbackProxy proxy, long tab);
         void deleteTabCallbackProxy(long proxy);
     }
 }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
index 7c903868..1823c7d 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
@@ -76,16 +76,15 @@
      * This constructor is called when the native side triggers creation of a TabImpl
      * (as happens with popups).
      */
-    public TabImpl(ProfileImpl profile, WindowAndroid windowAndroid, long nativeBrowserController) {
+    public TabImpl(ProfileImpl profile, WindowAndroid windowAndroid, long nativeTab) {
         mId = ++sNextId;
-        TabImplJni.get().setJavaImpl(nativeBrowserController, TabImpl.this);
-        init(profile, windowAndroid, nativeBrowserController);
+        TabImplJni.get().setJavaImpl(nativeTab, TabImpl.this);
+        init(profile, windowAndroid, nativeTab);
     }
 
-    private void init(
-            ProfileImpl profile, WindowAndroid windowAndroid, long nativeBrowserController) {
+    private void init(ProfileImpl profile, WindowAndroid windowAndroid, long nativeTab) {
         mProfile = profile;
-        mNativeTab = nativeBrowserController;
+        mNativeTab = nativeTab;
         mWebContents = TabImplJni.get().getWebContents(mNativeTab, TabImpl.this);
         mViewAndroidDelegate = new ViewAndroidDelegate(null) {
             @Override
@@ -160,7 +159,7 @@
         return mWebContents;
     }
 
-    long getNativeBrowserController() {
+    long getNativeTab() {
         return mNativeTab;
     }
 
@@ -263,7 +262,7 @@
         void setJavaImpl(long nativeTabImpl, TabImpl impl);
         void setTopControlsContainerView(
                 long nativeTabImpl, TabImpl caller, long nativeTopControlsContainerView);
-        void deleteTab(long browserController);
+        void deleteTab(long tab);
         WebContents getWebContents(long nativeTabImpl, TabImpl caller);
         void executeScript(long nativeTabImpl, String script, boolean useSeparateIsolate,
                 Callback<String> callback);
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TopControlsContainerView.java b/weblayer/browser/java/org/chromium/weblayer_private/TopControlsContainerView.java
index 997bdc48..c2c1f9d5 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/TopControlsContainerView.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TopControlsContainerView.java
@@ -43,7 +43,7 @@
  *
  * The flow of this code is roughly:
  * . WebContentsGestureStateTracker generally detects a touch first
- * . BrowserControllerImpl is notified and caches state.
+ * . TabImpl is notified and caches state.
  * . onTopControlsChanged() is called. This triggers hiding the real view and calling to native code
  *   to move the cc::Layers.
  * . the move continues.
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
index 45040e8709..b67a606 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
@@ -6,11 +6,16 @@
 
 import android.content.Context;
 import android.content.pm.PackageInfo;
+import android.content.res.AssetManager;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.support.v4.content.FileProvider;
+import android.util.SparseArray;
 import android.webkit.ValueCallback;
+import android.webkit.WebViewDelegate;
+import android.webkit.WebViewFactory;
 
 import org.chromium.base.BuildInfo;
 import org.chromium.base.CommandLine;
@@ -35,7 +40,13 @@
 import org.chromium.weblayer_private.interfaces.WebLayerVersion;
 
 import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
 
+/**
+ * Root implementation class for WebLayer.
+ * This is constructed by the client library using reflection.
+ */
 @UsedByReflection("WebLayer")
 public final class WebLayerImpl extends IWebLayer.Stub {
     // TODO: should there be one tag for all this code?
@@ -75,19 +86,18 @@
     }
 
     @Override
-    public void initAndLoadAsync(IObjectWrapper appContextWrapper,
-            IObjectWrapper packageInfoWrapper, IObjectWrapper loadedCallbackWrapper,
-            int resourcesPackageId) {
-        // TODO: The call to onResourcesLoaded() can be slow, we may need to parallelize this with
-        // other expensive startup tasks.
-        R.onResourcesLoaded(resourcesPackageId);
-
+    public void initAndLoadAsync(
+            IObjectWrapper appContextWrapper, IObjectWrapper loadedCallbackWrapper) {
         // Wrap the app context so that it can be used to load WebLayer implementation classes.
         Context appContext = ClassLoaderContextWrapperFactory.get(
                 ObjectWrapper.unwrap(appContextWrapper, Context.class));
-        PackageInfo packageInfo = ObjectWrapper.unwrap(packageInfoWrapper, PackageInfo.class);
+        PackageInfo packageInfo = WebViewFactory.getLoadedPackageInfo();
         ContextUtils.initApplicationContext(appContext);
         BuildInfo.setBrowserPackageInfo(packageInfo);
+        int resourcesPackageId = getPackageId(appContext, packageInfo.packageName);
+        // TODO: The call to onResourcesLoaded() can be slow, we may need to parallelize this with
+        // other expensive startup tasks.
+        R.onResourcesLoaded(resourcesPackageId);
 
         ResourceBundle.setAvailablePakLocales(new String[] {}, LocaleConfig.UNCOMPRESSED_LOCALES);
         PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
@@ -153,4 +163,34 @@
     public IProfile getProfile(String profilePath) {
         return mProfileManager.getProfile(profilePath);
     }
+
+    /**
+     * Returns the package ID to use when calling R.onResourcesLoaded().
+     */
+    private static int getPackageId(Context appContext, String implPackageName) {
+        try {
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
+                Constructor constructor = WebViewDelegate.class.getDeclaredConstructor();
+                constructor.setAccessible(true);
+                WebViewDelegate delegate = (WebViewDelegate) constructor.newInstance();
+                return delegate.getPackageId(appContext.getResources(), implPackageName);
+            } else {
+                // In L WebViewDelegate did not yet exist, so we have to look inside AssetManager.
+                Method getAssignedPackageIdentifiers =
+                        AssetManager.class.getMethod("getAssignedPackageIdentifiers");
+                SparseArray packageIdentifiers = (SparseArray) getAssignedPackageIdentifiers.invoke(
+                        appContext.getResources().getAssets());
+                for (int i = 0; i < packageIdentifiers.size(); i++) {
+                    final String name = (String) packageIdentifiers.valueAt(i);
+
+                    if (implPackageName.equals(name)) {
+                        return packageIdentifiers.keyAt(i);
+                    }
+                }
+                throw new RuntimeException("Package not found: " + implPackageName);
+            }
+        } catch (ReflectiveOperationException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl
index c08f6b88..4e9f2a10 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl
+++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl
@@ -16,12 +16,9 @@
   // It is expected that this method is called before anything else.
   //
   // @param appContext     A Context that refers to the Application using WebLayer.
-  // @param packageInfo    The PackageInfo for the package from which WebLayer is loaded. 
   // @param loadedCallback A ValueCallback that will be called when load completes.
   void initAndLoadAsync(in IObjectWrapper appContext,
-                        in IObjectWrapper packageInfo,
-                        in IObjectWrapper loadedCallback,
-                        int resourcesPackageId) = 1;
+                        in IObjectWrapper loadedCallback) = 1;
 
   // Blocks until loading has completed.
   void loadSync() = 2;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersion.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersion.java
index 0ca25cae..e89c342 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersion.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersion.java
@@ -9,4 +9,4 @@
  *
  * Whenever any AIDL file is changed, sVersionNumber must be incremented.
  * */
-public final class WebLayerVersion { public static final int sVersionNumber = 9; }
+public final class WebLayerVersion { public static final int sVersionNumber = 10; }
diff --git a/weblayer/browser/navigation_controller_impl.cc b/weblayer/browser/navigation_controller_impl.cc
index 712aed88..37ec041 100644
--- a/weblayer/browser/navigation_controller_impl.cc
+++ b/weblayer/browser/navigation_controller_impl.cc
@@ -242,11 +242,10 @@
 }
 
 #if defined(OS_ANDROID)
-static jlong JNI_NavigationControllerImpl_GetNavigationController(
-    JNIEnv* env,
-    jlong browserController) {
+static jlong JNI_NavigationControllerImpl_GetNavigationController(JNIEnv* env,
+                                                                  jlong tab) {
   return reinterpret_cast<jlong>(
-      reinterpret_cast<Tab*>(browserController)->GetNavigationController());
+      reinterpret_cast<Tab*>(tab)->GetNavigationController());
 }
 #endif
 
diff --git a/weblayer/browser/tab_impl.cc b/weblayer/browser/tab_impl.cc
index f511b815..b43c9b5 100644
--- a/weblayer/browser/tab_impl.cc
+++ b/weblayer/browser/tab_impl.cc
@@ -45,18 +45,18 @@
   // the only ones that should be hit for this code path.
   switch (disposition) {
     case WindowOpenDisposition::NEW_FOREGROUND_TAB:
-      return NewTabType::FOREGROUND_TAB;
+      return NewTabType::kForeground;
     case WindowOpenDisposition::NEW_BACKGROUND_TAB:
-      return NewTabType::BACKGROUND_TAB;
+      return NewTabType::kBackground;
     case WindowOpenDisposition::NEW_POPUP:
-      return NewTabType::NEW_POPUP;
+      return NewTabType::kNewPopup;
     case WindowOpenDisposition::NEW_WINDOW:
-      return NewTabType::NEW_WINDOW;
+      return NewTabType::kNewWindow;
     default:
       // The set of allowed types are in
       // ContentTabClientImpl::CanCreateWindow().
       NOTREACHED();
-      return NewTabType::FOREGROUND_TAB;
+      return NewTabType::kForeground;
   }
 }
 
diff --git a/weblayer/public/java/BUILD.gn b/weblayer/public/java/BUILD.gn
index 82c27ed5..928152f 100644
--- a/weblayer/public/java/BUILD.gn
+++ b/weblayer/public/java/BUILD.gn
@@ -54,10 +54,6 @@
     "//weblayer/browser/java:interfaces_java",
   ]
 
-  # Needed for android.webkit.WebViewDelegate.
-  alternative_android_sdk_dep =
-      "//third_party/android_sdk:public_framework_system_java"
-
   android_manifest_for_lint = weblayer_client_manifest
 }
 
diff --git a/weblayer/public/java/org/chromium/weblayer/Browser.java b/weblayer/public/java/org/chromium/weblayer/Browser.java
index 36dfb86..26cef370 100644
--- a/weblayer/public/java/org/chromium/weblayer/Browser.java
+++ b/weblayer/public/java/org/chromium/weblayer/Browser.java
@@ -129,7 +129,7 @@
      *
      * @throws IllegalStateException is {@link tab} is not in this Browser.
      */
-    public void disposeTab(Tab browserController) {
+    public void disposeTab(Tab tab) {
         ThreadCheck.ensureOnUiThread();
         // TODO(sky): implement this.
     }
diff --git a/weblayer/public/java/org/chromium/weblayer/NavigationCallback.java b/weblayer/public/java/org/chromium/weblayer/NavigationCallback.java
index 9ad4585..543df4c5 100644
--- a/weblayer/public/java/org/chromium/weblayer/NavigationCallback.java
+++ b/weblayer/public/java/org/chromium/weblayer/NavigationCallback.java
@@ -19,7 +19,7 @@
  */
 public abstract class NavigationCallback {
     /**
-     * Called when a navigation started in the BrowserController. |navigation| is unique to a
+     * Called when a navigation started in the Tab. |navigation| is unique to a
      * specific navigation. The same |navigation| will be  provided on subsequent calls to
      * NavigationRedirected, NavigationCommitted, NavigationCompleted and NavigationFailed when
      * related to this navigation. Observers should clear any references to |navigation| in
@@ -31,7 +31,7 @@
      * pushState/replaceState, which will not result in a document change. To filter these out, use
      * Navigation::IsSameDocument.
      *
-     * Note that more than one navigation can be ongoing in the BrowserController at the same time.
+     * Note that more than one navigation can be ongoing in the Tab at the same time.
      * Each will get its own Navigation object.
      *
      * Note that there is no guarantee that NavigationCompleted/NavigationFailed will be called for
@@ -55,20 +55,20 @@
      * mime sniffing the response). The browser then is ready to switch rendering the new document.
      * Most observers should use NavigationCompleted or NavigationFailed instead, which happens
      * right after the navigation commits. This method is for observers that want to initialize
-     * renderer-side state just before the BrowserController commits the navigation.
+     * renderer-side state just before the Tab commits the navigation.
      *
-     * This is the first point in time where a BrowserController is associated with the navigation.
+     * This is the first point in time where a Tab is associated with the navigation.
      *
      * @param navigation the unique object for this navigation.
      */
     public void readyToCommitNavigation(@NonNull Navigation navigation) {}
 
     /**
-     * Called when a navigation completes successfully in the BrowserController.
+     * Called when a navigation completes successfully in the Tab.
      *
-     * The document load will still be ongoing in the BrowserController. Use the document loads
+     * The document load will still be ongoing in the Tab. Use the document loads
      * events such as onFirstContentfulPaint and related methods to listen for continued events from
-     * this BrowserController.
+     * this Tab.
      *
      * Note that this is fired by same-document navigations, such as fragment navigations or
      * pushState/replaceState, which will not result in a document change. To filter these out, use
@@ -82,7 +82,7 @@
     public void navigationCompleted(@NonNull Navigation navigation) {}
 
     /**
-     * Called when a navigation aborts in the BrowserController.
+     * Called when a navigation aborts in the Tab.
      *
      * Note that |navigation| will be destroyed at the end of this call, so do not keep a reference
      * to it afterward.
diff --git a/weblayer/public/java/org/chromium/weblayer/Tab.java b/weblayer/public/java/org/chromium/weblayer/Tab.java
index ded5190..7d8f41a 100644
--- a/weblayer/public/java/org/chromium/weblayer/Tab.java
+++ b/weblayer/public/java/org/chromium/weblayer/Tab.java
@@ -38,9 +38,9 @@
     private DownloadCallbackClientImpl mDownloadCallbackClient;
     private NewTabCallback mNewTabCallback;
 
-    Tab(ITab impl, Browser browserFragmentController) {
+    Tab(ITab impl, Browser browser) {
         mImpl = impl;
-        mBrowser = browserFragmentController;
+        mBrowser = browser;
         try {
             mImpl.setClient(new TabClientImpl());
         } catch (RemoteException e) {
diff --git a/weblayer/public/java/org/chromium/weblayer/WebLayer.java b/weblayer/public/java/org/chromium/weblayer/WebLayer.java
index 8dbc1628..84f60d2ad 100644
--- a/weblayer/public/java/org/chromium/weblayer/WebLayer.java
+++ b/weblayer/public/java/org/chromium/weblayer/WebLayer.java
@@ -7,15 +7,14 @@
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.AssetManager;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.support.v4.app.Fragment;
 import android.util.AndroidRuntimeException;
 import android.webkit.ValueCallback;
-import android.webkit.WebViewDelegate;
-import android.webkit.WebViewFactory;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -31,14 +30,17 @@
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 import java.util.concurrent.TimeUnit;
 
 /**
  * WebLayer is responsible for initializing state necessary to use any of the classes in web layer.
  */
 public final class WebLayer {
-    // TODO: Using a metadata key for the WebLayerImpl package is just being used for testing,
-    // production will use a different mechanism.
+    // This metadata key, if defined, overrides the default behaviour of loading WebLayer from the
+    // current WebView implementation. This is only intended for testing, and does not enforce any
+    // signature requirements on the implementation, nor does it use the production code path to
+    // load the code. Do not set this in production APKs!
     private static final String PACKAGE_MANIFEST_KEY = "org.chromium.weblayer.WebLayerPackage";
 
     private static ListenableFuture<WebLayer> sFuture;
@@ -71,29 +73,6 @@
     }
 
     /**
-     * Loads assets for WebLayer and returns the package ID to use when calling
-     * R.onResourcesLoaded().
-     */
-    private static int loadAssets(Context appContext, PackageInfo implPackageInfo)
-            throws ReflectiveOperationException {
-        WebViewDelegate delegate;
-        // TODO: Make asset loading work on L, where WebViewDelegate doesn't exist.
-        // WebViewDelegate.addWebViewAssetPath() accesses the currently loaded package info from
-        // WebViewFactory, so we have to fake it.
-        Field packageInfo = WebViewFactory.class.getDeclaredField("sPackageInfo");
-        packageInfo.setAccessible(true);
-        packageInfo.set(null, implPackageInfo);
-
-        // TODO(torne): Figure out how to load assets for production.
-        // Load assets using the WebViewDelegate.
-        Constructor constructor = WebViewDelegate.class.getDeclaredConstructor();
-        constructor.setAccessible(true);
-        delegate = (WebViewDelegate) constructor.newInstance();
-        delegate.addWebViewAssetPath(appContext);
-        return delegate.getPackageId(appContext.getResources(), implPackageInfo.packageName);
-    }
-
-    /**
      * Asynchronously creates and initializes WebLayer. Calling this more than once returns the same
      * object.
      *
@@ -111,12 +90,7 @@
                 appContext = appContext.getApplicationContext();
                 ClassLoader remoteClassLoader = createRemoteClassLoader(appContext);
                 IWebLayer iWebLayer = connectToWebLayerImplementation(remoteClassLoader);
-                PackageInfo packageInfo = appContext.getPackageManager().getPackageInfo(
-                        getImplPackageName(appContext),
-                        PackageManager.GET_SHARED_LIBRARY_FILES | PackageManager.GET_META_DATA);
-                int resourcesPackageId = loadAssets(appContext, packageInfo);
-                sFuture = new WebLayerLoadFuture(
-                        iWebLayer, appContext, packageInfo, resourcesPackageId);
+                sFuture = new WebLayerLoadFuture(iWebLayer, appContext);
             } catch (Exception e) {
                 throw new AndroidRuntimeException(e);
             }
@@ -130,8 +104,7 @@
     private static final class WebLayerLoadFuture extends ListenableFuture<WebLayer> {
         private final IWebLayer mIWebLayer;
 
-        WebLayerLoadFuture(IWebLayer iWebLayer, Context appContext, PackageInfo packageInfo,
-                int resourcesPackageId) {
+        WebLayerLoadFuture(IWebLayer iWebLayer, Context appContext) {
             mIWebLayer = iWebLayer;
             ValueCallback<Boolean> loadCallback = new ValueCallback<Boolean>() {
                 @Override
@@ -142,9 +115,8 @@
                 }
             };
             try {
-                iWebLayer.initAndLoadAsync(ObjectWrapper.wrap(appContext),
-                        ObjectWrapper.wrap(packageInfo), ObjectWrapper.wrap(loadCallback),
-                        resourcesPackageId);
+                iWebLayer.initAndLoadAsync(
+                        ObjectWrapper.wrap(appContext), ObjectWrapper.wrap(loadCallback));
             } catch (RemoteException e) {
                 throw new APICallException(e);
             }
@@ -224,19 +196,87 @@
     /**
      * Creates a ClassLoader for the remote (weblayer implementation) side.
      */
-    static ClassLoader createRemoteClassLoader(Context localContext) {
-        try {
-            // TODO(cduvall): Might want to cache the remote context so we don't need to call into
-            // package manager more than we need to.
-            Context remoteContext =
-                    localContext.createPackageContext(getImplPackageName(localContext),
-                            Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
-            return remoteContext.getClassLoader();
-        } catch (NameNotFoundException e) {
-            throw new AndroidRuntimeException(e);
+    static ClassLoader createRemoteClassLoader(Context appContext)
+            throws PackageManager.NameNotFoundException, ReflectiveOperationException {
+        String implPackageName = getImplPackageName(appContext);
+        if (implPackageName == null) {
+            return createRemoteClassLoaderFromWebViewFactory(appContext);
+        } else {
+            return createRemoteClassLoaderFromPackage(appContext, implPackageName);
         }
     }
 
+    /**
+     * Creates a ClassLoader for the remote (weblayer implementation) side
+     * using a specified package name as the implementation. This is only
+     * intended for testing, not production use.
+     */
+    private static ClassLoader createRemoteClassLoaderFromPackage(
+            Context appContext, String implPackageName)
+            throws PackageManager.NameNotFoundException, ReflectiveOperationException {
+        // Load the code for the target package.
+        Context remoteContext = appContext.createPackageContext(
+                implPackageName, Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
+
+        // Get the package info for the target package.
+        PackageInfo implPackageInfo = appContext.getPackageManager().getPackageInfo(implPackageName,
+                PackageManager.GET_SHARED_LIBRARY_FILES | PackageManager.GET_META_DATA);
+
+        // Store this package info in WebViewFactory as if it had been loaded as WebView,
+        // because other parts of the implementation need to be able to fetch it from there.
+        Class<?> webViewFactory = Class.forName("android.webkit.WebViewFactory");
+        Field sPackageInfo = webViewFactory.getDeclaredField("sPackageInfo");
+        sPackageInfo.setAccessible(true);
+        sPackageInfo.set(null, implPackageInfo);
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
+            // Load assets using the WebViewDelegate.
+            Class<?> webViewDelegateClass = Class.forName("android.webkit.WebViewDelegate");
+            Constructor constructor = webViewDelegateClass.getDeclaredConstructor();
+            constructor.setAccessible(true);
+            Method addWebViewAssetPath =
+                    webViewDelegateClass.getDeclaredMethod("addWebViewAssetPath", Context.class);
+            Object delegate = constructor.newInstance();
+            addWebViewAssetPath.invoke(delegate, appContext);
+        } else {
+            // In L WebViewDelegate did not yet exist, so we have to poke AssetManager directly.
+            // Note: like the implementation in WebView's Api21CompatibilityDelegate this does
+            // not support split APKs.
+            Method addAssetPath = AssetManager.class.getMethod("addAssetPath", String.class);
+            addAssetPath.invoke(appContext.getResources().getAssets(),
+                    implPackageInfo.applicationInfo.sourceDir);
+        }
+
+        return remoteContext.getClassLoader();
+    }
+
+    /**
+     * Creates a ClassLoader for the remote (weblayer implementation) side
+     * using WebViewFactory to load the current WebView implementation.
+     */
+    private static ClassLoader createRemoteClassLoaderFromWebViewFactory(Context appContext)
+            throws ReflectiveOperationException {
+        Class<?> webViewFactory = Class.forName("android.webkit.WebViewFactory");
+        Class<?> providerClass;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            // In M+ this method loads the native library and the Java code, and adds the assets
+            // to the app.
+            Method getProviderClass = webViewFactory.getDeclaredMethod("getProviderClass");
+            getProviderClass.setAccessible(true);
+            providerClass = (Class) getProviderClass.invoke(null);
+        } else {
+            // In L we have to load the native library separately first.
+            Method loadNativeLibrary = webViewFactory.getDeclaredMethod("loadNativeLibrary");
+            loadNativeLibrary.setAccessible(true);
+            loadNativeLibrary.invoke(null);
+            // In L the method had a different name but still adds the assets to the app.
+            Method getFactoryClass = webViewFactory.getDeclaredMethod("getFactoryClass");
+            getFactoryClass.setAccessible(true);
+            providerClass = (Class) getFactoryClass.invoke(null);
+        }
+        return providerClass.getClassLoader();
+    }
+
     private static String sanitizeProfilePath(String profilePath) {
         if ("".equals(profilePath)) {
             throw new AndroidRuntimeException("Profile path cannot be empty");
@@ -244,11 +284,11 @@
         return profilePath == null ? "" : profilePath;
     }
 
-    private static String getImplPackageName(Context localContext)
+    private static String getImplPackageName(Context appContext)
             throws PackageManager.NameNotFoundException {
-        Bundle metaData = localContext.getPackageManager()
-                                  .getApplicationInfo(localContext.getPackageName(),
-                                          PackageManager.GET_META_DATA)
+        Bundle metaData = appContext.getPackageManager()
+                                  .getApplicationInfo(
+                                          appContext.getPackageName(), PackageManager.GET_META_DATA)
                                   .metaData;
         if (metaData != null) return metaData.getString(PACKAGE_MANIFEST_KEY);
         return null;
diff --git a/weblayer/public/navigation_observer.h b/weblayer/public/navigation_observer.h
index 4249dde..6b0d2dd 100644
--- a/weblayer/public/navigation_observer.h
+++ b/weblayer/public/navigation_observer.h
@@ -24,7 +24,7 @@
  public:
   virtual ~NavigationObserver() {}
 
-  // Called when a navigation started in the BrowserController. |navigation| is
+  // Called when a navigation started in the Tab. |navigation| is
   // unique to a specific navigation. The same |navigation| will be  provided on
   // subsequent calls to NavigationRedirected, NavigationCommitted,
   // NavigationCompleted and NavigationFailed when related to this navigation.
@@ -37,7 +37,7 @@
   // navigations or pushState/replaceState, which will not result in a document
   // change. To filter these out, use Navigation::IsSameDocument.
   //
-  // Note that more than one navigation can be ongoing in the BrowserController
+  // Note that more than one navigation can be ongoing in the Tab
   // at the same time. Each will get its own Navigation object.
   //
   // Note that there is no guarantee that NavigationCompleted/NavigationFailed
@@ -56,17 +56,17 @@
   // Most observers should use NavigationCompleted or NavigationFailed instead,
   // which happens right after the navigation commits. This method is for
   // observers that want to initialize renderer-side state just before the
-  // BrowserController commits the navigation.
+  // Tab commits the navigation.
   //
-  // This is the first point in time where a BrowserController is associated
+  // This is the first point in time where a Tab is associated
   // with the navigation.
   virtual void ReadyToCommitNavigation(Navigation* navigation) {}
 
-  // Called when a navigation completes successfully in the BrowserController.
+  // Called when a navigation completes successfully in the Tab.
   //
-  // The document load will still be ongoing in the BrowserController. Use the
+  // The document load will still be ongoing in the Tab. Use the
   // document loads events such as OnFirstContentfulPaint and related methods to
-  // listen for continued events from this BrowserController.
+  // listen for continued events from this Tab.
   //
   // Note that this is fired by same-document navigations, such as fragment
   // navigations or pushState/replaceState, which will not result in a document
@@ -76,7 +76,7 @@
   // keep a reference to it afterward.
   virtual void NavigationCompleted(Navigation* navigation) {}
 
-  // Called when a navigation aborts in the BrowserController.
+  // Called when a navigation aborts in the Tab.
   //
   // Note that |navigation| will be destroyed at the end of this call, so do not
   // keep a reference to it afterward.
diff --git a/weblayer/public/new_tab_delegate.h b/weblayer/public/new_tab_delegate.h
index 685189ac..b3983f12 100644
--- a/weblayer/public/new_tab_delegate.h
+++ b/weblayer/public/new_tab_delegate.h
@@ -16,17 +16,17 @@
 // Corresponds to type of browser the page requested.
 enum class NewTabType {
   // The new browser should be opened in the foreground.
-  FOREGROUND_TAB = 0,
+  kForeground = 0,
 
   // The new browser should be opened in the foreground.
-  BACKGROUND_TAB,
+  kBackground,
 
   // The page requested the browser be shown in a new window with minimal
   // browser UI. For example, no tabstrip.
-  NEW_POPUP,
+  kNewPopup,
 
   // The page requested the browser be shown in a new window.
-  NEW_WINDOW,
+  kNewWindow,
 };
 
 // An interface that allows clients to handle requests for new browsers, or
diff --git a/weblayer/shell/android/BUILD.gn b/weblayer/shell/android/BUILD.gn
index 9d117fe..c561c7e 100644
--- a/weblayer/shell/android/BUILD.gn
+++ b/weblayer/shell/android/BUILD.gn
@@ -42,7 +42,9 @@
   jinja_template(_manifest_target) {
     input = "shell_apk/AndroidManifest.xml"
     output = _weblayer_shell_manifest
-    variables = [ "weblayer_package=" + invoker.weblayer_package ]
+    if (defined(invoker.weblayer_package)) {
+      variables = [ "weblayer_package=" + invoker.weblayer_package ]
+    }
   }
 
   android_apk(target_name + "_apk") {
@@ -69,14 +71,8 @@
   apk_name = "WebLayerShell"
 }
 
-weblayer_shell_apk_helper("weblayer_shell_monochrome") {
-  weblayer_package = "org.chromium.chrome"
-  apk_name = "WebLayerShellChrome"
-}
-
-weblayer_shell_apk_helper("weblayer_shell_webview") {
-  weblayer_package = system_webview_package_name
-  apk_name = "WebLayerShellWebView"
+weblayer_shell_apk_helper("weblayer_shell_system_webview") {
+  apk_name = "WebLayerShellSystemWebView"
 }
 
 generate_wrapper("run_weblayer_shell") {
@@ -97,37 +93,22 @@
 }
 
 if (public_android_sdk) {
-  generate_wrapper("run_weblayer_shell_monochrome") {
-    testonly = true
-    wrapper_script = "$root_out_dir/bin/run_weblayer_shell_monochrome"
-    executable = "//weblayer/tools/run_weblayer_shell.py"
-    executable_args = [
-      "--shell-apk-path",
-      "@WrappedPath(apks/WebLayerShellChrome.apk)",
-      "--support-apk-path",
-      "@WrappedPath(apks/MonochromePublic.apk)",
-    ]
-
-    deps = [
-      ":weblayer_shell_monochrome_apk",
-      "//chrome/android:monochrome_public_apk",
-    ]
-  }
-
   generate_wrapper("run_weblayer_shell_trichrome") {
     testonly = true
     wrapper_script = "$root_out_dir/bin/run_weblayer_shell_trichrome"
     executable = "//weblayer/tools/run_weblayer_shell.py"
     executable_args = [
       "--shell-apk-path",
-      "@WrappedPath(apks/WebLayerShellWebView.apk)",
+      "@WrappedPath(apks/WebLayerShellSystemWebView.apk)",
       "--support-apk-path",
       "@WrappedPath(apks/TrichromeLibrary.apk)",
       "@WrappedPath(apks/TrichromeWebView.apk)",
+      "--switch-webview-to",
+      system_webview_package_name,
     ]
 
     deps = [
-      ":weblayer_shell_webview_apk",
+      ":weblayer_shell_system_webview_apk",
       "//android_webview:trichrome_webview_apk",
       "//chrome/android:trichrome_library_apk",
     ]
@@ -139,13 +120,15 @@
     executable = "//weblayer/tools/run_weblayer_shell.py"
     executable_args = [
       "--shell-apk-path",
-      "@WrappedPath(apks/WebLayerShellWebView.apk)",
+      "@WrappedPath(apks/WebLayerShellSystemWebView.apk)",
       "--support-apk-path",
       "@WrappedPath(apks/SystemWebView.apk)",
+      "--switch-webview-to",
+      system_webview_package_name,
     ]
 
     deps = [
-      ":weblayer_shell_webview_apk",
+      ":weblayer_shell_system_webview_apk",
       "//android_webview:system_webview_apk",
     ]
   }
diff --git a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/NewTabCallbackTest.java b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/NewTabCallbackTest.java
index 80188fd8..87ac783 100644
--- a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/NewTabCallbackTest.java
+++ b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/NewTabCallbackTest.java
@@ -74,9 +74,9 @@
         Assert.assertNotNull(mActivity);
         NewTabCallbackImpl callback = new NewTabCallbackImpl();
         Tab firstTab = TestThreadUtils.runOnUiThreadBlockingNoException(() -> {
-            Tab browserController = mActivity.getBrowser().getActiveTab();
-            browserController.setNewTabCallback(callback);
-            return browserController;
+            Tab tab = mActivity.getBrowser().getActiveTab();
+            tab.setNewTabCallback(callback);
+            return tab;
         });
 
         EventUtils.simulateTouchCenterOfView(mActivity.getWindow().getDecorView());
diff --git a/weblayer/shell/android/shell_apk/AndroidManifest.xml b/weblayer/shell/android/shell_apk/AndroidManifest.xml
index eb09494..f77ec27 100644
--- a/weblayer/shell/android/shell_apk/AndroidManifest.xml
+++ b/weblayer/shell/android/shell_apk/AndroidManifest.xml
@@ -22,7 +22,9 @@
         </activity>
         <activity android:name="InstrumentationActivity">
         </activity>
-        <meta-data android:name="org.chromium.weblayer.WebLayerPackage"
-                   android:value="{{ weblayer_package }}"/>
+        {% if weblayer_package is defined %}
+            <meta-data android:name="org.chromium.weblayer.WebLayerPackage"
+                       android:value="{{ weblayer_package }}"/>
+        {% endif %}
     </application>
 </manifest>
diff --git a/weblayer/tools/run_weblayer_shell.py b/weblayer/tools/run_weblayer_shell.py
index 3dfa1ad..6ba522b3 100755
--- a/weblayer/tools/run_weblayer_shell.py
+++ b/weblayer/tools/run_weblayer_shell.py
@@ -19,6 +19,8 @@
   parser.add_argument('--support-apk-path', nargs='+', type=os.path.abspath,
                       required=True,
                       help='Absolute path to the WebLayer support APKs to use.')
+  parser.add_argument('--switch-webview-to', type=str, required=False,
+                      help='Package name to set as the WebView implementation.')
   parser.add_argument('-d', '--device', dest='devices', action='append',
                       default=[],
                       help='Target device for apk to install on. Enter multiple'
@@ -36,6 +38,10 @@
       print 'Installing %s...' % path
       device.Install(path, reinstall=True, allow_downgrade=True)
       print 'Success'
+    if args.switch_webview_to:
+      print 'Setting WebView implementation to %s' % args.switch_webview_to
+      device.SetWebViewImplementation(args.switch_webview_to)
+      print 'Done'
 
     device.adb.Shell('monkey -p org.chromium.weblayer.shell 1')